DS GX: Start implementing matrix operations

This commit is contained in:
Vicki Pfau 2017-02-27 17:51:30 -08:00
parent e8bfc7bcca
commit 338d29f5ad
4 changed files with 142 additions and 0 deletions

View File

@ -13,6 +13,7 @@ CXX_GUARD_START
#include <mgba/core/interface.h> #include <mgba/core/interface.h>
#include <mgba/core/log.h> #include <mgba/core/log.h>
#include <mgba/core/timing.h> #include <mgba/core/timing.h>
#include <mgba/internal/ds/matrix.h>
#include <mgba-util/circle-buffer.h> #include <mgba-util/circle-buffer.h>
mLOG_DECLARE_CATEGORY(DS_GX); mLOG_DECLARE_CATEGORY(DS_GX);
@ -119,10 +120,24 @@ struct DSGX {
int outstandingParams[4]; int outstandingParams[4];
uint8_t outstandingCommand[4]; uint8_t outstandingCommand[4];
int activeParams;
int activeEntries[32];
bool swapBuffers; bool swapBuffers;
int bufferIndex; int bufferIndex;
struct DSGXVertex* vertexBuffer[2]; struct DSGXVertex* vertexBuffer[2];
struct DSGXPolygon* polygonBuffer[2]; struct DSGXPolygon* polygonBuffer[2];
int mtxMode;
struct DSGXMatrix projMatrixStack;
struct DSGXMatrix texMatrixStack;
struct DSGXMatrix posMatrixStack[32];
struct DSGXMatrix vecMatrixStack[32];
struct DSGXMatrix projMatrix;
struct DSGXMatrix texMatrix;
struct DSGXMatrix posMatrix;
struct DSGXMatrix vecMatrix;
}; };
void DSGXInit(struct DSGX*); void DSGXInit(struct DSGX*);

View File

@ -0,0 +1,21 @@
/* Copyright (c) 2013-2017 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef DS_MATRIX_H
#define DS_MATRIX_H
#include <mgba-util/common.h>
CXX_GUARD_START
struct DSGXMatrix {
int32_t m[16]; // 20.12
};
void DSGXMtxIdentity(struct DSGXMatrix*);
CXX_GUARD_END
#endif

View File

@ -145,6 +145,10 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate)
break; break;
} }
DSRegGXSTAT gxstat = gx->p->memory.io9[DS9_REG_GXSTAT_LO >> 1];
int pvMatrixPointer = DSRegGXSTATGetPVMatrixStackLevel(gxstat);
int projMatrixPointer = DSRegGXSTATGetProjMatrixStackLevel(gxstat);
if (CircleBufferSize(&gx->pipe) <= 2 * sizeof(struct DSGXEntry)) { if (CircleBufferSize(&gx->pipe) <= 2 * sizeof(struct DSGXEntry)) {
_pullPipe(gx); _pullPipe(gx);
} }
@ -165,6 +169,71 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate)
CircleBufferRead8(&gx->pipe, (int8_t*) &entry.params[3]); CircleBufferRead8(&gx->pipe, (int8_t*) &entry.params[3]);
switch (entry.command) { switch (entry.command) {
case DS_GX_CMD_MTX_MODE:
if (entry.params[0] < 4) {
gx->mtxMode = entry.params[0];
} else {
mLOG(DS_GX, GAME_ERROR, "Invalid GX MTX_MODE %02X", entry.params[0]);
}
break;
case DS_GX_CMD_MTX_IDENTITY:
switch (gx->mtxMode) {
case 0:
DSGXMtxIdentity(&gx->projMatrix);
break;
case 2:
DSGXMtxIdentity(&gx->vecMatrix);
// Fall through
case 1:
DSGXMtxIdentity(&gx->posMatrix);
break;
case 3:
DSGXMtxIdentity(&gx->texMatrix);
break;
}
break;
case DS_GX_CMD_MTX_PUSH:
switch (gx->mtxMode) {
case 0:
memcpy(&gx->projMatrixStack, &gx->projMatrix, sizeof(gx->projMatrix));
++projMatrixPointer;
break;
case 2:
memcpy(&gx->vecMatrixStack[pvMatrixPointer & 0x1F], &gx->vecMatrix, sizeof(gx->vecMatrix));
// Fall through
case 1:
memcpy(&gx->posMatrixStack[pvMatrixPointer & 0x1F], &gx->posMatrix, sizeof(gx->posMatrix));
++pvMatrixPointer;
break;
case 3:
mLOG(DS_GX, STUB, "Unimplemented GX MTX_PUSH mode");
break;
}
break;
case DS_GX_CMD_MTX_POP: {
int8_t offset = entry.params[0];
offset <<= 2;
offset >>= 2;
switch (gx->mtxMode) {
case 0:
projMatrixPointer -= offset;
memcpy(&gx->projMatrix, &gx->projMatrixStack, sizeof(gx->projMatrix));
break;
case 1:
pvMatrixPointer -= offset;
memcpy(&gx->posMatrix, &gx->posMatrixStack[pvMatrixPointer & 0x1F], sizeof(gx->posMatrix));
break;
case 2:
pvMatrixPointer -= offset;
memcpy(&gx->vecMatrix, &gx->vecMatrixStack[pvMatrixPointer & 0x1F], sizeof(gx->vecMatrix));
memcpy(&gx->posMatrix, &gx->posMatrixStack[pvMatrixPointer & 0x1F], sizeof(gx->posMatrix));
break;
case 3:
mLOG(DS_GX, STUB, "Unimplemented GX MTX_POP mode");
break;
}
break;
}
case DS_GX_CMD_SWAP_BUFFERS: case DS_GX_CMD_SWAP_BUFFERS:
gx->swapBuffers = true; gx->swapBuffers = true;
break; break;
@ -172,6 +241,12 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate)
mLOG(DS_GX, STUB, "Unimplemented GX command %02X:%02X %02X %02X %02X", entry.command, entry.params[0], entry.params[1], entry.params[2], entry.params[3]); mLOG(DS_GX, STUB, "Unimplemented GX command %02X:%02X %02X %02X %02X", entry.command, entry.params[0], entry.params[1], entry.params[2], entry.params[3]);
break; break;
} }
gxstat = DSRegGXSTATSetPVMatrixStackLevel(gxstat, pvMatrixPointer);
gxstat = DSRegGXSTATSetProjMatrixStackLevel(gxstat, projMatrixPointer);
gxstat = DSRegGXSTATTestFillMatrixStackError(gxstat, projMatrixPointer || pvMatrixPointer >= 0x1F);
gx->p->memory.io9[DS9_REG_GXSTAT_LO >> 1] = gxstat;
if (cyclesLate >= cycles) { if (cyclesLate >= cycles) {
cyclesLate -= cycles; cyclesLate -= cycles;
} }
@ -205,7 +280,22 @@ void DSGXDeinit(struct DSGX* gx) {
void DSGXReset(struct DSGX* gx) { void DSGXReset(struct DSGX* gx) {
CircleBufferClear(&gx->fifo); CircleBufferClear(&gx->fifo);
CircleBufferClear(&gx->pipe); CircleBufferClear(&gx->pipe);
DSGXMtxIdentity(&gx->projMatrix);
DSGXMtxIdentity(&gx->texMatrix);
DSGXMtxIdentity(&gx->posMatrix);
DSGXMtxIdentity(&gx->vecMatrix);
DSGXMtxIdentity(&gx->projMatrixStack);
DSGXMtxIdentity(&gx->texMatrixStack);
int i;
for (i = 0; i < 32; ++i) {
DSGXMtxIdentity(&gx->posMatrixStack[i]);
DSGXMtxIdentity(&gx->vecMatrixStack[i]);
}
gx->swapBuffers = false; gx->swapBuffers = false;
gx->bufferIndex = 0;
gx->mtxMode = 0;
memset(gx->outstandingParams, 0, sizeof(gx->outstandingParams)); memset(gx->outstandingParams, 0, sizeof(gx->outstandingParams));
memset(gx->outstandingCommand, 0, sizeof(gx->outstandingCommand)); memset(gx->outstandingCommand, 0, sizeof(gx->outstandingCommand));
} }

16
src/ds/matrix.c Normal file
View File

@ -0,0 +1,16 @@
/* Copyright (c) 2013-2017 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <mgba/internal/ds/matrix.h>
#define MTX_ONE 0x00001000
void DSGXMtxIdentity(struct DSGXMatrix* mtx) {
memset(mtx, 0, sizeof(*mtx));
mtx->m[0] = MTX_ONE;
mtx->m[5] = MTX_ONE;
mtx->m[10] = MTX_ONE;
mtx->m[15] = MTX_ONE;
}