From f26954ba9be5ec1685a43576c4d5d0599c72821b Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Sun, 30 Nov 2025 21:45:22 -0600 Subject: [PATCH 01/11] PPC EABI: Update cmath header with atan --- .../include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath b/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath index 48173d423..70e0fd02a 100644 --- a/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath +++ b/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath @@ -9,6 +9,7 @@ namespace std #ifndef INLINE float atan2f(float y, float x); + float atan(float x); float sinf(float x); float cosf(float x); float tanf(float x); @@ -25,6 +26,11 @@ namespace std return (float)atan2((double)y, (double)x); } + inline float atan(float x) + { + return (float)atan((double)x); + } + inline float sinf(float x) { return (float)sin((double)x); From 0bfca4ebd8091bf4b4d60b7a19b2b05383634397 Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Sun, 30 Nov 2025 21:45:43 -0600 Subject: [PATCH 02/11] xCamera: Correctly export gCameraLastFov --- src/SB/Core/x/xCamera.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SB/Core/x/xCamera.h b/src/SB/Core/x/xCamera.h index c12240f5e..a1e72caf3 100644 --- a/src/SB/Core/x/xCamera.h +++ b/src/SB/Core/x/xCamera.h @@ -66,6 +66,7 @@ extern RpAtomic* sInvisWallHack; extern xMat4x3 sCameraFXMatOld; extern cameraFX sCameraFX[10]; extern cameraFXTableEntry sCameraFXTable[3]; +extern F32 gCameraLastFov; struct xScene; From ec1f5ef873f33e4c81907d14842a015a1c0805eb Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Sun, 30 Nov 2025 21:46:35 -0600 Subject: [PATCH 03/11] xCutscene: 100% match for xCutscene_SetSpeed --- src/SB/Core/x/xCutscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SB/Core/x/xCutscene.cpp b/src/SB/Core/x/xCutscene.cpp index 02c6921f7..5679d6d42 100644 --- a/src/SB/Core/x/xCutscene.cpp +++ b/src/SB/Core/x/xCutscene.cpp @@ -231,7 +231,7 @@ void xCutscene_SetSpeed(xCutscene* csn, F32 speed) csn->PlaybackSpeed = speed; F32 semitones; - if (speed != 0.0f) + if (speed) { semitones = xlog(speed) / 0.057762269f; } From 7e0b3df1cde09088bf037b4be84fba299f65df29 Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Sun, 30 Nov 2025 21:49:17 -0600 Subject: [PATCH 04/11] xCutscene: Correctly order xCutsceneConvertBreak for eventual linking --- src/SB/Core/x/xCutscene.cpp | 62 ++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/SB/Core/x/xCutscene.cpp b/src/SB/Core/x/xCutscene.cpp index 5679d6d42..638c46ea3 100644 --- a/src/SB/Core/x/xCutscene.cpp +++ b/src/SB/Core/x/xCutscene.cpp @@ -144,6 +144,37 @@ S32 xCutscene_LoadStart(xCutscene* csn) return 1; } +F32 xCutsceneConvertBreak(float param_1, xCutsceneBreak* param_2, U32 param_3, int param_4) +{ + int i = 0; + if (param_3 == 0) + { + return param_1; + } + while (true) + { + if (param_4 != param_2[i].Index) + { + break; + } + if (param_2[i].Time - param_1 <= 0.0f) + { + break; + } + if (0.03333333f <= param_2[i].Time - param_1) + { + break; + } + i++; + param_3--; + if (param_3 == 0) + { + return param_1; + } + } + return param_2[i].Time - 0.03333333f; +} + S32 xCutscene_Update(xCutscene* csn, F32 dt) { if ((csn->SndStarted == FALSE) && (csn->SndNumChannel != 0)) @@ -263,37 +294,6 @@ void xVec3Lerp(xVec3* out, const xVec3* a, const xVec3* b, float alpha) out->z = a->z + (b->z - a->z) * alpha; } -F32 xCutsceneConvertBreak(float param_1, xCutsceneBreak* param_2, U32 param_3, int param_4) -{ - int i = 0; - if (param_3 == 0) - { - return param_1; - } - while (true) - { - if (param_4 != param_2[i].Index) - { - break; - } - if (param_2[i].Time - param_1 <= 0.0f) - { - break; - } - if (0.03333333f <= param_2[i].Time - param_1) - { - break; - } - i++; - param_3--; - if (param_3 == 0) - { - return param_1; - } - } - return param_2[i].Time - 0.03333333f; -} - void CutsceneShadowRender(CutsceneShadowModel* smod) { RpAtomic* model = smod->model; From 147e72b071bcbea417331d23ad402e03f9868de1 Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Sun, 30 Nov 2025 21:49:54 -0600 Subject: [PATCH 05/11] xCutscene: Move XCSNNosey to header to match weak definitions --- src/SB/Core/x/xCutscene.cpp | 8 -------- src/SB/Core/x/xCutscene.h | 9 +++++++-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/SB/Core/x/xCutscene.cpp b/src/SB/Core/x/xCutscene.cpp index 638c46ea3..49431d4f7 100644 --- a/src/SB/Core/x/xCutscene.cpp +++ b/src/SB/Core/x/xCutscene.cpp @@ -318,11 +318,3 @@ xCutscene* xCutscene_CurrentCutscene() { return &sActiveCutscene; } - -void XCSNNosey::CanRenderNow() -{ -} - -void XCSNNosey::UpdatedAnimated(RpAtomic*, RwMatrixTag*, U32, U32) -{ -} diff --git a/src/SB/Core/x/xCutscene.h b/src/SB/Core/x/xCutscene.h index c9f9352ad..bf1b74bac 100644 --- a/src/SB/Core/x/xCutscene.h +++ b/src/SB/Core/x/xCutscene.h @@ -56,8 +56,13 @@ struct XCSNNosey void* userdata; S32 flg_nosey; - void CanRenderNow(); - void UpdatedAnimated(RpAtomic*, RwMatrixTag*, U32, U32); + void CanRenderNow() + { + } + + void UpdatedAnimated(RpAtomic*, RwMatrixTag*, U32, U32) + { + } }; struct xCutscene From b14ea359c354af2569acd768b26d5bd6c0eef813 Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Tue, 2 Dec 2025 21:12:36 -0600 Subject: [PATCH 06/11] xCutscene: Update header with additional constant def and xCutsceneAnimHdr struct --- src/SB/Core/x/xCutscene.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/SB/Core/x/xCutscene.h b/src/SB/Core/x/xCutscene.h index bf1b74bac..513363e5f 100644 --- a/src/SB/Core/x/xCutscene.h +++ b/src/SB/Core/x/xCutscene.h @@ -3,6 +3,16 @@ #include "xFile.h" #include "rpworld.h" +#include "xCamera.h" + +#define XCUTSCENEDATA_TYPE_CAMERA 3 +#define XCUTSCENEDATA_TYPE_SOUND 5 +#define XCUTSCENEDATA_TYPE_6 6 + +struct xCutsceneAnimHdr { + U32 RootIndex; + F32 Translate[3]; +}; struct xCutsceneInfo { @@ -34,9 +44,6 @@ struct xCutsceneData }; }; -#define XCUTSCENEDATA_TYPE_SOUND 5 -#define XCUTSCENEDATA_TYPE_6 6 - struct xCutsceneBreak { F32 Time; @@ -120,6 +127,7 @@ xCutscene* xCutscene_Create(U32 id); S32 xCutscene_Destroy(xCutscene* csn); S32 xCutscene_LoadStart(xCutscene* csn); void xCutscene_SetSpeed(xCutscene* csn, F32 speed); +void xCutscene_SetCamera(xCutscene* csn, xCamera* cam); F32 xCutsceneConvertBreak(float time, xCutsceneBreak* breaklist, U32 breakcount, int idx); S32 xCutscene_Update(xCutscene* csn, F32 dt); void CutsceneShadowRender(CutsceneShadowModel* smod); From 8392e03ef144a6a921daafcb08cc3aa5243ce052 Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Tue, 2 Dec 2025 21:13:10 -0600 Subject: [PATCH 07/11] xCutscene: Equivalent match for xcsCalcAnimMatrices --- src/SB/Core/x/xCutscene.cpp | 81 +++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/SB/Core/x/xCutscene.cpp b/src/SB/Core/x/xCutscene.cpp index 49431d4f7..483a6646c 100644 --- a/src/SB/Core/x/xCutscene.cpp +++ b/src/SB/Core/x/xCutscene.cpp @@ -7,6 +7,9 @@ #include "iCutscene.h" #include "iModel.h" +#include "zCamera.h" +#include "zGlobals.h" +#include "iAnim.h" #include #include @@ -287,6 +290,84 @@ float std::logf(float x) return (float)log((double)x); } +static void xcsCalcAnimMatrices(RwMatrixTag* animMat, RpAtomic* model, xCutsceneAnimHdr* ahdr, F32 time, U32 tworoot) +{ + xQuat quatresult[65]; + xVec3 tranresult[65]; + + void* afile = &ahdr[1]; + iAnimEval(afile, time, 0x0, tranresult, quatresult); + + if (iModelNumBones(model) != 0) + { + xMat4x3Identity((xMat4x3*)animMat); + animMat->pos.x = ahdr->Translate[0]; + animMat->pos.y = ahdr->Translate[1]; + animMat->pos.z = ahdr->Translate[2]; + + + if (tworoot) + { + xMat4x3 m1; + xMat4x3 m2; + + quatresult[1].s = -quatresult[1].s; + quatresult[2].s = -quatresult[2].s; + xQuatToMat(&quatresult[1], &m1); + xQuatToMat(&quatresult[2], &m2); + + m1.pos = tranresult[1]; + m2.pos = tranresult[2]; + + xMat4x3Mul(&m1, &m2, &m1); + + tranresult[2].x = 0.0f; + tranresult[2].y = 0.0f; + tranresult[2].z = 0.0f; + quatresult[2].v.x = 0.0f; + quatresult[2].v.y = 0.0f; + quatresult[2].v.z = 0.0f; + quatresult[2].s = 1.0f; + + xQuatFromMat(&quatresult[1], &m1); + + quatresult[1].s = -quatresult[1].s; + m1.pos = tranresult[1]; + } + + U32 numbone = iModelNumBones(model); + U32 boneidx = 0; + xQuat* qqq = quatresult; + xVec3* ttt = tranresult; + while (boneidx < numbone && boneidx <= ahdr->RootIndex) + { + animMat->pos.x += tranresult[boneidx].x; + animMat->pos.y += tranresult[boneidx].y; + animMat->pos.z += tranresult[boneidx].z; + + tranresult[boneidx].x = 0.0f; + tranresult[boneidx].y = 0.0f; + tranresult[boneidx].z = 0.0f; + + if (FABS(quatresult[boneidx].s) < 0.9999f) + { + break; + } + + boneidx++; + } + + iModelAnimMatrices(model, quatresult, tranresult, &animMat[1]); + } + else + { + xQuatToMat(quatresult, (xMat4x3*)animMat); + animMat->pos.x = tranresult[0].x + ahdr->Translate[0]; + animMat->pos.y = tranresult[0].y + ahdr->Translate[1]; + animMat->pos.z = tranresult[0].z + ahdr->Translate[2]; + } +} + void xVec3Lerp(xVec3* out, const xVec3* a, const xVec3* b, float alpha) { out->x = a->x + (b->x - a->x) * alpha; From a996bc124f9d9c670c79acbf4faa7f86dfaf50ba Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Tue, 2 Dec 2025 21:13:26 -0600 Subject: [PATCH 08/11] Configure sym on for xCutscene.cpp --- configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.py b/configure.py index 6460232ba..19869c542 100644 --- a/configure.py +++ b/configure.py @@ -418,7 +418,7 @@ def MatchingFor(*versions): Object(Matching, "SB/Core/x/xCollideFast.cpp"), Object(Matching, "SB/Core/x/xColor.cpp"), Object(Matching, "SB/Core/x/xCounter.cpp"), - Object(NonMatching, "SB/Core/x/xCutscene.cpp"), + Object(NonMatching, "SB/Core/x/xCutscene.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Core/x/xDebug.cpp", extra_cflags=["-sym on"]), Object(Equivalent, "SB/Core/x/xEnt.cpp", extra_cflags=["-sym on"]), Object(Equivalent, "SB/Core/x/xEntDrive.cpp", extra_cflags=["-sym on"]), From 66e0fa2c559f3072bd628d20723a70469d481d6b Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Thu, 4 Dec 2025 21:28:22 -0600 Subject: [PATCH 09/11] xCutscene: Create data type macros as discovered and documented by Heavy Iron Modding Community --- src/SB/Core/x/xCutscene.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/SB/Core/x/xCutscene.h b/src/SB/Core/x/xCutscene.h index 513363e5f..682ac35e3 100644 --- a/src/SB/Core/x/xCutscene.h +++ b/src/SB/Core/x/xCutscene.h @@ -5,9 +5,13 @@ #include "rpworld.h" #include "xCamera.h" +#define XCUTSCENEDATA_TYPE_RW_MODEL 1 +#define XCUTSCENEDATA_TYPE_ANIMATION 2 #define XCUTSCENEDATA_TYPE_CAMERA 3 +#define XCUTSCENEDATA_TYPE_MORPHTARGET 4 #define XCUTSCENEDATA_TYPE_SOUND 5 -#define XCUTSCENEDATA_TYPE_6 6 +#define XCUTSCENEDATA_TYPE_JDELTAMODEL 6 +#define XCUTSCENEDATA_TYPE_JDELTAANIM 7 struct xCutsceneAnimHdr { U32 RootIndex; From f63030c86cfef61cbe7347a23e3ed64fc7d1632e Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Sun, 7 Dec 2025 21:25:37 -0600 Subject: [PATCH 10/11] iCutscene: Use updated macros for xCutscene Data Type --- src/SB/Core/gc/iCutscene.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SB/Core/gc/iCutscene.cpp b/src/SB/Core/gc/iCutscene.cpp index 973bf9f2e..79011b3f0 100644 --- a/src/SB/Core/gc/iCutscene.cpp +++ b/src/SB/Core/gc/iCutscene.cpp @@ -232,7 +232,7 @@ S32 iCSLoadStep(xCutscene* csn) while (csn->DataLoading < (S32)csn->Info->NumData) { - if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_6) + if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_JDELTAMODEL) { foundModel = NULL; } @@ -260,7 +260,7 @@ S32 iCSLoadStep(xCutscene* csn) if (csn->GotData) { - if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_6) + if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_JDELTAMODEL) { csn->Data[csn->DataLoading].DataPtr = RwMalloc(csn->Data[csn->DataLoading].ChunkSize); From 896767ce3570201cbc1f75e3240765d1bc109d7d Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Sun, 7 Dec 2025 21:26:09 -0600 Subject: [PATCH 11/11] xCutscene: Close match for xCutscene_SetCamera --- src/SB/Core/x/xCutscene.cpp | 75 ++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/src/SB/Core/x/xCutscene.cpp b/src/SB/Core/x/xCutscene.cpp index 483a6646c..107ded1dd 100644 --- a/src/SB/Core/x/xCutscene.cpp +++ b/src/SB/Core/x/xCutscene.cpp @@ -290,7 +290,73 @@ float std::logf(float x) return (float)log((double)x); } -static void xcsCalcAnimMatrices(RwMatrixTag* animMat, RpAtomic* model, xCutsceneAnimHdr* ahdr, F32 time, U32 tworoot) +// TODO: general pointer/index mismatching in here +// instructions and control flow should be close match though +void xCutscene_SetCamera(xCutscene* csn, xCamera* cam) +{ + xCutsceneData* data = (xCutsceneData*)&csn->Play[1]; + for (U32 i = 0; i < csn->Play->NumData; i++) + { + if (data[i].DataType == XCUTSCENEDATA_TYPE_CAMERA) + { + U32 dataIndex = data[i + 1].DataType; + S32 frame = std::floorf(30.0f * csn->CamTime); + zFlyKey* keys = (zFlyKey*)((char*)&data[i] + 0x14); + + F32 lerp; + if (keys[i + 1].frame < frame) + { + lerp = 0.0f; + } + else if (keys[i].frame >= frame) + { + lerp = 1.0f; + keys += keys[i].frame - 2; + } + else + { + lerp = 30.0f * csn->CamTime - std::floorf(30.0f * csn->CamTime); + keys += keys[i].frame - frame; + } + + F32 invlerp = 1.0f - lerp; + + xMat4x3 camMat; + xMat3x3 tmpMat; + xQuat quats[2]; + for (U32 j = 0; j < 2; j++) + { + tmpMat.right.x = -keys[j].matrix[0]; + tmpMat.right.y = -keys[j].matrix[1]; + tmpMat.right.z = -keys[j].matrix[2]; + tmpMat.up.x = keys[j].matrix[3]; + tmpMat.up.y = keys[j].matrix[4]; + tmpMat.up.z = keys[j].matrix[5]; + tmpMat.at.x = -keys[j].matrix[6]; + tmpMat.at.y = -keys[j].matrix[7]; + tmpMat.at.z = -keys[j].matrix[8]; + xQuatFromMat(&quats[j], &tmpMat); + } + + xQuat qresult; + xQuatSlerp(&qresult, &quats[0], &quats[1], lerp); + xQuatToMat(&qresult, &camMat); + xVec3Lerp(&camMat.pos, (xVec3*)&keys[0].matrix[9], (xVec3*)&keys[1].matrix[9], lerp); + + U32 count; + + F32 camFOV = 114.59155f * + std::atan((12.7f * (keys[0].aperture[0] * lerp + keys[1].aperture[0] * invlerp)) / + (keys[0].focal * lerp + keys[1].focal * invlerp)); + cam->mat = camMat; + gCameraLastFov = 0.0f; + xCameraSetFOV(&xglobals->camera, camFOV); + } + } +} + +static void xcsCalcAnimMatrices(RwMatrixTag* animMat, RpAtomic* model, xCutsceneAnimHdr* ahdr, + F32 time, U32 tworoot) { xQuat quatresult[65]; xVec3 tranresult[65]; @@ -305,7 +371,6 @@ static void xcsCalcAnimMatrices(RwMatrixTag* animMat, RpAtomic* model, xCutscene animMat->pos.y = ahdr->Translate[1]; animMat->pos.z = ahdr->Translate[2]; - if (tworoot) { xMat4x3 m1; @@ -344,11 +409,11 @@ static void xcsCalcAnimMatrices(RwMatrixTag* animMat, RpAtomic* model, xCutscene animMat->pos.x += tranresult[boneidx].x; animMat->pos.y += tranresult[boneidx].y; animMat->pos.z += tranresult[boneidx].z; - + tranresult[boneidx].x = 0.0f; tranresult[boneidx].y = 0.0f; tranresult[boneidx].z = 0.0f; - + if (FABS(quatresult[boneidx].s) < 0.9999f) { break; @@ -391,7 +456,7 @@ void CutsceneShadowRender(CutsceneShadowModel* smod) } } -void xCutscene_Render(xCutscene*, xEnt**, S32*, F32*) +void xCutscene_Render(xCutscene* csn, xEnt**, S32*, F32*) { }