More accurate DMA write conflicts

This commit is contained in:
Lior Halphon 2022-02-13 12:56:16 +02:00
parent c730ba767b
commit efe31cefc9

View File

@ -255,9 +255,9 @@ static bool is_addr_in_dma_use(GB_gameboy_t *gb, uint16_t addr)
if (gb->dma_current_dest == 0xFF || gb->dma_current_dest == 0x0) return false; // Warm up if (gb->dma_current_dest == 0xFF || gb->dma_current_dest == 0x0) return false; // Warm up
if (addr >= 0xfe00) return false; if (addr >= 0xfe00) return false;
if (gb->dma_current_src == addr) return false; // Shortcut for DMA access flow if (gb->dma_current_src == addr) return false; // Shortcut for DMA access flow
if (gb->dma_current_src > 0xe000 && (gb->dma_current_src & ~0x2000) == addr) return false; if (gb->dma_current_src >= 0xe000 && (gb->dma_current_src & ~0x2000) == addr) return false;
if (GB_is_cgb(gb)) { if (GB_is_cgb(gb)) {
if (addr >= 0xe000) { if (addr >= 0xc000) {
return bus_for_addr(gb, gb->dma_current_src) != GB_BUS_VRAM; return bus_for_addr(gb, gb->dma_current_src) != GB_BUS_VRAM;
} }
if (gb->dma_current_src >= 0xe000) { if (gb->dma_current_src >= 0xe000) {
@ -485,7 +485,7 @@ internal uint8_t GB_read_oam(GB_gameboy_t *gb, uint8_t addr)
return (addr & 0xF0) | (addr >> 4); return (addr & 0xF0) | (addr >> 4);
case GB_MODEL_CGB_D: case GB_MODEL_CGB_D:
if (addr > 0xc0) { if (addr >= 0xc0) {
addr |= 0xf0; addr |= 0xf0;
} }
return gb->extra_oam[addr - 0xa0]; return gb->extra_oam[addr - 0xa0];
@ -752,7 +752,7 @@ uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr)
// TODO: this should probably affect the DMA dest as well // TODO: this should probably affect the DMA dest as well
addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000; addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000;
} }
else if (GB_is_cgb(gb) && gb->dma_current_src >= 0xe000 && addr > 0xc000) { else if (GB_is_cgb(gb) && gb->dma_current_src >= 0xe000 && addr >= 0xc000) {
// TODO: this should probably affect the DMA dest as well // TODO: this should probably affect the DMA dest as well
addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000; addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000;
} }
@ -1206,7 +1206,7 @@ static void write_oam(GB_gameboy_t *gb, uint8_t addr, uint8_t value)
} }
switch (gb->model) { switch (gb->model) {
case GB_MODEL_CGB_D: case GB_MODEL_CGB_D:
if (addr > 0xc0) { if (addr >= 0xc0) {
addr |= 0xf0; addr |= 0xf0;
} }
gb->extra_oam[addr - 0xa0] = value; gb->extra_oam[addr - 0xa0] = value;
@ -1661,19 +1661,20 @@ void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
return; return;
} }
if (GB_is_cgb(gb) && bus_for_addr(gb, gb->dma_current_src) != GB_BUS_RAM && addr >= 0xc000) { if (GB_is_cgb(gb) && (gb->dma_current_src < 0xc000 || gb->dma_current_src >= 0xe000) && addr >= 0xc000) {
// TODO: this should probably affect the DMA dest as well // TODO: this should probably affect the DMA dest as well
addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000; addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000;
goto write;
} }
else if (GB_is_cgb(gb) && gb->dma_current_src >= 0xe000 && addr > 0xc000) { else if (GB_is_cgb(gb) && gb->dma_current_src >= 0xe000 && addr >= 0xc000) {
// TODO: this should probably affect the DMA dest as well // TODO: this should probably affect the DMA dest as well
addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000; addr = ((gb->dma_current_src - 1) & 0x1000) | (addr & 0xFFF) | 0xC000;
} }
else { else {
addr = (gb->dma_current_src - 1); addr = (gb->dma_current_src - 1);
} }
if (GB_is_cgb(gb) || addr > 0xc000) { if (GB_is_cgb(gb) || addr >= 0xa000) {
if (addr < 0xc000) { if (addr < 0xa000) {
gb->oam[gb->dma_current_dest - 1] = 0; gb->oam[gb->dma_current_dest - 1] = 0;
} }
else if ((gb->model < GB_MODEL_CGB_0 || gb->model == GB_MODEL_CGB_B)) { else if ((gb->model < GB_MODEL_CGB_0 || gb->model == GB_MODEL_CGB_B)) {
@ -1682,9 +1683,10 @@ void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
else if ((gb->model < GB_MODEL_CGB_C || gb->model > GB_MODEL_CGB_E) && !oam_write) { else if ((gb->model < GB_MODEL_CGB_C || gb->model > GB_MODEL_CGB_E) && !oam_write) {
gb->oam[gb->dma_current_dest - 1] = value; gb->oam[gb->dma_current_dest - 1] = value;
} }
if (gb->model < GB_MODEL_CGB_E || addr >= 0xc000) return; if (gb->model < GB_MODEL_CGB_E || addr >= 0xa000) return;
} }
} }
write:
write_map[addr >> 12](gb, addr, value); write_map[addr >> 12](gb, addr, value);
} }