Simplified FIFO logic

This commit is contained in:
Lior Halphon 2018-04-06 18:26:04 +03:00
parent cb01259073
commit 0461fb5b2a
2 changed files with 24 additions and 22 deletions

View File

@ -8,7 +8,7 @@
static inline unsigned fifo_size(GB_fifo_t *fifo) static inline unsigned fifo_size(GB_fifo_t *fifo)
{ {
return (fifo->write_end - fifo->read_end) & 0xF; return (fifo->write_end - fifo->read_end) & (GB_FIFO_LENGTH - 1);
} }
static void fifo_clear(GB_fifo_t *fifo) static void fifo_clear(GB_fifo_t *fifo)
@ -20,7 +20,7 @@ static GB_fifo_item_t *fifo_pop(GB_fifo_t *fifo)
{ {
GB_fifo_item_t *ret = &fifo->fifo[fifo->read_end]; GB_fifo_item_t *ret = &fifo->fifo[fifo->read_end];
fifo->read_end++; fifo->read_end++;
fifo->read_end &= 0xF; fifo->read_end &= (GB_FIFO_LENGTH - 1);
return ret; return ret;
} }
@ -38,7 +38,7 @@ static void fifo_push_bg_row(GB_fifo_t *fifo, uint8_t lower, uint8_t upper, uint
upper <<= 1; upper <<= 1;
fifo->write_end++; fifo->write_end++;
fifo->write_end &= 0xF; fifo->write_end &= (GB_FIFO_LENGTH - 1);
} }
} }
else { else {
@ -53,7 +53,7 @@ static void fifo_push_bg_row(GB_fifo_t *fifo, uint8_t lower, uint8_t upper, uint
upper >>= 1; upper >>= 1;
fifo->write_end++; fifo->write_end++;
fifo->write_end &= 0xF; fifo->write_end &= (GB_FIFO_LENGTH - 1);
} }
} }
} }
@ -63,14 +63,14 @@ static void fifo_overlay_object_row(GB_fifo_t *fifo, uint8_t lower, uint8_t uppe
while (fifo_size(fifo) < 8) { while (fifo_size(fifo) < 8) {
fifo->fifo[fifo->write_end] = (GB_fifo_item_t) {0,}; fifo->fifo[fifo->write_end] = (GB_fifo_item_t) {0,};
fifo->write_end++; fifo->write_end++;
fifo->write_end &= 0xF; fifo->write_end &= (GB_FIFO_LENGTH - 1);
} }
uint8_t flip_xor = flip_x? 0: 0x7; uint8_t flip_xor = flip_x? 0: 0x7;
for (unsigned i = 8; i--;) { for (unsigned i = 8; i--;) {
uint8_t pixel = (lower >> 7) | ((upper >> 7) << 1); uint8_t pixel = (lower >> 7) | ((upper >> 7) << 1);
GB_fifo_item_t *target = &fifo->fifo[(fifo->read_end + (i ^ flip_xor)) & 0xF]; GB_fifo_item_t *target = &fifo->fifo[(fifo->read_end + (i ^ flip_xor)) & (GB_FIFO_LENGTH - 1)];
if (pixel != 0 && (target->pixel == 0 || target->priority > priority)) { if (pixel != 0 && (target->pixel == 0 || target->priority > priority)) {
target->pixel = pixel; target->pixel = pixel;
target->palette = palette; target->palette = palette;
@ -329,7 +329,7 @@ static void render_pixel_if_possible(GB_gameboy_t *gb)
GB_fifo_item_t *oam_fifo_item = NULL; GB_fifo_item_t *oam_fifo_item = NULL;
bool draw_oam = false; bool draw_oam = false;
bool bg_enabled = true, bg_priority = false; bool bg_enabled = true, bg_priority = false;
if (!gb->bg_fifo_paused) { if (!gb->bg_fifo_paused) {
fifo_item = fifo_pop(&gb->bg_fifo); fifo_item = fifo_pop(&gb->bg_fifo);
bg_priority = fifo_item->bg_priority; bg_priority = fifo_item->bg_priority;
@ -556,6 +556,8 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
gb->cycles_for_line = MODE2_LENGTH + 4; gb->cycles_for_line = MODE2_LENGTH + 4;
fifo_clear(&gb->bg_fifo); fifo_clear(&gb->bg_fifo);
fifo_clear(&gb->oam_fifo); fifo_clear(&gb->oam_fifo);
/* Fill the FIFO with 8 pixels of "junk", it's going to be dropped anyway. */
fifo_push_bg_row(&gb->bg_fifo, 0, 0, 0, false, false);
/* Todo: find out actual access time of SCX */ /* Todo: find out actual access time of SCX */
gb->position_in_line = - (gb->io_registers[GB_IO_SCX] & 7) - 8; gb->position_in_line = - (gb->io_registers[GB_IO_SCX] & 7) - 8;
gb->fetcher_x = ((gb->io_registers[GB_IO_SCX]) / 8) & 0x1f; gb->fetcher_x = ((gb->io_registers[GB_IO_SCX]) / 8) & 0x1f;
@ -567,7 +569,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
/* The actual rendering cycle */ /* The actual rendering cycle */
gb->fetcher_divisor = false; gb->fetcher_divisor = false;
gb->fetcher_state = GB_FETCHER_GET_TILE; gb->fetcher_state = GB_FETCHER_GET_TILE;
gb->bg_fifo_paused = true; gb->bg_fifo_paused = false;
gb->oam_fifo_paused = false; gb->oam_fifo_paused = false;
gb->in_window = false; gb->in_window = false;
while (true) { while (true) {
@ -636,7 +638,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
gb->fetcher_x = 0; gb->fetcher_x = 0;
gb->fetcher_state = GB_FETCHER_GET_TILE; gb->fetcher_state = GB_FETCHER_GET_TILE;
} }
bool push = false;
if (gb->fetcher_divisor) { if (gb->fetcher_divisor) {
switch (gb->fetcher_state) { switch (gb->fetcher_state) {
@ -720,8 +722,16 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
} }
break; break;
case GB_FETCHER_SLEEP: case GB_FETCHER_SLEEP: {
push = true; gb->cycles_for_line += gb->fetcher_stop_penalty;
GB_SLEEP(gb, display, 19, gb->fetcher_stop_penalty);
gb->fetcher_stop_penalty = 0;
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->bg_fifo_paused = false;
gb->oam_fifo_paused = false;
}
break; break;
} }
gb->fetcher_state++; gb->fetcher_state++;
@ -730,16 +740,6 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
gb->fetcher_divisor ^= true; gb->fetcher_divisor ^= true;
render_pixel_if_possible(gb); render_pixel_if_possible(gb);
if (push) {
gb->cycles_for_line += gb->fetcher_stop_penalty;
GB_SLEEP(gb, display, 19, gb->fetcher_stop_penalty);
gb->fetcher_stop_penalty = 0;
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->bg_fifo_paused = false;
gb->oam_fifo_paused = false;
}
if (gb->position_in_line == 160) break; if (gb->position_in_line == 160) break;
gb->cycles_for_line++; gb->cycles_for_line++;
GB_SLEEP(gb, display, 21, 1); GB_SLEEP(gb, display, 21, 1);

View File

@ -195,8 +195,9 @@ typedef struct {
bool bg_priority; // For sprite FIFO the BG priority bit. For the BG FIFO  the CGB attributes priority bit bool bg_priority; // For sprite FIFO the BG priority bit. For the BG FIFO  the CGB attributes priority bit
} GB_fifo_item_t; } GB_fifo_item_t;
#define GB_FIFO_LENGTH 16
typedef struct { typedef struct {
GB_fifo_item_t fifo[16]; GB_fifo_item_t fifo[GB_FIFO_LENGTH];
uint8_t read_end; uint8_t read_end;
uint8_t write_end; uint8_t write_end;
} GB_fifo_t; } GB_fifo_t;
@ -430,6 +431,7 @@ struct GB_gameboy_internal_s {
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 */