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/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*);
|
||||||
|
|
|
@ -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;
|
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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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