More reasonable implementation of sprite timings

This commit is contained in:
Lior Halphon 2018-04-07 03:00:26 +03:00
parent 0751eae90b
commit fed2556fc3
2 changed files with 20 additions and 12 deletions

View File

@ -421,7 +421,6 @@ static uint8_t advance_fetcher_state_machine(GB_gameboy_t *gb)
}; };
uint8_t delay = 0; uint8_t delay = 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;
@ -452,6 +451,7 @@ static uint8_t advance_fetcher_state_machine(GB_gameboy_t *gb)
gb->fetcher_x++; gb->fetcher_x++;
gb->fetcher_x &= 0x1f; gb->fetcher_x &= 0x1f;
} }
gb->fetcher_state++;
break; break;
case GB_FETCHER_GET_TILE_DATA_LOWER: { case GB_FETCHER_GET_TILE_DATA_LOWER: {
@ -475,6 +475,7 @@ static uint8_t advance_fetcher_state_machine(GB_gameboy_t *gb)
gb->current_tile_data[0] = gb->current_tile_data[0] =
gb->vram[tile_address + ((y & 7) ^ y_flip) * 2]; gb->vram[tile_address + ((y & 7) ^ y_flip) * 2];
} }
gb->fetcher_state++;
break; break;
case GB_FETCHER_GET_TILE_DATA_HIGH: { case GB_FETCHER_GET_TILE_DATA_HIGH: {
@ -501,24 +502,26 @@ static uint8_t advance_fetcher_state_machine(GB_gameboy_t *gb)
gb->current_tile_data[1] = gb->current_tile_data[1] =
gb->vram[tile_address + ((y & 7) ^ y_flip) * 2 + 1]; gb->vram[tile_address + ((y & 7) ^ y_flip) * 2 + 1];
} }
gb->fetcher_state++;
break; break;
case GB_FETCHER_PUSH: { case GB_FETCHER_PUSH: {
if (fifo_size(&gb->bg_fifo) > 1) 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);
gb->bg_fifo_paused = false; gb->bg_fifo_paused = false;
gb->oam_fifo_paused = false; gb->oam_fifo_paused = false;
delay = gb->fetcher_stop_penalty; gb->fetcher_state++;
gb->fetcher_stop_penalty = 0;
} }
break; break;
case GB_FETCHER_SLEEP: case GB_FETCHER_SLEEP:
{
gb->fetcher_state++;
}
break; break;
} }
gb->fetcher_state++;
gb->fetcher_state &= 7; gb->fetcher_state &= 7;
return delay; return delay;
} }
@ -553,6 +556,8 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
GB_STATE(gb, display, 24); GB_STATE(gb, display, 24);
GB_STATE(gb, display, 25); GB_STATE(gb, display, 25);
GB_STATE(gb, display, 26); GB_STATE(gb, display, 26);
GB_STATE(gb, display, 27);
GB_STATE(gb, display, 28);
} }
if (!(gb->io_registers[GB_IO_LCDC] & 0x80)) { if (!(gb->io_registers[GB_IO_LCDC] & 0x80)) {
@ -709,12 +714,17 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
(gb->io_registers[GB_IO_LCDC] & 2 || gb->is_cgb) && (gb->io_registers[GB_IO_LCDC] & 2 || gb->is_cgb) &&
gb->obj_comperators[gb->n_visible_objs - 1] == (uint8_t)(gb->position_in_line + 8)) { gb->obj_comperators[gb->n_visible_objs - 1] == (uint8_t)(gb->position_in_line + 8)) {
if (gb->fetcher_stop_penalty == 0) { while (gb->fetcher_state < 5) {
/* TODO: figure out why the penalty works this way and actual access timings */ advance_fetcher_state_machine(gb);
/* Penalty for interrupting the fetcher */ gb->cycles_for_line++;
gb->fetcher_stop_penalty = (uint8_t[]){5, 4, 3, 2, 1, 0, 0, 0}[gb->fetcher_state]; GB_SLEEP(gb, display, 27, 1);
}
if (gb->extra_penalty_for_sprite_at_0 != 0) {
if (gb->obj_comperators[gb->n_visible_objs - 1] == 0) { if (gb->obj_comperators[gb->n_visible_objs - 1] == 0) {
gb->fetcher_stop_penalty += gb->extra_penalty_for_sprite_at_0; gb->cycles_for_line += gb->extra_penalty_for_sprite_at_0;
GB_SLEEP(gb, display, 28, gb->extra_penalty_for_sprite_at_0);
gb->extra_penalty_for_sprite_at_0 = 0;
} }
} }

View File

@ -418,13 +418,11 @@ struct GB_gameboy_internal_s {
uint8_t visible_objs[10]; uint8_t visible_objs[10];
uint8_t obj_comperators[10]; uint8_t obj_comperators[10];
uint8_t n_visible_objs; uint8_t n_visible_objs;
uint8_t fetcher_stop_penalty;
uint8_t oam_search_index; uint8_t oam_search_index;
uint8_t accessed_oam_row; uint8_t accessed_oam_row;
uint8_t extra_penalty_for_sprite_at_0; uint8_t extra_penalty_for_sprite_at_0;
bool is_first_line_mode2; bool is_first_line_mode2;
bool oam_interrupt_line; bool oam_interrupt_line;
bool ready_to_push;
); );
/* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */ /* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */