From 3fcdbd0d8983c024a1c88d85a1cc137e9c9482db Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 28 Feb 2017 23:21:09 -0800 Subject: [PATCH] DS GX: Start implementing FIFO full --- include/mgba/internal/ds/ds.h | 7 ++++++- include/mgba/internal/ds/gx.h | 1 + src/ds/dma.c | 4 ++-- src/ds/ds.c | 2 +- src/ds/gx.c | 21 ++++++++++++++++----- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/include/mgba/internal/ds/ds.h b/include/mgba/internal/ds/ds.h index 205d9b8fd..520622f56 100644 --- a/include/mgba/internal/ds/ds.h +++ b/include/mgba/internal/ds/ds.h @@ -49,6 +49,11 @@ enum DSIRQ { DS_IRQ_WIFI = 0x18, }; +enum { + DS_CPU_BLOCK_DMA = 1, + DS_CPU_BLOCK_GX = 2 +}; + struct ARMCore; struct DS; struct Patch; @@ -89,7 +94,7 @@ struct DS { struct ARMDebugger* debugger; - bool cpuBlocked; + int cpuBlocked; bool earlyExit; uint32_t bios7Checksum; diff --git a/include/mgba/internal/ds/gx.h b/include/mgba/internal/ds/gx.h index 004e13b18..469c9cf22 100644 --- a/include/mgba/internal/ds/gx.h +++ b/include/mgba/internal/ds/gx.h @@ -130,6 +130,7 @@ struct DSGX { int outstandingParams[4]; uint8_t outstandingCommand[4]; + struct DSGXEntry outstandingEntry; int activeParams; struct DSGXEntry activeEntries[32]; diff --git a/src/ds/dma.c b/src/ds/dma.c index 3ac286c7f..698884698 100644 --- a/src/ds/dma.c +++ b/src/ds/dma.c @@ -115,7 +115,7 @@ void _dmaEvent(struct mTiming* timing, void* context, uint32_t cyclesLate) { dma->when = mTimingCurrentTime(&dscore->timing); } if (dma->nextCount & 0xFFFFF) { - dscore->p->cpuBlocked = true; // TODO: Fix for ITCM + dscore->p->cpuBlocked |= DS_CPU_BLOCK_DMA; // TODO: Fix for ITCM DSDMAService(dscore, memory->activeDMA, dma); } else { dma->nextCount = 0; @@ -152,7 +152,7 @@ void DSDMAUpdate(struct DSCommon* dscore) { mTimingDeschedule(&dscore->timing, &memory->dmaEvent); mTimingSchedule(&dscore->timing, &memory->dmaEvent, memory->dma[memory->activeDMA].when - currentTime); } else { - dscore->p->cpuBlocked = false; + dscore->p->cpuBlocked &= ~DS_CPU_BLOCK_DMA; } } diff --git a/src/ds/ds.c b/src/ds/ds.c index 9ec42d20f..0813a51ca 100644 --- a/src/ds/ds.c +++ b/src/ds/ds.c @@ -383,7 +383,7 @@ static void DSProcessEvents(struct DSCommon* dscore) { nextEvent = cycles; do { nextEvent = mTimingTick(&dscore->timing, nextEvent); - } while (ds->cpuBlocked); + } while (ds->cpuBlocked && !ds->earlyExit); if (ds->earlyExit) { ds->earlyExit = false; diff --git a/src/ds/gx.c b/src/ds/gx.c index bb0ed6baa..842b68b80 100644 --- a/src/ds/gx.c +++ b/src/ds/gx.c @@ -644,10 +644,10 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) break; } } - DSGXUpdateGXSTAT(gx); if (cycles && !gx->swapBuffers) { mTimingSchedule(timing, &gx->fifoEvent, cycles - cyclesLate); } + DSGXUpdateGXSTAT(gx); } void DSGXInit(struct DSGX* gx) { @@ -707,6 +707,7 @@ void DSGXReset(struct DSGX* gx) { memset(gx->outstandingParams, 0, sizeof(gx->outstandingParams)); memset(gx->outstandingCommand, 0, sizeof(gx->outstandingCommand)); + memset(&gx->outstandingEntry, 0, sizeof(gx->outstandingEntry)); gx->activeParams = 0; memset(&gx->currentVertex, 0, sizeof(gx->currentVertex)); } @@ -738,6 +739,11 @@ 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; + + if (gx->p->cpuBlocked & DS_CPU_BLOCK_GX && entries < DS_GX_FIFO_SIZE) { + DSGXWriteFIFO(gx, gx->outstandingEntry); + gx->p->cpuBlocked &= ~DS_CPU_BLOCK_GX; + } } static void DSGXUnpackCommand(struct DSGX* gx, uint32_t command) { @@ -762,7 +768,7 @@ static void DSGXUnpackCommand(struct DSGX* gx, uint32_t command) { gx->outstandingParams[2] = _gxCommandParams[gx->outstandingCommand[2]]; gx->outstandingParams[3] = _gxCommandParams[gx->outstandingCommand[3]]; while (gx->outstandingCommand[0] && !gx->outstandingParams[0]) { - DSGXWriteFIFO(gx, (struct DSGXEntry) { 0 }); + DSGXWriteFIFO(gx, (struct DSGXEntry) { gx->outstandingCommand[0] }); } } @@ -780,11 +786,13 @@ static void DSGXWriteFIFO(struct DSGX* gx, struct DSGXEntry entry) { gx->outstandingCommand[3] = 0; } } else { - gx->outstandingCommand[0] = entry.command; gx->outstandingParams[0] = _gxCommandParams[entry.command]; if (gx->outstandingParams[0]) { --gx->outstandingParams[0]; } + if (gx->outstandingParams[0]) { + gx->outstandingCommand[0] = entry.command; + } } uint32_t cycles = _gxCommandCycleBase[entry.command]; if (!cycles) { @@ -804,13 +812,16 @@ static void DSGXWriteFIFO(struct DSGX* gx, struct DSGXEntry entry) { CircleBufferWrite8(&gx->fifo, entry.params[3]); } else { mLOG(DS_GX, STUB, "Unimplemented GX full"); + gx->p->cpuBlocked |= DS_CPU_BLOCK_GX; + gx->outstandingEntry = entry; + gx->p->ds9.cpu->nextEvent = 0; } if (!gx->swapBuffers && !mTimingIsScheduled(&gx->p->ds9.timing, &gx->fifoEvent)) { mTimingSchedule(&gx->p->ds9.timing, &gx->fifoEvent, cycles); } if (gx->outstandingCommand[0] && !gx->outstandingParams[0]) { - DSGXWriteFIFO(gx, (struct DSGXEntry) { 0 }); + DSGXWriteFIFO(gx, (struct DSGXEntry) { gx->outstandingCommand[0] }); } } @@ -913,10 +924,10 @@ void DSGXSwapBuffers(struct DSGX* gx) { gx->vertexIndex = 0; gx->polygonIndex = 0; - DSGXUpdateGXSTAT(gx); if (CircleBufferSize(&gx->fifo)) { mTimingSchedule(&gx->p->ds9.timing, &gx->fifoEvent, 0); } + DSGXUpdateGXSTAT(gx); } static void DSGXDummyRendererInit(struct DSGXRenderer* renderer) {