diff --git a/include/dolphin/os/OSFastCast.h b/include/dolphin/os/OSFastCast.h index b6ca50d..25cae66 100644 --- a/include/dolphin/os/OSFastCast.h +++ b/include/dolphin/os/OSFastCast.h @@ -13,12 +13,13 @@ extern "C" { #define OS_FASTCAST_U8 2 #define OS_FASTCAST_U16 3 +#define OS_FASTCAST_S8 4 #define OS_FASTCAST_S16 5 -// clang-format off + static inline void OSInitFastCast(void) { #ifdef __MWERKS__ - asm - { + // clang-format off + asm { li r3, OS_GQR_U8 oris r3, r3, OS_GQR_U8 mtspr GQR2, r3 @@ -34,12 +35,160 @@ static inline void OSInitFastCast(void) { li r3, OS_GQR_S16 oris r3, r3, OS_GQR_S16 mtspr GQR5, r3 - } -#else - + } + // clang-format off #endif } -// clang-format off + +static inline f32 __OSu8tof32(register u8* arg) { + register f32 ret; + +#ifdef __MWERKS__ + // clang-format off + asm { + psq_l ret, 0(arg), 1, OS_FASTCAST_U8 + } + // clang-format on +#else + ret = (f32)*arg; +#endif + + return ret; +} + +static inline f32 __OSu16tof32(register u16* arg) { + register f32 ret; + +#ifdef __MWERKS__ + // clang-format off + asm { + psq_l ret, 0(arg), 1, OS_FASTCAST_U16 + } + // clang-format on +#else + ret = (f32)*arg; +#endif + + return ret; +} + +static inline f32 __OSs8tof32(register s8* arg) { + register f32 ret; + +#ifdef __MWERKS__ + // clang-format off + asm { + psq_l ret, 0(arg), 1, OS_FASTCAST_S8 + } + // clang-format on +#else + ret = (f32)*arg; +#endif + + return ret; +} + +static inline f32 __OSs16tof32(register s16* arg) { + register f32 ret; + +#ifdef __MWERKS__ + // clang-format off + asm { + psq_l ret, 0(arg), 1, OS_FASTCAST_S16 + } + // clang-format on +#else + ret = (f32)*arg; +#endif + + return ret; +} + +static inline void OSu8tof32(u8* in, f32* out) { *out = __OSu8tof32(in); } +static inline void OSu16tof32(u16* in, f32* out) { *out = __OSu16tof32(in); } +static inline void OSs8tof32(s8* in, f32* out) { *out = __OSs8tof32(in); } +static inline void OSs16tof32(s16* in, f32* out) { *out = __OSs16tof32(in); } + +static inline u8 __OSf32tou8(register f32 arg) { + f32 a; + register f32* ptr = &a; + u8 r; + +#ifdef __MWERKS__ + // clang-format off + asm { + psq_st arg, 0(ptr), 1, OS_FASTCAST_U8 + } + // clang-format on + r = *(u8*)ptr; +#else + r = (u8)arg; +#endif + + return r; +} + +static inline u16 __OSf32tou16(register f32 arg) { + f32 a; + register f32* ptr = &a; + u16 r; + +#ifdef __MWERKS__ + // clang-format off + asm { + psq_st arg, 0(ptr), 1, OS_FASTCAST_U16 + } + // clang-format on + r = *(u16*)ptr; +#else + r = (u16)arg; +#endif + + return r; +} + +static inline s8 __OSf32tos8(register f32 arg) { + f32 a; + register f32* ptr = &a; + s8 r; + +#ifdef __MWERKS__ + // clang-format off + asm { + psq_st arg, 0(ptr), 1, OS_FASTCAST_S8 + } + // clang-format on + r = *(s8*)ptr; +#else + r = (s8)arg; +#endif + + return r; +} + +static inline s16 __OSf32tos16(register f32 arg) { + f32 a; + register f32* ptr = &a; + s16 r; + +#ifdef __MWERKS__ + // clang-format off + asm { + psq_st arg, 0(ptr), 1, OS_FASTCAST_S16 + } + // clang-format on + r = *(s16*)ptr; +#else + r = (s16)arg; +#endif + + return r; +} + +static inline void OSf32tou8(f32* in, u8* out) { *out = __OSf32tou8(*in); } +static inline void OSf32tou16(f32* in, u16* out) { *out = __OSf32tou16(*in); } +static inline void OSf32tos8(f32* in, s8* out) { *out = __OSf32tos8(*in); } +static inline void OSf32tos16(f32* in, s16* out) { *out = __OSf32tos16(*in); } #ifdef __cplusplus } diff --git a/include/emulator/frame.h b/include/emulator/frame.h index c0a471b..357cb19 100644 --- a/include/emulator/frame.h +++ b/include/emulator/frame.h @@ -133,16 +133,16 @@ typedef struct FrameBuffer { } FrameBuffer; // size = 0x14 // __anon_0x274AD -typedef struct Vect3F { +typedef struct Vec3f { /* 0x0 */ f32 x; /* 0x4 */ f32 y; /* 0x8 */ f32 z; -} Vect3F; // size = 0xC +} Vec3f; // size = 0xC // __anon_0x23CAB typedef struct Light { /* 0x00 */ bool bTransformed; - /* 0x04 */ Vect3F rVecOrigTowards; + /* 0x04 */ Vec3f rVecOrigTowards; /* 0x10 */ f32 rColorR; /* 0x14 */ f32 rColorG; /* 0x18 */ f32 rColorB; @@ -160,10 +160,10 @@ typedef struct Light { // __anon_0x23EDB typedef struct LookAt { /* 0x00 */ bool bTransformed; - /* 0x04 */ Vect3F rS; - /* 0x10 */ Vect3F rT; - /* 0x1C */ Vect3F rSRaw; - /* 0x28 */ Vect3F rTRaw; + /* 0x04 */ Vec3f rS; + /* 0x10 */ Vec3f rT; + /* 0x1C */ Vec3f rSRaw; + /* 0x28 */ Vec3f rTRaw; } LookAt; // size = 0x34 // __anon_0x23FC4 @@ -171,7 +171,7 @@ typedef struct Vertex { /* 0x00 */ f32 rSum; /* 0x04 */ f32 rS; /* 0x08 */ f32 rT; - /* 0x0C */ Vect3F vec; + /* 0x0C */ Vec3f vec; /* 0x18 */ u8 anColor[4]; } Vertex; // size = 0x1C diff --git a/include/emulator/rsp.h b/include/emulator/rsp.h index b861473..8ceea86 100644 --- a/include/emulator/rsp.h +++ b/include/emulator/rsp.h @@ -64,7 +64,7 @@ typedef struct __anon_0x575BD { typedef struct __anon_0x57890 { /* 0x00 */ s32 iDL; - /* 0x04 */ s32 bValid; + /* 0x04 */ bool bValid; /* 0x08 */ struct __anon_0x575BD task; /* 0x48 */ s32 nCountVertex; /* 0x4C */ __anon_0x60B3F eTypeUCode; @@ -107,9 +107,9 @@ typedef struct __anon_0x57E56 { /* 0x0 */ u8 nRed; /* 0x1 */ u8 nGreen; /* 0x2 */ u8 nBlue; - /* 0x3 */ char rVectorX; - /* 0x4 */ char rVectorY; - /* 0x5 */ char rVectorZ; + /* 0x3 */ s8 rVectorX; + /* 0x4 */ s8 rVectorY; + /* 0x5 */ s8 rVectorZ; } __anon_0x57E56; // size = 0x6 typedef struct __anon_0x58107 { @@ -215,11 +215,11 @@ typedef struct Rsp { /* 0x39C8 */ s32* dctBuf; } Rsp; // size = 0x39CC -s32 rspInvalidateCache(Rsp* pRSP, s32 nOffset0, s32 nOffset1); -s32 rspEnableABI(Rsp* pRSP, s32 bFlag); -s32 rspFrameComplete(Rsp* pRSP); -s32 rspUpdate(Rsp* pRSP, RspUpdateMode eMode); -s32 rspEvent(Rsp* pRSP, s32 nEvent, void* pArgument); +bool rspInvalidateCache(Rsp* pRSP, s32 nOffset0, s32 nOffset1); +bool rspEnableABI(Rsp* pRSP, bool bFlag); +bool rspFrameComplete(Rsp* pRSP); +bool rspUpdate(Rsp* pRSP, RspUpdateMode eMode); +bool rspEvent(Rsp* pRSP, s32 nEvent, void* pArgument); extern _XL_OBJECTTYPE gClassRSP; diff --git a/include/macros.h b/include/macros.h index e7647ff..c9c0fe2 100644 --- a/include/macros.h +++ b/include/macros.h @@ -10,6 +10,8 @@ #define OFFSETOF(p, field) ((u8*)&(p)->field - (u8*)(p)) +#define SQ(x) ((x) * (x)) + // Adds no-ops to increase a function's size, preventing automatic inlining #define NO_INLINE() \ (void)0; \ diff --git a/libc/math.h b/libc/math.h index 240a475..3525218 100644 --- a/libc/math.h +++ b/libc/math.h @@ -121,6 +121,8 @@ _MATH_INLINE float powf(float __x, float __y) { return pow(__x, __y); } #define FP_NORMAL 4 #define FP_SUBNORMAL 5 +double __frsqrte(double x); + static inline int __fpclassifyf(float x) { switch ((*(_INT32*)&x) & 0x7f800000) { case 0x7f800000: { @@ -174,13 +176,10 @@ extern inline float sqrtf(float x) { volatile float y; if (x > 0.0f) { - double guess = __frsqrte((double)x); /* returns an approximation to */ - guess = _half * guess * (_three - guess * guess * x); /* now have 12 sig bits - */ - guess = _half * guess * (_three - guess * guess * x); /* now have 24 sig bits - */ - guess = _half * guess * (_three - guess * guess * x); /* now have 32 sig bits - */ + double guess = __frsqrte((double)x); /* returns an approximation to */ + guess = _half * guess * (_three - guess * guess * x); /* now have 12 sig bits */ + guess = _half * guess * (_three - guess * guess * x); /* now have 24 sig bits */ + guess = _half * guess * (_three - guess * guess * x); /* now have 32 sig bits */ y = (float)(x * guess); return y; } @@ -203,6 +202,22 @@ _MATH_INLINE double sqrt(double x) { return INFINITY; } +_MATH_INLINE float _inv_sqrtf(float x) { + const float _half = .5f; + const float _three = 3.0f; + + if (x > 0.0f) { + float guess = __frsqrte((double)x); /* returns an approximation to */ + guess = _half * guess * (_three - guess * guess * x); /* now have 8 sig bits */ + guess = _half * guess * (_three - guess * guess * x); /* now have 16 sig bits */ + guess = _half * guess * (_three - guess * guess * x); /* now have >24 sig bits */ + return guess; + } else if (x) { + return NAN; + } + return INFINITY; +} + static inline float ldexpf(float x, int exp) { return (float)ldexp((double)x, exp); } static inline double scalbn(double x, int n) { return ldexp(x, n); } static inline float scalbnf(float x, int n) { return (float)ldexpf(x, n); } diff --git a/src/emulator/frame.c b/src/emulator/frame.c index 8ae152e..7675eb0 100644 --- a/src/emulator/frame.c +++ b/src/emulator/frame.c @@ -9,6 +9,7 @@ #include "emulator/xlHeap.h" #include "emulator/xlObject.h" #include "macros.h" +#include "math.h" const s32 D_800D31C0[] = { 0x00000006, 0x00000000, 0x00000005, 0x00020000, 0x00000004, 0x00030000, 0x00000003, 0x00038000, @@ -415,17 +416,15 @@ const f32 D_80135F7C = 0.25999999046325684; const f32 D_80135F80 = 8.4399995803833; const f64 D_80135F88 = 8.44; -// TODO: caused by inline asm somewhere, remove when that function is matched -#pragma peephole off - static bool frameDrawSetupSP(Frame* pFrame, s32* pnColors, bool* pbFlag, s32 nVertexCount); static bool frameDrawSetupDP(Frame* pFrame, s32* pnColors, bool* pbFlag, s32); static bool frameDrawRectFill(Frame* pFrame, Rectangle* pRectangle); static bool frameDrawTriangle_Setup(Frame* pFrame, Primitive* pPrimitive); static bool frameDrawRectTexture_Setup(Frame* pFrame, Rectangle* pRectangle); -inline bool frameGetMatrixHint(Frame* pFrame, u32 nAddress, s32* piHint); +static inline bool frameGetMatrixHint(Frame* pFrame, u32 nAddress, s32* piHint); static inline bool frameResetCache(Frame* pFrame); static bool frameSetupCache(Frame* pFrame); +void PSMTX44MultVecNoW(Mtx44 m, Vec3f* src, Vec3f* dst); inline bool frameSetProjection(Frame* pFrame, s32 iHint) { MatrixHint* pHint = &pFrame->aMatrixHint[iHint]; @@ -2137,7 +2136,314 @@ bool frameGetMatrix(Frame* pFrame, Mtx44 matrix, FrameMatrixType eType, bool bPu return true; } +// TODO: move these paired-single/quantization functions to a separate header +// along with the GQR initialization in xlMain()? +inline void s16tof32(register s16* in, register f32* out) { OSs16tof32(in, out); } + +inline void s16tof32Pair(register s16* in, register f32* out) { +#ifdef __MWERKS__ + // clang-format off + asm { + psq_l f1, 0(in), 0, OS_FASTCAST_S16 + psq_st f1, 0(out), 0, 0 + } + // clang-format on +#else + out[0] = (f32)in[0]; + out[1] = (f32)in[1]; +#endif +} + +inline void s8tof32Scaled128(register s8* in, register f32* out) { +#ifdef __MWERKS__ + // clang-format off + asm { + psq_l f1, 0(in), 1, 6 + stfs f1, 0(out) + } + // clang-format on +#else + *out = (f32)*in / 128.0f; +#endif +} + +inline void s8tof32Scaled128Pair(register s8* in, register f32* out) { +#ifdef __MWERKS__ + // clang-format off + asm { + psq_l f1, 0(in), 0, 6 + psq_st f1, 0(out), 0, 0 + } + // clang-format on +#else + out[0] = (f32)in[0] / 128.0f; + out[1] = (f32)in[1] / 128.0f; +#endif +} + +inline void s16tof32Scaled32Pair(register s16* src, register f32* dst) { +#ifdef __MWERKS__ + // clang-format off + asm { + psq_l f1, 0(src), 0, 7 + psq_st f1, 0(dst), 0, 0 + } + // clang-format on +#else + dst[0] = (f32)src[0] / 32.0f; + dst[1] = (f32)src[1] / 32.0f; +#endif +} + +// Matches but data doesn't +#ifndef NON_MATCHING #pragma GLOBAL_ASM("asm/non_matchings/frame/frameLoadVertex.s") +#else +bool frameLoadVertex(Frame* pFrame, void* pBuffer, s32 iVertex0, s32 nCount) { + f32 mag; + s32 iLight; + s32 nLight; + s32 nTexGen; + f32 colorS; + f32 colorT; + f32 rS; + f32 rT; + f32 arNormal[3]; + f32 arPosition[3]; + Vertex* pVertex; + u32 nData32; + Light* aLight; + Light* pLight; + s32 iVertex1; + // f32 rScale; + // f32 rScaleST; + s8* pnData8; + s16* pnData16; + Mtx44Ptr matrixView; + Mtx44Ptr matrixModel; + f32 rColorR; + f32 rColorG; + f32 rColorB; + f32 rDiffuse; + f32 rInverseW; + f32 rInverseLength; + Vec3f vec; + f32 distance; + + pnData8 = pBuffer; + pnData16 = pBuffer; + iVertex1 = iVertex0 + nCount - 1; + if (iVertex0 < 0 || iVertex0 >= 80 || iVertex1 < 0 || iVertex1 >= 80) { + return false; + } + + matrixModel = pFrame->aMatrixModel[pFrame->iMatrixModel]; + if (pFrame->nMode & 0x08000000) { + // TODO: volatile hacks + if (!(*(volatile u32*)&pFrame->nMode & 0x400000)) { + PSMTX44Concat(matrixModel, pFrame->matrixProjectionExtra, pFrame->matrixView); + pFrame->nMode |= 0x400000; + if (pFrame->iHintProjection != -1) { + if (!frameScaleMatrix(pFrame->matrixView, pFrame->matrixView, + pFrame->aMatrixHint[pFrame->iHintProjection].rScale)) { + return false; + } + } + } + matrixView = pFrame->matrixView; + // TODO: volatile hacks + } else if (!(*(volatile u32*)&pFrame->nMode & 0x400000) && pFrame->iHintProjection != -1) { + if (!frameScaleMatrix(pFrame->matrixView, matrixModel, pFrame->aMatrixHint[pFrame->iHintProjection].rScale)) { + return false; + } + pFrame->nMode |= 0x400000; + matrixView = pFrame->matrixView; + } else { + matrixView = matrixModel; + } + + if (pFrame->aMode[1] & 0x20) { + nLight = pFrame->nCountLight; + nTexGen = pFrame->aMode[1] & 0x180; + aLight = pFrame->aLight; + + for (iLight = 0; iLight < nLight; iLight++) { + pLight = &aLight[iLight]; + if (!pLight->bTransformed || !(pFrame->nMode & 0x200000)) { + PSMTX44MultVecNoW(matrixModel, &pLight->rVecOrigTowards, &vec); + rInverseLength = _inv_sqrtf(SQ(vec.x) + SQ(vec.y) + SQ(vec.z)); + pLight->rVectorX = vec.x * rInverseLength; + pLight->rVectorY = vec.y * rInverseLength; + pLight->rVectorZ = vec.z * rInverseLength; + pLight->bTransformed = true; + } + } + + if (nTexGen != 0 && (!pFrame->lookAt.bTransformed || !(pFrame->nMode & 0x200000))) { + if (!(pFrame->nMode & 0x01000000)) { + pFrame->lookAt.rSRaw.x = 0.0f; + pFrame->lookAt.rSRaw.y = 1.0f; + pFrame->lookAt.rSRaw.z = 0.0f; + } + if (!(pFrame->nMode & 0x02000000)) { + pFrame->lookAt.rTRaw.x = 1.0f; + pFrame->lookAt.rTRaw.y = 0.0f; + pFrame->lookAt.rTRaw.z = 0.0f; + } + PSMTX44MultVecNoW(matrixModel, &pFrame->lookAt.rSRaw, &pFrame->lookAt.rS); + PSMTX44MultVecNoW(matrixModel, &pFrame->lookAt.rTRaw, &pFrame->lookAt.rT); + + mag = SQ(pFrame->lookAt.rS.x) + SQ(pFrame->lookAt.rS.y) + SQ(pFrame->lookAt.rS.z); + if (mag > 0.0f) { + rInverseLength = _inv_sqrtf(mag); + pFrame->lookAt.rS.x *= rInverseLength; + pFrame->lookAt.rS.y *= rInverseLength; + pFrame->lookAt.rS.z *= rInverseLength; + } + + mag = SQ(pFrame->lookAt.rT.x) + SQ(pFrame->lookAt.rT.y) + SQ(pFrame->lookAt.rT.z); + if (mag > 0.0f) { + rInverseLength = _inv_sqrtf(mag); + pFrame->lookAt.rT.x *= rInverseLength; + pFrame->lookAt.rT.y *= rInverseLength; + pFrame->lookAt.rT.z *= rInverseLength; + } + + pFrame->lookAt.bTransformed = true; + } + pFrame->nMode |= 0x200000; + } else { + nTexGen = 0; + nLight = 0; + } + + pVertex = &pFrame->aVertex[iVertex0]; + while (nCount-- != 0) { + s16tof32Pair(&pnData16[0], &arPosition[0]); + s16tof32(&pnData16[2], &arPosition[2]); + + pVertex->rSum = arPosition[0] + arPosition[1] + arPosition[2]; + rInverseW = 1.0f / (matrixView[0][3] * arPosition[0] + matrixView[1][3] * arPosition[1] + + matrixView[2][3] * arPosition[2] + matrixView[3][3]); + pVertex->vec.x = rInverseW * (arPosition[0] * matrixView[0][0] + arPosition[1] * matrixView[1][0] + + arPosition[2] * matrixView[2][0] + matrixView[3][0]); + pVertex->vec.y = rInverseW * (arPosition[0] * matrixView[0][1] + arPosition[1] * matrixView[1][1] + + arPosition[2] * matrixView[2][1] + matrixView[3][1]); + pVertex->vec.z = rInverseW * (arPosition[0] * matrixView[0][2] + arPosition[1] * matrixView[1][2] + + arPosition[2] * matrixView[2][2] + matrixView[3][2]); + + if (nLight != 0) { + s8tof32Scaled128Pair(&pnData8[12], &arNormal[0]); + s8tof32Scaled128(&pnData8[14], &arNormal[2]); + + iLight = nLight; + pLight = &aLight[iLight]; + if (gpSystem->eTypeROM == SRT_STARFOX) { + while ((rColorR = pLight->rColorR) + (rColorG = pLight->rColorG) + (rColorB = pLight->rColorB) == + 0.0f) { + pLight++; + } + pLight = &aLight[iLight]; + } else { + rColorR = pLight->rColorR; + rColorG = pLight->rColorG; + rColorB = pLight->rColorB; + } + + while (--iLight >= 0) { + pLight--; + if ((pFrame->aMode[1] & 0x800) && pLight->kc != 0.0f) { + distance = sqrtf(SQ(pLight->coordX - arPosition[0]) + SQ(pLight->coordY - arPosition[1]) + + SQ(pLight->coordZ - arPosition[2])); + pLight->rVectorX = (pLight->coordX - arPosition[0]) / distance; + pLight->rVectorY = (pLight->coordY - arPosition[1]) / distance; + pLight->rVectorZ = (pLight->coordZ - arPosition[2]) / distance; + rDiffuse = (pLight->rVectorX * arNormal[0] + pLight->rVectorY * arNormal[1] + + pLight->rVectorZ * arNormal[2]) / + (pLight->kc + pLight->kl * distance + pLight->kq * distance * distance); + if (rDiffuse > 1.0f) { + rDiffuse = 1.0f; + } + } else { + rDiffuse = pLight->rVectorX * arNormal[0] + pLight->rVectorY * arNormal[1] + + pLight->rVectorZ * arNormal[2]; + } + + if (rDiffuse > 0.0f) { + rColorR += pLight->rColorR * rDiffuse; + rColorG += pLight->rColorG * rDiffuse; + rColorB += pLight->rColorB * rDiffuse; + } + } + + OSf32tou8(&rColorR, &pVertex->anColor[0]); + OSf32tou8(&rColorG, &pVertex->anColor[1]); + OSf32tou8(&rColorB, &pVertex->anColor[2]); + pVertex->anColor[3] = pnData8[15]; + + if (nTexGen != 0) { + rS = arNormal[0] * pFrame->lookAt.rS.x + arNormal[1] * pFrame->lookAt.rS.y + + arNormal[2] * pFrame->lookAt.rS.z; + rT = arNormal[0] * pFrame->lookAt.rT.x + arNormal[1] * pFrame->lookAt.rT.y + + arNormal[2] * pFrame->lookAt.rT.z; + if (nTexGen & 0x100) { + colorS = rS * rS * rS; + colorS = (0.22673f * colorS) + colorS; + rS = ((1.0f / (f32)M_PI) * rS) + colorS; + colorT = rT * rT * rT; + colorT = (0.22673f * colorT) + colorT; + rT = ((1.0f / (f32)M_PI) * rT) + colorT; + } else { + rS *= 0.5f; + rT *= 0.5f; + } + pVertex->rS = rS + 0.5f; + pVertex->rT = rT + 0.5f; + } + } else { + nData32 = *(u32*)&pnData8[12]; + pVertex->anColor[0] = nData32 >> 24; + pVertex->anColor[1] = nData32 >> 16; + pVertex->anColor[2] = nData32 >> 8; + pVertex->anColor[3] = nData32; + if (nTexGen != 0) { + s8tof32Scaled128Pair(&pnData8[12], &arNormal[0]); + s8tof32Scaled128(&pnData8[14], &arNormal[2]); + + rS = arNormal[0] * pFrame->lookAt.rS.x + arNormal[1] * pFrame->lookAt.rS.y + + arNormal[2] * pFrame->lookAt.rS.z; + rT = arNormal[0] * pFrame->lookAt.rT.x + arNormal[1] * pFrame->lookAt.rT.y + + arNormal[2] * pFrame->lookAt.rT.z; + + if (nTexGen & 0x100) { + colorS = rS * rS * rS; + colorS = (0.22673f * colorS) + colorS; + rS = ((1.0f / (f32)M_PI) * rS) + colorS; + colorT = rT * rT * rT; + colorT = (0.22673f * colorT) + colorT; + rT = ((1.0f / (f32)M_PI) * rT) + colorT; + } else { + rS *= 0.5f; + rT *= 0.5f; + } + + pVertex->rS = rS + 0.5f; + pVertex->rT = rT + 0.5f; + } + } + + if (nTexGen == 0) { + s16tof32Scaled32Pair(&pnData16[4], &pVertex->rS); + } + + pVertex++; + pnData8 += 0x10; + pnData16 += 0x8; + } + + return true; +} +#endif #pragma GLOBAL_ASM("asm/non_matchings/frame/frameCullDL.s") @@ -2150,9 +2456,63 @@ bool frameSetLightCount(Frame* pFrame, s32 nCount) { return true; } +// Matches but data doesn't +#ifndef NON_MATCHING #pragma GLOBAL_ASM("asm/non_matchings/frame/frameSetLight.s") +#else +bool frameSetLight(Frame* pFrame, s32 iLight, s8* pData) { + Light* pLight; -#pragma GLOBAL_ASM("asm/non_matchings/frame/frameSetLookAt.s") + if (iLight >= 0 && iLight < 8) { + pLight = &pFrame->aLight[iLight]; + pLight->bTransformed = false; + + if (pData[3] != 0) { + pLight->kc = (u8)pData[3] * 0.0078125f + 0.0625f; + pLight->kl = (u8)pData[7] / 4096.0f; + pLight->kq = (u8)pData[14] / 4194304.0f; + pLight->coordX = *(s16*)&pData[8]; + pLight->coordY = *(s16*)&pData[10]; + pLight->coordZ = *(s16*)&pData[12]; + } else { + pLight->kc = 0.0f; + } + + OSu8tof32((u8*)&pData[0], &pLight->rColorR); + OSu8tof32((u8*)&pData[1], &pLight->rColorG); + OSu8tof32((u8*)&pData[2], &pLight->rColorB); + + s8tof32Scaled128(&pData[8], &pLight->rVecOrigTowards.x); + s8tof32Scaled128(&pData[9], &pLight->rVecOrigTowards.y); + s8tof32Scaled128(&pData[10], &pLight->rVecOrigTowards.z); + return true; + } else { + return false; + } +} +#endif + +bool frameSetLookAt(Frame* pFrame, s32 iLookAt, s8* pData) { + switch (iLookAt) { + case 0: + s8tof32Scaled128(&pData[8], &pFrame->lookAt.rSRaw.x); + s8tof32Scaled128(&pData[9], &pFrame->lookAt.rSRaw.y); + s8tof32Scaled128(&pData[10], &pFrame->lookAt.rSRaw.z); + pFrame->nMode |= 0x01000000; + break; + case 1: + s8tof32Scaled128(&pData[8], &pFrame->lookAt.rTRaw.x); + s8tof32Scaled128(&pData[9], &pFrame->lookAt.rTRaw.y); + s8tof32Scaled128(&pData[10], &pFrame->lookAt.rTRaw.z); + pFrame->nMode |= 0x02000000; + break; + default: + return false; + } + + pFrame->lookAt.bTransformed = false; + return true; +} #pragma GLOBAL_ASM("asm/non_matchings/frame/frameSetViewport.s") @@ -2233,7 +2593,7 @@ bool frameSetMatrixHint(Frame* pFrame, FrameMatrixProjection eProjection, s32 nA } if (eProjection == 1) { - rScale = 0.0f; + rNear = 0.0f; } pFrame->aMatrixHint[iHint].nCount = 4; @@ -2308,4 +2668,29 @@ bool frameGetTextureInfo(Frame* pFrame, TextureInfo* pInfo) { } #endif -#pragma GLOBAL_ASM("asm/non_matchings/frame/PSMTX44MultVecNoW.s") +ASM void PSMTX44MultVecNoW(Mtx44 m, Vec3f* src, Vec3f* dst) { +#ifdef __MWERKS__ // clang-format off + nofralloc + + psq_l f0, 0(r4), 0, 0 + psq_l f1, 8(r4), 1, 0 + psq_l f4, 0(r3), 0, 0 + psq_l f5, 8(r3), 0, 0 + psq_l f6, 16(r3), 0, 0 + psq_l f7, 24(r3), 0, 0 + psq_l f8, 32(r3), 0, 0 + psq_l f9, 40(r3), 0, 0 + ps_mul f4, f0, f4 + ps_madd f2, f1, f5, f4 + ps_mul f6, f0, f6 + ps_madd f3, f1, f7, f6 + ps_mul f8, f0, f8 + ps_sum0 f2, f2, f2, f2 + ps_madd f9, f1, f9, f8 + ps_sum1 f2, f3, f2, f3 + ps_sum0 f3, f9, f9, f9 + psq_st f2, 0(r5), 0, 0 + psq_st f3, 8(r5), 1, 0 + blr +#endif // clang-format on +} diff --git a/src/emulator/rsp.c b/src/emulator/rsp.c index ebd5e4a..e362649 100644 --- a/src/emulator/rsp.c +++ b/src/emulator/rsp.c @@ -1,5 +1,9 @@ #include "emulator/rsp.h" +#include "emulator/cpu.h" +#include "emulator/ram.h" +#include "emulator/rdp.h" #include "emulator/rsp_jumptables.h" +#include "emulator/system.h" _XL_OBJECTTYPE gClassRSP = { "RSP", @@ -315,7 +319,132 @@ const f32 D_80136074 = 1.52587890625e-05; #pragma GLOBAL_ASM("asm/non_matchings/rsp/rspParseGBI_F3DEX2.s") +// Matches but data doesn't +#ifndef NON_MATCHING #pragma GLOBAL_ASM("asm/non_matchings/rsp/rspLoadMatrix.s") +#else +static bool rspLoadMatrix(Rsp* pRSP, s32 nAddress, Mtx44 matrix) { + s32* pMtx; + s32 nDataA; + s32 nDataB; + f32 rScale; + f32 rUpper; + f32 rLower; + u16 nUpper; + u16 nLower; + + rScale = 1.0f / 65536.0f; + if (!ramGetBuffer(SYSTEM_RAM(pRSP->pHost), &pMtx, nAddress, NULL)) { + return false; + } + + nDataA = pMtx[0]; + nDataB = pMtx[8]; + nUpper = nDataA >> 16; + nLower = nDataB >> 16; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[0][0] = rUpper + rLower * rScale; + nUpper = nDataA & 0xFFFF; + nLower = nDataB & 0xFFFF; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[0][1] = rUpper + rLower * rScale; + + nDataA = pMtx[1]; + nDataB = pMtx[9]; + nUpper = nDataA >> 16; + nLower = nDataB >> 16; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[0][2] = rUpper + rLower * rScale; + nUpper = nDataA & 0xFFFF; + nLower = nDataB & 0xFFFF; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[0][3] = rUpper + rLower * rScale; + + nDataA = pMtx[2]; + nDataB = pMtx[10]; + nUpper = nDataA >> 16; + nLower = nDataB >> 16; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[1][0] = rUpper + rLower * rScale; + nUpper = nDataA & 0xFFFF; + nLower = nDataB & 0xFFFF; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[1][1] = rUpper + rLower * rScale; + + nDataA = pMtx[3]; + nDataB = pMtx[11]; + nUpper = nDataA >> 16; + nLower = nDataB >> 16; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[1][2] = rUpper + rLower * rScale; + nUpper = nDataA & 0xFFFF; + nLower = nDataB & 0xFFFF; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[1][3] = rUpper + rLower * rScale; + + nDataA = pMtx[4]; + nDataB = pMtx[12]; + nUpper = nDataA >> 16; + nLower = nDataB >> 16; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[2][0] = rUpper + rLower * rScale; + nUpper = nDataA & 0xFFFF; + nLower = nDataB & 0xFFFF; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[2][1] = rUpper + rLower * rScale; + + nDataA = pMtx[5]; + nDataB = pMtx[13]; + nUpper = nDataA >> 16; + nLower = nDataB >> 16; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[2][2] = rUpper + rLower * rScale; + nUpper = nDataA & 0xFFFF; + nLower = nDataB & 0xFFFF; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[2][3] = rUpper + rLower * rScale; + + nDataA = pMtx[6]; + nDataB = pMtx[14]; + nUpper = nDataA >> 16; + nLower = nDataB >> 16; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[3][0] = rUpper + rLower * rScale; + nUpper = nDataA & 0xFFFF; + nLower = nDataB & 0xFFFF; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[3][1] = rUpper + rLower * rScale; + + nDataA = pMtx[7]; + nDataB = pMtx[15]; + nUpper = nDataA >> 16; + nLower = nDataB >> 16; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[3][2] = rUpper + rLower * rScale; + nUpper = nDataA & 0xFFFF; + nLower = nDataB & 0xFFFF; + OSs16tof32((s16*)&nUpper, &rUpper); + OSu16tof32(&nLower, &rLower); + matrix[3][3] = rUpper + rLower * rScale; + + return true; +} +#endif #pragma GLOBAL_ASM("asm/non_matchings/rsp/rspFindUCode.s") diff --git a/src/emulator/xlCoreGCN.c b/src/emulator/xlCoreGCN.c index 0c9973f..e85b6f1 100644 --- a/src/emulator/xlCoreGCN.c +++ b/src/emulator/xlCoreGCN.c @@ -155,23 +155,7 @@ int main(int nCount, char** aszArgument) { __PADDisableRecalibration(true); OSInitAlarm(); - -#ifdef __MWERKS__ - asm { - li r3, 4 - oris r3, r3, 4 - mtspr GQR2, r3 - li r3, 5 - oris r3, r3, 5 - mtspr GQR3, r3 - li r3, 6 - oris r3, r3, 6 - mtspr GQR4, r3 - li r3, 7 - oris r3, r3, 7 - mtspr GQR5, r3 - } -#endif + OSInitFastCast(); nSizeHeap = 0;