diff --git a/CHANGES b/CHANGES index 139ed6443..c8e390b8c 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,7 @@ Features: - DS GX: Toon shading - DS GX: Clear depth - DS GX: Position test + - DS GX: Vector result Bugfixes: - DS GX: Fix vertex texture transformation (fixes mgba.io/i/702) - DS GX: Automatically normalize winding culling calculations (fixes mgba.io/i/699) diff --git a/include/mgba/internal/ds/io.h b/include/mgba/internal/ds/io.h index f4c5b7121..8355e8cfe 100644 --- a/include/mgba/internal/ds/io.h +++ b/include/mgba/internal/ds/io.h @@ -555,7 +555,6 @@ enum DS9IORegisters { DS9_REG_VECMTX_RESULT_0F = 0x69E, DS9_REG_VECMTX_RESULT_10 = 0x6A0, DS9_REG_VECMTX_RESULT_11 = 0x6A2, - DS9_REG_VECMTX_RESULT_12 = 0x6A4, DS9_REG_MAX = 0x106E, diff --git a/src/ds/gx.c b/src/ds/gx.c index c1d7c1392..4ac267600 100644 --- a/src/ds/gx.c +++ b/src/ds/gx.c @@ -162,6 +162,27 @@ static void _updateClipMatrix(struct DSGX* gx) { gx->p->memory.io9[DS9_REG_CLIPMTX_RESULT_1F >> 1] = gx->clipMatrix.m[15] >> 16; } +static void _updateVecMatrix(struct DSGX* gx) { + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_00 >> 1] = gx->vecMatrix.m[0]; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_01 >> 1] = gx->vecMatrix.m[0] >> 16; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_02 >> 1] = gx->vecMatrix.m[1]; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_03 >> 1] = gx->vecMatrix.m[1] >> 16; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_04 >> 1] = gx->vecMatrix.m[2]; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_05 >> 1] = gx->vecMatrix.m[2] >> 16; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_06 >> 1] = gx->vecMatrix.m[4]; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_07 >> 1] = gx->vecMatrix.m[4] >> 16; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_08 >> 1] = gx->vecMatrix.m[5]; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_09 >> 1] = gx->vecMatrix.m[5] >> 16; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_0A >> 1] = gx->vecMatrix.m[6]; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_0B >> 1] = gx->vecMatrix.m[6] >> 16; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_0C >> 1] = gx->vecMatrix.m[8]; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_0D >> 1] = gx->vecMatrix.m[8] >> 16; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_0E >> 1] = gx->vecMatrix.m[9]; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_0F >> 1] = gx->vecMatrix.m[9] >> 16; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_10 >> 1] = gx->vecMatrix.m[10]; + gx->p->memory.io9[DS9_REG_VECMTX_RESULT_11 >> 1] = gx->vecMatrix.m[10] >> 16; +} + static inline int32_t _lerp(int32_t x0, int32_t x1, int32_t q, int64_t r) { int64_t x = x1 - x0; x *= q; @@ -743,6 +764,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) gx->pvMatrixPointer -= offset; memcpy(&gx->vecMatrix, &gx->vecMatrixStack[gx->pvMatrixPointer & 0x1F], sizeof(gx->vecMatrix)); memcpy(&gx->posMatrix, &gx->posMatrixStack[gx->pvMatrixPointer & 0x1F], sizeof(gx->posMatrix)); + _updateVecMatrix(gx); break; case 3: mLOG(DS_GX, STUB, "Unimplemented GX MTX_POP mode"); @@ -780,6 +802,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) case 2: memcpy(&gx->vecMatrix, &gx->vecMatrixStack[offset], sizeof(gx->vecMatrix)); memcpy(&gx->posMatrix, &gx->posMatrixStack[offset], sizeof(gx->posMatrix)); + _updateVecMatrix(gx); break; case 3: mLOG(DS_GX, STUB, "Unimplemented GX MTX_RESTORE mode"); @@ -795,6 +818,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) break; case 2: DSGXMtxIdentity(&gx->vecMatrix); + _updateVecMatrix(gx); // Fall through case 1: DSGXMtxIdentity(&gx->posMatrix); @@ -820,6 +844,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) break; case 2: memcpy(&gx->vecMatrix, &m, sizeof(gx->vecMatrix)); + _updateVecMatrix(gx); // Fall through case 1: memcpy(&gx->posMatrix, &m, sizeof(gx->posMatrix)); @@ -850,6 +875,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) break; case 2: memcpy(&gx->vecMatrix, &m, sizeof(gx->vecMatrix)); + _updateVecMatrix(gx); // Fall through case 1: memcpy(&gx->posMatrix, &m, sizeof(gx->posMatrix)); @@ -876,6 +902,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) break; case 2: DSGXMtxMultiply(&gx->vecMatrix, &m, &gx->vecMatrix); + _updateVecMatrix(gx); // Fall through case 1: DSGXMtxMultiply(&gx->posMatrix, &m, &gx->posMatrix); @@ -906,6 +933,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) break; case 2: DSGXMtxMultiply(&gx->vecMatrix, &m, &gx->vecMatrix); + _updateVecMatrix(gx); // Fall through case 1: DSGXMtxMultiply(&gx->posMatrix, &m, &gx->posMatrix); @@ -939,6 +967,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) break; case 2: DSGXMtxMultiply(&gx->vecMatrix, &m, &gx->vecMatrix); + _updateVecMatrix(gx); // Fall through case 1: DSGXMtxMultiply(&gx->posMatrix, &m, &gx->posMatrix); @@ -970,6 +999,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) break; case 2: DSGXMtxTranslate(&gx->vecMatrix, m); + _updateVecMatrix(gx); // Fall through case 1: DSGXMtxTranslate(&gx->posMatrix, m); diff --git a/src/ds/io.c b/src/ds/io.c index 4c44a0461..b58ec3216 100644 --- a/src/ds/io.c +++ b/src/ds/io.c @@ -604,7 +604,7 @@ void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) { value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value); } else if ((address >= DS9_REG_B_DISPCNT_LO && address <= DS9_REG_B_BLDY) || address == DS9_REG_B_MASTER_BRIGHT) { value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value); - } else if ((address >= DS9_REG_RDLINES_COUNT && address <= DS9_REG_VECMTX_RESULT_12) || address == DS9_REG_DISP3DCNT) { + } else if ((address >= DS9_REG_RDLINES_COUNT && address <= DS9_REG_VECMTX_RESULT_11) || address == DS9_REG_DISP3DCNT) { value = DSGXWriteRegister(&ds->gx, address, value); } else { uint16_t oldValue; @@ -719,7 +719,7 @@ void DS9IOWrite8(struct DS* ds, uint32_t address, uint8_t value) { } void DS9IOWrite32(struct DS* ds, uint32_t address, uint32_t value) { - if ((address >= DS9_REG_RDLINES_COUNT && address <= DS9_REG_VECMTX_RESULT_12) || address == DS9_REG_DISP3DCNT) { + if ((address >= DS9_REG_RDLINES_COUNT && address <= DS9_REG_VECMTX_RESULT_11) || address == DS9_REG_DISP3DCNT) { value = DSGXWriteRegister32(&ds->gx, address, value); } else { switch (address) { @@ -900,6 +900,24 @@ uint16_t DS9IORead(struct DS* ds, uint32_t address) { case DS9_REG_CLIPMTX_RESULT_1D: case DS9_REG_CLIPMTX_RESULT_1E: case DS9_REG_CLIPMTX_RESULT_1F: + case DS9_REG_VECMTX_RESULT_00: + case DS9_REG_VECMTX_RESULT_01: + case DS9_REG_VECMTX_RESULT_02: + case DS9_REG_VECMTX_RESULT_03: + case DS9_REG_VECMTX_RESULT_04: + case DS9_REG_VECMTX_RESULT_05: + case DS9_REG_VECMTX_RESULT_06: + case DS9_REG_VECMTX_RESULT_07: + case DS9_REG_VECMTX_RESULT_08: + case DS9_REG_VECMTX_RESULT_09: + case DS9_REG_VECMTX_RESULT_0A: + case DS9_REG_VECMTX_RESULT_0B: + case DS9_REG_VECMTX_RESULT_0C: + case DS9_REG_VECMTX_RESULT_0D: + case DS9_REG_VECMTX_RESULT_0E: + case DS9_REG_VECMTX_RESULT_0F: + case DS9_REG_VECMTX_RESULT_10: + case DS9_REG_VECMTX_RESULT_11: case DS9_REG_B_BG0CNT: case DS9_REG_B_BG1CNT: case DS9_REG_B_BG2CNT: