diff --git a/src/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs b/src/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs index 8adeb00472..bfc13572c3 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs @@ -21,8 +21,8 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 DEC16, SPl, SPh, INT_GET, 1, W, WR, SPl, SPh, PCl, - IRQ_CLEAR, IDLE, + IRQ_CLEAR, TR, PCl, W, OP }; } @@ -50,8 +50,8 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 DEC16, SPl, SPh, INT_GET, 1, W, WR, SPl, SPh, PCl, - IRQ_CLEAR, IDLE, + IRQ_CLEAR, TR, PCl, W, OP }; } diff --git a/src/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs b/src/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs index 1f322d5e56..767a3e99a1 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs @@ -600,7 +600,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 // interrupt src = 5 sets the PC to zero as observed // also the triggering interrupt seems like it is held low (i.e. cannot trigger I flag) until the interrupt is serviced ushort bit_check = instr_table[instr_pntr++]; - //Console.WriteLine(interrupt_src + " " + interrupt_enable + " " + TotalExecutedCycles); + //Console.WriteLine("int " + TotalExecutedCycles); interrupt_src_reg = GetIntRegs(0); interrupt_enable_reg = GetIntRegs(1); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IDebuggable.cs index 97e7456582..c252c3a04a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IDebuggable.cs @@ -20,5 +20,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public void Step(StepType type) => throw new NotImplementedException(); public long TotalExecutedCycles => (long)cpu.TotalExecutedCycles; + //public long TotalExecutedCycles => CycleCount; } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs index e197d5b967..6e792d20b4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs @@ -20,6 +20,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public bool controller_was_checked; public bool delays_to_process; public int controller_delay_cd; + //public long CycleCount; public bool FrameAdvance(IController controller, bool render, bool rendersound) { @@ -112,8 +113,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk cpu.ExecuteOne(); timer.divider_reg++; if (delays_to_process) { process_delays(); } + + REG_FF0F_OLD = REG_FF0F; } - + if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); } serialport.serial_transfer_tick(); timer.tick(); @@ -130,6 +133,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk cpu.TotalExecutedCycles++; timer.divider_reg++; if (delays_to_process) { process_delays(); } + + REG_FF0F_OLD = REG_FF0F; } timer.tick(); @@ -139,6 +144,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (delays_to_process) { process_delays(); } } + //CycleCount++; + if (in_vblank && !in_vblank_old) { _islag = false; @@ -194,14 +201,7 @@ 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 && !cpu.stopped) { ppu.DMA_tick(); } - serialport.serial_transfer_tick(); - timer.tick(); - cpu.ExecuteOne(); - timer.divider_reg++; - - if (delays_to_process) { process_delays(); } - + // Note that DMA is halted when the CPU is halted if (double_speed) { if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); } @@ -209,26 +209,36 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk timer.tick(); cpu.ExecuteOne(); timer.divider_reg++; - if (delays_to_process) { process_delays(); } + + REG_FF0F_OLD = REG_FF0F; } - } - else - { + + if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); } + serialport.serial_transfer_tick(); timer.tick(); - cpu.TotalExecutedCycles++; + cpu.ExecuteOne(); timer.divider_reg++; if (delays_to_process) { process_delays(); } - + } + else + { if (double_speed) { timer.tick(); cpu.TotalExecutedCycles++; timer.divider_reg++; - if (delays_to_process) { process_delays(); } + + REG_FF0F_OLD = REG_FF0F; } + + timer.tick(); + cpu.TotalExecutedCycles++; + timer.divider_reg++; + + if (delays_to_process) { process_delays(); } } if (in_vblank && !in_vblank_old) @@ -314,7 +324,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk else { // reset the divider (only way for speed_change_timing_fine.gbc and speed_change_cancel.gbc to both work) - timer.divider_reg = 1; + //Console.WriteLine("at stop " + timer.divider_reg); + timer.divider_reg = 0x1; + + // TODO: resetting the divider causes an increment, but exact timing unclear + //timer.tick(); + double_speed = !double_speed; return 0; } @@ -343,7 +358,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public void SetIntRegs(byte r) { + // For timer interrupts or serial interrupts that occur on the same cycle as the IRQ clear + // the clear wins on GB but the set wins on GBC if (((REG_FF0F & 4) == 4) && ((r & 4) == 0) && timer.IRQ_block && !is_GBC) { r |= 4; } + if (((REG_FF0F & 8) == 8) && ((r & 8) == 0) && serialport.IRQ_block && !is_GBC) { r |= 8; } REG_FF0F = r; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs index 7489d4110d..3cb1a10762 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs @@ -220,6 +220,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk iptr3 = Marshal.AllocHGlobal(ppu.color_palette.Length * 8 * 8 + 1); _scanlineCallback = null; + + /* + for (int i = 0; i < ZP_RAM.Length; i++) + { + ZP_RAM[i] = 0xFF; + } + + for (int i = 0; i < RAM.Length; i++) + { + RAM[i] = 0xFF; + } + */ } public bool IsCGBMode() => is_GBC; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs index dc13349b27..701cdefde1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs @@ -50,6 +50,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk blank_frame = true; } LCDC = value; + //Console.WriteLine(LY + " " + cycle); break; case 0xFF41: // STAT // writing to STAT during mode 0 or 1 causes a STAT IRQ diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs index 328fd3006f..3bfa0b06cd 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs @@ -38,6 +38,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // Interrupt flags case 0xFF0F: // TODO: Maybe some PPU bits are immediately visible, see 10spritesPrLine_10xposA7_m0irq_2_dmg08_cgb04c_out2.gbc + //Console.WriteLine("FF0F " + cpu.TotalExecutedCycles); ret = REG_FF0F_OLD; break; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs index bcd271f47b..508e58cfd8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs @@ -25,6 +25,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { public partial class GBHawk { + //public byte[] RAM_read = new byte[0x8000]; + //public byte[] ZP_RAM_read = new byte[0x80]; + public byte ReadMemory(ushort addr) { if (MemoryCallbacks.HasReads) @@ -61,6 +64,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (addr >= 0xF000 && addr < 0xFE00) { + //if (RAM_read[(RAM_Bank * 0x1000) + (addr - 0xF000)] == 0) { Console.WriteLine("RAM: " + addr + " " + cpu.TotalExecutedCycles); } return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)]; } @@ -85,6 +89,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { if (addr != 0xFFFF) { + //if (ZP_RAM_read[addr - 0xFF80] == 0) { Console.WriteLine("ZP: " + (addr - 0xFF80) + " " + cpu.TotalExecutedCycles); } return ZP_RAM[addr - 0xFF80]; } else @@ -158,6 +163,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (addr < 0xFE00) { addr = (ushort)(RAM_Bank * (addr & 0x1000) + (addr & 0xFFF)); + //if (RAM_read[addr] == 0) { Console.WriteLine("RAM: " + addr + " " + cpu.TotalExecutedCycles); } return RAM[addr]; } @@ -215,6 +221,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (addr < 0xFFFF) { + //if (ZP_RAM_read[addr - 0xFF80] == 0) { Console.WriteLine("ZP: " + (addr - 0xFF80) + " " + cpu.TotalExecutedCycles); } return ZP_RAM[addr - 0xFF80]; } @@ -234,7 +241,6 @@ 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 @@ -243,10 +249,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (addr >= 0xE000 && addr < 0xF000) { + //RAM_read[addr - 0xE000] = 1; RAM[addr - 0xE000] = value; } else if (addr >= 0xF000 && addr < 0xFE00) { + //RAM_read[RAM_Bank * 0x1000 + (addr - 0xF000)] = 1; RAM[RAM_Bank * 0x1000 + (addr - 0xF000)] = value; } else if (addr >= 0xFE00 && addr < 0xFEA0 && ppu.DMA_OAM_access) @@ -261,6 +269,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { if (addr != 0xFFFF) { + //ZP_RAM_read[addr - 0xFF80] = 1; ZP_RAM[addr - 0xFF80] = value; } else @@ -281,6 +290,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } else if (addr < 0xFFFF) { + //ZP_RAM_read[addr - 0xFF80] = 1; ZP_RAM[addr - 0xFF80] = value; } else @@ -294,7 +304,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { if (ppu.OAM_access_write) { OAM[addr - 0xFE00] = value; } } - // unmapped memory writes depend on console + // unmapped memory writes depend on console else { if (is_GBC) @@ -318,6 +328,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk else if (addr >= 0xC000) { addr = (ushort)(RAM_Bank * (addr & 0x1000) + (addr & 0xFFF)); + //RAM_read[addr] = 1; RAM[addr] = value; } else if (addr >= 0xA000) @@ -326,7 +337,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } else if (addr >= 0x8000) { - if (ppu.VRAM_access_write) { VRAM[(VRAM_Bank * 0x2000) + (addr - 0x8000)] = value; } + if (ppu.VRAM_access_write) + { + VRAM[(VRAM_Bank * 0x2000) + (addr - 0x8000)] = value; + } } else { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs index d65d562a00..327ed9e68d 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs @@ -1,5 +1,6 @@ using BizHawk.Common.NumberExtensions; using BizHawk.Common; +using System; namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { @@ -15,6 +16,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public int clk_rate; public byte going_out; public byte coming_in; + public int serial_bits_old; + public bool IRQ_block; public byte ReadReg(int addr) { @@ -40,20 +43,24 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk case 0xFF02: if ((value & 0x1) == 1) { + serial_bits = 8; if (((value & 2) > 0) && Core.GBC_compat) { clk_rate = 16; - serial_clock = (16 - (int)(Core.cpu.TotalExecutedCycles % 8)) + 1; + serial_clock = 16 - (int)(Core.timer.divider_reg % 8) - 1; + + // if the clock rate is changing and it's on a GBA/C, the parity of (cpu.totalexecutedcycles & 512) effects the first bit + // Not sure exactly how yet } else { clk_rate = 512; - serial_clock = 512 - (int)(Core.cpu.TotalExecutedCycles % 256) + 1; + serial_clock = 512 - (int)(Core.timer.divider_reg % 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 + // not sure of the exact nature of it, here is one method that gives correct result on one test rom but not others /* if (Core._syncSettings.GBACGB && Core.is_GBC) { @@ -68,10 +75,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } else { + serial_bits_old = serial_bits; serial_bits = 8; clk_rate = -1; serial_clock = clk_rate; can_pulse = false; + } if (Core.GBC_compat) @@ -90,6 +99,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public void serial_transfer_tick() { + IRQ_block = false; + if (serial_clock > 0) { serial_clock--; @@ -108,6 +119,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk if (Core.REG_FFFF.Bit(3)) { Core.cpu.FlagI = true; } Core.REG_FF0F |= 0x08; + //Console.WriteLine("SIRQ " + Core.cpu.TotalExecutedCycles); + IRQ_block = true; } else { @@ -141,6 +154,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk ser.Sync(nameof(going_out), ref going_out); ser.Sync(nameof(coming_in), ref coming_in); ser.Sync(nameof(can_pulse), ref can_pulse); + ser.Sync(nameof(IRQ_block), ref IRQ_block); } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Timer.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Timer.cs index 13830c0b25..d6febab9e7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Timer.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Timer.cs @@ -204,6 +204,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // set interrupts if (Core.REG_FFFF.Bit(2)) { Core.cpu.FlagI = true; } + //Console.WriteLine("timer " + Core.cpu.TotalExecutedCycles); Core.REG_FF0F |= 0x04; IRQ_block = true; }