DS GX: Stub out GX renderer
@@ -10,6 +10,7 @@ #include <mgba-util/common.h>
CXX_GUARD_START +#include <mgba/core/interface.h> #include <mgba/core/log.h> #include <mgba/core/timing.h> #include <mgba-util/circle-buffer.h>@@ -80,9 +81,36 @@ uint8_t params[4];
}; #pragma pack(pop) +struct DSGXVertex { + // Viewport coords + int32_t x; // 16.16 + int32_t y; // 16.16 + int32_t z; // 16.16 + uint16_t color; + // Texcoords + int16_t s; // 12.4 + int16_t t; // 12.4 +}; + +struct DSGXPolygon { + int verts; + unsigned vertIds[4]; +}; + +struct DSGXRenderer { + void (*init)(struct DSGXRenderer* renderer); + void (*reset)(struct DSGXRenderer* renderer); + void (*deinit)(struct DSGXRenderer* renderer); + + void (*setRAM)(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount); + void (*drawScanline)(struct DSGXRenderer* renderer, int y); + void (*getScanline)(struct DSGXRenderer* renderer, int y, color_t** output); +}; + struct DS; struct DSGX { struct DS* p; + struct DSGXRenderer* renderer; struct CircleBuffer fifo; struct CircleBuffer pipe;@@ -92,11 +120,15 @@ int outstandingParams[4];
uint8_t outstandingCommand[4]; bool swapBuffers; + int bufferIndex; + struct DSGXVertex* vertexBuffer[2]; + struct DSGXPolygon* polygonBuffer[2]; }; void DSGXInit(struct DSGX*); void DSGXDeinit(struct DSGX*); void DSGXReset(struct DSGX*); +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);
@@ -70,6 +70,7 @@ DECL_BITFIELD(DSRegisterMASTER_BRIGHT, uint16_t);
DECL_BITS(DSRegisterMASTER_BRIGHT, Y, 0, 5); DECL_BITS(DSRegisterMASTER_BRIGHT, Mode, 14, 2); +struct DSGX; struct DSVideoRenderer { void (*init)(struct DSVideoRenderer* renderer); void (*reset)(struct DSVideoRenderer* renderer);@@ -96,6 +97,7 @@ uint16_t* vramBOBJ[32];
uint16_t* vramBBGExtPal[4]; uint16_t* vramBOBJExtPal; union DSOAM* oam; + struct DSGX* gx; }; struct DS;
@@ -13,6 +13,13 @@
#define DS_GX_FIFO_SIZE 256 #define DS_GX_PIPE_SIZE 4 +static void DSGXDummyRendererInit(struct DSGXRenderer* renderer); +static void DSGXDummyRendererReset(struct DSGXRenderer* renderer); +static void DSGXDummyRendererDeinit(struct DSGXRenderer* renderer); +static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount); +static void DSGXDummyRendererDrawScanline(struct DSGXRenderer* renderer, int y); +static void DSGXDummyRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output); + static const int32_t _gxCommandCycleBase[DS_GX_CMD_MAX] = { [DS_GX_CMD_NOP] = 0, [DS_GX_CMD_MTX_MODE] = 2,@@ -91,6 +98,15 @@ [DS_GX_CMD_POS_TEST] = 2,
[DS_GX_CMD_VEC_TEST] = 1, }; +static struct DSGXRenderer dummyRenderer = { + .init = DSGXDummyRendererInit, + .reset = DSGXDummyRendererReset, + .deinit = DSGXDummyRendererDeinit, + .setRAM = DSGXDummyRendererSetRAM, + .drawScanline = DSGXDummyRendererDrawScanline, + .getScanline = DSGXDummyRendererGetScanline, +}; + static void _pullPipe(struct DSGX* gx) { if (CircleBufferSize(&gx->fifo) >= sizeof(struct DSGXEntry)) { struct DSGXEntry entry = { 0 };@@ -171,6 +187,7 @@ }
} void DSGXInit(struct DSGX* gx) { + gx->renderer = &dummyRenderer; CircleBufferInit(&gx->fifo, sizeof(struct DSGXEntry) * DS_GX_FIFO_SIZE); CircleBufferInit(&gx->pipe, sizeof(struct DSGXEntry) * DS_GX_PIPE_SIZE); gx->fifoEvent.name = "DS GX FIFO";@@ -180,6 +197,7 @@ gx->fifoEvent.callback = _fifoRun;
} void DSGXDeinit(struct DSGX* gx) { + DSGXAssociateRenderer(gx, &dummyRenderer); CircleBufferDeinit(&gx->fifo); CircleBufferDeinit(&gx->pipe); }@@ -190,6 +208,12 @@ CircleBufferClear(&gx->pipe);
gx->swapBuffers = false; memset(gx->outstandingParams, 0, sizeof(gx->outstandingParams)); memset(gx->outstandingCommand, 0, sizeof(gx->outstandingCommand)); +} + +void DSGXAssociateRenderer(struct DSGX* gx, struct DSGXRenderer* renderer) { + gx->renderer->deinit(gx->renderer); + gx->renderer = renderer; + gx->renderer->init(gx->renderer); } void DSGXUpdateGXSTAT(struct DSGX* gx) {@@ -379,3 +403,39 @@ if (CircleBufferSize(&gx->fifo)) {
mTimingSchedule(&gx->p->ds9.timing, &gx->fifoEvent, 0); } } + +static void DSGXDummyRendererInit(struct DSGXRenderer* renderer) { + UNUSED(renderer); + // Nothing to do +} + +static void DSGXDummyRendererReset(struct DSGXRenderer* renderer) { + UNUSED(renderer); + // Nothing to do +} + +static void DSGXDummyRendererDeinit(struct DSGXRenderer* renderer) { + UNUSED(renderer); + // Nothing to do +} + +static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) { + UNUSED(renderer); + UNUSED(verts); + UNUSED(polys); + UNUSED(polyCount); + // Nothing to do +} + +static void DSGXDummyRendererDrawScanline(struct DSGXRenderer* renderer, int y) { + UNUSED(renderer); + UNUSED(y); + // Nothing to do +} + +static void DSGXDummyRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output) { + UNUSED(renderer); + UNUSED(y); + *output = NULL; + // Nothing to do +}
@@ -7,6 +7,7 @@ #include <mgba/internal/ds/renderers/software.h>
#include "gba/renderers/software-private.h" #include <mgba/internal/arm/macros.h> +#include <mgba/internal/ds/gx.h> #include <mgba/internal/ds/io.h> static void DSVideoSoftwareRendererInit(struct DSVideoRenderer* renderer);@@ -354,7 +355,7 @@ struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer;
_regenerateExtPalette(softwareRenderer, obj, engB, slot); } -static void DSVideoSoftwareRendererDrawGBAScanline(struct GBAVideoRenderer* renderer, int y) { +static void DSVideoSoftwareRendererDrawGBAScanline(struct GBAVideoRenderer* renderer, struct DSGX* gx, int y) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; int x;@@ -381,7 +382,9 @@ if (spriteLayers & (1 << priority)) {
GBAVideoSoftwareRendererPostprocessSprite(softwareRenderer, priority); } if (TEST_LAYER_ENABLED(0)) { - if (DSRegisterDISPCNTIs3D(softwareRenderer->dispcnt)) { + if (DSRegisterDISPCNTIs3D(softwareRenderer->dispcnt) && gx) { + color_t* scanline; + gx->renderer->getScanline(gx->renderer, y, &scanline); // TODO } else { GBAVideoSoftwareRendererDrawBackgroundMode0(softwareRenderer, &softwareRenderer->bg[0], y);@@ -472,7 +475,7 @@ row[x] = GBA_COLOR_WHITE;
} return; case 1: - DSVideoSoftwareRendererDrawGBAScanline(&softwareRenderer->engA.d, y); + DSVideoSoftwareRendererDrawGBAScanline(&softwareRenderer->engA.d, softwareRenderer->d.gx, y); return; case 2: { uint16_t* vram = &softwareRenderer->d.vram[0x10000 * DSRegisterDISPCNTGetVRAMBlock(softwareRenderer->dispcntA)];@@ -527,7 +530,7 @@ row[x] = GBA_COLOR_WHITE;
} return; case 1: - DSVideoSoftwareRendererDrawGBAScanline(&softwareRenderer->engB.d, y); + DSVideoSoftwareRendererDrawGBAScanline(&softwareRenderer->engB.d, NULL, y); return; }