parent
ca69e52229
commit
380b9f085e
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue