From 6532aef089dc7a434b982eb59248682e5a714db8 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 26 May 2018 18:06:40 +0300 Subject: [PATCH] Correct emulation of the DMG stat write bug --- Core/memory.c | 9 --------- Core/z80_cpu.c | 12 +++++++++++- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Core/memory.c b/Core/memory.c index 1cb2eb9..f280c94 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -664,15 +664,6 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) return; case GB_IO_STAT: - /* A DMG bug: http://www.devrs.com/gb/files/faqs.html#GBBugs */ - if (!gb->is_cgb && /* Only occurs on DMGs */ - (gb->io_registers[GB_IO_LCDC] & 0x80) && /* LCD must be on */ - !gb->stat_interrupt_line && /* The interrupt line must be off */ - gb->display_state != 2 && /* State 2 is line 0's faux Mode 2 */ - !gb->oam_read_blocked /* OAM must be readable (Modes 0 and 1) */ - ) { - gb->io_registers[GB_IO_IF] |= 2; - } /* Delete previous R/W bits */ gb->io_registers[GB_IO_STAT] &= 7; /* Set them by value */ diff --git a/Core/z80_cpu.c b/Core/z80_cpu.c index 5119ff7..90c50f5 100644 --- a/Core/z80_cpu.c +++ b/Core/z80_cpu.c @@ -17,6 +17,7 @@ typedef enum { GB_CONFLICT_WRITE_CPU, /* Register specific values */ GB_CONFLICT_STAT_CGB, + GB_CONFLICT_STAT_DMG, } GB_conflict_t; /* Todo: How does double speed mode affect these? */ @@ -33,7 +34,7 @@ static const GB_conflict_t dmg_conflict_map[0x80] = { [GB_IO_LYC] = GB_CONFLICT_READ_OLD, [GB_IO_LCDC] = GB_CONFLICT_READ_NEW, [GB_IO_SCY] = GB_CONFLICT_READ_NEW, - [GB_IO_STAT] = GB_CONFLICT_READ_NEW, + [GB_IO_STAT] = GB_CONFLICT_STAT_DMG, /* Todo: these are GB_CONFLICT_READ_NEW on MGB/SGB2 */ [GB_IO_BGP] = GB_CONFLICT_READ_OR, @@ -112,6 +113,15 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value) GB_write_memory(gb, addr, value); gb->pending_cycles = 3; } + + /* 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); + GB_advance_cycles(gb, 1); + GB_write_memory(gb, addr, value); + gb->pending_cycles = 3; + return; } }