DMA during mode 3 emulation

This commit is contained in:
Lior Halphon 2022-01-14 17:09:39 +02:00
parent 4ce8e77796
commit ffa53eda20
3 changed files with 23 additions and 10 deletions

View File

@ -844,13 +844,13 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb)
}
}
static uint8_t oam_read(GB_gameboy_t *gb, uint8_t addr)
static inline uint8_t oam_read(GB_gameboy_t *gb, uint8_t addr)
{
if (unlikely(gb->oam_ppu_blocked)) {
return 0xFF;
}
if (unlikely(GB_is_dma_active(gb))) {
if (unlikely(gb->dma_current_dest > 0 && gb->dma_current_dest <= 0xa0)) { // TODO: what happens in the last and first M cycles?
return gb->oam[((gb->dma_current_dest - 1) & ~1) | (addr & 1)];
}
return gb->oam[addr];
}
@ -1611,6 +1611,18 @@ void GB_display_run(GB_gameboy_t *gb, unsigned cycles, bool force)
goto abort_fetching_object;
}
if (unlikely(GB_is_dma_active(gb) || gb->dma_current_src == 0xFF)) {
unsigned offset = cycles - gb->display_cycles; // Time passed in 8MHz ticks
if (offset) {
if (!gb->cgb_double_speed) {
offset >>= 1; // Convert to T-cycles
}
unsigned old = gb->dma_cycles;
gb->dma_cycles = offset;
GB_dma_run(gb);
gb->dma_cycles += old - offset;
}
}
gb->object_low_line_address = get_object_line_address(gb,
gb->objects_y[gb->n_visible_objs - 1],
@ -1618,7 +1630,7 @@ void GB_display_run(GB_gameboy_t *gb, unsigned cycles, bool force)
gb->object_flags = oam_read(gb, gb->visible_objs[gb->n_visible_objs - 1] * 4 + 3)
);
gb->cycles_for_line++;
gb->cycles_for_line += 1;
GB_SLEEP(gb, display, 39, 1);
if (gb->object_fetch_aborted) {
goto abort_fetching_object;

View File

@ -252,6 +252,7 @@ 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)
{
if (!GB_is_dma_active(gb) || addr >= 0xfe00) return false;
if (gb->dma_current_dest == 0xFF) return false; // Warm up
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;
@ -1459,8 +1460,8 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
return;
case GB_IO_DMA:
gb->dma_cycles = -3;
gb->dma_current_dest = 0;
gb->dma_cycles = 0;
gb->dma_current_dest = 0xFF;
gb->dma_current_src = value << 8;
gb->io_registers[GB_IO_DMA] = value;
return;
@ -1681,12 +1682,12 @@ void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
bool GB_is_dma_active(GB_gameboy_t *gb)
{
return gb->dma_current_dest < 0xa1;
return gb->dma_current_dest != 0xa1;
}
void GB_dma_run(GB_gameboy_t *gb)
{
if (gb->dma_current_dest >= 0xa1) return;
if (gb->dma_current_dest == 0xa1) return;
while (unlikely(gb->dma_cycles >= 4)) {
gb->dma_cycles -= 4;
if (gb->dma_current_dest >= 0xa0) {

View File

@ -428,12 +428,12 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
gb->rumble_on_cycles += gb->rumble_strength & 3;
gb->rumble_off_cycles += (gb->rumble_strength & 3) ^ 3;
GB_apu_run(gb, false);
GB_display_run(gb, cycles, false);
if (unlikely(!gb->stopped)) { // TODO: Verify what happens in STOP mode
GB_dma_run(gb);
GB_hdma_run(gb);
}
GB_apu_run(gb, false);
GB_display_run(gb, cycles, false);
ir_run(gb, cycles);
rtc_run(gb, cycles);
}