DS GX: Add additional matrix operations

This commit is contained in:
Vicki Pfau 2017-02-27 19:02:24 -08:00
parent 64034e387f
commit 1bc3170755
3 changed files with 284 additions and 17 deletions

View File

@ -10,11 +10,16 @@
CXX_GUARD_START
#define MTX_ONE 0x00001000
struct DSGXMatrix {
int32_t m[16]; // 20.12
};
void DSGXMtxIdentity(struct DSGXMatrix*);
void DSGXMtxMultiply(struct DSGXMatrix*, const struct DSGXMatrix*);
void DSGXMtxScale(struct DSGXMatrix*, const int32_t* m);
void DSGXMtxTranslate(struct DSGXMatrix*, const int32_t* m);
CXX_GUARD_END

View File

@ -194,22 +194,6 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate)
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:
@ -252,6 +236,222 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate)
}
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_LOAD_4x4: {
struct DSGXMatrix m;
int i;
for (i = 0; i < 16; ++i) {
m.m[i] = gx->activeEntries[i].params[0];
m.m[i] |= gx->activeEntries[i].params[1] << 8;
m.m[i] |= gx->activeEntries[i].params[2] << 16;
m.m[i] |= gx->activeEntries[i].params[3] << 24;
}
switch (gx->mtxMode) {
case 0:
memcpy(&gx->projMatrix, &m, sizeof(gx->projMatrix));
break;
case 2:
memcpy(&gx->vecMatrix, &m, sizeof(gx->vecMatrix));
// Fall through
case 1:
memcpy(&gx->posMatrix, &m, sizeof(gx->posMatrix));
break;
case 3:
memcpy(&gx->texMatrix, &m, sizeof(gx->texMatrix));
break;
}
break;
}
case DS_GX_CMD_MTX_LOAD_4x3: {
struct DSGXMatrix m;
int i, j;
for (j = 0; j < 4; ++j) {
for (i = 0; i < 3; ++i) {
m.m[i + j * 4] = gx->activeEntries[i + j * 3].params[0];
m.m[i + j * 4] |= gx->activeEntries[i + j * 3].params[1] << 8;
m.m[i + j * 4] |= gx->activeEntries[i + j * 3].params[2] << 16;
m.m[i + j * 4] |= gx->activeEntries[i + j * 3].params[3] << 24;
}
m.m[j * 4 + 3] = 0;
}
m.m[15] = MTX_ONE;
switch (gx->mtxMode) {
case 0:
memcpy(&gx->projMatrix, &m, sizeof(gx->projMatrix));
break;
case 2:
memcpy(&gx->vecMatrix, &m, sizeof(gx->vecMatrix));
// Fall through
case 1:
memcpy(&gx->posMatrix, &m, sizeof(gx->posMatrix));
break;
case 3:
memcpy(&gx->texMatrix, &m, sizeof(gx->texMatrix));
break;
}
break;
}
case DS_GX_CMD_MTX_MULT_4x4: {
struct DSGXMatrix m;
int i;
for (i = 0; i < 16; ++i) {
m.m[i] = gx->activeEntries[i].params[0];
m.m[i] |= gx->activeEntries[i].params[1] << 8;
m.m[i] |= gx->activeEntries[i].params[2] << 16;
m.m[i] |= gx->activeEntries[i].params[3] << 24;
}
switch (gx->mtxMode) {
case 0:
DSGXMtxMultiply(&gx->projMatrix, &m);
break;
case 2:
DSGXMtxMultiply(&gx->vecMatrix, &m);
// Fall through
case 1:
DSGXMtxMultiply(&gx->posMatrix, &m);
break;
case 3:
DSGXMtxMultiply(&gx->texMatrix, &m);
break;
}
break;
}
case DS_GX_CMD_MTX_MULT_4x3: {
struct DSGXMatrix m;
int i, j;
for (j = 0; j < 4; ++j) {
for (i = 0; i < 3; ++i) {
m.m[i + j * 4] = gx->activeEntries[i + j * 3].params[0];
m.m[i + j * 4] |= gx->activeEntries[i + j * 3].params[1] << 8;
m.m[i + j * 4] |= gx->activeEntries[i + j * 3].params[2] << 16;
m.m[i + j * 4] |= gx->activeEntries[i + j * 3].params[3] << 24;
}
m.m[j * 4 + 3] = 0;
}
m.m[15] = MTX_ONE;
switch (gx->mtxMode) {
case 0:
DSGXMtxMultiply(&gx->projMatrix, &m);
break;
case 2:
DSGXMtxMultiply(&gx->vecMatrix, &m);
// Fall through
case 1:
DSGXMtxMultiply(&gx->posMatrix, &m);
break;
case 3:
DSGXMtxMultiply(&gx->texMatrix, &m);
break;
}
break;
}
case DS_GX_CMD_MTX_MULT_3x3: {
struct DSGXMatrix m;
int i, j;
for (j = 0; j < 3; ++j) {
for (i = 0; i < 3; ++i) {
m.m[i + j * 4] = gx->activeEntries[i + j * 3].params[0];
m.m[i + j * 4] |= gx->activeEntries[i + j * 3].params[1] << 8;
m.m[i + j * 4] |= gx->activeEntries[i + j * 3].params[2] << 16;
m.m[i + j * 4] |= gx->activeEntries[i + j * 3].params[3] << 24;
}
m.m[j * 4 + 3] = 0;
}
m.m[12] = 0;
m.m[13] = 0;
m.m[14] = 0;
m.m[15] = MTX_ONE;
switch (gx->mtxMode) {
case 0:
memcpy(&gx->projMatrix, &m, sizeof(gx->projMatrix));
break;
case 2:
memcpy(&gx->vecMatrix, &m, sizeof(gx->vecMatrix));
// Fall through
case 1:
memcpy(&gx->posMatrix, &m, sizeof(gx->posMatrix));
break;
case 3:
memcpy(&gx->texMatrix, &m, sizeof(gx->projMatrix));
break;
}
break;
}
case DS_GX_CMD_MTX_TRANS: {
int32_t m[3];
m[0] = gx->activeEntries[0].params[0];
m[0] |= gx->activeEntries[0].params[1] << 8;
m[0] |= gx->activeEntries[0].params[2] << 16;
m[0] |= gx->activeEntries[0].params[3] << 24;
m[1] = gx->activeEntries[1].params[0];
m[1] |= gx->activeEntries[1].params[1] << 8;
m[1] |= gx->activeEntries[1].params[2] << 16;
m[1] |= gx->activeEntries[1].params[3] << 24;
m[2] = gx->activeEntries[2].params[0];
m[2] |= gx->activeEntries[2].params[1] << 8;
m[2] |= gx->activeEntries[2].params[2] << 16;
m[2] |= gx->activeEntries[2].params[3] << 24;
switch (gx->mtxMode) {
case 0:
DSGXMtxTranslate(&gx->projMatrix, m);
break;
case 2:
DSGXMtxTranslate(&gx->vecMatrix, m);
// Fall through
case 1:
DSGXMtxTranslate(&gx->posMatrix, m);
break;
case 3:
DSGXMtxTranslate(&gx->texMatrix, m);
break;
}
break;
}
case DS_GX_CMD_MTX_SCALE: {
int32_t m[3];
m[0] = gx->activeEntries[0].params[0];
m[0] |= gx->activeEntries[0].params[1] << 8;
m[0] |= gx->activeEntries[0].params[2] << 16;
m[0] |= gx->activeEntries[0].params[3] << 24;
m[1] = gx->activeEntries[1].params[0];
m[1] |= gx->activeEntries[1].params[1] << 8;
m[1] |= gx->activeEntries[1].params[2] << 16;
m[1] |= gx->activeEntries[1].params[3] << 24;
m[2] = gx->activeEntries[2].params[0];
m[2] |= gx->activeEntries[2].params[1] << 8;
m[2] |= gx->activeEntries[2].params[2] << 16;
m[2] |= gx->activeEntries[2].params[3] << 24;
switch (gx->mtxMode) {
case 0:
DSGXMtxScale(&gx->projMatrix, m);
break;
case 2:
DSGXMtxScale(&gx->vecMatrix, m);
// Fall through
case 1:
DSGXMtxScale(&gx->posMatrix, m);
break;
case 3:
DSGXMtxScale(&gx->texMatrix, m);
break;
}
break;
}
case DS_GX_CMD_SWAP_BUFFERS:
gx->swapBuffers = true;
break;

View File

@ -5,7 +5,24 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <mgba/internal/ds/matrix.h>
#define MTX_ONE 0x00001000
static int32_t _dot(const int32_t* col, const int32_t* row) {
int64_t a;
int64_t b;
int64_t sum;
a = col[0];
b = row[0];
sum = a * b;
a = col[4];
b = row[1];
sum += a * b;
a = col[8];
b = row[2];
sum += a * b;
a = col[12];
b = row[3];
sum += a * b;
return sum >> 12LL;
}
void DSGXMtxIdentity(struct DSGXMatrix* mtx) {
memset(mtx, 0, sizeof(*mtx));
@ -14,3 +31,48 @@ void DSGXMtxIdentity(struct DSGXMatrix* mtx) {
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 DSGXMtxScale(struct DSGXMatrix* mtx, const int32_t* m) {
struct DSGXMatrix s = {
.m = {
m[0], 0, 0, 0,
0, m[1], 0, 0,
0, 0, m[2], 0,
0, 0, 0, MTX_ONE
}
};
DSGXMtxMultiply(mtx, &s);
}
void DSGXMtxTranslate(struct DSGXMatrix* mtx, const int32_t* m) {
struct DSGXMatrix t = {
.m = {
MTX_ONE, 0, 0, 0,
0, MTX_ONE, 0, 0,
0, 0, MTX_ONE, 0,
m[0], m[1], m[2], MTX_ONE
}
};
DSGXMtxMultiply(mtx, &t);
}