diff --git a/include/mgba/internal/ds/dma.h b/include/mgba/internal/ds/dma.h index f79d41c8c..eedfa0b17 100644 --- a/include/mgba/internal/ds/dma.h +++ b/include/mgba/internal/ds/dma.h @@ -39,6 +39,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 DSDMAUpdate(struct DSCommon* dscore); CXX_GUARD_END diff --git a/src/ds/dma.c b/src/ds/dma.c index 2e5fb2216..b64103932 100644 --- a/src/ds/dma.c +++ b/src/ds/dma.c @@ -145,6 +145,20 @@ void _dmaEvent(struct mTiming* timing, void* context, uint32_t cyclesLate) { } } +void DSDMARunVblank(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) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_VBLANK && !dma->nextCount) { + dma->when = mTimingCurrentTime(&dscore->timing) + 3 + cycles; + dma->nextCount = dma->count; + } + } + DSDMAUpdate(dscore); +} + void DSDMAUpdate(struct DSCommon* dscore) { int i; struct DSCoreMemory* memory = &dscore->memory; diff --git a/src/ds/video.c b/src/ds/video.c index fd97d305e..e75d29635 100644 --- a/src/ds/video.c +++ b/src/ds/video.c @@ -292,6 +292,7 @@ void _startHdraw7(struct mTiming* timing, void* context, uint32_t cyclesLate) { switch (video->vcount) { case DS_VIDEO_VERTICAL_PIXELS: + DSDMARunVblank(&video->p->ds7, -cyclesLate); video->p->ds7.memory.io[DS_REG_DISPSTAT >> 1] = GBARegisterDISPSTATFillInVblank(dispstat); if (GBARegisterDISPSTATIsVblankIRQ(dispstat)) { DSRaiseIRQ(video->p->ds7.cpu, video->p->ds7.memory.io, DS_IRQ_VBLANK); @@ -349,6 +350,7 @@ void _startHdraw9(struct mTiming* timing, void* context, uint32_t cyclesLate) { video->inCapture = DSRegisterDISPCAPCNTIsEnable(video->p->ds9.memory.io[DS9_REG_DISPCAPCNT_HI >> 1] << 16); break; case DS_VIDEO_VERTICAL_PIXELS: + DSDMARunVblank(&video->p->ds9, -cyclesLate); video->p->ds9.memory.io[DS_REG_DISPSTAT >> 1] = GBARegisterDISPSTATFillInVblank(dispstat); video->p->ds9.memory.io[DS9_REG_DISPCAPCNT_HI >> 1] = DSRegisterDISPCAPCNTClearEnable(video->p->ds9.memory.io[DS9_REG_DISPCAPCNT_HI >> 1] << 16) >> 16; if (video->frameskipCounter <= 0) {