diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs index c7782789c6..bf3137c315 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs @@ -58,6 +58,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk do_frame(controller); + // if the game is stopped but controller interrupts are on, check for interrupts + if ((cpu.stopped || cpu.halted) && _islag && ((REG_FFFF & 0x10) == 0x10)) + { + // update the controller state on VBlank + GetControllerState(controller); + + do_controller_check(); + } + if (_scanlineCallback != null) { if (_scanlineCallbackLine == -1) @@ -88,14 +97,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { // These things all tick twice as fast in GBC double speed mode // Note that DMA is halted when the CPU is halted - if (ppu.DMA_start && !cpu.halted) { ppu.DMA_tick(); } + if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); } serialport.serial_transfer_tick(); cpu.ExecuteOne(); timer.tick(); if (double_speed) { - if (ppu.DMA_start && !cpu.halted) { ppu.DMA_tick(); } + if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); } serialport.serial_transfer_tick(); cpu.ExecuteOne(); timer.tick(); @@ -104,11 +113,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk else { cpu.TotalExecutedCycles++; - timer.tick(); + timer.tick(); if (double_speed) { cpu.TotalExecutedCycles++; - timer.tick(); + timer.tick(); } } @@ -165,14 +174,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (!HDMA_transfer) { // These things all tick twice as fast in GBC double speed mode - if (ppu.DMA_start && !cpu.halted) { ppu.DMA_tick(); } + if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); } serialport.serial_transfer_tick(); cpu.ExecuteOne(); timer.tick(); if (double_speed) { - if (ppu.DMA_start && !cpu.halted) { ppu.DMA_tick(); } + if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); } serialport.serial_transfer_tick(); cpu.ExecuteOne(); timer.tick(); @@ -244,7 +253,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { speed_switch = false; Console.WriteLine("Speed Switch: " + cpu.TotalExecutedCycles); - int ret = double_speed ? 35112 : 35112; // actual time needs checking + int ret = double_speed ? (32768 - 19) : (32768 - 19); // actual time needs checking double_speed = !double_speed; return ret; } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs index 7b3b323beb..3ef89d2449 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs @@ -33,7 +33,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } - private GBSettings _settings = new GBSettings(); + public GBSettings _settings = new GBSettings(); public GBSyncSettings _syncSettings = new GBSyncSettings(); public class GBSettings diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs index 21c1035897..1d2ddb902f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs @@ -47,16 +47,20 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk return mapper.ReadMemoryLow(addr); } - if (addr >= 0xE000 && (addr < 0xF000)) + if (addr >= 0xA000 && addr < 0xC000 && is_GBC) { - return RAM[addr - 0xE000]; + // on GBC only, cart is accessible during DMA + return mapper.ReadMemoryHigh(addr); } + if (addr >= 0xE000 && addr < 0xF000) + { + return RAM[addr - 0xE000]; + } if (addr >= 0xF000 && addr < 0xFE00) { return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)]; } - if (addr >= 0xFE00 && addr < 0xFEA0 && ppu.DMA_OAM_access) { return OAM[addr - 0xFE00]; @@ -67,13 +71,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk return Read_Registers(addr); } - if ((addr >= 0xFF80)) + if (addr >= 0xFF80) { - // register FFFF? - return ZP_RAM[addr - 0xFF80]; + if (addr != 0xFFFF) + { + return ZP_RAM[addr - 0xFF80]; + } + else + { + return Read_Registers(addr); + } } - return 0xFF; + return ppu.DMA_byte; } if (addr < 0x8000) @@ -171,6 +181,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (ppu.DMA_start) { // some of gekkio's tests require this to be accessible during DMA + + if (addr >= 0xA000 && addr < 0xC000 && is_GBC) + { + // on GBC only, cart is accessible during DMA + mapper.WriteMemory(addr, value); + } + if (addr >= 0xE000 && addr < 0xF000) { RAM[addr - 0xE000] = value; @@ -189,7 +206,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } else if (addr >= 0xFF80) { - ZP_RAM[addr - 0xFF80] = value; + if (addr != 0xFFFF) + { + ZP_RAM[addr - 0xFF80] = value; + } + else + { + Write_Registers(addr, value); + } } return; @@ -284,11 +308,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk return mapper.PeekMemoryLow(addr); } + if (addr >= 0xA000 && addr < 0xC000 && is_GBC) + { + // on GBC only, cart is accessible during DMA + return mapper.ReadMemoryHigh(addr); + } + if (addr >= 0xE000 && addr < 0xF000) { return RAM[addr - 0xE000]; } - if (addr >= 0xF000 && addr < 0xFE00) { return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)]; @@ -306,10 +335,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (addr >= 0xFF80) { - return ZP_RAM[addr - 0xFF80]; + if (addr != 0xFFFF) + { + return ZP_RAM[addr - 0xFF80]; + } + else + { + return Read_Registers(addr); + } } - return 0xFF; + return ppu.DMA_byte; } if (addr < 0x8000) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs index 6dbe89875c..ba2dd399ad 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs @@ -48,12 +48,24 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (((value & 2) > 0) && Core.GBC_compat) { clk_rate = 16; - serial_clock = (15 - (int)(Core.cpu.TotalExecutedCycles % 16)) + 1; + serial_clock = (16 - (int)(Core.cpu.TotalExecutedCycles % 8)) + 1; } else { clk_rate = 512; - serial_clock = (511 - (int)(Core.cpu.TotalExecutedCycles % 512)) + 1; + serial_clock = 512 - (int)(Core.cpu.TotalExecutedCycles % 256) + 1; + + // there seems to be some clock inverting happening on some transfers + // not sure of the exact nature of it, here is one methor that gives correct result on one test rom but not others + /* + if (Core._syncSettings.GBACGB && Core.is_GBC) + { + if ((Core.TotalExecutedCycles % 256) > 127) + { + serial_clock = (8 - (int)(Core.cpu.TotalExecutedCycles % 8)) + 1; + } + } + */ } can_pulse = true; } @@ -71,12 +83,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (((value & 2) > 0) && Core.GBC_compat) { clk_rate = 16; - serial_clock = (15 - (int)(Core.cpu.TotalExecutedCycles % 16)) + 1; + serial_clock = (16 - (int)(Core.cpu.TotalExecutedCycles % 8)) + 1; } else { clk_rate = 512; - serial_clock = (511 - (int)(Core.cpu.TotalExecutedCycles % 512)) + 1; + serial_clock = 512 - (int)(Core.cpu.TotalExecutedCycles % 256) + 1; } can_pulse = true; }