diff --git a/include/mgba/internal/ds/gx.h b/include/mgba/internal/ds/gx.h index 0502f4425..25e9cb242 100644 --- a/include/mgba/internal/ds/gx.h +++ b/include/mgba/internal/ds/gx.h @@ -200,7 +200,7 @@ void DSGXAssociateRenderer(struct DSGX* video, struct DSGXRenderer* renderer); uint16_t DSGXWriteRegister(struct DSGX*, uint32_t address, uint16_t value); uint32_t DSGXWriteRegister32(struct DSGX*, uint32_t address, uint32_t value); -void DSGXSwapBuffers(struct DSGX*); +void DSGXFlush(struct DSGX*); void DSGXUpdateGXSTAT(struct DSGX*); CXX_GUARD_END diff --git a/include/mgba/internal/ds/gx/software.h b/include/mgba/internal/ds/gx/software.h index 504a97c6f..7c75cd69b 100644 --- a/include/mgba/internal/ds/gx/software.h +++ b/include/mgba/internal/ds/gx/software.h @@ -77,6 +77,7 @@ struct DSGXSoftwareRenderer { uint16_t depthBuffer[DS_VIDEO_HORIZONTAL_PIXELS]; color_t* scanlineCache; + bool flushPending; struct DSGXVertex* verts; }; diff --git a/src/ds/gx.c b/src/ds/gx.c index 9e1d15bcd..d57831fab 100644 --- a/src/ds/gx.c +++ b/src/ds/gx.c @@ -901,6 +901,7 @@ static void DSGXUnpackCommand(struct DSGX* gx, uint32_t command) { gx->outstandingParams[2] = _gxCommandParams[gx->outstandingCommand[2]]; gx->outstandingParams[3] = _gxCommandParams[gx->outstandingCommand[3]]; _flushOutstanding(gx); + DSGXUpdateGXSTAT(gx); } static void DSGXWriteFIFO(struct DSGX* gx, struct DSGXEntry entry) { @@ -1049,14 +1050,14 @@ uint32_t DSGXWriteRegister32(struct DSGX* gx, uint32_t address, uint32_t value) return value; } -void DSGXSwapBuffers(struct DSGX* gx) { - gx->swapBuffers = false; - - gx->renderer->setRAM(gx->renderer, gx->vertexBuffer[gx->bufferIndex], gx->polygonBuffer[gx->bufferIndex], gx->polygonIndex); - - gx->bufferIndex ^= 1; - gx->vertexIndex = 0; - gx->polygonIndex = 0; +void DSGXFlush(struct DSGX* gx) { + if (gx->swapBuffers) { + gx->renderer->setRAM(gx->renderer, gx->vertexBuffer[gx->bufferIndex], gx->polygonBuffer[gx->bufferIndex], gx->polygonIndex); + gx->swapBuffers = false; + gx->bufferIndex ^= 1; + gx->vertexIndex = 0; + gx->polygonIndex = 0; + } if (CircleBufferSize(&gx->fifo)) { mTimingSchedule(&gx->p->ds9.timing, &gx->fifoEvent, 0); diff --git a/src/ds/gx/software.c b/src/ds/gx/software.c index fe790ad27..d1c4d57e4 100644 --- a/src/ds/gx/software.c +++ b/src/ds/gx/software.c @@ -225,12 +225,12 @@ static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer) { DSGXSoftwareEdgeListInit(&softwareRenderer->activeEdges, DS_GX_POLYGON_BUFFER_SIZE); DSGXSoftwareSpanListInit(&softwareRenderer->activeSpans, DS_GX_POLYGON_BUFFER_SIZE / 2); softwareRenderer->bucket = anonymousMemoryMap(sizeof(*softwareRenderer->bucket) * DS_GX_POLYGON_BUFFER_SIZE); - softwareRenderer->scanlineCache = anonymousMemoryMap(sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48); + softwareRenderer->scanlineCache = anonymousMemoryMap(sizeof(color_t) * DS_VIDEO_VERTICAL_PIXELS * DS_VIDEO_HORIZONTAL_PIXELS); } static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer) { struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer; - // TODO + softwareRenderer->flushPending = false; } static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer) { @@ -239,7 +239,7 @@ static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer) { DSGXSoftwareEdgeListDeinit(&softwareRenderer->activeEdges); DSGXSoftwareSpanListDeinit(&softwareRenderer->activeSpans); mappedMemoryFree(softwareRenderer->bucket, sizeof(*softwareRenderer->bucket) * DS_GX_POLYGON_BUFFER_SIZE); - mappedMemoryFree(softwareRenderer->scanlineCache, sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48); + mappedMemoryFree(softwareRenderer->scanlineCache, sizeof(color_t) * DS_VIDEO_VERTICAL_PIXELS * DS_VIDEO_HORIZONTAL_PIXELS); } static void DSGXSoftwareRendererInvalidateTex(struct DSGXRenderer* renderer, int slot) { @@ -250,6 +250,7 @@ static void DSGXSoftwareRendererInvalidateTex(struct DSGXRenderer* renderer, int static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) { struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer; + softwareRenderer->flushPending = true; softwareRenderer->verts = verts; DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys); DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges); @@ -351,6 +352,9 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y) { struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer; + if (!softwareRenderer->flushPending) { + return; + } DSGXSoftwareSpanListClear(&softwareRenderer->activeSpans); memset(softwareRenderer->bucket, 0, sizeof(*softwareRenderer->bucket) * DS_GX_POLYGON_BUFFER_SIZE); int i; @@ -383,7 +387,6 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int } qsort(DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, 0), DSGXSoftwareSpanListSize(&softwareRenderer->activeSpans), sizeof(struct DSGXSoftwareSpan), _spanSort); - y %= 48; color_t* scanline = &softwareRenderer->scanlineCache[DS_VIDEO_HORIZONTAL_PIXELS * y]; int nextSpanX = DS_VIDEO_HORIZONTAL_PIXELS; @@ -438,10 +441,12 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int } } } + if (y == DS_VIDEO_VERTICAL_PIXELS - 1) { + softwareRenderer->flushPending = false; + } } static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output) { struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer; - y %= 48; *output = &softwareRenderer->scanlineCache[DS_VIDEO_HORIZONTAL_PIXELS * y]; } diff --git a/src/ds/video.c b/src/ds/video.c index c16f52ad1..ab75406ec 100644 --- a/src/ds/video.c +++ b/src/ds/video.c @@ -290,9 +290,7 @@ void _startHdraw9(struct mTiming* timing, void* context, uint32_t cyclesLate) { video->p->ds9.memory.io[DS_REG_DISPSTAT >> 1] = GBARegisterDISPSTATFillInVblank(dispstat); if (video->frameskipCounter <= 0) { video->renderer->finishFrame(video->renderer); - if (video->p->gx.swapBuffers) { - DSGXSwapBuffers(&video->p->gx); - } + DSGXFlush(&video->p->gx); } if (GBARegisterDISPSTATIsVblankIRQ(dispstat)) { DSRaiseIRQ(video->p->ds9.cpu, video->p->ds9.memory.io, DS_IRQ_VBLANK);