all repos — mgba @ 9ad56b1b798d1df66eaab8b7099aac4f07d11ac0

mGBA Game Boy Advance Emulator

DS GX: Update matrix transforms
Vicki Pfau vi@endrift.com
Tue, 28 Feb 2017 13:05:25 -0800
commit

9ad56b1b798d1df66eaab8b7099aac4f07d11ac0

parent

0d5a15380be36553925d8903adffd7be960e0d4f

4 files changed, 69 insertions(+), 52 deletions(-)

jump to
M include/mgba/internal/ds/gx.hinclude/mgba/internal/ds/gx.h

@@ -153,7 +153,14 @@ struct DSGXMatrix texMatrix;

struct DSGXMatrix posMatrix; struct DSGXMatrix vecMatrix; - struct DSGXMatrix vertexMatrix; + struct DSGXMatrix clipMatrix; + + int viewportX1; + int viewportY1; + int viewportX2; + int viewportY2; + int viewportWidth; + int viewportHeight; int vertexMode; struct DSGXVertex currentVertex;
M include/mgba/internal/ds/matrix.hinclude/mgba/internal/ds/matrix.h

@@ -17,7 +17,7 @@ int32_t m[16]; // 20.12

}; void DSGXMtxIdentity(struct DSGXMatrix*); -void DSGXMtxMultiply(struct DSGXMatrix*, const struct DSGXMatrix*); +void DSGXMtxMultiply(struct DSGXMatrix*, const struct DSGXMatrix*, const struct DSGXMatrix*); void DSGXMtxScale(struct DSGXMatrix*, const int32_t* m); void DSGXMtxTranslate(struct DSGXMatrix*, const int32_t* m);
M src/ds/gx.csrc/ds/gx.c

@@ -136,9 +136,8 @@ CircleBufferWrite8(&gx->pipe, entry.params[3]);

} } -static void _updateVertexMatrix(struct DSGX* gx) { - memcpy(&gx->vertexMatrix, &gx->projMatrix, sizeof(gx->vertexMatrix)); - DSGXMtxMultiply(&gx->vertexMatrix, &gx->posMatrix); +static void _updateClipMatrix(struct DSGX* gx) { + DSGXMtxMultiply(&gx->clipMatrix, &gx->projMatrix, &gx->posMatrix); } static int32_t _dotViewport(struct DSGXVertex* vertex, int32_t* col) {

@@ -167,10 +166,13 @@ }

gx->currentVertex.x = x; gx->currentVertex.y = y; gx->currentVertex.z = z; - gx->currentVertex.vx = _dotViewport(&gx->currentVertex, &gx->vertexMatrix.m[0]); - gx->currentVertex.vy = _dotViewport(&gx->currentVertex, &gx->vertexMatrix.m[1]); - gx->currentVertex.vz = _dotViewport(&gx->currentVertex, &gx->vertexMatrix.m[2]); - gx->currentVertex.vw = _dotViewport(&gx->currentVertex, &gx->vertexMatrix.m[3]); + gx->currentVertex.vx = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[0]); + gx->currentVertex.vy = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[1]); + gx->currentVertex.vz = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[2]); + gx->currentVertex.vw = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[3]); + + gx->currentVertex.vx = (gx->currentVertex.vx + gx->currentVertex.vw) * gx->viewportWidth / (gx->currentVertex.vw * 2) + gx->viewportX1; + gx->currentVertex.vy = (gx->currentVertex.vy + gx->currentVertex.vw) * gx->viewportHeight / (gx->currentVertex.vw * 2) + gx->viewportY1; struct DSGXVertex* vbuf = gx->vertexBuffer[gx->bufferIndex]; vbuf[gx->vertexIndex] = gx->currentVertex;

@@ -240,7 +242,7 @@ cycles = _gxCommandCycleBase[entry.command];

if (first) { first = false; - } else if (cycles > cyclesLate) { + } else if (!gx->activeParams && cycles > cyclesLate) { break; } CircleBufferRead8(&gx->pipe, (int8_t*) &entry.command);

@@ -292,7 +294,7 @@ case 3:

mLOG(DS_GX, STUB, "Unimplemented GX MTX_PUSH mode"); break; } - _updateVertexMatrix(gx); + _updateClipMatrix(gx); break; case DS_GX_CMD_MTX_POP: { int8_t offset = entry.params[0];

@@ -316,7 +318,7 @@ case 3:

mLOG(DS_GX, STUB, "Unimplemented GX MTX_POP mode"); break; } - _updateVertexMatrix(gx); + _updateClipMatrix(gx); break; } case DS_GX_CMD_MTX_IDENTITY:

@@ -334,7 +336,7 @@ case 3:

DSGXMtxIdentity(&gx->texMatrix); break; } - _updateVertexMatrix(gx); + _updateClipMatrix(gx); break; case DS_GX_CMD_MTX_LOAD_4x4: { struct DSGXMatrix m;

@@ -359,7 +361,7 @@ case 3:

memcpy(&gx->texMatrix, &m, sizeof(gx->texMatrix)); break; } - _updateVertexMatrix(gx); + _updateClipMatrix(gx); break; } case DS_GX_CMD_MTX_LOAD_4x3: {

@@ -389,7 +391,7 @@ case 3:

memcpy(&gx->texMatrix, &m, sizeof(gx->texMatrix)); break; } - _updateVertexMatrix(gx); + _updateClipMatrix(gx); break; } case DS_GX_CMD_MTX_MULT_4x4: {

@@ -403,19 +405,19 @@ m.m[i] |= gx->activeEntries[i].params[3] << 24;

} switch (gx->mtxMode) { case 0: - DSGXMtxMultiply(&gx->projMatrix, &m); + DSGXMtxMultiply(&gx->projMatrix, &m, &gx->projMatrix); break; case 2: - DSGXMtxMultiply(&gx->vecMatrix, &m); + DSGXMtxMultiply(&gx->vecMatrix, &m, &gx->vecMatrix); // Fall through case 1: - DSGXMtxMultiply(&gx->posMatrix, &m); + DSGXMtxMultiply(&gx->posMatrix, &m, &gx->posMatrix); break; case 3: - DSGXMtxMultiply(&gx->texMatrix, &m); + DSGXMtxMultiply(&gx->texMatrix, &m, &gx->texMatrix); break; } - _updateVertexMatrix(gx); + _updateClipMatrix(gx); break; } case DS_GX_CMD_MTX_MULT_4x3: {

@@ -433,19 +435,19 @@ }

m.m[15] = MTX_ONE; switch (gx->mtxMode) { case 0: - DSGXMtxMultiply(&gx->projMatrix, &m); + DSGXMtxMultiply(&gx->projMatrix, &m, &gx->projMatrix); break; case 2: - DSGXMtxMultiply(&gx->vecMatrix, &m); + DSGXMtxMultiply(&gx->vecMatrix, &m, &gx->vecMatrix); // Fall through case 1: - DSGXMtxMultiply(&gx->posMatrix, &m); + DSGXMtxMultiply(&gx->posMatrix, &m, &gx->posMatrix); break; case 3: - DSGXMtxMultiply(&gx->texMatrix, &m); + DSGXMtxMultiply(&gx->texMatrix, &m, &gx->texMatrix); break; } - _updateVertexMatrix(gx); + _updateClipMatrix(gx); break; } case DS_GX_CMD_MTX_MULT_3x3: {

@@ -466,19 +468,19 @@ m.m[14] = 0;

m.m[15] = MTX_ONE; switch (gx->mtxMode) { case 0: - memcpy(&gx->projMatrix, &m, sizeof(gx->projMatrix)); + DSGXMtxMultiply(&gx->projMatrix, &m, &gx->projMatrix); break; case 2: - memcpy(&gx->vecMatrix, &m, sizeof(gx->vecMatrix)); + DSGXMtxMultiply(&gx->vecMatrix, &m, &gx->vecMatrix); // Fall through case 1: - memcpy(&gx->posMatrix, &m, sizeof(gx->posMatrix)); + DSGXMtxMultiply(&gx->posMatrix, &m, &gx->posMatrix); break; case 3: - memcpy(&gx->texMatrix, &m, sizeof(gx->projMatrix)); + DSGXMtxMultiply(&gx->texMatrix, &m, &gx->texMatrix); break; } - _updateVertexMatrix(gx); + _updateClipMatrix(gx); break; } case DS_GX_CMD_MTX_TRANS: {

@@ -666,7 +668,7 @@ DSGXMtxIdentity(&gx->texMatrix);

DSGXMtxIdentity(&gx->posMatrix); DSGXMtxIdentity(&gx->vecMatrix); - DSGXMtxIdentity(&gx->vertexMatrix); + DSGXMtxIdentity(&gx->clipMatrix); DSGXMtxIdentity(&gx->projMatrixStack); DSGXMtxIdentity(&gx->texMatrixStack); int i;

@@ -681,6 +683,13 @@ gx->polygonIndex = 0;

gx->mtxMode = 0; gx->pvMatrixPointer = 0; gx->vertexMode = -1; + + gx->viewportX1 = 0; + gx->viewportY1 = 0; + gx->viewportX2 = DS_VIDEO_HORIZONTAL_PIXELS - 1; + gx->viewportY2 = DS_VIDEO_VERTICAL_PIXELS - 1; + gx->viewportWidth = gx->viewportX2 - gx->viewportX1; + gx->viewportHeight = gx->viewportY2 - gx->viewportY1; memset(gx->outstandingParams, 0, sizeof(gx->outstandingParams)); memset(gx->outstandingCommand, 0, sizeof(gx->outstandingCommand));
M src/ds/matrix.csrc/ds/matrix.c

@@ -32,25 +32,26 @@ mtx->m[10] = MTX_ONE;

mtx->m[15] = MTX_ONE; } -void DSGXMtxMultiply(struct DSGXMatrix* mtx, const struct DSGXMatrix* m) { - struct DSGXMatrix out; - out.m[0] = _dot(&mtx->m[0], &m->m[0]); - out.m[1] = _dot(&mtx->m[1], &m->m[0]); - out.m[2] = _dot(&mtx->m[2], &m->m[0]); - out.m[3] = _dot(&mtx->m[3], &m->m[0]); - out.m[4] = _dot(&mtx->m[0], &m->m[4]); - out.m[5] = _dot(&mtx->m[1], &m->m[4]); - out.m[6] = _dot(&mtx->m[2], &m->m[4]); - out.m[7] = _dot(&mtx->m[3], &m->m[4]); - out.m[8] = _dot(&mtx->m[0], &m->m[8]); - out.m[9] = _dot(&mtx->m[1], &m->m[8]); - out.m[10] = _dot(&mtx->m[2], &m->m[8]); - out.m[11] = _dot(&mtx->m[3], &m->m[8]); - out.m[12] = _dot(&mtx->m[0], &m->m[12]); - out.m[13] = _dot(&mtx->m[1], &m->m[12]); - out.m[14] = _dot(&mtx->m[2], &m->m[12]); - out.m[15] = _dot(&mtx->m[3], &m->m[12]); - *mtx = out; +void DSGXMtxMultiply(struct DSGXMatrix* out, const struct DSGXMatrix* a, const struct DSGXMatrix* b) { + struct DSGXMatrix o; + // XXX: This is transposed because DS matrices are transposed + o.m[0] = _dot(&a->m[0], &b->m[0]); + o.m[1] = _dot(&a->m[1], &b->m[0]); + o.m[2] = _dot(&a->m[2], &b->m[0]); + o.m[3] = _dot(&a->m[3], &b->m[0]); + o.m[4] = _dot(&a->m[0], &b->m[4]); + o.m[5] = _dot(&a->m[1], &b->m[4]); + o.m[6] = _dot(&a->m[2], &b->m[4]); + o.m[7] = _dot(&a->m[3], &b->m[4]); + o.m[8] = _dot(&a->m[0], &b->m[8]); + o.m[9] = _dot(&a->m[1], &b->m[8]); + o.m[10] = _dot(&a->m[2], &b->m[8]); + o.m[11] = _dot(&a->m[3], &b->m[8]); + o.m[12] = _dot(&a->m[0], &b->m[12]); + o.m[13] = _dot(&a->m[1], &b->m[12]); + o.m[14] = _dot(&a->m[2], &b->m[12]); + o.m[15] = _dot(&a->m[3], &b->m[12]); + *out = o; } void DSGXMtxScale(struct DSGXMatrix* mtx, const int32_t* m) {

@@ -62,7 +63,7 @@ 0, 0, m[2], 0,

0, 0, 0, MTX_ONE } }; - DSGXMtxMultiply(mtx, &s); + DSGXMtxMultiply(mtx, &s, mtx); } void DSGXMtxTranslate(struct DSGXMatrix* mtx, const int32_t* m) {

@@ -74,5 +75,5 @@ 0, 0, MTX_ONE, 0,

m[0], m[1], m[2], MTX_ONE } }; - DSGXMtxMultiply(mtx, &t); + DSGXMtxMultiply(mtx, &t, mtx); }