Implemented some obscure PPU rendering quirks, verified some timings
This commit is contained in:
parent
d785e45308
commit
9aadc80f75
@ -394,6 +394,11 @@ static void render_pixel_if_possible(GB_gameboy_t *gb)
|
|||||||
|
|
||||||
Todo: Add support to CPU C and older */
|
Todo: Add support to CPU C and older */
|
||||||
|
|
||||||
|
static inline uint8_t fetcher_y(GB_gameboy_t *gb)
|
||||||
|
{
|
||||||
|
return gb->current_line + (gb->in_window? - gb->io_registers[GB_IO_WY] - gb->wy_diff : gb->io_registers[GB_IO_SCY]);
|
||||||
|
}
|
||||||
|
|
||||||
void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
||||||
{
|
{
|
||||||
GB_object_t *objects = (GB_object_t *) &gb->oam;
|
GB_object_t *objects = (GB_object_t *) &gb->oam;
|
||||||
@ -632,23 +637,29 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
}
|
}
|
||||||
bool push = false;
|
bool push = false;
|
||||||
if (gb->fetcher_divisor) {
|
if (gb->fetcher_divisor) {
|
||||||
|
|
||||||
switch (gb->fetcher_state) {
|
switch (gb->fetcher_state) {
|
||||||
case GB_FETCHER_GET_TILE: {
|
case GB_FETCHER_GET_TILE: {
|
||||||
uint16_t map = 0x1800;
|
uint16_t map = 0x1800;
|
||||||
|
|
||||||
/* Todo: Verify access timings */
|
/* Todo: Verified for DMG (Tested: SGB2), CGB timing is wrong. */
|
||||||
if (gb->io_registers[GB_IO_LCDC] & 0x08 && !gb->in_window) {
|
if (gb->io_registers[GB_IO_LCDC] & 0x08 && !gb->in_window) {
|
||||||
map = 0x1C00;
|
map = 0x1C00;
|
||||||
}
|
}
|
||||||
else if (gb->io_registers[GB_IO_LCDC] & 0x40 && gb->in_window) {
|
else if (gb->io_registers[GB_IO_LCDC] & 0x40 && gb->in_window) {
|
||||||
map = 0x1C00;
|
map = 0x1C00;
|
||||||
}
|
}
|
||||||
gb->fetcher_y =
|
|
||||||
gb->current_line + (gb->in_window? - gb->io_registers[GB_IO_WY] - gb->wy_diff : gb->io_registers[GB_IO_SCY]);
|
/* Todo: Verified for DMG (Tested: SGB2), CGB timing is wrong. */
|
||||||
gb->current_tile = gb->vram[map + gb->fetcher_x + gb->fetcher_y / 8 * 32];
|
uint8_t y = fetcher_y(gb);
|
||||||
|
if (gb->is_cgb) {
|
||||||
|
/* This value is cached on the CGB, so it cannot be used to mix tiles together */
|
||||||
|
gb->fetcher_y = y;
|
||||||
|
}
|
||||||
|
gb->current_tile = gb->vram[map + gb->fetcher_x + y / 8 * 32];
|
||||||
if (gb->is_cgb) {
|
if (gb->is_cgb) {
|
||||||
/* TODO: The timing is wrong (two reads a the same time)*/
|
/* TODO: The timing is wrong (two reads a the same time)*/
|
||||||
gb->current_tile_attributes = gb->vram[map + gb->fetcher_x + gb->fetcher_y / 8 * 32 + 0x2000];
|
gb->current_tile_attributes = gb->vram[map + gb->fetcher_x + y / 8 * 32 + 0x2000];
|
||||||
}
|
}
|
||||||
gb->fetcher_x++;
|
gb->fetcher_x++;
|
||||||
gb->fetcher_x &= 0x1f;
|
gb->fetcher_x &= 0x1f;
|
||||||
@ -657,32 +668,50 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
|
|
||||||
case GB_FETCHER_GET_TILE_DATA_LOWER: {
|
case GB_FETCHER_GET_TILE_DATA_LOWER: {
|
||||||
uint8_t y_flip = 0;
|
uint8_t y_flip = 0;
|
||||||
|
uint16_t tile_address = 0;
|
||||||
|
uint8_t y = gb->is_cgb? gb->fetcher_y : fetcher_y(gb);
|
||||||
|
|
||||||
/* Todo: Verify access timings */
|
/* Todo: Verified for DMG (Tested: SGB2), CGB timing is wrong. */
|
||||||
if (gb->io_registers[GB_IO_LCDC] & 0x10) {
|
if (gb->io_registers[GB_IO_LCDC] & 0x10) {
|
||||||
gb->current_tile_address = gb->current_tile * 0x10;
|
tile_address = gb->current_tile * 0x10;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gb->current_tile_address = (int8_t)gb->current_tile * 0x10 + 0x1000;
|
tile_address = (int8_t)gb->current_tile * 0x10 + 0x1000;
|
||||||
}
|
}
|
||||||
if (gb->current_tile_attributes & 8) {
|
if (gb->current_tile_attributes & 8) {
|
||||||
gb->current_tile_address += 0x2000;
|
tile_address += 0x2000;
|
||||||
}
|
}
|
||||||
if (gb->current_tile_attributes & 0x40) {
|
if (gb->current_tile_attributes & 0x40) {
|
||||||
y_flip = 0x7;
|
y_flip = 0x7;
|
||||||
}
|
}
|
||||||
gb->current_tile_data[0] =
|
gb->current_tile_data[0] =
|
||||||
gb->vram[gb->current_tile_address + ((gb->fetcher_y & 7) ^ y_flip) * 2];
|
gb->vram[tile_address + ((y & 7) ^ y_flip) * 2];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GB_FETCHER_GET_TILE_DATA_HIGH: {
|
case GB_FETCHER_GET_TILE_DATA_HIGH: {
|
||||||
|
/* Todo: Verified for DMG (Tested: SGB2), CGB timing is wrong.
|
||||||
|
Additionally, on the CGB mixing two tiles by changing the tileset bit
|
||||||
|
mid-fetching causes a glitched mixing of the two, in comparison to the
|
||||||
|
more logical DMG version. */
|
||||||
|
uint16_t tile_address = 0;
|
||||||
|
uint8_t y = gb->is_cgb? gb->fetcher_y : fetcher_y(gb);
|
||||||
|
|
||||||
|
if (gb->io_registers[GB_IO_LCDC] & 0x10) {
|
||||||
|
tile_address = gb->current_tile * 0x10;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tile_address = (int8_t)gb->current_tile * 0x10 + 0x1000;
|
||||||
|
}
|
||||||
|
if (gb->current_tile_attributes & 8) {
|
||||||
|
tile_address += 0x2000;
|
||||||
|
}
|
||||||
uint8_t y_flip = 0;
|
uint8_t y_flip = 0;
|
||||||
if (gb->current_tile_attributes & 0x40) {
|
if (gb->current_tile_attributes & 0x40) {
|
||||||
y_flip = 0x7;
|
y_flip = 0x7;
|
||||||
}
|
}
|
||||||
gb->current_tile_data[1] =
|
gb->current_tile_data[1] =
|
||||||
gb->vram[gb->current_tile_address + ((gb->fetcher_y & 7) ^ y_flip) * 2 + 1];
|
gb->vram[tile_address + ((y & 7) ^ y_flip) * 2 + 1];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -409,7 +409,6 @@ struct GB_gameboy_internal_s {
|
|||||||
uint16_t cycles_for_line;
|
uint16_t cycles_for_line;
|
||||||
uint8_t current_tile;
|
uint8_t current_tile;
|
||||||
uint8_t current_tile_attributes;
|
uint8_t current_tile_attributes;
|
||||||
uint16_t current_tile_address;
|
|
||||||
uint8_t current_tile_data[2];
|
uint8_t current_tile_data[2];
|
||||||
enum {
|
enum {
|
||||||
GB_FETCHER_GET_TILE,
|
GB_FETCHER_GET_TILE,
|
||||||
|
@ -222,7 +222,6 @@ int GB_load_state(GB_gameboy_t *gb, const char *path)
|
|||||||
gb->bg_fifo.write_end &= 0xF;
|
gb->bg_fifo.write_end &= 0xF;
|
||||||
gb->oam_fifo.read_end &= 0xF;
|
gb->oam_fifo.read_end &= 0xF;
|
||||||
gb->oam_fifo.write_end &= 0xF;
|
gb->oam_fifo.write_end &= 0xF;
|
||||||
gb->current_tile_address &= (gb->vram_size - 1);
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
fclose(f);
|
fclose(f);
|
||||||
@ -318,7 +317,6 @@ int GB_load_state_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t le
|
|||||||
gb->bg_fifo.write_end &= 0xF;
|
gb->bg_fifo.write_end &= 0xF;
|
||||||
gb->oam_fifo.read_end &= 0xF;
|
gb->oam_fifo.read_end &= 0xF;
|
||||||
gb->oam_fifo.write_end &= 0xF;
|
gb->oam_fifo.write_end &= 0xF;
|
||||||
gb->current_tile_address &= (gb->vram_size - 1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user