mirror of
https://github.com/encounter/oot-gc.git
synced 2026-07-10 12:18:42 -07:00
Match paired-single/quantization (psq) functions (#89)
* Match rspLoadMatrix * Match frameSetLookAt * Match frameSetLight * Match handwritten PSMTX44MultVecNoW * Match frameLoadVertex * Format and small fixes * Missed some bools * Decode some float constants
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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; \
|
||||
|
||||
+22
-7
@@ -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); }
|
||||
|
||||
+392
-7
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user