From ca01ff6f798363429b3001511250e10f7877c38d Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 8 Jun 2018 17:16:15 +0300 Subject: [PATCH] Finally, perfect emulation of the STAT write bug. --- Core/display.c | 3 +-- Core/z80_cpu.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Core/display.c b/Core/display.c index 2024904..20580de 100644 --- a/Core/display.c +++ b/Core/display.c @@ -230,7 +230,6 @@ void GB_set_color_correction_mode(GB_gameboy_t *gb, GB_color_correction_mode_t m */ -/* Todo: When the CPU and PPU write to IF at the same T-cycle, the PPU write is ignored. */ void GB_STAT_update(GB_gameboy_t *gb) { if (!(gb->io_registers[GB_IO_LCDC] & 0x80)) return; @@ -643,7 +642,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) gb->ly_for_comparison = gb->current_line? -1 : 0; /* The OAM STAT interrupt occurs 1 T-cycle before STAT actually changes, except on line 0. - PPU glitch. */ + PPU glitch? */ if (gb->current_line != 0) { gb->mode_for_interrupt = 2; gb->io_registers[GB_IO_STAT] &= ~3; diff --git a/Core/z80_cpu.c b/Core/z80_cpu.c index 86b479e..693804a 100644 --- a/Core/z80_cpu.c +++ b/Core/z80_cpu.c @@ -115,10 +115,19 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value) return; } - /* The DMG STAT-write bug is basically the STAT register being read as FF for a single T-cycle*/ + /* The DMG STAT-write bug is basically the STAT register being read as FF for a single T-cycle */ case GB_CONFLICT_STAT_DMG: GB_advance_cycles(gb, gb->pending_cycles); - GB_write_memory(gb, addr, 0xFF); + /* State 7 is the edge between HBlank and OAM mode, and it behaves a bit weird. + The OAM interrupt seems to be blocked by HBlank interrupts in that case, despite + the timing not making much sense for that. + This is a hack to simulate this effect */ + if (gb->display_state == 7 && (gb->io_registers[GB_IO_STAT] & 0x28) == 0x08) { + GB_write_memory(gb, addr, ~0x20); + } + else { + GB_write_memory(gb, addr, 0xFF); + } GB_advance_cycles(gb, 1); GB_write_memory(gb, addr, value); gb->pending_cycles = 3;