Simplified FIFO logic
This commit is contained in:
parent
cb01259073
commit
0461fb5b2a
@ -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);
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user