From 409ab2a6d4ae64a3211a568acdb9a7f42a249fcd Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Tue, 3 Mar 2020 02:21:19 +0200 Subject: [PATCH] Accurate emulation of tilemap advancement timings --- Core/display.c | 34 ++++++++++++++++++++-------------- Core/memory.c | 4 ++++ Core/save_state.c | 2 -- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/Core/display.c b/Core/display.c index ce9f74f..cbf4196 100644 --- a/Core/display.c +++ b/Core/display.c @@ -547,7 +547,7 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb) GB_FETCHER_SLEEP, } fetcher_step_t; - fetcher_step_t fetcher_state_machine [8] = { + fetcher_step_t fetcher_state_machine [9] = { GB_FETCHER_SLEEP, GB_FETCHER_GET_TILE, GB_FETCHER_SLEEP, @@ -555,9 +555,13 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb) GB_FETCHER_SLEEP, GB_FETCHER_GET_TILE_DATA_HIGH, GB_FETCHER_PUSH, - GB_FETCHER_PUSH, // Compatibility + GB_FETCHER_PUSH, + GB_FETCHER_PUSH, }; - + + if (gb->fetcher_state >= sizeof(fetcher_state_machine)) { + gb->fetcher_state = 0; + } switch (fetcher_state_machine[gb->fetcher_state]) { case GB_FETCHER_GET_TILE: { uint16_t map = 0x1800; @@ -659,19 +663,23 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb) } } gb->fetcher_state++; + if (gb->wx_triggered) { + gb->window_tile_x++; + gb->window_tile_x &= 0x1f; + } + // fallthrough - case GB_FETCHER_PUSH: { - if (fifo_size(&gb->bg_fifo) > 0) break; - - if (gb->wx_triggered) { - gb->window_tile_x++; - gb->window_tile_x &= 0x1f; - } - else { + if (gb->fetcher_state == 7) { + /* The background map index increase at this specific point. If this state is not reached, + it will simply not increase. */ gb->fetcher_x++; gb->fetcher_x &= 0x1f; } + if (gb->fetcher_state < 8) { + gb->fetcher_state++; + } + if (fifo_size(&gb->bg_fifo) > 0) break; fifo_push_bg_row(&gb->bg_fifo, gb->current_tile_data[0], gb->current_tile_data[1], gb->current_tile_attributes & 7, gb->current_tile_attributes & 0x80, gb->current_tile_attributes & 0x20); @@ -685,8 +693,6 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb) } break; } - - gb->fetcher_state &= 7; } static uint16_t get_object_line_address(GB_gameboy_t *gb, const GB_object_t *object) @@ -946,7 +952,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) gb->fetcher_state = 0; while (true) { /* Handle window */ - /* TODO: It appears that WX checks if the window beings *next* pixel, not *this* pixel. For this reason, + /* TODO: It appears that WX checks if the window begins *next* pixel, not *this* pixel. For this reason, WX=167 has no effect at all (It checks if the PPU X position is 161, which never happens) and WX=166 has weird artifacts (It appears to activate the window during HBlank, as PPU X is temporarily 160 at that point. The code should be updated to represent this, and this will fix the time travel hack in diff --git a/Core/memory.c b/Core/memory.c index 631b71f..abad063 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -742,6 +742,10 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) GB_lcd_off(gb); } gb->io_registers[GB_IO_LCDC] = value; + if (!(value & 0x20)) { + gb->wx_triggered = false; + gb->wx166_glitch = false; + } return; case GB_IO_STAT: diff --git a/Core/save_state.c b/Core/save_state.c index fd7d814..8f10152 100644 --- a/Core/save_state.c +++ b/Core/save_state.c @@ -267,7 +267,6 @@ int GB_load_state(GB_gameboy_t *gb, const char *path) gb->oam_fifo.write_end &= 0xF; gb->object_low_line_address &= gb->vram_size & ~1; gb->fetcher_x &= 0x1f; - gb->fetcher_state &= 7; if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) { gb->object_priority = gb->cgb_mode? GB_OBJECT_PRIORITY_INDEX : GB_OBJECT_PRIORITY_X; @@ -379,7 +378,6 @@ int GB_load_state_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t le gb->oam_fifo.write_end &= 0xF; gb->object_low_line_address &= gb->vram_size & ~1; gb->fetcher_x &= 0x1f; - gb->fetcher_state &= 7; if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) { gb->object_priority = gb->cgb_mode? GB_OBJECT_PRIORITY_INDEX : GB_OBJECT_PRIORITY_X;