mirror of https://github.com/mgba-emu/mgba.git
DS GX: Start implementing matrix operations
This commit is contained in:
parent
e8bfc7bcca
commit
338d29f5ad
|
@ -13,6 +13,7 @@ CXX_GUARD_START
|
|||
#include <mgba/core/interface.h>
|
||||
#include <mgba/core/log.h>
|
||||
#include <mgba/core/timing.h>
|
||||
#include <mgba/internal/ds/matrix.h>
|
||||
#include <mgba-util/circle-buffer.h>
|
||||
|
||||
mLOG_DECLARE_CATEGORY(DS_GX);
|
||||
|
@ -119,10 +120,24 @@ struct DSGX {
|
|||
int outstandingParams[4];
|
||||
uint8_t outstandingCommand[4];
|
||||
|
||||
int activeParams;
|
||||
int activeEntries[32];
|
||||
|
||||
bool swapBuffers;
|
||||
int bufferIndex;
|
||||
struct DSGXVertex* vertexBuffer[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*);
|
||||
|
|
|
@ -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
|
90
src/ds/gx.c
90
src/ds/gx.c
|
@ -145,6 +145,10 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate)
|
|||
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)) {
|
||||
_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]);
|
||||
|
||||
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:
|
||||
gx->swapBuffers = true;
|
||||
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]);
|
||||
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) {
|
||||
cyclesLate -= cycles;
|
||||
}
|
||||
|
@ -205,7 +280,22 @@ void DSGXDeinit(struct DSGX* gx) {
|
|||
void DSGXReset(struct DSGX* gx) {
|
||||
CircleBufferClear(&gx->fifo);
|
||||
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->bufferIndex = 0;
|
||||
gx->mtxMode = 0;
|
||||
|
||||
memset(gx->outstandingParams, 0, sizeof(gx->outstandingParams));
|
||||
memset(gx->outstandingCommand, 0, sizeof(gx->outstandingCommand));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue