GBA DMA: Fix ordering and timing of overlapping DMAs
Vicki Pfau vi@endrift.com
Fri, 21 Aug 2020 04:42:50 -0700
2 files changed,
12 insertions(+),
1 deletions(-)
M
CHANGES
→
CHANGES
@@ -28,6 +28,7 @@ - GBA BIOS: Improve HLE BIOS timing
- 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)
M
src/gba/dma.c
→
src/gba/dma.c
@@ -219,7 +219,7 @@ for (i = 0; i < 4; ++i) {
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 @@
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) {