This commit is contained in:
Lior Halphon 2018-03-03 17:22:23 +02:00
parent b08f02c4f3
commit 5ea33cc931
2 changed files with 73 additions and 76 deletions

View File

@ -409,23 +409,18 @@ void GB_lcd_off(GB_gameboy_t *gb)
static void render_pixel_if_possible(GB_gameboy_t *gb)
{
GB_fifo_item_t *fifo_item = NULL;
if (!gb->fifo_paused) {
fifo_item = fifo_pop(&gb->bg_fifo);
}
/* Drop pixels for scrollings */
if (gb->position_in_line >= 160 || gb->disable_rendering) {
gb->position_in_line++;
if (fifo_size(&gb->bg_fifo) != 0) {
fifo_pop(&gb->bg_fifo);
}
return;
}
#ifndef NDEBUG
if (fifo_size(&gb->bg_fifo) == 0) {
GB_log(gb, "Defective BG FIFO!\n");
return;
}
#endif
GB_fifo_item_t *fifo_item = fifo_pop(&gb->bg_fifo);
if (gb->fifo_paused) return;
uint8_t pixel = ((gb->io_registers[GB_IO_BGP] >> (fifo_item->pixel << 1)) & 3);
gb->screen[gb->position_in_line + gb->current_line * WIDTH] = gb->background_palettes_rgb[pixel];
@ -454,14 +449,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
GB_STATE(gb, display, 16);
GB_STATE(gb, display, 17);
GB_STATE(gb, display, 21);
GB_STATE(gb, display, 22);
GB_STATE(gb, display, 23);
GB_STATE(gb, display, 24);
GB_STATE(gb, display, 25);
GB_STATE(gb, display, 26);
GB_STATE(gb, display, 27);
GB_STATE(gb, display, 28);
GB_STATE(gb, display, 20);
}
@ -551,72 +539,72 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
gb->position_in_line = - (gb->io_registers[GB_IO_SCX] & 7) - 8;
gb->fetcher_x = ((gb->io_registers[GB_IO_SCX]) / 8) & 0x1f;
#define RENDER_AND_SLEEP(label) \
{ \
render_pixel_if_possible(gb); \
if (gb->position_in_line == 160) break; \
else if (gb->position_in_line == 159) {\
gb->io_registers[GB_IO_STAT] &= ~3; \
gb->oam_read_blocked = false; \
gb->vram_read_blocked = false; \
gb->oam_write_blocked = false; \
gb->vram_write_blocked = false; \
if (gb->hdma_on_hblank) { \
gb->hdma_on = true; \
gb->hdma_cycles = 0; \
} \
} \
gb->cycles_for_line++; \
GB_SLEEP(gb, display, label, 1); \
}
gb->cycles_for_line += 6;
GB_SLEEP(gb, display, 10, 6);
/* The actual rendering cycle */
gb->fetcher_divisor = false;
gb->fetcher_state = GB_FETCHER_GET_TILE;
gb->fifo_paused = true;
while (true) {
// First read; the tile
RENDER_AND_SLEEP(21);
{
uint16_t map = 0x1800;
if (gb->io_registers[GB_IO_LCDC] & 0x08) {
map = 0x1C00;
if (gb->fetcher_divisor) {
switch (gb->fetcher_state) {
case GB_FETCHER_GET_TILE: {
uint16_t map = 0x1800;
if (gb->io_registers[GB_IO_LCDC] & 0x08) {
map = 0x1C00;
}
uint8_t y = gb->current_line + gb->io_registers[GB_IO_SCY];
gb->current_tile = gb->vram[map + gb->fetcher_x + y / 8 * 32];
gb->fetcher_x++;
gb->fetcher_x &= 0x1f;
}
break;
case GB_FETCHER_GET_TILE_DATA_LOWER: {
if (gb->io_registers[GB_IO_LCDC] & 0x10) {
gb->current_tile_address = gb->current_tile * 0x10;
}
else {
gb->current_tile_address = (int8_t)gb->current_tile * 0x10 + 0x1000;
}
gb->current_tile_data[0] =
gb->vram[gb->current_tile_address + ((gb->current_line + gb->io_registers[GB_IO_SCY]) & 7) * 2];
}
break;
case GB_FETCHER_GET_TILE_DATA_HIGH: {
gb->current_tile_data[1] =
gb->vram[gb->current_tile_address + ((gb->current_line + gb->io_registers[GB_IO_SCY]) & 7) * 2 + 1];
}
break;
case GB_FETCHER_SLEEP:
fifo_push_bg_row(&gb->bg_fifo, gb->current_tile_data[0], gb->current_tile_data[1], 0, false);
gb->fifo_paused = false;
break;
}
uint8_t y = gb->current_line + gb->io_registers[GB_IO_SCY];
gb->current_tile = gb->vram[map + gb->fetcher_x + y / 8 * 32];
gb->fetcher_x++;
gb->fetcher_x &= 0x1f;
gb->fetcher_state++;
gb->fetcher_state &= 3;
}
RENDER_AND_SLEEP(22);
gb->fetcher_divisor ^= true;
// Second read, lower tile data
RENDER_AND_SLEEP(23);
{
if (gb->io_registers[GB_IO_LCDC] & 0x10) {
gb->current_tile_address = gb->current_tile * 0x10;
render_pixel_if_possible(gb);
if (gb->position_in_line == 160) break;
else if (gb->position_in_line == 159) {
gb->io_registers[GB_IO_STAT] &= ~3;
gb->oam_read_blocked = false;
gb->vram_read_blocked = false;
gb->oam_write_blocked = false;
gb->vram_write_blocked = false;
if (gb->hdma_on_hblank) {
gb->hdma_on = true;
gb->hdma_cycles = 0;
}
else {
gb->current_tile_address = (int8_t)gb->current_tile * 0x10 + 0x1000;
}
gb->current_tile_data[0] =
gb->vram[gb->current_tile_address + ((gb->current_line + gb->io_registers[GB_IO_SCY]) & 7) * 2];
}
RENDER_AND_SLEEP(24);
// Third read, upper tile data
RENDER_AND_SLEEP(25);
gb->current_tile_data[1] =
gb->vram[gb->current_tile_address + ((gb->current_line + gb->io_registers[GB_IO_SCY]) & 7) * 2 + 1];
RENDER_AND_SLEEP(26);
// The cycle ends with a fetcher sleep
RENDER_AND_SLEEP(27);
RENDER_AND_SLEEP(28);
fifo_push_bg_row(&gb->bg_fifo, gb->current_tile_data[0], gb->current_tile_data[1], 0, false);
gb->cycles_for_line++;
GB_SLEEP(gb, display, 20, 1);
}
GB_STAT_update(gb);
GB_SLEEP(gb, display, 11, LINE_LENGTH - gb->cycles_for_line);
}

View File

@ -410,6 +410,15 @@ struct GB_gameboy_internal_s {
uint8_t current_tile;
uint16_t current_tile_address; // TODO: is this actually cached? If not, it could be used to "mix" two tiles
uint8_t current_tile_data[2];
enum {
GB_FETCHER_GET_TILE,
GB_FETCHER_GET_TILE_DATA_LOWER,
GB_FETCHER_GET_TILE_DATA_HIGH,
GB_FETCHER_SLEEP,
GB_FETCHER_MAX = GB_FETCHER_SLEEP,
} fetcher_state:8;
bool fetcher_divisor; // The fetcher runs at 2MHz
bool fifo_paused;
);