diff --git a/include/mgba/internal/ds/dma.h b/include/mgba/internal/ds/dma.h index eedfa0b17..d122b9890 100644 --- a/include/mgba/internal/ds/dma.h +++ b/include/mgba/internal/ds/dma.h @@ -40,6 +40,7 @@ void DS9DMAWriteCNT(struct DSCommon* dscore, int dma, uint32_t value); struct DSDMA; void DSDMASchedule(struct DSCommon* dscore, int number, struct GBADMA* info); void DSDMARunVblank(struct DSCommon* dscore, int32_t cycles); +void DSDMARunHblank(struct DSCommon* dscore, int32_t cycles); void DSDMAUpdate(struct DSCommon* dscore); CXX_GUARD_END diff --git a/src/ds/dma.c b/src/ds/dma.c index b64103932..ff599ff9c 100644 --- a/src/ds/dma.c +++ b/src/ds/dma.c @@ -103,6 +103,10 @@ void DSDMASchedule(struct DSCommon* dscore, int number, struct GBADMA* info) { DSGXScheduleDMA(dscore, number, info); return; case DS_DMA_TIMING_HBLANK: // DS7_DMA_TIMING_SLOT1 + if (dscore == &dscore->p->ds9) { + // Handled implicitly + return; + } default: mLOG(DS_MEM, STUB, "Unimplemented DMA"); } @@ -151,7 +155,21 @@ void DSDMARunVblank(struct DSCommon* dscore, int32_t cycles) { int i; for (i = 0; i < 4; ++i) { dma = &memory->dma[i]; - if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_VBLANK && !dma->nextCount) { + if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DS_DMA_TIMING_VBLANK && !dma->nextCount) { + dma->when = mTimingCurrentTime(&dscore->timing) + 3 + cycles; + dma->nextCount = dma->count; + } + } + DSDMAUpdate(dscore); +} + +void DSDMARunHblank(struct DSCommon* dscore, int32_t cycles) { + struct DSCoreMemory* memory = &dscore->memory; + struct GBADMA* dma; + int i; + for (i = 0; i < 4; ++i) { + dma = &memory->dma[i]; + if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming9(dma->reg) == DS_DMA_TIMING_HBLANK && !dma->nextCount) { dma->when = mTimingCurrentTime(&dscore->timing) + 3 + cycles; dma->nextCount = dma->count; } diff --git a/src/ds/video.c b/src/ds/video.c index acde4c7b5..0ae78b109 100644 --- a/src/ds/video.c +++ b/src/ds/video.c @@ -399,6 +399,9 @@ void _startHblank9(struct mTiming* timing, void* context, uint32_t cyclesLate) { _performCapture(video, video->vcount); } + if (video->vcount < DS_VIDEO_VERTICAL_PIXELS) { + DSDMARunHblank(&video->p->ds9, -cyclesLate); + } if (GBARegisterDISPSTATIsHblankIRQ(dispstat)) { DSRaiseIRQ(video->p->ds9.cpu, video->p->ds9.memory.io, DS_IRQ_HBLANK); }