diff --git a/Core/display.c b/Core/display.c index 908c5518..256d9814 100644 --- a/Core/display.c +++ b/Core/display.c @@ -1042,7 +1042,7 @@ abort_fetching_object: // Too late to enable the window } else if (gb->io_registers[GB_IO_WX] == (uint8_t) (gb->position_in_line + 7) || - gb->io_registers[GB_IO_WX] == (uint8_t) (gb->position_in_line + 6)) { + (gb->io_registers[GB_IO_WX] == (uint8_t) (gb->position_in_line + 6) && !gb->wx_just_changed)) { gb->window_y++; if (gb->io_registers[GB_IO_WX] != 166) { gb->wx_triggered = true; diff --git a/Core/gb.h b/Core/gb.h index e02c7ad5..b8cbd978 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -651,6 +651,9 @@ struct GB_gameboy_internal_s { bool vblank_just_occured; // For slow operations involving syscalls; these should only run once per vblank uint8_t cycles_since_run; // How many cycles have passed since the last call to GB_run(), in 8MHz units double clock_multiplier; + + /* Temporary state */ + bool wx_just_changed; ); }; diff --git a/Core/sm83_cpu.c b/Core/sm83_cpu.c index b0e28f48..f25e14bd 100644 --- a/Core/sm83_cpu.c +++ b/Core/sm83_cpu.c @@ -20,6 +20,7 @@ typedef enum { GB_CONFLICT_PALETTE_CGB, GB_CONFLICT_DMG_LCDC, GB_CONFLICT_SGB_LCDC, + GB_CONFLICT_WX, } GB_conflict_t; /* Todo: How does double speed mode affect these? */ @@ -46,9 +47,9 @@ static const GB_conflict_t dmg_conflict_map[0x80] = { [GB_IO_OBP0] = GB_CONFLICT_PALETTE_DMG, [GB_IO_OBP1] = GB_CONFLICT_PALETTE_DMG, [GB_IO_WY] = GB_CONFLICT_READ_OLD, + [GB_IO_WX] = GB_CONFLICT_WX, /* Todo: these were not verified at all */ - [GB_IO_WX] = GB_CONFLICT_READ_NEW, [GB_IO_SCX] = GB_CONFLICT_READ_NEW, }; @@ -64,9 +65,9 @@ static const GB_conflict_t sgb_conflict_map[0x80] = { [GB_IO_OBP0] = GB_CONFLICT_READ_NEW, [GB_IO_OBP1] = GB_CONFLICT_READ_NEW, [GB_IO_WY] = GB_CONFLICT_READ_OLD, + [GB_IO_WX] = GB_CONFLICT_WX, /* Todo: these were not verified at all */ - [GB_IO_WX] = GB_CONFLICT_READ_NEW, [GB_IO_SCX] = GB_CONFLICT_READ_NEW, }; @@ -261,6 +262,15 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value) gb->pending_cycles = 5; return; } + + case GB_CONFLICT_WX: + GB_advance_cycles(gb, gb->pending_cycles); + GB_write_memory(gb, addr, value); + gb->wx_just_changed = true; + GB_advance_cycles(gb, 1); + gb->wx_just_changed = false; + gb->pending_cycles = 3; + return; } }