Accurate emulation of tilemap advancement timings
This commit is contained in:
parent
e846f4f3b0
commit
409ab2a6d4
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user