OMA DMA improvements (WIP)

This commit is contained in:
Lior Halphon 2022-01-03 16:51:45 +02:00
parent 81e45b00b9
commit cd16431699

View File

@ -9,7 +9,6 @@ typedef enum {
GB_BUS_MAIN, /* In DMG: Cart and RAM. In CGB: Cart only */ GB_BUS_MAIN, /* In DMG: Cart and RAM. In CGB: Cart only */
GB_BUS_RAM, /* In CGB only. */ GB_BUS_RAM, /* In CGB only. */
GB_BUS_VRAM, GB_BUS_VRAM,
GB_BUS_INTERNAL, /* Anything in highram. Might not be the most correct name. */
} bus_t; } bus_t;
static bus_t bus_for_addr(GB_gameboy_t *gb, uint16_t addr) static bus_t bus_for_addr(GB_gameboy_t *gb, uint16_t addr)
@ -23,10 +22,7 @@ static bus_t bus_for_addr(GB_gameboy_t *gb, uint16_t addr)
if (addr < 0xC000) { if (addr < 0xC000) {
return GB_BUS_MAIN; return GB_BUS_MAIN;
} }
if (addr < 0xFE00) { return GB_is_cgb(gb)? GB_BUS_RAM : GB_BUS_MAIN;
return GB_is_cgb(gb)? GB_BUS_RAM : GB_BUS_MAIN;
}
return GB_BUS_INTERNAL;
} }
static uint16_t bitwise_glitch(uint16_t a, uint16_t b, uint16_t c) static uint16_t bitwise_glitch(uint16_t a, uint16_t b, uint16_t c)
@ -255,7 +251,18 @@ void GB_trigger_oam_bug_read(GB_gameboy_t *gb, uint16_t address)
static bool is_addr_in_dma_use(GB_gameboy_t *gb, uint16_t addr) static bool is_addr_in_dma_use(GB_gameboy_t *gb, uint16_t addr)
{ {
if (!gb->dma_steps_left || (gb->dma_cycles < 0 && !gb->is_dma_restarting) || addr >= 0xFE00) return false; if (!gb->dma_steps_left || (gb->dma_cycles < 0 && !gb->is_dma_restarting) || 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 > 0xe000 && (gb->dma_current_src & ~0x2000) == addr) return false;
if (GB_is_cgb(gb)) {
if (addr >= 0xe000) {
return bus_for_addr(gb, gb->dma_current_src) != GB_BUS_VRAM;
}
if (gb->dma_current_src >= 0xe000) {
return bus_for_addr(gb, addr) != GB_BUS_VRAM;
}
}
return bus_for_addr(gb, addr) == bus_for_addr(gb, gb->dma_current_src); return bus_for_addr(gb, addr) == bus_for_addr(gb, gb->dma_current_src);
} }
@ -732,7 +739,22 @@ uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr)
GB_debugger_test_read_watchpoint(gb, addr); GB_debugger_test_read_watchpoint(gb, addr);
} }
if (unlikely(is_addr_in_dma_use(gb, addr))) { if (unlikely(is_addr_in_dma_use(gb, addr))) {
addr = gb->dma_current_src; if (GB_is_cgb(gb) && bus_for_addr(gb, addr) == GB_BUS_MAIN && gb->dma_current_src >= 0xe000) {
/* This is cart specific! Everdrive 7X on a CGB-A or 0 behaves differently. */
return 0xFF;
}
if (GB_is_cgb(gb) && bus_for_addr(gb, gb->dma_current_src) != GB_BUS_RAM && addr >= 0xc000) {
// TODO: this should probably affect the DMA dest as well
addr = (gb->dma_current_src & 0x1000) | (addr & 0xFFF) | 0xC000;
}
else if (GB_is_cgb(gb) && gb->dma_current_src >= 0xe000 && addr > 0xc000) {
// TODO: this should probably affect the DMA dest as well
addr = (gb->dma_current_src & 0x1000) | (addr & 0xFFF) | 0xC000;
}
else {
addr = gb->dma_current_src;
}
} }
uint8_t data = read_map[addr >> 12](gb, addr); uint8_t data = read_map[addr >> 12](gb, addr);
GB_apply_cheat(gb, addr, &data); GB_apply_cheat(gb, addr, &data);
@ -1631,8 +1653,22 @@ void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
} }
if (unlikely(is_addr_in_dma_use(gb, addr))) { if (unlikely(is_addr_in_dma_use(gb, addr))) {
/* Todo: What should happen? Will this affect DMA? Will data be written? What and where? */ if (GB_is_cgb(gb) && bus_for_addr(gb, addr) == GB_BUS_MAIN && gb->dma_current_src >= 0xe000) {
return; /* This is cart specific! Everdrive 7X on a CGB-A or 0 behaves differently. */
return;
}
if (GB_is_cgb(gb) && bus_for_addr(gb, gb->dma_current_src) != GB_BUS_RAM && addr >= 0xc000) {
// TODO: this should probably affect the DMA dest as well
addr = (gb->dma_current_src & 0x1000) | (addr & 0xFFF) | 0xC000;
}
else if (GB_is_cgb(gb) && gb->dma_current_src >= 0xe000 && addr > 0xc000) {
// TODO: this should probably affect the DMA dest as well
addr = (gb->dma_current_src & 0x1000) | (addr & 0xFFF) | 0xC000;
}
else {
addr = gb->dma_current_src;
}
} }
write_map[addr >> 12](gb, addr, value); write_map[addr >> 12](gb, addr, value);
} }
@ -1648,8 +1684,12 @@ void GB_dma_run(GB_gameboy_t *gb)
gb->oam[gb->dma_current_dest++] = GB_read_memory(gb, gb->dma_current_src); gb->oam[gb->dma_current_dest++] = GB_read_memory(gb, gb->dma_current_src);
} }
else { else {
/* Todo: Not correct on the CGB */ if (GB_is_cgb(gb)) {
gb->oam[gb->dma_current_dest++] = GB_read_memory(gb, gb->dma_current_src & ~0x2000); gb->oam[gb->dma_current_dest++] = 0xFF;
}
else {
gb->oam[gb->dma_current_dest++] = GB_read_memory(gb, gb->dma_current_src & ~0x2000);
}
} }
/* dma_current_src must be the correct value during GB_read_memory */ /* dma_current_src must be the correct value during GB_read_memory */