diff --git a/include/mgba/internal/ds/gx.h b/include/mgba/internal/ds/gx.h index 7795132de..bf6abbd8c 100644 --- a/include/mgba/internal/ds/gx.h +++ b/include/mgba/internal/ds/gx.h @@ -157,6 +157,7 @@ struct DSGX { struct CircleBuffer pipe; struct mTimingEvent fifoEvent; + int dmaSource; int outstandingParams[4]; uint8_t outstandingCommand[4]; @@ -214,6 +215,10 @@ uint32_t DSGXWriteRegister32(struct DSGX*, uint32_t address, uint32_t value); void DSGXFlush(struct DSGX*); void DSGXUpdateGXSTAT(struct DSGX*); +struct GBADMA; +struct DSCommon; +void DSGXScheduleDMA(struct DSCommon* dscore, int number, struct GBADMA* info); + CXX_GUARD_END #endif diff --git a/src/ds/dma.c b/src/ds/dma.c index 40387b757..2e5fb2216 100644 --- a/src/ds/dma.c +++ b/src/ds/dma.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -98,6 +99,9 @@ void DSDMASchedule(struct DSCommon* dscore, int number, struct GBADMA* info) { case DS9_DMA_TIMING_SLOT1: DSSlot1ScheduleDMA(dscore, number, info); return; + case DS_DMA_TIMING_GEOM_FIFO: + DSGXScheduleDMA(dscore, number, info); + return; case DS_DMA_TIMING_HBLANK: // DS7_DMA_TIMING_SLOT1 default: mLOG(DS_MEM, STUB, "Unimplemented DMA"); diff --git a/src/ds/gx.c b/src/ds/gx.c index e932a0514..38b0896f5 100644 --- a/src/ds/gx.c +++ b/src/ds/gx.c @@ -1021,6 +1021,7 @@ void DSGXReset(struct DSGX* gx) { memset(&gx->currentVertex, 0, sizeof(gx->currentVertex)); memset(&gx->nextPoly, 0, sizeof(gx-> nextPoly)); gx->currentVertex.color = 0x7FFF; + gx->dmaSource = -1; } void DSGXAssociateRenderer(struct DSGX* gx, struct DSGXRenderer* renderer) { @@ -1052,6 +1053,21 @@ void DSGXUpdateGXSTAT(struct DSGX* gx) { value = DSRegGXSTATSetBusy(value, mTimingIsScheduled(&gx->p->ds9.timing, &gx->fifoEvent) || gx->swapBuffers); gx->p->memory.io9[DS9_REG_GXSTAT_HI >> 1] = value >> 16; + + struct GBADMA* dma = NULL; + if (gx->dmaSource >= 0) { + dma = &gx->p->ds9.memory.dma[gx->dmaSource]; + if (GBADMARegisterGetTiming9(dma->reg) != DS_DMA_TIMING_GEOM_FIFO) { + gx->dmaSource = -1; + } else if (GBADMARegisterIsEnable(dma->reg) && entries < (DS_GX_FIFO_SIZE / 2) && !dma->nextCount) { + dma->nextCount = dma->count; + if (dma->count > 112) { + dma->nextCount = 112; + } + dma->when = mTimingCurrentTime(&gx->p->ds9.timing); + DSDMAUpdate(&gx->p->ds9); + } + } } static void DSGXUnpackCommand(struct DSGX* gx, uint32_t command) { @@ -1246,6 +1262,11 @@ void DSGXFlush(struct DSGX* gx) { DSGXUpdateGXSTAT(gx); } +void DSGXScheduleDMA(struct DSCommon* dscore, int number, struct GBADMA* info) { + UNUSED(info); + dscore->p->gx.dmaSource = number; +} + static void DSGXDummyRendererInit(struct DSGXRenderer* renderer) { UNUSED(renderer); // Nothing to do