Finally, perfect emulation of the STAT write bug.

This commit is contained in:
Lior Halphon 2018-06-08 17:16:15 +03:00
parent 127324d2d6
commit ca01ff6f79
2 changed files with 12 additions and 4 deletions

View File

@ -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) void GB_STAT_update(GB_gameboy_t *gb)
{ {
if (!(gb->io_registers[GB_IO_LCDC] & 0x80)) return; 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; 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. /* 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) { if (gb->current_line != 0) {
gb->mode_for_interrupt = 2; gb->mode_for_interrupt = 2;
gb->io_registers[GB_IO_STAT] &= ~3; gb->io_registers[GB_IO_STAT] &= ~3;

View File

@ -115,10 +115,19 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
return; 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: case GB_CONFLICT_STAT_DMG:
GB_advance_cycles(gb, gb->pending_cycles); 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_advance_cycles(gb, 1);
GB_write_memory(gb, addr, value); GB_write_memory(gb, addr, value);
gb->pending_cycles = 3; gb->pending_cycles = 3;