GBHawk : GBC Commits round 2

-HDMA
-GBA setting
This commit is contained in:
alyosha-tas 2018-03-25 17:58:21 -04:00
parent ca69e52229
commit 380b9f085e
7 changed files with 151 additions and 13 deletions

View File

@ -57,6 +57,7 @@ namespace BizHawk.Emulation.Common.Components.LR35902
public ushort int_src;
public int stop_time;
public bool stop_check;
public bool is_GBC; // GBC automatically adds a NOP to avoid the HALT bug (according to Sinimas)
private void ResetInterrupts()
{

View File

@ -480,6 +480,7 @@ namespace BizHawk.Emulation.Common.Components.LR35902
ser.Sync("int_src", ref int_src);
ser.Sync("stop_time", ref stop_time);
ser.Sync("stop_check", ref stop_check);
ser.Sync("is_GBC", ref is_GBC);
ser.Sync("instruction_pointer", ref instr_pntr);
ser.Sync("current instruction", ref cur_instr, false);

View File

@ -16,11 +16,21 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public byte HDMA_src_lo;
public byte HDMA_dest_hi;
public byte HDMA_dest_lo;
public byte HDMA_ctrl;
public byte HDMA_ctrl
{
get { return (byte)(((HDMA_active ? 0 : 1) << 7) | ((HDMA_length >> 16) - 1)); }
}
// controls for tile attributes
public byte tile_attr_byte;
public int VRAM_sel;
public bool HDMA_active;
public bool HDMA_mode;
public ushort cur_DMA_src;
public ushort cur_DMA_dest;
public int HDMA_length;
public int HDMA_countdown;
public override byte ReadReg(int addr)
{
@ -140,7 +150,37 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
HDMA_dest_lo = value;
break;
case 0xFF55: // HDMA5
HDMA_ctrl = value;
if (!HDMA_active)
{
HDMA_mode = value.Bit(7);
HDMA_countdown = 4;
if (value.Bit(7))
{
// HDMA during HBlank only
HDMA_active = true;
}
else
{
// HDMA immediately
HDMA_active = true;
Core.HDMA_transfer = true;
}
// latch read locations
cur_DMA_dest = (ushort)(((HDMA_dest_hi & 0x1F) << 8) | (HDMA_dest_lo & 0xF0));
cur_DMA_src = (ushort)(((HDMA_src_hi & 0xFF) << 8) | (HDMA_src_lo & 0xF0));
HDMA_length = ((HDMA_ctrl & 0x7F) + 1) * 16;
}
else
{
//terminate the transfer
if (!value.Bit(7))
{
HDMA_active = false;
}
}
break;
case 0xFF68: // BGPI
BG_pal_index = value;
@ -159,6 +199,71 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public override void tick()
{
// Do HDMA ticks
if (HDMA_active)
{
if (HDMA_countdown == 0)
{
if (!HDMA_mode)
{
// immediately transfer bytes, 2 bytes per cycles
if (HDMA_length > 0)
{
Core.VRAM[(Core.VRAM_Bank * 0x2000) + cur_DMA_dest] = Core.ReadMemory(cur_DMA_src);
cur_DMA_dest = (ushort)((cur_DMA_dest + 1) & 0x1FFF);
cur_DMA_src = (ushort)((cur_DMA_src + 1) & 0xFFFF);
HDMA_length--;
Core.VRAM[(Core.VRAM_Bank * 0x2000) + cur_DMA_dest] = Core.ReadMemory(cur_DMA_src);
cur_DMA_dest = (ushort)((cur_DMA_dest + 1) & 0x1FFF);
cur_DMA_src = (ushort)((cur_DMA_src + 1) & 0xFFFF);
HDMA_length--;
if (HDMA_length == 0)
{
HDMA_active = false;
Core.HDMA_transfer = false;
}
}
}
else
{
// only transfer during mode 3, otherwise
if ((STAT & 3) == 3)
{
Core.HDMA_transfer = true;
if (HDMA_length > 0)
{
Core.VRAM[(Core.VRAM_Bank * 0x2000) + cur_DMA_dest] = Core.ReadMemory(cur_DMA_src);
cur_DMA_dest = (ushort)((cur_DMA_dest + 1) & 0x1FFF);
cur_DMA_src = (ushort)((cur_DMA_src + 1) & 0xFFFF);
HDMA_length--;
Core.VRAM[(Core.VRAM_Bank * 0x2000) + cur_DMA_dest] = Core.ReadMemory(cur_DMA_src);
cur_DMA_dest = (ushort)((cur_DMA_dest + 1) & 0x1FFF);
cur_DMA_src = (ushort)((cur_DMA_src + 1) & 0xFFFF);
HDMA_length--;
if (HDMA_length == 0)
{
HDMA_active = false;
Core.HDMA_transfer = false;
}
}
}
else
{
Core.HDMA_transfer = false;
}
}
}
else
{
HDMA_countdown--;
}
}
// the ppu only does anything if it is turned on via bit 7 of LCDC
if (LCDC.Bit(7))
{
@ -1180,10 +1285,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
ser.Sync("HDMA_src_lo", ref HDMA_src_lo);
ser.Sync("HDMA_dest_hi", ref HDMA_dest_hi);
ser.Sync("HDMA_dest_lo", ref HDMA_dest_lo);
ser.Sync("HDMA_ctrl", ref HDMA_ctrl);
ser.Sync("tile_attr_byte", ref tile_attr_byte);
ser.Sync("VRAM_sel", ref VRAM_sel);
ser.Sync("HDMA_active", ref HDMA_active);
ser.Sync("HDMA_mode", ref HDMA_mode);
ser.Sync("cur_DMA_src", ref cur_DMA_src);
ser.Sync("cur_DMA_dest", ref cur_DMA_dest);
ser.Sync("HDMA_length", ref HDMA_length);
ser.Sync("HDMA_countdown", ref HDMA_countdown);
base.SyncState(ser);
}

View File

@ -117,20 +117,23 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
ppu.tick();
if (Use_RTC) { mapper.RTC_Tick(); }
// These things all tick twice as fast in GBC double speed mode
ppu.DMA_tick();
timer.tick_1();
serialport.serial_transfer_tick();
cpu.ExecuteOne(ref REG_FF0F, REG_FFFF);
timer.tick_2();
if (double_speed)
if (!HDMA_transfer)
{
// These things all tick twice as fast in GBC double speed mode
ppu.DMA_tick();
timer.tick_1();
serialport.serial_transfer_tick();
cpu.ExecuteOne(ref REG_FF0F, REG_FFFF);
timer.tick_2();
if (double_speed)
{
ppu.DMA_tick();
timer.tick_1();
serialport.serial_transfer_tick();
cpu.ExecuteOne(ref REG_FF0F, REG_FFFF);
timer.tick_2();
}
}
if (in_vblank && !in_vblank_old)

View File

@ -87,6 +87,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
[DefaultValue(ConsoleModeType.Auto)]
public ConsoleModeType ConsoleMode { get; set; }
[DisplayName("CGB in GBA")]
[Description("Emulate GBA hardware running a CGB game, instead of CGB hardware. Relevant only for titles that detect the presense of a GBA, such as Shantae.")]
[DefaultValue(false)]
public bool GBACGB { get; set; }
[DisplayName("RTC Initial Time")]
[Description("Set the initial RTC time in terms of elapsed seconds.")]
[DefaultValue(0)]

View File

@ -82,11 +82,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
ser.Sync("VRAM", ref VRAM, false);
ser.Sync("OAM", ref OAM, false);
ser.Sync("_bios", ref _bios, false);
ser.Sync("RAM_Bank", ref RAM_Bank);
ser.Sync("VRAM_Bank", ref VRAM_Bank);
ser.Sync("is_GBC", ref is_GBC);
ser.Sync("double_speed", ref double_speed);
ser.Sync("speed_switch", ref speed_switch);
ser.Sync("HDMA_transfer", ref HDMA_transfer);
ser.Sync("Use_RTC", ref Use_RTC);

View File

@ -56,9 +56,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public bool is_GBC;
public bool double_speed;
public bool speed_switch;
public bool HDMA_transfer; // stalls CPU when in progress
public readonly byte[] _rom;
public readonly byte[] _bios;
public byte[] _bios;
public readonly byte[] _rom;
public readonly byte[] header = new byte[0x50];
public byte[] cart_RAM;
@ -78,6 +79,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public Audio audio;
public SerialPort serialport;
private static byte[] GBA_override = { 0xFF, 0x00, 0xCD, 0x03, 0x35, 0xAA, 0x31, 0x90, 0x94, 0x00, 0x00, 0x00, 0x00 };
[CoreConstructor("GB", "GBC")]
public GBHawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ object settings, object syncSettings)
{
@ -140,6 +143,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
_bios = Bios;
// Here we modify the BIOS if GBA mode is set (credit to ExtraTricky)
if (is_GBC && _syncSettings.GBACGB)
{
for (int i = 0; i < 13; i++)
{
_bios[i + 0xF3] = (byte)((GBA_override[i] + _bios[i + 0xF3]) & 0xFF);
}
}
// CPU needs to know about GBC status too
cpu.is_GBC = is_GBC;
Buffer.BlockCopy(rom, 0x100, header, 0, 0x50);
string hash_md5 = null;