DMA/PPU VRAM conflicts on the CGB/AGB
This commit is contained in:
parent
b45761146f
commit
ab75858c86
@ -677,9 +677,25 @@ static inline uint8_t vram_read(GB_gameboy_t *gb, uint16_t addr)
|
||||
}
|
||||
if (unlikely(gb->dma_current_dest <= 0xa0 && gb->dma_current_dest > 0 && (gb->dma_current_src & 0xE000) == 0x8000)) { // TODO: what happens in the last and first M cycles?
|
||||
// DMAing from VRAM!
|
||||
/* TODO: This is only correct on a DMG/MGB, CGBs and AGBs use some other pattern; AGS has a completely different one */
|
||||
/* TODO: AGS has its own, very different pattern, but AGS is not currently a supported model */
|
||||
if (GB_is_cgb(gb)) {
|
||||
if (gb->dma_ppu_vram_conflict) {
|
||||
addr = (gb->dma_ppu_vram_conflict_addr & 0x1FFF) | (addr & 0x2000);
|
||||
}
|
||||
else if (gb->dma_cycles_modulo) {
|
||||
addr &= 0x2000;
|
||||
addr |= ((gb->dma_current_src - 1) & 0x1FFF);
|
||||
gb->oam[gb->dma_current_dest - 1] = gb->vram[addr];
|
||||
}
|
||||
else {
|
||||
addr &= 0x2000 | ((gb->dma_current_src - 1) & 0x1FFF);
|
||||
gb->dma_ppu_vram_conflict_addr = addr;
|
||||
gb->dma_ppu_vram_conflict = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
addr |= ((gb->dma_current_src - 1) & 0x1FFF);
|
||||
}
|
||||
gb->oam[gb->dma_current_dest - 1] = gb->vram[(addr & 0x1FFF) | (gb->cgb_vram_bank? 0x2000 : 0)];
|
||||
}
|
||||
return gb->vram[addr];
|
||||
}
|
||||
|
@ -429,6 +429,8 @@ struct GB_gameboy_internal_s {
|
||||
uint16_t dma_current_src;
|
||||
uint16_t dma_cycles;
|
||||
int8_t dma_cycles_modulo;
|
||||
bool dma_ppu_vram_conflict;
|
||||
uint16_t dma_ppu_vram_conflict_addr;
|
||||
uint8_t last_opcode_read; /* Required to emulate HDMA reads from Exxx */
|
||||
bool hdma_starting;
|
||||
)
|
||||
@ -775,6 +777,7 @@ struct GB_gameboy_internal_s {
|
||||
bool wx_just_changed;
|
||||
bool tile_sel_glitch;
|
||||
bool disable_oam_corruption; // For safe memory reads
|
||||
bool in_dma_read;
|
||||
|
||||
GB_gbs_header_t gbs_header;
|
||||
)
|
||||
|
@ -303,7 +303,7 @@ static uint8_t read_vram(GB_gameboy_t *gb, uint16_t addr)
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(gb->vram_read_blocked)) {
|
||||
if (unlikely(gb->vram_read_blocked && !gb->in_dma_read)) {
|
||||
return 0xFF;
|
||||
}
|
||||
if (unlikely(gb->display_state == 22 && GB_is_cgb(gb) && !gb->cgb_double_speed)) {
|
||||
@ -1700,6 +1700,7 @@ void GB_dma_run(GB_gameboy_t *gb)
|
||||
{
|
||||
if (gb->dma_current_dest == 0xa1) return;
|
||||
signed cycles = gb->dma_cycles + gb->dma_cycles_modulo;
|
||||
gb->in_dma_read = true;
|
||||
while (unlikely(cycles >= 4)) {
|
||||
cycles -= 4;
|
||||
if (gb->dma_current_dest >= 0xa0) {
|
||||
@ -1720,7 +1721,9 @@ void GB_dma_run(GB_gameboy_t *gb)
|
||||
|
||||
/* dma_current_src must be the correct value during GB_read_memory */
|
||||
gb->dma_current_src++;
|
||||
gb->dma_ppu_vram_conflict = false;
|
||||
}
|
||||
gb->in_dma_read = false;
|
||||
gb->dma_cycles_modulo = cycles;
|
||||
gb->dma_cycles = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user