DS GX: Start implementing FIFO full

This commit is contained in:
Vicki Pfau 2017-02-28 23:21:09 -08:00
parent 4073175409
commit 3fcdbd0d89
5 changed files with 26 additions and 9 deletions

View File

@ -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;

View File

@ -130,6 +130,7 @@ struct DSGX {
int outstandingParams[4];
uint8_t outstandingCommand[4];
struct DSGXEntry outstandingEntry;
int activeParams;
struct DSGXEntry activeEntries[32];

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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) {