Partial emulation of reading VRAM right after mode 3

This commit is contained in:
Lior Halphon 2020-05-29 23:10:23 +03:00
parent 29b64d7545
commit ffa569deeb
3 changed files with 33 additions and 4 deletions

View File

@ -603,14 +603,15 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb)
/* This value is cached on the CGB-D and newer, so it cannot be used to mix tiles together */
gb->fetcher_y = y;
}
gb->current_tile = gb->vram[map + x + y / 8 * 32];
gb->last_tile_index_address = map + x + y / 8 * 32;
gb->current_tile = gb->vram[gb->last_tile_index_address];
if (gb->vram_ppu_blocked) {
gb->current_tile = 0xFF;
}
if (GB_is_cgb(gb)) {
/* The CGB actually accesses both the tile index AND the attributes in the same T-cycle.
This probably means the CGB has a 16-bit data bus for the VRAM. */
gb->current_tile_attributes = gb->vram[map + x + y / 8 * 32 + 0x2000];
This probably means the CGB has a 16-bit data bus for the VRAM. */
gb->current_tile_attributes = gb->vram[gb->last_tile_index_address + 0x2000];
if (gb->vram_ppu_blocked) {
gb->current_tile_attributes = 0xFF;
}
@ -667,8 +668,9 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb)
if (gb->current_tile_attributes & 0x40) {
y_flip = 0x7;
}
gb->last_tile_data_address = tile_address + ((y & 7) ^ y_flip) * 2 + 1;
gb->current_tile_data[1] =
gb->vram[tile_address + ((y & 7) ^ y_flip) * 2 + 1];
gb->vram[gb->last_tile_data_address];
if (gb->vram_ppu_blocked) {
gb->current_tile_data[1] = 0xFF;
}

View File

@ -538,6 +538,8 @@ struct GB_gameboy_internal_s {
uint8_t window_tile_x;
uint8_t lcd_x; // The LCD can go out of sync since the push signal is skipped in some cases.
bool is_odd_frame;
uint16_t last_tile_data_address;
uint16_t last_tile_index_address;
);
/* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */

View File

@ -146,6 +146,18 @@ static uint8_t read_vram(GB_gameboy_t *gb, uint16_t addr)
if (gb->vram_read_blocked) {
return 0xFF;
}
if (gb->display_state == 22 && GB_is_cgb(gb) && !gb->cgb_double_speed) {
if (addr & 0x1000) {
addr = gb->last_tile_index_address;
}
else if (gb->last_tile_data_address & 0x1000) {
/* TODO: This is case is more complicated then the rest and differ between revisions
It's probably affected by how VRAM is layed out, might be easier after a decap is done*/
}
else {
addr = gb->last_tile_data_address;
}
}
return gb->vram[(addr & 0x1FFF) + (uint16_t) gb->cgb_vram_bank * 0x2000];
}
@ -551,6 +563,19 @@ static void write_vram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
//GB_log(gb, "Wrote %02x to %04x (VRAM) during mode 3\n", value, addr);
return;
}
/* TODO: not verified */
if (gb->display_state == 22 && GB_is_cgb(gb) && !gb->cgb_double_speed) {
if (addr & 0x1000) {
addr = gb->last_tile_index_address;
}
else if (gb->last_tile_data_address & 0x1000) {
/* TODO: This is case is more complicated then the rest and differ between revisions
It's probably affected by how VRAM is layed out, might be easier after a decap is done */
}
else {
addr = gb->last_tile_data_address;
}
}
gb->vram[(addr & 0x1FFF) + (uint16_t) gb->cgb_vram_bank * 0x2000] = value;
}