all repos — mgba @ 1743dd24b8fee1c76c0e32e588521f5786231e11

mGBA Game Boy Advance Emulator

DS GX: Start setting up lighting parameters
Vicki Pfau vi@endrift.com
Fri, 17 Mar 2017 16:35:02 -0700
commit

1743dd24b8fee1c76c0e32e588521f5786231e11

parent

8b276c92626eea35438f2e83fdeab75a75120f20

2 files changed, 82 insertions(+), 10 deletions(-)

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

@@ -155,6 +155,13 @@ int viewportWidth;

int viewportHeight; }; +struct DSGXLight { + int16_t color; + int16_t x; + int16_t y; + int16_t z; +}; + struct DS; struct DSGX { struct DS* p;

@@ -200,6 +207,12 @@ struct DSGXMatrix posMatrix;

struct DSGXMatrix vecMatrix; struct DSGXMatrix clipMatrix; + + struct DSGXLight lights[4]; + int16_t diffuse; + int16_t ambient; + int16_t specular; + int16_t emit; int viewportX1; int viewportY1;
M src/ds/gx.csrc/ds/gx.c

@@ -687,6 +687,25 @@ }

return sum >> 20; } +static int32_t _dotFrac(int16_t x, int16_t y, int16_t z, int32_t* col) { + int64_t a; + int64_t b; + int64_t sum; + a = col[0]; + b = x; + sum = a * b; + a = col[4]; + b = y; + sum += a * b; + a = col[8]; + b = z; + sum += a * b; + a = col[12]; + b = MTX_ONE; + sum += a * b; + return sum >> 12; +} + static void _emitVertex(struct DSGX* gx, uint16_t x, uint16_t y, uint16_t z) { if (gx->vertexMode < 0 || gx->vertexIndex == DS_GX_VERTEX_BUFFER_SIZE || gx->polygonIndex == DS_GX_POLYGON_BUFFER_SIZE) { return;

@@ -699,20 +718,18 @@ 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]); - if (DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams) > 0) { + if (DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams) == 0) { + gx->currentVertex.vs = gx->currentVertex.s; + gx->currentVertex.vt = gx->currentVertex.t; + } else if (DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams) == 3) { int32_t m12 = gx->texMatrix.m[12]; int32_t m13 = gx->texMatrix.m[13]; - if (DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams) > 1) { - gx->texMatrix.m[12] = gx->currentVertex.vs; - gx->texMatrix.m[13] = gx->currentVertex.vt; - } - gx->currentVertex.vs = _dotTexture(&gx->currentVertex, DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams), &gx->texMatrix.m[0]); - gx->currentVertex.vt = _dotTexture(&gx->currentVertex, DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams), &gx->texMatrix.m[1]); + gx->texMatrix.m[12] = gx->currentVertex.vs; + gx->texMatrix.m[13] = gx->currentVertex.vt; + gx->currentVertex.vs = _dotTexture(&gx->currentVertex, 3, &gx->texMatrix.m[0]); + gx->currentVertex.vt = _dotTexture(&gx->currentVertex, 3, &gx->texMatrix.m[1]); gx->texMatrix.m[12] = m12; gx->texMatrix.m[13] = m13; - } else { - gx->currentVertex.vs = gx->currentVertex.s; - gx->currentVertex.vt = gx->currentVertex.t; } gx->pendingVertices[gx->pendingVertexIndex] = gx->currentVertex;

@@ -1255,6 +1272,10 @@ gx->currentVertex.s = entry.params[0];

gx->currentVertex.s |= entry.params[1] << 8; gx->currentVertex.t = entry.params[2]; gx->currentVertex.t |= entry.params[3] << 8; + if (DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams) == 1) { + gx->currentVertex.vs = _dotTexture(&gx->currentVertex, 1, &gx->texMatrix.m[0]); + gx->currentVertex.vt = _dotTexture(&gx->currentVertex, 1, &gx->texMatrix.m[1]); + } break; case DS_GX_CMD_VTX_16: { int16_t x = gx->activeEntries[0].params[0];

@@ -1310,6 +1331,44 @@ int16_t x = (xyz << 6) & 0xFFC0;

int16_t y = (xyz >> 4) & 0xFFC0; int16_t z = (xyz >> 14) & 0xFFC0; _emitVertex(gx, gx->currentVertex.x + (x >> 6), gx->currentVertex.y + (y >> 6), gx->currentVertex.z + (z >> 6)); + break; + } + case DS_GX_CMD_DIF_AMB: + gx->diffuse = entry.params[0]; + gx->diffuse |= entry.params[1] << 8; + if (gx->diffuse & 0x8000) { + gx->currentVertex.color = gx->diffuse; + } + gx->ambient = entry.params[2]; + gx->ambient |= entry.params[3] << 8; + break; + case DS_GX_CMD_SPE_EMI: + gx->specular = entry.params[0]; + gx->specular |= entry.params[1] << 8; + gx->emit = entry.params[2]; + gx->emit |= entry.params[3] << 8; + break; + case DS_GX_CMD_LIGHT_VECTOR: { + uint32_t xyz = entry.params[0]; + xyz |= entry.params[1] << 8; + xyz |= entry.params[2] << 16; + xyz |= entry.params[3] << 24; + struct DSGXLight* light = &gx->lights[xyz >> 30]; + int16_t x = (xyz << 6) & 0xFFC0; + int16_t y = (xyz >> 4) & 0xFFC0; + int16_t z = (xyz >> 14) & 0xFFC0; + light->x = x >> 6; + light->y = y >> 6; + light->z = z >> 6; + light->x = _dotFrac(x, y, z, &gx->vecMatrix.m[0]) << 22 >> 22; + light->y = _dotFrac(x, y, z, &gx->vecMatrix.m[1]) << 22 >> 22; + light->z = _dotFrac(x, y, z, &gx->vecMatrix.m[2]) << 22 >> 22; + break; + } + case DS_GX_CMD_LIGHT_COLOR: { + struct DSGXLight* light = &gx->lights[entry.params[3] >> 6]; + light->color = entry.params[0]; + light->color |= entry.params[1] << 8; break; } case DS_GX_CMD_POLYGON_ATTR: