Accurate emulation of tilemap advancement timings

This commit is contained in:
Lior Halphon 2020-03-03 02:21:19 +02:00
parent e846f4f3b0
commit 409ab2a6d4
3 changed files with 24 additions and 16 deletions

View File

@ -547,7 +547,7 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb)
GB_FETCHER_SLEEP, GB_FETCHER_SLEEP,
} fetcher_step_t; } fetcher_step_t;
fetcher_step_t fetcher_state_machine [8] = { fetcher_step_t fetcher_state_machine [9] = {
GB_FETCHER_SLEEP, GB_FETCHER_SLEEP,
GB_FETCHER_GET_TILE, GB_FETCHER_GET_TILE,
GB_FETCHER_SLEEP, GB_FETCHER_SLEEP,
@ -555,9 +555,13 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb)
GB_FETCHER_SLEEP, GB_FETCHER_SLEEP,
GB_FETCHER_GET_TILE_DATA_HIGH, GB_FETCHER_GET_TILE_DATA_HIGH,
GB_FETCHER_PUSH, 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]) { switch (fetcher_state_machine[gb->fetcher_state]) {
case GB_FETCHER_GET_TILE: { case GB_FETCHER_GET_TILE: {
uint16_t map = 0x1800; uint16_t map = 0x1800;
@ -659,19 +663,23 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb)
} }
} }
gb->fetcher_state++; gb->fetcher_state++;
if (gb->wx_triggered) {
gb->window_tile_x++;
gb->window_tile_x &= 0x1f;
}
// fallthrough // fallthrough
case GB_FETCHER_PUSH: { case GB_FETCHER_PUSH: {
if (fifo_size(&gb->bg_fifo) > 0) break; if (gb->fetcher_state == 7) {
/* The background map index increase at this specific point. If this state is not reached,
if (gb->wx_triggered) { it will simply not increase. */
gb->window_tile_x++;
gb->window_tile_x &= 0x1f;
}
else {
gb->fetcher_x++; gb->fetcher_x++;
gb->fetcher_x &= 0x1f; 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], 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); 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; break;
} }
gb->fetcher_state &= 7;
} }
static uint16_t get_object_line_address(GB_gameboy_t *gb, const GB_object_t *object) 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; gb->fetcher_state = 0;
while (true) { while (true) {
/* Handle window */ /* 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 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 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 that point. The code should be updated to represent this, and this will fix the time travel hack in

View File

@ -742,6 +742,10 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
GB_lcd_off(gb); GB_lcd_off(gb);
} }
gb->io_registers[GB_IO_LCDC] = value; gb->io_registers[GB_IO_LCDC] = value;
if (!(value & 0x20)) {
gb->wx_triggered = false;
gb->wx166_glitch = false;
}
return; return;
case GB_IO_STAT: case GB_IO_STAT:

View File

@ -267,7 +267,6 @@ int GB_load_state(GB_gameboy_t *gb, const char *path)
gb->oam_fifo.write_end &= 0xF; gb->oam_fifo.write_end &= 0xF;
gb->object_low_line_address &= gb->vram_size & ~1; gb->object_low_line_address &= gb->vram_size & ~1;
gb->fetcher_x &= 0x1f; gb->fetcher_x &= 0x1f;
gb->fetcher_state &= 7;
if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) { if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) {
gb->object_priority = gb->cgb_mode? GB_OBJECT_PRIORITY_INDEX : GB_OBJECT_PRIORITY_X; 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->oam_fifo.write_end &= 0xF;
gb->object_low_line_address &= gb->vram_size & ~1; gb->object_low_line_address &= gb->vram_size & ~1;
gb->fetcher_x &= 0x1f; gb->fetcher_x &= 0x1f;
gb->fetcher_state &= 7;
if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) { if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) {
gb->object_priority = gb->cgb_mode? GB_OBJECT_PRIORITY_INDEX : GB_OBJECT_PRIORITY_X; gb->object_priority = gb->cgb_mode? GB_OBJECT_PRIORITY_INDEX : GB_OBJECT_PRIORITY_X;