DS GX: Start implementing FIFO full
Vicki Pfau vi@endrift.com
Tue, 28 Feb 2017 23:21:09 -0800
5 files changed,
26 insertions(+),
9 deletions(-)
M
include/mgba/internal/ds/ds.h
→
include/mgba/internal/ds/ds.h
@@ -49,6 +49,11 @@ DS_IRQ_SPI = 0x17,
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 @@ int32_t cycleDrift;
struct ARMDebugger* debugger; - bool cpuBlocked; + int cpuBlocked; bool earlyExit; uint32_t bios7Checksum;
M
include/mgba/internal/ds/gx.h
→
include/mgba/internal/ds/gx.h
@@ -130,6 +130,7 @@ struct mTimingEvent fifoEvent;
int outstandingParams[4]; uint8_t outstandingCommand[4]; + struct DSGXEntry outstandingEntry; int activeParams; struct DSGXEntry activeEntries[32];
M
src/ds/dma.c
→
src/ds/dma.c
@@ -115,7 +115,7 @@ if (dma->nextCount == dma->count) {
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 @@ if (memory->activeDMA >= 0) {
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; } }
M
src/ds/ds.c
→
src/ds/ds.c
@@ -383,7 +383,7 @@ #endif
nextEvent = cycles; do { nextEvent = mTimingTick(&dscore->timing, nextEvent); - } while (ds->cpuBlocked); + } while (ds->cpuBlocked && !ds->earlyExit); if (ds->earlyExit) { ds->earlyExit = false;
M
src/ds/gx.c
→
src/ds/gx.c
@@ -644,10 +644,10 @@ } else {
break; } } - DSGXUpdateGXSTAT(gx); if (cycles && !gx->swapBuffers) { mTimingSchedule(timing, &gx->fifoEvent, cycles - cyclesLate); } + DSGXUpdateGXSTAT(gx); } void DSGXInit(struct DSGX* gx) {@@ -707,6 +707,7 @@ gx->viewportHeight = gx->viewportY2 - gx->viewportY1;
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 @@
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 @@ gx->outstandingParams[1] = _gxCommandParams[gx->outstandingCommand[1]];
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 @@ gx->outstandingParams[3] = 0;
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 @@ CircleBufferWrite8(&gx->fifo, entry.params[2]);
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 @@ gx->bufferIndex ^= 1;
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) {