From 66842997dc50540c59f9f079aa903ab996fa3172 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 21 Aug 2020 04:42:50 -0700 Subject: [PATCH] GBA DMA: Fix ordering and timing of overlapping DMAs --- CHANGES | 1 + src/gba/dma.c | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 8b414a59d..7b2bce2bf 100644 --- a/CHANGES +++ b/CHANGES @@ -28,6 +28,7 @@ Emulation fixes: - GBA BIOS: Fix reloading video registers after reset (fixes mgba.io/i/1808) - GBA BIOS: Make HLE BIOS calls interruptable (fixes mgba.io/i/1711 and mgba.io/i/1823) - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) + - GBA DMA: Fix ordering and timing of overlapping DMAs - GBA Hardware: Fix GB Player detection on big endian platforms - GBA Memory: Improve gamepak prefetch timing - GBA Memory: Stall on VRAM access in mode 2 (fixes mgba.io/i/190) diff --git a/src/gba/dma.c b/src/gba/dma.c index 3343033ec..d30f0291a 100644 --- a/src/gba/dma.c +++ b/src/gba/dma.c @@ -219,7 +219,7 @@ void GBADMAUpdate(struct GBA* gba) { struct GBADMA* dma = &memory->dma[i]; if (GBADMARegisterIsEnable(dma->reg) && dma->nextCount) { int32_t time = dma->when - currentTime; - if (memory->activeDMA == -1 || (dma->count == dma->nextCount && time < leastTime)) { + if (memory->activeDMA == -1 || time < leastTime) { leastTime = time; memory->activeDMA = i; } @@ -303,6 +303,16 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { info->nextCount = wordsRemaining; info->nextSource = source; info->nextDest = dest; + + int i; + for (i = 0; i < 4; ++i) { + struct GBADMA* dma = &memory->dma[i]; + int32_t time = dma->when - info->when; + if (time < 0 && GBADMARegisterIsEnable(dma->reg) && dma->nextCount) { + dma->when = info->when; + } + } + if (!wordsRemaining) { info->nextCount |= 0x80000000; if (sourceRegion < REGION_CART0 || destRegion < REGION_CART0) {