summaryrefslogtreecommitdiff
path: root/src/code
diff options
context:
space:
mode:
authorThar0 <17233964+Thar0@users.noreply.github.com>2022-06-25 23:10:14 +0100
committerThar0 <17233964+Thar0@users.noreply.github.com>2022-06-25 23:10:14 +0100
commit05b199dd3dd65317890fcab51eadcac6b91bff09 (patch)
treed277ae509a96428c0646b5119cd7551069cd4b26 /src/code
parent78eeb3ffe832da80abc75c6976c228398d724e2a (diff)
parentf77c4770f7ae50b522d9183b79abe60070f6895b (diff)
Merge branch 'master' of https://github.com/zeldaret/mm into ovl_En_Death
Diffstat (limited to 'src/code')
-rw-r--r--src/code/code_800E8EA0.c153
-rw-r--r--src/code/flg_set.c2
-rw-r--r--src/code/game.c6
-rw-r--r--src/code/sys_math_atan.c48
-rw-r--r--src/code/sys_matrix.c1935
-rw-r--r--src/code/z_DLF.c1
-rw-r--r--src/code/z_actor.c124
-rw-r--r--src/code/z_bgcheck.c27
-rw-r--r--src/code/z_collision_check.c4
-rw-r--r--src/code/z_debug_display.c8
-rw-r--r--src/code/z_demo.c16
-rw-r--r--src/code/z_eff_footmark.c2
-rw-r--r--src/code/z_effect_soft_sprite.c1
-rw-r--r--src/code/z_effect_soft_sprite_old_init.c16
-rw-r--r--src/code/z_en_item00.c17
-rw-r--r--src/code/z_fcurve_data.c85
-rw-r--r--src/code/z_fcurve_data_skelanime.c255
-rw-r--r--src/code/z_fireobj.c2
-rw-r--r--src/code/z_kaleido_manager.c1
-rw-r--r--src/code/z_kaleido_setup.c2
-rw-r--r--src/code/z_lights.c2
-rw-r--r--src/code/z_message.c16
-rw-r--r--src/code/z_message_nes.c21
-rw-r--r--src/code/z_overlay.c1
-rw-r--r--src/code/z_play.c6
-rw-r--r--src/code/z_rcp.c8
-rw-r--r--src/code/z_scene.c20
-rw-r--r--src/code/z_skelanime.c96
-rw-r--r--src/code/z_skin.c18
-rw-r--r--src/code/z_skin_matrix.c495
-rw-r--r--src/code/z_sub_s.c664
-rw-r--r--src/code/z_view.c16
-rw-r--r--src/code/z_vismono.c177
-rw-r--r--src/code/z_vr_box_draw.c16
34 files changed, 3524 insertions, 737 deletions
diff --git a/src/code/code_800E8EA0.c b/src/code/code_800E8EA0.c
index d95f53269..6fb787451 100644
--- a/src/code/code_800E8EA0.c
+++ b/src/code/code_800E8EA0.c
@@ -1,107 +1,148 @@
#include "global.h"
-void func_800E8EA0(GlobalContext* globalCtx, Actor* actor, u16 textId) {
+void Actor_ContinueText(GlobalContext* globalCtx, Actor* actor, u16 textId) {
func_80151938(globalCtx, textId);
actor->textId = textId;
}
-s32 nop_800E8ED0(UNK_TYPE4 param_1) {
- return 0;
+/**
+ * EventCheckInf does not exist, so this always returns false
+ */
+s32 Flags_GetEventChkInf(s32 flag) {
+ return false;
}
-void nop_800E8EE0(UNK_TYPE4 param_1) {
+/**
+ * EventCheckInf does not exist, so this does nothing
+ */
+void Flags_SetEventChkInf(s32 flag) {
}
-s32 nop_800E8EEC(UNK_TYPE4 param_1) {
- return 0;
+/**
+ * InfTable does not exist, so this always returns false
+ */
+s32 Flags_GetInfTable(s32 flag) {
+ return false;
}
-void nop_800E8EFC(UNK_TYPE4 param_1) {
+/**
+ * InfTable does not exist, so this does nothing
+ */
+void Flags_SetInfTable(s32 flag) {
}
-s32 func_800E8F08(Vec3s* param_1, Vec3s* param_2) {
- Math_SmoothStepToS(&param_1->y, 0, 6, 6200, 100);
- Math_SmoothStepToS(&param_1->x, 0, 6, 6200, 100);
- Math_SmoothStepToS(&param_2->y, 0, 6, 6200, 100);
- Math_SmoothStepToS(&param_2->x, 0, 6, 6200, 100);
- return 1;
+s32 Actor_TrackNone(Vec3s* headRot, Vec3s* torsoRot) {
+ Math_SmoothStepToS(&headRot->y, 0, 6, 0x1838, 0x64);
+ Math_SmoothStepToS(&headRot->x, 0, 6, 0x1838, 0x64);
+ Math_SmoothStepToS(&torsoRot->y, 0, 6, 0x1838, 0x64);
+ Math_SmoothStepToS(&torsoRot->x, 0, 6, 0x1838, 0x64);
+ return true;
}
-s32 func_800E8FA4(Actor* actor, Vec3f* param_2, Vec3s* param_3, Vec3s* param_4) {
+s32 Actor_TrackPoint(Actor* actor, Vec3f* target, Vec3s* headRot, Vec3s* torsoRot) {
s16 targetPitch;
s16 targetYaw;
- s16 yawDiffFromTarget;
+ s16 yawDiff;
- targetPitch = Math_Vec3f_Pitch(&actor->focus.pos, param_2);
- targetYaw = Math_Vec3f_Yaw(&actor->focus.pos, param_2) - actor->world.rot.y;
+ targetPitch = Math_Vec3f_Pitch(&actor->focus.pos, target);
+ targetYaw = Math_Vec3f_Yaw(&actor->focus.pos, target) - actor->world.rot.y;
- Math_SmoothStepToS(&param_3->x, targetPitch, 6, 2000, 1);
- param_3->x = CLAMP(param_3->x, -6000, 6000);
+ Math_SmoothStepToS(&headRot->x, targetPitch, 6, 0x7D0, 1);
+ headRot->x = CLAMP(headRot->x, -0x1770, 0x1770);
- yawDiffFromTarget = Math_SmoothStepToS(&param_3->y, targetYaw, 6, 2000, 1);
- param_3->y = CLAMP(param_3->y, -8000, 8000);
+ yawDiff = Math_SmoothStepToS(&headRot->y, targetYaw, 6, 0x7D0, 1);
+ headRot->y = CLAMP(headRot->y, -0x1F40, 0x1F40);
- if (yawDiffFromTarget != 0) {
- if (ABS_ALT(param_3->y) < 8000) {
- return 0;
- }
+ if ((yawDiff != 0) && (ABS_ALT(headRot->y) < 0x1F40)) {
+ return false;
}
- Math_SmoothStepToS(&param_4->y, targetYaw - param_3->y, 4, 2000, 1);
- param_4->y = CLAMP(param_4->y, -12000, 12000);
+ Math_SmoothStepToS(&torsoRot->y, targetYaw - headRot->y, 4, 0x7D0, 1);
+ torsoRot->y = CLAMP(torsoRot->y, -0x2EE0, 0x2EE0);
- return 1;
+ return true;
}
-s32 func_800E9138(GlobalContext* globalCtx, Actor* actor, Vec3s* param_3, Vec3s* param_4, f32 param_5) {
+/**
+ * Same as Actor_TrackPlayer, except use the actor's world position as the focus point, with the height
+ * specified.
+ *
+ * @param play
+ * @param actor
+ * @param headRot the computed actor's head's rotation step
+ * @param torsoRot the computed actor's torso's rotation step
+ * @param focusHeight the height of the focus point relative to their world position
+ *
+ * @return true if rotated towards player, false if rotations were stepped back to zero.
+ *
+ * @note same note as Actor_TrackPlayer
+ */
+s32 Actor_TrackPlayerSetFocusHeight(GlobalContext* globalCtx, Actor* actor, Vec3s* headRot, Vec3s* torsoRot,
+ f32 focusHeight) {
Player* player = GET_PLAYER(globalCtx);
- s16 sVar3;
- Vec3f local_14;
+ s16 yaw;
+ Vec3f target;
actor->focus.pos = actor->world.pos;
- actor->focus.pos.y += param_5;
+ actor->focus.pos.y += focusHeight;
- if (((globalCtx->csCtx).state == 0) && (D_801D0D50 == 0)) {
- sVar3 = ABS_ALT(BINANG_SUB(actor->yawTowardsPlayer, actor->shape.rot.y));
- if (sVar3 >= 0x4300) {
- func_800E8F08(param_3, param_4);
- return 0;
+ if (!((globalCtx->csCtx.state != 0) || gDbgCamEnabled)) {
+ yaw = ABS_ALT(BINANG_SUB(actor->yawTowardsPlayer, actor->shape.rot.y));
+ if (yaw >= 0x4300) {
+ Actor_TrackNone(headRot, torsoRot);
+ return false;
}
}
- if (((globalCtx->csCtx).state != 0) || (D_801D0D50 != 0)) {
- local_14 = globalCtx->view.eye;
+ if ((globalCtx->csCtx.state != 0) || gDbgCamEnabled) {
+ target = globalCtx->view.eye;
} else {
- local_14 = player->actor.focus.pos;
+ target = player->actor.focus.pos;
}
- func_800E8FA4(actor, &local_14, param_3, param_4);
+ Actor_TrackPoint(actor, &target, headRot, torsoRot);
- return 1;
+ return true;
}
-s32 func_800E9250(GlobalContext* globalCtx, Actor* actor, Vec3s* param_3, Vec3s* param_4, Vec3f param_5) {
+/**
+ * Computes the necessary HeadRot and TorsoRot steps to be added to the normal rotation to smoothly turn an actors's
+ * head and torso towards the player if within a certain yaw, else smoothly returns the rotations back to zero.
+ * Also sets the focus position with the specified point.
+ *
+ * @param play
+ * @param actor
+ * @param headRot the computed actor's head's rotation step
+ * @param torsoRot the computed actor's torso's rotation step
+ * @param focusPos the point to set as the actor's focus position
+ *
+ * @return true if rotated towards player, false if rotations were stepped back to zero.
+ *
+ * @note if in a cutscene or debug camera is enabled, the computed rotation will instead turn towards the view eye no
+ * matter the yaw.
+ */
+s32 Actor_TrackPlayer(GlobalContext* globalCtx, Actor* actor, Vec3s* headRot, Vec3s* torsoRot, Vec3f focusPos) {
Player* player = GET_PLAYER(globalCtx);
- s16 sVar3;
- Vec3f local_14;
+ s16 yaw;
+ Vec3f target;
- actor->focus.pos = param_5;
+ actor->focus.pos = focusPos;
- if (((globalCtx->csCtx).state == 0) && (D_801D0D50 == 0)) {
- sVar3 = ABS_ALT(BINANG_SUB(actor->yawTowardsPlayer, actor->shape.rot.y));
- if (sVar3 >= 0x4300) {
- func_800E8F08(param_3, param_4);
- return 0;
+ if (!((globalCtx->csCtx.state != 0) || gDbgCamEnabled)) {
+ yaw = ABS_ALT(BINANG_SUB(actor->yawTowardsPlayer, actor->shape.rot.y));
+ if (yaw >= 0x4300) {
+ Actor_TrackNone(headRot, torsoRot);
+ return false;
}
}
- if (((globalCtx->csCtx).state != 0) || (D_801D0D50 != 0)) {
- local_14 = globalCtx->view.eye;
+ if ((globalCtx->csCtx.state != 0) || gDbgCamEnabled) {
+ target = globalCtx->view.eye;
} else {
- local_14 = player->actor.focus.pos;
+ target = player->actor.focus.pos;
}
- func_800E8FA4(actor, &local_14, param_3, param_4);
+ Actor_TrackPoint(actor, &target, headRot, torsoRot);
- return 1;
+ return true;
}
diff --git a/src/code/flg_set.c b/src/code/flg_set.c
index 53be7b68d..715d3756f 100644
--- a/src/code/flg_set.c
+++ b/src/code/flg_set.c
@@ -135,7 +135,7 @@ static s32 sTimer = 0;
void FlagSet_Update(GameState* gameState) {
GlobalContext* globalCtx = (GlobalContext*)gameState;
- Input* input = CONTROLLER1(globalCtx);
+ Input* input = CONTROLLER1(&globalCtx->state);
/* Intra-byte navigation */
diff --git a/src/code/game.c b/src/code/game.c
index 2713be299..6f796bc12 100644
--- a/src/code/game.c
+++ b/src/code/game.c
@@ -52,7 +52,7 @@ void GameState_SetFBFilter(Gfx** gfx, u32 arg1) {
sMonoColors.envColor.g = R_FB_FILTER_ENV_COLOR(1);
sMonoColors.envColor.b = R_FB_FILTER_ENV_COLOR(2);
sMonoColors.envColor.a = R_FB_FILTER_A;
- VisMono_Draw(&sMonoColors, &dlist, arg1);
+ VisMono_Draw(&sMonoColors, &dlist);
}
}
}
@@ -213,7 +213,7 @@ void GameState_Init(GameState* gameState, GameStateFunc init, GraphicsContext* g
func_80140CE0(&D_801F8010);
func_801420C0(&D_801F8020);
- func_801418B0(&sMonoColors);
+ VisMono_Init(&sMonoColors);
func_80140898(&D_801F8048);
func_801773A0(&D_801F7FF0);
func_8013ED9C();
@@ -235,7 +235,7 @@ void GameState_Destroy(GameState* gameState) {
func_801773C4(&D_801F7FF0);
func_80140D04(&D_801F8010);
func_801420F4(&D_801F8020);
- func_80141900(&sMonoColors);
+ VisMono_Destroy(&sMonoColors);
func_80140900(&D_801F8048);
THA_Dt(&gameState->heap);
GameAlloc_Cleanup(&gameState->alloc);
diff --git a/src/code/sys_math_atan.c b/src/code/sys_math_atan.c
index 09f355d64..d68e1e293 100644
--- a/src/code/sys_math_atan.c
+++ b/src/code/sys_math_atan.c
@@ -77,57 +77,57 @@ u16 sATan2Tbl[] = {
0x1FF6, 0x1FFB, 0x2000,
};
-u16 Math_GetAtan2Tbl(f32 opposite, f32 adjacent) {
- return sATan2Tbl[(s32)((opposite / adjacent) * 0x400)];
+u16 Math_GetAtan2Tbl(f32 y, f32 x) {
+ return sATan2Tbl[(s32)((y / x) * 0x400)];
}
-s16 Math_Atan2S(f32 opposite, f32 adjacent) {
+s16 Math_Atan2S(f32 y, f32 x) {
s32 angle;
- if (opposite == 0.0f) {
- if (adjacent >= 0.0f) {
+ if (y == 0.0f) {
+ if (x >= 0.0f) {
angle = 0;
} else {
angle = 0x8000;
}
- } else if (adjacent == 0.0f) {
- if (opposite >= 0.0f) {
+ } else if (x == 0.0f) {
+ if (y >= 0.0f) {
angle = 0x4000;
} else {
angle = 0xC000;
}
- } else if (opposite >= 0.0f) {
- if (adjacent >= 0.0f) {
- if (opposite <= adjacent) {
- angle = Math_GetAtan2Tbl(opposite, adjacent);
+ } else if (y >= 0.0f) {
+ if (x >= 0.0f) {
+ if (y <= x) {
+ angle = Math_GetAtan2Tbl(y, x);
} else {
- angle = 0x4000 - Math_GetAtan2Tbl(adjacent, opposite);
+ angle = 0x4000 - Math_GetAtan2Tbl(x, y);
}
} else {
- if (-adjacent < opposite) {
- angle = Math_GetAtan2Tbl(-adjacent, opposite) + 0x4000;
+ if (-x < y) {
+ angle = Math_GetAtan2Tbl(-x, y) + 0x4000;
} else {
- angle = 0x8000 - Math_GetAtan2Tbl(opposite, -adjacent);
+ angle = 0x8000 - Math_GetAtan2Tbl(y, -x);
}
}
- } else if (adjacent < 0.0f) {
- if (-opposite <= -adjacent) {
- angle = Math_GetAtan2Tbl(-opposite, -adjacent) + 0x8000;
+ } else if (x < 0.0f) {
+ if (-y <= -x) {
+ angle = Math_GetAtan2Tbl(-y, -x) + 0x8000;
} else {
- angle = 0xC000 - Math_GetAtan2Tbl(-adjacent, -opposite);
+ angle = 0xC000 - Math_GetAtan2Tbl(-x, -y);
}
} else {
- if (adjacent < -opposite) {
- angle = Math_GetAtan2Tbl(adjacent, -opposite) + 0xC000;
+ if (x < -y) {
+ angle = Math_GetAtan2Tbl(x, -y) + 0xC000;
} else {
- angle = -Math_GetAtan2Tbl(-opposite, adjacent);
+ angle = -Math_GetAtan2Tbl(-y, x);
}
}
return angle;
}
-f32 Math_Atan2F(f32 opposite, f32 adjacent) {
- return Math_Atan2S(opposite, adjacent) * (M_PI / 0x8000);
+f32 Math_Atan2F(f32 y, f32 x) {
+ return Math_Atan2S(y, x) * (M_PI / 0x8000);
}
s16 Math_FAtan2F(f32 adjacent, f32 opposite) {
diff --git a/src/code/sys_matrix.c b/src/code/sys_matrix.c
index a09d95200..4e517c810 100644
--- a/src/code/sys_matrix.c
+++ b/src/code/sys_matrix.c
@@ -1,89 +1,1944 @@
+/**
+ * @file sys_matrix.c
+ * @brief: Matrix system that mostly uses a matrix stack, and concerns affine transformations.
+ *
+ * @note The RSP matrix format (and hence the `MtxF` format) is column-major: vectors are presumed to be row vectors,
+ * and matrices as a column of row vectors. This means that, for example, a translation matrix
+ * \f[
+ * \begin{pmatrix}
+ * 1 & 0 & 0 & x \\
+ * 0 & 1 & 0 & y \\
+ * 0 & 0 & 1 & z \\
+ * 0 & 0 & 0 & 1
+ * \end{pmatrix}
+ * \f]
+ * will be stored as
+ *
+ * { { 1, 0, 0, 0 },
+ * { 0, 1, 0, 0 },
+ * { 0, 0, 1, 0 },
+ * { x, y, z, 1 }, }
+ *
+ * @note As such, we label the elements in column-major order so we can follow the same conventions for multiplying
+ * matrices as the rest of the world, i.e. that \f$ [AB]_{ij} = \sum_k A_{ik} B_{kj} \f$.
+ *
+ * This file is primarily concerned with matrices representing affine transformations, implemented using an augmented
+ * matrix formalism,
+ *
+ * \f[
+ * \begin{pmatrix}
+ * A & b \\
+ * 0 & 1
+ * \end{pmatrix}
+ * \f]
+ *
+ * where \f$ A \f$ is a \f$ 3 \times 3 \f$ matrix (the *linear part*) and \f$ b \f$ a \f$ 3 \times 1 \f$ matrix, i.e. a
+ * 3D vector (the *translation part*), and most of the functions assume that the matrices have this form.
+ *
+ * Throughout this file, `mode` indicates whether to multiply the matrix on top of the stack by the new construction
+ * (APPLY), or to just overwrite it (NEW).
+ */
+#include "prevent_bss_reordering.h"
#include "global.h"
-void Matrix_StateAlloc(GameState* gameState) {
- sMatrixStack = (MtxF*)THA_AllocEndAlign16(&gameState->heap, 0x500);
+/* data */
+
+// clang-format off
+Mtx gIdentityMtx = gdSPDefMtx(
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+);
+// clang-format on
+
+MtxF gIdentityMtxF = { {
+ { 1.0f, 0.0f, 0.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 1.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f, 1.0f },
+} };
+
+/* bss */
+
+MtxF* sMatrixStack; //!< original name: "Matrix_stack"
+MtxF* sCurrentMatrix; //!< original name: "Matrix_now"
+
+#define MATRIX_STACK_SIZE 20
+
+/* Stack operations */
+
+/**
+ * @brief Create the matrix stack and set the pointer to the top of it.
+ *
+ * @remark original name: "new_Matrix"
+ */
+void Matrix_Init(GameState* gameState) {
+ sMatrixStack = THA_AllocEndAlign16(&gameState->heap, MATRIX_STACK_SIZE * sizeof(MtxF));
sCurrentMatrix = sMatrixStack;
}
-void Matrix_StatePush(void) {
+/**
+ * @brief Place a new matrix on the top of the stack and move the stack pointer up.
+ *
+ * @remark original name: "Matrix_push"
+ */
+void Matrix_Push(void) {
MtxF* prev = sCurrentMatrix;
sCurrentMatrix++;
Matrix_MtxFCopy(sCurrentMatrix, prev);
}
-void Matrix_StatePop(void) {
+/**
+ * @brief Discard the top matrix on the stack and move stack pointer to the next one down.
+ *
+ * @remark original name: "Matrix_pull"
+ */
+void Matrix_Pop(void) {
sCurrentMatrix--;
}
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_CopyCurrentState.s")
+/**
+ * @brief Copy the top matrix from the stack.
+ *
+ * @param[out] dest Matrix into which to copy.
+ *
+ * @remark original name: "Matrix_get"
+ */
+void Matrix_Get(MtxF* dest) {
+ Matrix_MtxFCopy(dest, sCurrentMatrix);
+}
+
+/**
+ * @brief Overwrite the top matrix on the stack.
+ *
+ * @param[in] src Matrix from which to copy.
+ *
+ * @remark original name: "Matrix_put"
+ */
+void Matrix_Put(MtxF* src) {
+ Matrix_MtxFCopy(sCurrentMatrix, src);
+}
+
+/**
+ * @brief Return pointer to the top of the matrix stack.
+ *
+ * @return pointer to top matrix on the stack.
+ *
+ * @remark original name: get_Matrix_now
+ */
+MtxF* Matrix_GetCurrent(void) {
+ return sCurrentMatrix;
+}
+
+/* General transformation matrix functions */
+
+/**
+ * @brief General multiplication of current by a matrix.
+ * - APPLY: current * mf -> current
+ * - NEW: mf -> current
+ *
+ * @param mf Matrix to multiply by.
+ * @param mode APPLY or NEW.
+ *
+ * @remark original name: "Matrix_mult"
+ */
+void Matrix_Mult(MtxF* mf, MatrixMode mode) {
+ MtxF* cmf = Matrix_GetCurrent();
+
+ if (mode == MTXMODE_APPLY) {
+ SkinMatrix_MtxFMtxFMult(cmf, mf, cmf);
+ } else {
+ Matrix_MtxFCopy(sCurrentMatrix, mf);
+ }
+}
+
+/**
+ * @brief Right-multiply current by a translation matrix T.
+ * - APPLY: current * T -> current
+ * - NEW: T -> current
+ *
+ * T is given by
+ *
+ * \f[
+ * \begin{pmatrix}
+ * 1 & 0 & 0 & x \\
+ * 0 & 1 & 0 & y \\
+ * 0 & 0 & 1 & z \\
+ * 0 & 0 & 0 & 1
+ * \end{pmatrix} .
+ * \f]
+ *
+ * @param x translation distance in the x direction.
+ * @param y translation distance in the y direction.
+ * @param z translation distance in the z direction.
+ * @param mode APPLY or NEW.
+ *
+ * @remark original name: "Matrix_translate"
+ */
+void Matrix_Translate(f32 x, f32 y, f32 z, MatrixMode mode) {
+ MtxF* cmf = sCurrentMatrix;
+ f32 tempX;
+ f32 tempY;
+
+ if (mode == MTXMODE_APPLY) {
+ tempX = cmf->xx;
+ tempY = cmf->xy;
+ cmf->xw += tempX * x + tempY * y + cmf->xz * z;
+ tempX = cmf->yx;
+ tempY = cmf->yy;
+ cmf->yw += tempX * x + tempY * y + cmf->yz * z;
+ tempX = cmf->zx;
+ tempY = cmf->zy;
+ cmf->zw += tempX * x + tempY * y + cmf->zz * z;
+ tempX = cmf->wx;
+ tempY = cmf->wy;
+ cmf->ww += tempX * x + tempY * y + cmf->wz * z;
+ } else {
+ SkinMatrix_SetTranslate(cmf, x, y, z);
+ }
+}
+
+/**
+ * @brief Right-multiply by the diagonal scale matrix S = diag(x,y,z,1).
+ * - APPLY: current * S -> current
+ * - NEW: S -> current
+ *
+ * S is given by
+ *
+ * \f[
+ * \begin{pmatrix}
+ * x & 0 & 0 & 0 \\
+ * 0 & y & 0 & 0 \\
+ * 0 & 0 & z & 0 \\
+ * 0 & 0 & 0 & 1
+ * \end{pmatrix} .
+ * \f]
+ *
+ * @param x scale in x direction.
+ * @param y scale in y direction.
+ * @param z scale in z direction.
+ * @param mode APPLY or NEW.
+ *
+ * @remark original name: "Matrix_scale"
+ */
+void Matrix_Scale(f32 x, f32 y, f32 z, MatrixMode mode) {
+ MtxF* cmf = sCurrentMatrix;
+
+ if (mode == MTXMODE_APPLY) {
+ cmf->xx *= x;
+ cmf->yx *= x;
+ cmf->zx *= x;
+ cmf->xy *= y;
+ cmf->yy *= y;
+ cmf->zy *= y;
+ cmf->xz *= z;
+ cmf->yz *= z;
+ cmf->zz *= z;
+ cmf->wx *= x;
+ cmf->wy *= y;
+ cmf->wz *= z;
+ } else {
+ SkinMatrix_SetScale(cmf, x, y, z);
+ }
+}
+
+/**
+ * @brief Right-multiply by a rotation about the x axis
+ * - APPLY: current * R -> current
+ * - NEW: R -> current
+ *
+ * R is given by
+ *
+ * \f[
+ * \begin{pmatrix}
+ * 1 & 0 & 0 & 0 \\
+ * 0 & c & -s & 0 \\
+ * 0 & s & c & 0 \\
+ * 0 & 0 & 0 & 1
+ * \end{pmatrix}
+ * \f]
+ *
+ * where \f$ c = \cos x, s = \sin x \f$.
+ *
+ * @note The same as Matrix_RotateXF(), but uses a binary angle.
+ *
+ * @param x rotation angle (binary).
+ * @param mode APPLY or NEW.
+ *
+ * @remark original name: "Matrix_RotateX"
+ */
+void Matrix_RotateXS(s16 x, MatrixMode mode) {
+ MtxF* cmf;
+ f32 sin;
+ f32 cos;
+ f32 tempY;
+ f32 tempZ;
+
+ if (mode == MTXMODE_APPLY) {
+ if (x != 0) {
+ cmf = sCurrentMatrix;
+
+ sin = Math_SinS(x);
+ cos = Math_CosS(x);
+
+ tempY = cmf->xy;
+ tempZ = cmf->xz;
+ cmf->xy = tempY * cos + tempZ * sin;
+ cmf->xz = tempZ * cos - tempY * sin;
+
+ tempY = cmf->yy;
+ tempZ = cmf->yz;
+ cmf->yy = tempY * cos + tempZ * sin;
+ cmf->yz = tempZ * cos - tempY * sin;
+
+ tempY = cmf->zy;
+ tempZ = cmf->zz;
+ cmf->zy = tempY * cos + tempZ * sin;
+ cmf->zz = tempZ * cos - tempY * sin;
+
+ tempY = cmf->wy;
+ tempZ = cmf->wz;
+ cmf->wy = tempY * cos + tempZ * sin;
+ cmf->wz = tempZ * cos - tempY * sin;
+ }
+ } else {
+ cmf = sCurrentMatrix;
+
+ if (x != 0) {
+ sin = Math_SinS(x);
+ cos = Math_CosS(x);
+ } else {
+ sin = 0.0f;
+ cos = 1.0f;
+ }
+
+ cmf->yx = 0.0f;
+ cmf->zx = 0.0f;
+ cmf->wx = 0.0f;
+ cmf->xy = 0.0f;
+ cmf->wy = 0.0f;
+ cmf->xz = 0.0f;
+ cmf->wz = 0.0f;
+ cmf->xw = 0.0f;
+ cmf->yw = 0.0f;
+ cmf->zw = 0.0f;
+ cmf->xx = 1.0f;
+ cmf->ww = 1.0f;
+ cmf->yy = cos;
+ cmf->zz = cos;
+ cmf->zy = sin;
+ cmf->yz = -sin;
+ }
+}
+
+// Unused
+/**
+ * @brief Right-multiply by a rotation about the x axis.
+ * - APPLY: current * R -> current
+ * - NEW: R -> current
+ *
+ * R is given by
+ *
+ * \f[
+ * \begin{pmatrix}
+ * 1 & 0 & 0 & 0 \\
+ * 0 & c & -s & 0 \\
+ * 0 & s & c & 0 \\
+ * 0 & 0 & 0 & 1
+ * \end{pmatrix}
+ * \f]
+ *
+ * where \f$ c = \cos x, s = \sin x \f$.
+ *
+ * @note The same as Matrix_RotateXS(), but uses a float angle in radians.
+ *
+ * @param x rotation angle (radians).
+ * @param mode APPLY or NEW.
+ *
+ * @remark original name may have been "Matrix_RotateX", but clashed with the previous function.
+ */
+void Matrix_RotateXF(f32 x, MatrixMode mode) {
+ MtxF* cmf;
+ f32 sin;
+ f32 cos;
+ f32 tempY;
+ f32 tempZ;
+ f32 zero = 0.0;
+ f32 one = 1.0;
+
+ if (mode == MTXMODE_APPLY) {
+ if (x != 0) {
+ cmf = sCurrentMatrix;
+
+ sin = sinf(x);
+ cos = cosf(x);
+
+ tempY = cmf->xy;
+ tempZ = cmf->xz;
+ cmf->xy = tempY * cos + tempZ * sin;
+ cmf->xz = tempZ * cos - tempY * sin;
+
+ tempY = cmf->yy;
+ tempZ = cmf->yz;
+ cmf->yy = tempY * cos + tempZ * sin;
+ cmf->yz = tempZ * cos - tempY * sin;
+
+ tempY = cmf->zy;
+ tempZ = cmf->zz;
+ cmf->zy = tempY * cos + tempZ * sin;
+ cmf->zz = tempZ * cos - tempY * sin;
+
+ tempY = cmf->wy;
+ tempZ = cmf->wz;
+ cmf->wy = tempY * cos + tempZ * sin;
+ cmf->wz = tempZ * cos - tempY * sin;
+ }
+ } else {
+ cmf = sCurrentMatrix;
+
+ if (x != 0) {
+ sin = sinf(x);
+ cos = cosf(x);
+ } else {
+ sin = zero;
+ cos = one;
+ }
+
+ cmf->xx = one;
+ cmf->yx = zero;
+ cmf->zx = zero;
+ cmf->wx = zero;
+ cmf->xy = zero;
+ cmf->yy = cos;
+ cmf->zy = sin;
+ cmf->wy = zero;
+ cmf->xz = zero;
+ cmf->yz = -sin;
+ cmf->zz = cos;
+ cmf->wz = zero;
+ cmf->xw = zero;
+ cmf->yw = zero;
+ cmf->zw = zero;
+ cmf->ww = one;
+ }
+}
+
+/**
+ * @brief Right-multiply by a rotation about the x axis.
+ * current * R -> current
+ *
+ * @note Matrix_RotateXF() with mode APPLY.
+ *
+ * @param x rotation angle (radians).
+ */
+void Matrix_RotateXFApply(f32 x) {
+ MtxF* cmf;
+ f32 sin;
+ f32 cos;
+ f32 tempY;
+ f32 tempZ;
+ s32 pad;
+
+ if (x != 0.0f) {
+ cmf = sCurrentMatrix;
+
+ sin = sins(RADF_TO_BINANG(x)) * SHT_MINV;
+ cos = coss(RADF_TO_BINANG(x)) * SHT_MINV;
+
+ tempY = cmf->xy;
+ tempZ = cmf->xz;
+ cmf->xy = (tempY * cos) + (tempZ * sin);
+ cmf->xz = (tempZ * cos) - (tempY * sin);
+
+ tempY = cmf->yy;
+ tempZ = cmf->yz;
+ cmf->yy = (tempY * cos) + (tempZ * sin);
+ cmf->yz = (tempZ * cos) - (tempY * sin);
+
+ tempY = cmf->zy;
+ tempZ = cmf->zz;
+ cmf->zy = (tempY * cos) + (tempZ * sin);
+ cmf->zz = (tempZ * cos) - (tempY * sin);
+
+ tempY = cmf->wy;
+ tempZ = cmf->wz;
+ cmf->wy = (tempY * cos) + (tempZ * sin);
+ cmf->wz = (tempZ * cos) - (tempY * sin);
+ }
+}
+
+/**
+ * @brief Replace current by a rotation about the x axis.
+ * R -> current
+ *
+ * @note Matrix_RotateXF() with mode NEW.
+ *
+ * @param x rotation angle (radians).
+ */
+void Matrix_RotateXFNew(f32 x) {
+ MtxF* cmf = sCurrentMatrix;
+ s32 pad[2];
+ f32 sin;
+ f32 cos;
+
+ cmf->xx = 1.0f;
+ cmf->yx = 0.0f;
+ cmf->zx = 0.0f;
+ cmf->wx = 0.0f;
+ cmf->xy = 0.0f;
+ cmf->wy = 0.0f;
+ cmf->xz = 0.0f;
+ cmf->wz = 0.0f;
+ cmf->xw = 0.0f;
+ cmf->yw = 0.0f;
+ cmf->zw = 0.0f;
+ cmf->ww = 1.0f;
+
+ if (x != 0.0f) {
+ sin = sinf(x);
+ cos = cosf(x);
+
+ cmf->yy = cos;
+ cmf->zz = cos;
+ cmf->yz = -sin;
+ cmf->zy = sin;
+ } else {
+ cmf->yy = 1.0f;
+ cmf->zy = 0.0f;
+ cmf->yz = 0.0f;
+ cmf->zz = 1.0f;
+ }
+}
+
+/**
+ * @brief Right-multiply by a rotation about the y axis
+ * - APPLY: current * R -> current
+ * - NEW: R -> current
+ *
+ * R is given by
+ *
+ * \f[
+ * \begin{pmatrix}
+ * c & 0 & s & 0 \\
+ * 0 & 1 & 0 & 0 \\
+ * -s & 0 & c & 0 \\
+ * 0 & 0 & 0 & 1
+ * \end{pmatrix}
+ * \f]
+ *
+ * where \f$ c = \cos y, s = \sin y \f$.
+ *
+ * @note The same as Matrix_RotateYF(), but uses a binary angle.
+ *
+ * @param y rotation angle (binary).
+ * @param mode APPLY or NEW.
+ *
+ * @remark original name: "Matrix_RotateY"
+ */
+void Matrix_RotateYS(s16 y, MatrixMode mode) {
+ MtxF* cmf;
+ f32 sin;
+ f32 cos;
+ f32 tempX;
+ f32 tempZ;
+
+ if (mode == MTXMODE_APPLY) {
+ if (y != 0) {
+ cmf = sCurrentMatrix;
+
+ sin = Math_SinS(y);
+ cos = Math_CosS(y);
+
+ tempX = cmf->xx;
+ tempZ = cmf->xz;
+ cmf->xx = tempX * cos - tempZ * sin;
+ cmf->xz = tempX * sin + tempZ * cos;
+
+ tempX = cmf->yx;
+ tempZ = cmf->yz;
+ cmf->yx = tempX * cos - tempZ * sin;
+ cmf->yz = tempX * sin + tempZ * cos;
+
+ tempX = cmf->zx;
+ tempZ = cmf->zz;
+ cmf->zx = tempX * cos - tempZ * sin;
+ cmf->zz = tempX * sin + tempZ * cos;
+
+ tempX = cmf->wx;
+ tempZ = cmf->wz;
+ cmf->wx = tempX * cos - tempZ * sin;
+ cmf->wz = tempX * sin + tempZ * cos;
+ }
+ } else {
+ cmf = sCurrentMatrix;
+
+ if (y != 0) {
+ sin = Math_SinS(y);
+ cos = Math_CosS(y);
+ } else {
+ sin = 0.0f;
+ cos = 1.0f;
+ }
+
+ cmf->yx = 0.0f;
+ cmf->wx = 0.0f;
+ cmf->xy = 0.0f;
+ cmf->zy = 0.0f;
+ cmf->wy = 0.0f;
+ cmf->yz = 0.0f;
+ cmf->wz = 0.0f;
+ cmf->xw = 0.0f;
+ cmf->yw = 0.0f;
+ cmf->zw = 0.0f;
+ cmf->yy = 1.0f;
+ cmf->ww = 1.0f;
+ cmf->xx = cos;
+ cmf->zz = cos;
+ cmf->zx = -sin;
+ cmf->xz = sin;
+ }
+}
+
+/**
+ * @brief Right-multiply by a rotation about the y axis.
+ * - APPLY: current * R -> current
+ * - NEW: R -> current
+ *
+ * R is given by
+ *
+ * \f[
+ * \begin{pmatrix}
+ * c & 0 & s & 0 \\
+ * 0 & 1 & 0 & 0 \\
+ * -s & 0 & c & 0 \\
+ * 0 & 0 & 0 & 1
+ * \end{pmatrix}
+ * \f]
+ *
+ * where \f$ c = \cos y, s = \sin y \f$.
+ *
+ * @note The same as Matrix_RotateYS(), but uses a float angle in radians.
+ *
+ * @param y rotation angle (radians).
+ * @param mode APPLY or NEW.
+ *
+ * @remark original name may have been "Matrix_RotateY", but clashed with the previous function.
+ */
+void Matrix_RotateYF(f32 y, MatrixMode mode) {
+ MtxF* cmf;
+ f32 sin;
+ f32 cos;
+ f32 tempX;
+ f32 tempZ;
+ f32 zero = 0.0;
+ f32 one = 1.0;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_SetCurrentState.s")
+ if (mode == MTXMODE_APPLY) {
+ if (y != 0.0f) {
+ cmf = sCurrentMatrix;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_GetCurrentState.s")
+ sin = sinf(y);
+ cos = cosf(y);
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertMatrix.s")
+ tempX = cmf->xx;
+ tempZ = cmf->xz;
+ cmf->xx = tempX * cos - tempZ * sin;
+ cmf->xz = tempX * sin + tempZ * cos;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertTranslation.s")
+ tempX = cmf->yx;
+ tempZ = cmf->yz;
+ cmf->yx = tempX * cos - tempZ * sin;
+ cmf->yz = tempX * sin + tempZ * cos;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_Scale.s")
+ tempX = cmf->zx;
+ tempZ = cmf->zz;
+ cmf->zx = tempX * cos - tempZ * sin;
+ cmf->zz = tempX * sin + tempZ * cos;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertXRotation_s.s")
+ tempX = cmf->wx;
+ tempZ = cmf->wz;
+ cmf->wx = tempX * cos - tempZ * sin;
+ cmf->wz = tempX * sin + tempZ * cos;
+ }
+ } else {
+ cmf = sCurrentMatrix;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertXRotation_f.s")
+ if (y != 0.0f) {
+ sin = sinf(y);
+ cos = cosf(y);
+ } else {
+ cos = one;
+ sin = zero;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_RotateStateAroundXAxis.s")
+ cmf->yx = zero;
+ cmf->wx = zero;
+ cmf->xy = zero;
+ cmf->zy = zero;
+ cmf->wy = zero;
+ cmf->yz = zero;
+ cmf->wz = zero;
+ cmf->xw = zero;
+ cmf->yw = zero;
+ cmf->zw = zero;
+ cmf->yy = one;
+ cmf->ww = one;
+ cmf->xx = cos;
+ cmf->zz = cos;
+ cmf->zx = -sin;
+ cmf->xz = sin;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_SetStateXRotation.s")
+/**
+ * @brief Right-multiply by a rotation about the z axis.
+ * - APPLY: current * R -> current
+ * - NEW: R -> current
+ *
+ * R is given by
+ *
+ * \f[
+ * \begin{pmatrix}
+ * c & -s & 0 & 0 \\
+ * s & c & 0 & 0 \\
+ * 0 & 0 & 1 & 0 \\
+ * 0 & 0 & 0 & 1
+ * \end{pmatrix}
+ * \f]
+ *
+ * where \f$ c = \cos z, s = \sin z \f$.
+ *
+ * @note The same as Matrix_RotateZF, but uses a binary angle.
+ *
+ * @param z rotation angle (binary).
+ * @param mode APPLY or NEW.
+ *
+ * @remark original name: "Matrix_RotateZ"
+ */
+void Matrix_RotateZS(s16 z, MatrixMode mode) {
+ MtxF* cmf;
+ f32 sin;
+ f32 cos;
+ f32 tempX;
+ f32 tempY;
+ f32 zero = 0.0;
+ f32 one = 1.0;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_RotateY.s")
+ if (mode == MTXMODE_APPLY) {
+ if (z != 0) {
+ cmf = sCurrentMatrix;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertYRotation_f.s")
+ sin = Math_SinS(z);
+ cos = Math_CosS(z);
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertZRotation_s.s")
+ tempX = cmf->xx;
+ tempY = cmf->xy;
+ cmf->xx = tempX * cos + tempY * sin;
+ cmf->xy = tempY * cos - tempX * sin;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertZRotation_f.s")
+ tempX = cmf->yx;
+ tempY = cmf->yy;
+ cmf->yx = tempX * cos + tempY * sin;
+ cmf->yy = tempY * cos - tempX * sin;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertRotation.s")
+ tempX = cmf->zx;
+ tempY = cmf->zy;
+ cmf->zx = tempX * cos + tempY * sin;
+ cmf->zy = tempY * cos - tempX * sin;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_JointPosition.s")
+ tempX = cmf->wx;
+ tempY = cmf->wy;
+ cmf->wx = tempX * cos + tempY * sin;
+ cmf->wy = tempY * cos - tempX * sin;
+ }
+ } else {
+ cmf = sCurrentMatrix;
+
+ if (z != 0) {
+ sin = Math_SinS(z);
+ cos = Math_CosS(z);
+ } else {
+ sin = zero;
+ cos = one;
+ }
+
+ cmf->zx = zero;
+ cmf->wx = zero;
+ cmf->zy = zero;
+ cmf->wy = zero;
+ cmf->xz = zero;
+ cmf->yz = zero;
+ cmf->wz = zero;
+ cmf->xw = zero;
+ cmf->yw = zero;
+ cmf->zw = zero;
+ cmf->zz = one;
+ cmf->ww = one;
+ cmf->xx = cos;
+ cmf->yy = cos;
+ cmf->yx = sin;
+ cmf->xy = -sin;
+ }
+}
+
+/**
+ * @brief Right-multiply by a rotation about the z axis.
+ * - APPLY: current * R -> current
+ * - NEW: R -> current
+ *
+ * R is given by
+ *
+ * \f[
+ * \begin{pmatrix}
+ * c & -s & 0 & 0 \\
+ * s & c & 0 & 0 \\
+ * 0 & 0 & 1 & 0 \\
+ * 0 & 0 & 0 & 1
+ * \end{pmatrix}
+ * \f]
+ *
+ * where \f$ c = \cos z, s = \sin z \f$.
+ *
+ * @note The same as Matrix_RotateYS(), but uses a float angle in radians.
+ *
+ * @param z rotation angle (radians).
+ * @param mode APPLY or NEW.
+ *
+ * @remark original name may have been "Matrix_RotateZ", but clashed with the previous function.
+ */
+void Matrix_RotateZF(f32 z, MatrixMode mode) {
+ MtxF* cmf;
+ f32 sin;
+ f32 cos;
+ f32 tempX;
+ f32 tempY;
+
+ if (mode == MTXMODE_APPLY) {
+ if (z != 0) {
+ cmf = sCurrentMatrix;
+
+ sin = sinf(z);
+ cos = cosf(z);
+
+ tempX = cmf->xx;
+ tempY = cmf->xy;
+ cmf->xx = tempX * cos + tempY * sin;
+ cmf->xy = tempY * cos - tempX * sin;
+
+ tempX = cmf->yx;
+ tempY = cmf->yy;
+ cmf->yx = tempX * cos + tempY * sin;
+ cmf->yy = tempY * cos - tempX * sin;
+
+ tempX = cmf->zx;
+ tempY = cmf->zy;
+ cmf->zx = tempX * cos + tempY * sin;
+ cmf->zy = tempY * cos - tempX * sin;
+
+ tempX = cmf->wx;
+ tempY = cmf->wy;
+ cmf->wx = tempX * cos + tempY * sin;
+ cmf->wy = tempY * cos - tempX * sin;
+ }
+ } else {
+ cmf = sCurrentMatrix;
+
+ if (z != 0) {
+ sin = sinf(z);
+ cos = cosf(z);
+ } else {
+ sin = 0.0f;
+ cos = 1.0f;
+ }
+
+ cmf->zx = 0.0f;
+ cmf->wx = 0.0f;
+ cmf->zy = 0.0f;
+ cmf->wy = 0.0f;
+ cmf->xz = 0.0f;
+ cmf->yz = 0.0f;
+ cmf->wz = 0.0f;
+ cmf->xw = 0.0f;
+ cmf->yw = 0.0f;
+ cmf->zw = 0.0f;
+ cmf->zz = 1.0f;
+ cmf->ww = 1.0f;
+ cmf->xx = cos;
+ cmf->yy = cos;
+ cmf->yx = sin;
+ cmf->xy = -sin;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_SetStateRotationAndTranslation.s")
+/**
+ * @brief Rotate using ZYX Tait-Bryan angles.
+ * - APPLY: current Rz Ry Rx -> current
+ * - NEW: Rz Ry Rx -> current
+ *
+ * This means a (column) vector is first rotated around X, then around Y, then around Z, then (if `mode` is APPLY) gets
+ * transformed by what the matrix was before adding the ZYX rotation.
+ *
+ * See previous functions for the forms of Rz, Ry, Rx
+ *
+ * @param x binary angle to rotate about x axis
+ * @param y binary angle to rotate about y axis
+ * @param z binary angle to rotate about z axis
+ * @param mode APPLY or NEW
+ *
+ * @remark original name: "Matrix_RotateXYZ", changed to reflect rotation order.
+ */
+void Matrix_RotateZYX(s16 x, s16 y, s16 z, MatrixMode mode) {
+ MtxF* cmf = sCurrentMatrix;
+ f32 temp1;
+ f32 temp2;
+ f32 sin;
+ f32 cos;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_ToRSPMatrix.s")
+ if (mode == MTXMODE_APPLY) {
+ if (z != 0) { // Added in MM, OoT always follows the nonzero path
+ sin = Math_SinS(z);
+ cos = Math_CosS(z);
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_ToMtx.s")
+ temp1 = cmf->xx;
+ temp2 = cmf->xy;
+ cmf->xx = temp1 * cos + temp2 * sin;
+ cmf->xy = temp2 * cos - temp1 * sin;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_NewMtx.s")
+ temp1 = cmf->yx;
+ temp2 = cmf->yy;
+ cmf->yx = temp1 * cos + temp2 * sin;
+ cmf->yy = temp2 * cos - temp1 * sin;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_AppendToPolyOpaDisp.s")
+ temp1 = cmf->zx;
+ temp2 = cmf->zy;
+ cmf->zx = temp1 * cos + temp2 * sin;
+ cmf->zy = temp2 * cos - temp1 * sin;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_MultiplyVector3fByState.s")
+ temp1 = cmf->wx;
+ temp2 = cmf->wy;
+ cmf->wx = temp1 * cos + temp2 * sin;
+ cmf->wy = temp2 * cos - temp1 * sin;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_GetStateTranslation.s")
+ if (y != 0) {
+ sin = Math_SinS(y);
+ cos = Math_CosS(y);
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_GetStateTranslationAndScaledX.s")
+ temp1 = cmf->xx;
+ temp2 = cmf->xz;
+ cmf->xx = temp1 * cos - temp2 * sin;
+ cmf->xz = temp1 * sin + temp2 * cos;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_GetStateTranslationAndScaledY.s")
+ temp1 = cmf->yx;
+ temp2 = cmf->yz;
+ cmf->yx = temp1 * cos - temp2 * sin;
+ cmf->yz = temp1 * sin + temp2 * cos;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_GetStateTranslationAndScaledZ.s")
+ temp1 = cmf->zx;
+ temp2 = cmf->zz;
+ cmf->zx = temp1 * cos - temp2 * sin;
+ cmf->zz = temp1 * sin + temp2 * cos;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_MultiplyVector3fXZByCurrentState.s")
+ temp1 = cmf->wx;
+ temp2 = cmf->wz;
+ cmf->wx = temp1 * cos - temp2 * sin;
+ cmf->wz = temp1 * sin + temp2 * cos;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_MtxFCopy.s")
+ if (x != 0) {
+ sin = Math_SinS(x);
+ cos = Math_CosS(x);
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_FromRSPMatrix.s")
+ temp1 = cmf->xy;
+ temp2 = cmf->xz;
+ cmf->xy = temp1 * cos + temp2 * sin;
+ cmf->xz = temp2 * cos - temp1 * sin;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_MultiplyVector3fByMatrix.s")
+ temp1 = cmf->yy;
+ temp2 = cmf->yz;
+ cmf->yy = temp1 * cos + temp2 * sin;
+ cmf->yz = temp2 * cos - temp1 * sin;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_TransposeXYZ.s")
+ temp1 = cmf->zy;
+ temp2 = cmf->zz;
+ cmf->zy = temp1 * cos + temp2 * sin;
+ cmf->zz = temp2 * cos - temp1 * sin;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_NormalizeXYZ.s")
+ temp1 = cmf->wy;
+ temp2 = cmf->wz;
+ cmf->wy = temp1 * cos + temp2 * sin;
+ cmf->wz = temp2 * cos - temp1 * sin;
+ }
+ } else {
+ SkinMatrix_SetRotateRPY(cmf, x, y, z);
+ }
+}
+
+/**
+ * @brief Translate and rotate using ZYX Tait-Bryan angles.
+ * current T Rz Ry Rx -> current
+ *
+ * This means a (column) vector is first rotated around X, then around Y, then around Z, then translated, then gets
+ * transformed by whatever the matrix was previously.
+ *
+ * @param translation vector by which to translate.
+ * @param rot vector of rotation angles.
+ *
+ * @remark original name appears to be "Matrix_softcv3_mult"
+ */
+void Matrix_TranslateRotateZYX(Vec3f* translation, Vec3s* rot) {
+ MtxF* cmf = sCurrentMatrix;
+ f32 sin = Math_SinS(rot->z);
+ f32 cos = Math_CosS(rot->z);
+ f32 temp1;
+ f32 temp2;
+
+ // No check for z != 0, presumably since translation is interleaved.
+ temp1 = cmf->xx;
+ temp2 = cmf->xy;
+ cmf->xw += temp1 * translation->x + temp2 * translation->y + cmf->xz * translation->z;
+ cmf->xx = temp1 * cos + temp2 * sin;
+ cmf->xy = temp2 * cos - temp1 * sin;
+
+ temp1 = cmf->yx;
+ temp2 = cmf->yy;
+ cmf->yw += temp1 * translation->x + temp2 * translation->y + cmf->yz * translation->z;
+ cmf->yx = temp1 * cos + temp2 * sin;
+ cmf->yy = temp2 * cos - temp1 * sin;
+
+ temp1 = cmf->zx;
+ temp2 = cmf->zy;
+ cmf->zw += temp1 * translation->x + temp2 * translation->y + cmf->zz * translation->z;
+ cmf->zx = temp1 * cos + temp2 * sin;
+ cmf->zy = temp2 * cos - temp1 * sin;
+
+ temp1 = cmf->wx;
+ temp2 = cmf->wy;
+ cmf->ww += temp1 * translation->x + temp2 * translation->y + cmf->wz * translation->z;
+ cmf->wx = temp1 * cos + temp2 * sin;
+ cmf->wy = temp2 * cos - temp1 * sin;
+
+ if (rot->y != 0) {
+ sin = Math_SinS(rot->y);
+ cos = Math_CosS(rot->y);
+
+ temp1 = cmf->xx;
+ temp2 = cmf->xz;
+ cmf->xx = temp1 * cos - temp2 * sin;
+ cmf->xz = temp1 * sin + temp2 * cos;
+
+ temp1 = cmf->yx;
+ temp2 = cmf->yz;
+ cmf->yx = temp1 * cos - temp2 * sin;
+ cmf->yz = temp1 * sin + temp2 * cos;
+
+ temp1 = cmf->zx;
+ temp2 = cmf->zz;
+ cmf->zx = temp1 * cos - temp2 * sin;
+ cmf->zz = temp1 * sin + temp2 * cos;
+
+ temp1 = cmf->wx;
+ temp2 = cmf->wz;
+ cmf->wx = temp1 * cos - temp2 * sin;
+ cmf->wz = temp1 * sin + temp2 * cos;
+ }
+
+ if (rot->x != 0) {
+ sin = Math_SinS(rot->x);
+ cos = Math_CosS(rot->x);
+
+ temp1 = cmf->xy;
+ temp2 = cmf->xz;
+ cmf->xy = temp1 * cos + temp2 * sin;
+ cmf->xz = temp2 * cos - temp1 * sin;
+
+ temp1 = cmf->yy;
+ temp2 = cmf->yz;
+ cmf->yy = temp1 * cos + temp2 * sin;
+ cmf->yz = temp2 * cos - temp1 * sin;
+
+ temp1 = cmf->zy;
+ temp2 = cmf->zz;
+ cmf->zy = temp1 * cos + temp2 * sin;
+ cmf->zz = temp2 * cos - temp1 * sin;
+
+ temp1 = cmf->wy;
+ temp2 = cmf->wz;
+ cmf->wy = temp1 * cos + temp2 * sin;
+ cmf->wz = temp2 * cos - temp1 * sin;
+ }
+}
+
+/**
+ * @brief Set current to a general translation and rotation using YXZ Tait-Bryan angles: T Ry Rx Rz -> current
+ *
+ * This means a (column) vector is first rotated around Y, then around X, then around Z, then translated, then gets
+ * transformed by whatever the matrix was previously.
+ *
+ * @param x amount to translate in X direction.
+ * @param y amount to translate in Y direction.
+ * @param z amount to translate in Z direction.
+ * @param rot vector of rotation angles.
+ *
+ * @remark original name appears to be "Matrix_softcv3_load"
+ */
+void Matrix_SetTranslateRotateYXZ(f32 x, f32 y, f32 z, Vec3s* rot) {
+ MtxF* cmf = sCurrentMatrix;
+ f32 sinY = Math_SinS(rot->y);
+ f32 cosY = Math_CosS(rot->y);
+ f32 cosTemp;
+ f32 sinTemp;
+
+ cmf->xx = cosY;
+ cmf->zx = -sinY;
+ cmf->xw = x;
+ cmf->yw = y;
+ cmf->zw = z;
+ cmf->wx = 0.0f;
+ cmf->wy = 0.0f;
+ cmf->wz = 0.0f;
+ cmf->ww = 1.0f;
+
+ if (rot->x != 0) {
+ sinTemp = Math_SinS(rot->x);
+ cosTemp = Math_CosS(rot->x);
+
+ cmf->zz = cosY * cosTemp;
+ cmf->zy = cosY * sinTemp;
+ cmf->xz = sinY * cosTemp;
+ cmf->xy = sinY * sinTemp;
+ cmf->yz = -sinTemp;
+ cmf->yy = cosTemp;
+ } else {
+ cmf->zz = cosY;
+ cmf->xz = sinY;
+ cmf->yz = 0.0f;
+ cmf->zy = 0.0f;
+ cmf->xy = 0.0f;
+ cmf->yy = 1.0f;
+ }
+
+ if (rot->z != 0) {
+ sinTemp = Math_SinS(rot->z);
+ cosTemp = Math_CosS(rot->z);
+
+ sinY = cmf->xx;
+ cosY = cmf->xy;
+ cmf->xx = sinY * cosTemp + cosY * sinTemp;
+ cmf->xy = cosY * cosTemp - sinY * sinTemp;
+
+ sinY = cmf->zx;
+ cosY = cmf->zy;
+ cmf->zx = sinY * cosTemp + cosY * sinTemp;
+ cmf->zy = cosY * cosTemp - sinY * sinTemp;
+
+ cosY = cmf->yy;
+ cmf->yx = cosY * sinTemp;
+ cmf->yy = cosY * cosTemp;
+ } else {
+ cmf->yx = 0.0f;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/func_8018219C.s")
+/**
+ * @brief Converts a floating-point MtxF to a fixed-point RSP-compatible matrix.
+ *
+ * @param[in] src MtxF to convert.
+ * @param[out] dest mtx to output to.
+ *
+ * @return dest
+ *
+ * @remark original name: "_MtxF_to_Mtx"
+ */
+Mtx* Matrix_MtxFToMtx(MtxF* src, Mtx* dest) {
+ s32 temp;
+ u16* intPart = (u16*)&dest->m[0][0];
+ u16* fracPart = (u16*)&dest->m[2][0];
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/func_801822C4.s")
+ // For some reason the first 9 elements use the intPart temp for the fractional part.
+ temp = src->xx * 0x10000;
+ intPart[0] = (temp >> 0x10);
+ intPart[16 + 0] = temp;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertRotationAroundUnitVector_f.s")
+ temp = src->yx * 0x10000;
+ intPart[1] = (temp >> 0x10);
+ intPart[16 + 1] = temp;
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertRotationAroundUnitVector_s.s")
+ temp = src->zx * 0x10000;
+ intPart[2] = (temp >> 0x10);
+ intPart[16 + 2] = temp;
+
+ temp = src->wx * 0x10000;
+ intPart[3] = (temp >> 0x10);
+ intPart[16 + 3] = temp;
+
+ temp = src->xy * 0x10000;
+ intPart[4] = (temp >> 0x10);
+ intPart[16 + 4] = temp;
+
+ temp = src->yy * 0x10000;
+ intPart[5] = (temp >> 0x10);
+ intPart[16 + 5] = temp;
+
+ temp = src->zy * 0x10000;
+ intPart[6] = (temp >> 0x10);
+ intPart[16 + 6] = temp;
+
+ temp = src->wy * 0x10000;
+ intPart[7] = (temp >> 0x10);
+ intPart[16 + 7] = temp;
+
+ temp = src->xz * 0x10000;
+ intPart[8] = (temp >> 0x10);
+ intPart[16 + 8] = temp;
+
+ temp = src->yz * 0x10000;
+ intPart[9] = (temp >> 0x10);
+ fracPart[9] = temp;
+
+ temp = src->zz * 0x10000;
+ intPart[10] = (temp >> 0x10);
+ fracPart[10] = temp;
+
+ temp = src->wz * 0x10000;
+ intPart[11] = (temp >> 0x10);
+ fracPart[11] = temp;
+
+ temp = src->xw * 0x10000;
+ intPart[12] = (temp >> 0x10);
+ fracPart[12] = temp;
+
+ temp = src->yw * 0x10000;
+ intPart[13] = (temp >> 0x10);
+ fracPart[13] = temp;
+
+ temp = src->zw * 0x10000;
+ intPart[14] = (temp >> 0x10);
+ fracPart[14] = temp;
+
+ temp = src->ww * 0x10000;
+ intPart[15] = (temp >> 0x10);
+ fracPart[15] = temp;
+
+ return dest;
+}
+
+/**
+ * @brief Converts current to a fixed-point RSP-compatible matrix.
+ *
+ * @note Debug uses Matrix_CheckFloats to test current first.
+ *
+ * @param[out] dest mtx to output to.
+ *
+ * @return dest
+ *
+ * @remark original name: "_Matrix_to_Mtx"
+ */
+Mtx* Matrix_ToMtx(Mtx* dest) {
+ return Matrix_MtxFToMtx(sCurrentMatrix, dest);
+}
+
+/**
+ * @brief Converts current to a RSP-compatible matrix and saves it to allocated space in the OPA buffer.
+ *
+ * @param[in,out] gfxCtx Graphics context.
+ *
+ * @return allocated mtx.
+ *
+ * @remark original name: "_Matrix_to_Mtx_new"
+ */
+Mtx* Matrix_NewMtx(GraphicsContext* gfxCtx) {
+ return Matrix_ToMtx(GRAPH_ALLOC(gfxCtx, sizeof(Mtx)));
+}
+
+// Unused
+/**
+ * @brief Converts src to a RSP-compatible matrix and saves it to allocated space in the OPA buffer.
+ *
+ * @param[in] src MtxF to convert.
+ * @param[in,out] gfxCtx Graphics context.
+ *
+ * @return allocated mtx.
+ *
+ * @remark original name unknown, likely close to "_Matrix_MtxF_to_Mtx_new"
+ */
+Mtx* Matrix_MtxFToNewMtx(MtxF* src, GraphicsContext* gfxCtx) {
+ return Matrix_MtxFToMtx(src, GRAPH_ALLOC(gfxCtx, sizeof(Mtx)));
+}
+
+/**
+ * @brief Calculates current * (src,1) and writes its components to dest.
+ *
+ * This assumes that current has the form
+ *
+ * \f[
+ * M =
+ * \begin{pmatrix}
+ * A & b \\
+ * 0 & 1
+ * \end{pmatrix}
+ * \f]
+ *
+ * where A is \f$ 3 \times 3 \f$ and b \f$ 3 \times 1 \f$, and so calculates
+ *
+ * \f[
+ * MX =
+ * \begin{pmatrix}
+ * A & b \\
+ * 0 & 1
+ * \end{pmatrix}
+ * \begin{pmatrix}
+ * x \\
+ * 1
+ * \end{pmatrix}
+ * =
+ * \begin{pmatrix}
+ * Ax + b \\
+ * 1
+ * \end{pmatrix}
+ * \f]
+ *
+ * and discards the extra w component (1).
+ *
+ * @param[in] src input vector
+ * @param[out] dest output vector
+ *
+ * @remark original name: "Matrix_Position"
+ */
+void Matrix_MultVec3f(Vec3f* src, Vec3f* dest) {
+ MtxF* cmf = sCurrentMatrix;
+
+ dest->x = cmf->xw + (cmf->xx * src->x + cmf->xy * src->y + cmf->xz * src->z);
+ dest->y = cmf->yw + (cmf->yx * src->x + cmf->yy * src->y + cmf->yz * src->z);
+ dest->z = cmf->zw + (cmf->zx * src->x + cmf->zy * src->y + cmf->zz * src->z);
+}
+
+/**
+ * @brief Multiply the vector `(0, 0, 0, 1)` by current.
+ *
+ * Can also see it as obtaining the translation vector part of current, but the former interpretation is consistent with
+ * the other functions nearby.
+ *
+ * @note Special case of Matrix_MultVec3f() with `src = { 0, 0, 0 }`; the same assumptions apply.
+ *
+ * @param[out] dest output vector.
+ *
+ * @remark original name: "Matrix_Position_Zero"
+ */
+void Matrix_MultZero(Vec3f* dest) {
+ MtxF* cmf = sCurrentMatrix;
+
+ dest->x = cmf->xw;
+ dest->y = cmf->yw;
+ dest->z = cmf->zw;
+}
+
+/**
+ * @brief Multiply the vector `(x, 0, 0, 1)` by current.
+ *
+ * I.e. calculate \f$ A(x, 0, 0) + b \f$.
+ *
+ * @note Special case of Matrix_MultVec3f() with `src = { x, 0, 0 }`; the same assumptions apply.
+ *
+ * @param[in] x multiplier of unit vector in x direction.
+ * @param[out] dest output vector.
+ *
+ * @remark original name: "Matrix_Position_VecX"
+ */
+void Matrix_MultVecX(f32 x, Vec3f* dest) {
+ MtxF* cmf = sCurrentMatrix;
+
+ dest->x = cmf->xw + cmf->xx * x;
+ dest->y = cmf->yw + cmf->yx * x;
+ dest->z = cmf->zw + cmf->zx * x;
+}
+
+/**
+ * @brief Multiply the vector `(0, y, 0, 1)` by current.
+ *
+ * I.e. calculate \f$ A(0, y, 0) + b \f$.
+ *
+ * @note Special case of Matrix_MultVec3f() with `src = { 0, y, 0 }`; the same assumptions apply.
+ *
+ * @param[in] y multiplier of unit vector in y direction.
+ * @param[out] dest output vector.
+ *
+ * @remark original name is most likely "Matrix_Position_VecY" by analogy with the other two.
+ */
+void Matrix_MultVecY(f32 y, Vec3f* dest) {
+ MtxF* cmf = sCurrentMatrix;
+
+ dest->x = cmf->xw + cmf->xy * y;
+ dest->y = cmf->yw + cmf->yy * y;
+ dest->z = cmf->zw + cmf->zy * y;
+}
+
+/**
+ * @brief Multiply the vector `(0, 0, z, 1)` by current.
+ *
+ * I.e. calculate \f$ A(0, 0, z) + b \f$.
+ *
+ * @note Special case of Matrix_MultVec3f() with `src = { 0, 0, z }`; the same assumptions apply.
+ *
+ * @param[in] z multiplier of unit vector in z direction.
+ * @param[out] dest output vector.
+ *
+ * @remark original name: "Matrix_Position_VecZ"
+ */
+void Matrix_MultVecZ(f32 z, Vec3f* dest) {
+ MtxF* cmf = sCurrentMatrix;
+
+ dest->x = cmf->xw + cmf->xz * z;
+ dest->y = cmf->yw + cmf->yz * z;
+ dest->z = cmf->zw + cmf->zz * z;
+}
+
+/**
+ * @brief Calculates current * (src,1) and writes its x and z components to dest.
+ *
+ * The same as Matrix_MultVec3f(), but only applies to the x and z components; the same assumptions apply.
+ *
+ * @note Unlike the previous functions, does *not* just multiply (x, 0, z, 1) and save the x,y,z components.
+ *
+ * @param[in] src input vector.
+ * @param[out] dest output vector.
+ */
+void Matrix_MultVec3fXZ(Vec3f* src, Vec3f* dest) {
+ MtxF* cmf = sCurrentMatrix;
+
+ dest->x = cmf->xw + (cmf->xx * src->x + cmf->xy * src->y + cmf->xz * src->z);
+ dest->z = cmf->zw + (cmf->zx * src->x + cmf->zy * src->y + cmf->zz * src->z);
+}
+
+/**
+ * @brief Copies the matrix src into dest.
+ *
+ * @param[out] dest matrix to copy to.
+ * @param[in] src matrix to copy from.
+ *
+ * @remark original name: "Matrix_copy_MtxF"
+ */
+void Matrix_MtxFCopy(MtxF* dest, MtxF* src) {
+ f32 fv0;
+ f32 fv1;
+
+ // This ought to be a loop, but all attempts to match it as one have so far failed.
+ if (1) {
+ fv0 = src->mf[0][0];
+ fv1 = src->mf[0][1];
+ dest->mf[0][0] = fv0;
+ dest->mf[0][1] = fv1;
+ fv0 = src->mf[0][2];
+ fv1 = src->mf[0][3];
+ dest->mf[0][2] = fv0;
+ dest->mf[0][3] = fv1;
+ }
+ if (1) {
+ fv0 = src->mf[1][0];
+ fv1 = src->mf[1][1];
+ dest->mf[1][0] = fv0;
+ dest->mf[1][1] = fv1;
+ fv0 = src->mf[1][2];
+ fv1 = src->mf[1][3];
+ dest->mf[1][2] = fv0;
+ dest->mf[1][3] = fv1;
+ }
+ if (1) {
+ fv0 = src->mf[2][0];
+ fv1 = src->mf[2][1];
+ dest->mf[2][0] = fv0;
+ dest->mf[2][1] = fv1;
+ fv0 = src->mf[2][2];
+ fv1 = src->mf[2][3];
+ dest->mf[2][2] = fv0;
+ dest->mf[2][3] = fv1;
+ }
+ if (1) {
+ fv0 = src->mf[3][0];
+ fv1 = src->mf[3][1];
+ dest->mf[3][0] = fv0;
+ dest->mf[3][1] = fv1;
+ fv0 = src->mf[3][2];
+ fv1 = src->mf[3][3];
+ dest->mf[3][2] = fv0;
+ dest->mf[3][3] = fv1;
+ }
+}
+
+/**
+ * @brief Converts fixed-point RSP-compatible matrix to an MtxF.
+ *
+ * @param[in] src mtx to convert
+ * @param[out] dest MtxF to output to
+ *
+ * @remark original name: "Matrix_MtxtoMtxF"
+ */
+void Matrix_MtxToMtxF(Mtx* src, MtxF* dest) {
+ u16* intPart = (u16*)&src->m[0][0];
+ u16* fracPart = (u16*)&src->m[2][0];
+
+ dest->xx = ((intPart[0] << 0x10) | fracPart[0]) * (1 / (f32)0x10000);
+ dest->yx = ((intPart[1] << 0x10) | fracPart[1]) * (1 / (f32)0x10000);
+ dest->zx = ((intPart[2] << 0x10) | fracPart[2]) * (1 / (f32)0x10000);
+ dest->wx = ((intPart[3] << 0x10) | fracPart[3]) * (1 / (f32)0x10000);
+ dest->xy = ((intPart[4] << 0x10) | fracPart[4]) * (1 / (f32)0x10000);
+ dest->yy = ((intPart[5] << 0x10) | fracPart[5]) * (1 / (f32)0x10000);
+ dest->zy = ((intPart[6] << 0x10) | fracPart[6]) * (1 / (f32)0x10000);
+ dest->wy = ((intPart[7] << 0x10) | fracPart[7]) * (1 / (f32)0x10000);
+ dest->xz = ((intPart[8] << 0x10) | fracPart[8]) * (1 / (f32)0x10000);
+ dest->yz = ((intPart[9] << 0x10) | fracPart[9]) * (1 / (f32)0x10000);
+ dest->zz = ((intPart[10] << 0x10) | fracPart[10]) * (1 / (f32)0x10000);
+ dest->wz = ((intPart[11] << 0x10) | fracPart[11]) * (1 / (f32)0x10000);
+ dest->xw = ((intPart[12] << 0x10) | fracPart[12]) * (1 / (f32)0x10000);
+ dest->yw = ((intPart[13] << 0x10) | fracPart[13]) * (1 / (f32)0x10000);
+ dest->zw = ((intPart[14] << 0x10) | fracPart[14]) * (1 / (f32)0x10000);
+ dest->ww = ((intPart[15] << 0x10) | fracPart[15]) * (1 / (f32)0x10000);
+}
+
+// Unused
+/**
+ * @brief Calculates mf * (src,1) and writes its components to dest.
+ *
+ * This is the same as Matrix_MultVec3f() but using a specified matrix rather than the current one; the same
+ * assumptions apply.
+ *
+ * @param[in] src input vector
+ * @param[out] dest output vector
+ * @param[in] mf matrix to multiply by
+ */
+void Matrix_MultVec3fExt(Vec3f* src, Vec3f* dest, MtxF* mf) {
+ dest->x = mf->xw + (mf->xx * src->x + mf->xy * src->y + mf->xz * src->z);
+ dest->y = mf->yw + (mf->yx * src->x + mf->yy * src->y + mf->yz * src->z);
+ dest->z = mf->zw + (mf->zx * src->x + mf->zy * src->y + mf->zz * src->z);
+}
+
+/**
+ * @brief Overwrite the linear part of mf with its transpose (ignores the translational part).
+ *
+ * Viz.,
+ *
+ * \f[
+ * \begin{pmatrix}
+ * A & b \\
+ * 0 & 1
+ * \end{pmatrix}
+ * \longrightarrow
+ * \begin{pmatrix}
+ * A^T & b \\
+ * 0 & 1
+ * \end{pmatrix}
+ * \f]
+ *
+ * @param[in,out] mf matrix to transpose
+ *
+ * @remark original name: "Matrix_reverse"
+ */
+void Matrix_Transpose(MtxF* mf) {
+ f32 temp;
+
+ temp = mf->yx;
+ mf->yx = mf->xy;
+ mf->xy = temp;
+
+ temp = mf->zx;
+ mf->zx = mf->xz;
+ mf->xz = temp;
+
+ temp = mf->zy;
+ mf->zy = mf->yz;
+ mf->yz = temp;
+}
+
+/**
+ * @brief Decompose the linear part A of current into B * S, where B has normalised columns and S is diagonal, and
+ * replace B by `mf`.
+ *
+ * Since B is typically a rotation matrix, and the linear part R * S to `mf` * S, this operation can be
+ * seen as replacing the B rotation with `mf`, hence the function name.
+ *
+ * @param[in] mf matrix whose linear part will replace the normalised part of A.
+ */
+void Matrix_ReplaceRotation(MtxF* mf) {
+ MtxF* cmf = sCurrentMatrix;
+ f32 acc;
+ f32 component;
+ f32 curColNorm;
+
+ // compute the Euclidean norm of the first column of the current matrix
+ acc = cmf->xx;
+ acc *= acc;
+ component = cmf->yx;
+ acc += SQ(component);
+ component = cmf->zx;
+ acc += SQ(component);
+ curColNorm = sqrtf(acc);
+
+ cmf->xx = mf->xx * curColNorm;
+ cmf->yx = mf->yx * curColNorm;
+ cmf->zx = mf->zx * curColNorm;
+
+ // second column
+ acc = cmf->xy;
+ acc *= acc;
+ component = cmf->yy;
+ acc += SQ(component);
+ component = cmf->zy;
+ acc += SQ(component);
+ curColNorm = sqrtf(acc);
+
+ cmf->xy = mf->xy * curColNorm;
+ cmf->yy = mf->yy * curColNorm;
+ cmf->zy = mf->zy * curColNorm;
+
+ // third column
+ acc = cmf->xz;
+ acc *= acc;
+ component = cmf->yz;
+ acc += SQ(component);
+ component = cmf->zz;
+ acc += SQ(component);
+ curColNorm = sqrtf(acc);
+
+ cmf->xz = mf->xz * curColNorm;
+ cmf->yz = mf->yz * curColNorm;
+ cmf->zz = mf->zz * curColNorm;
+}
+
+/**
+ * @brief Extract the YXZ Tait-Bryan rotation angles from the linear part \f$ A \f$ of a matrix.
+ *
+ * \f$ A \f$ should have orthogonal columns; the most general matrix of this form can be written as \f$ RS \f$
+ * with \f$ S \f$ a scale matrix.
+ *
+ * If A has columns with the same norm (such as if it is just a rotation matrix), it is sufficient (and faster) to use
+ * `nonUniformScale` off: `nonUniformScale` being set enables extraction of the angles from a matrix with columns that
+ * are orthogonal but have different scales, at the cost of requiring extra calculation.
+ *
+ * @param[in] src Matrix to extract angles from.
+ * @param[out] dest vector to write angles to.
+ * @param[in] nonUniformScale boolean: true enables handling matrices with differently-scaled columns.
+ *
+ * @remark original name: "Matrix_to_rotate_new"?
+ */
+void Matrix_MtxFToYXZRot(MtxF* src, Vec3s* dest, s32 nonUniformScale) {
+ f32 temp;
+ f32 temp2;
+ f32 temp3;
+ f32 temp4;
+
+ temp = src->xz;
+ temp *= temp;
+ temp += SQ(src->zz);
+ dest->x = Math_Atan2S(-src->yz, sqrtf(temp));
+
+ if ((dest->x == 0x4000) || (dest->x == -0x4000)) {
+ // cos(x) = 0 if either of these is true, and we get gimbal locking
+ // (https://en.wikipedia.org/wiki/Gimbal_lock#Loss_of_a_degree_of_freedom_with_Euler_angles); fix z to make y
+ // well-defined.
+ dest->z = 0;
+
+ dest->y = Math_Atan2S(-src->zx, src->xx);
+ } else {
+ dest->y = Math_Atan2S(src->xz, src->zz);
+
+ if (!nonUniformScale) {
+ // assume the columns have the same normalisation
+ dest->z = Math_Atan2S(src->yx, src->yy);
+ } else {
+ temp = src->xx;
+ temp2 = src->zx;
+ temp3 = src->zy;
+
+ // find norm of the first column
+ temp *= temp;
+ temp += SQ(temp2);
+ temp2 = src->yx;
+ temp += SQ(temp2);
+ // temp = xx^2+zx^2+yx^2 == 1 for a rotation matrix
+ temp = sqrtf(temp);
+ temp = temp2 / temp; // yx in normalised column
+
+ // find norm of the second column
+ temp2 = src->xy;
+ temp2 *= temp2;
+ temp2 += SQ(temp3);
+ temp3 = src->yy;
+ temp2 += SQ(temp3);
+ // temp2 = xy^2+zy^2+yy^2 == 1 for a rotation matrix
+ temp2 = sqrtf(temp2);
+ temp2 = temp3 / temp2; // yy in normalised column
+
+ // for a rotation matrix, temp == yx and temp2 == yy which is the same as in the !nonUniformScale branch
+ dest->z = Math_Atan2S(temp, temp2);
+ }
+ }
+}
+
+/**
+ * @brief Extract the ZYX Tait-Bryan rotation angles from the linear part \f$ A \f$ of a matrix.
+ *
+ * \f$ A \f$ should have orthogonal columns; the most general matrix of this form can be written as \f$ RS \f$
+ * with \f$ S \f$ a scale matrix.
+ *
+ * If A has columns with the same norm (such as if it is just a rotation matrix), it is sufficient (and faster) to use
+ * `nonUniformScale` off: `nonUniformScale` being set enables extraction of the angles from a matrix with columns that
+ * are orthogonal but have different scales, at the cost of requiring extra calculation.
+ *
+ * @param[in] src Matrix to extract angles from.
+ * @param[out] dest vector to write angles to.
+ * @param[in] nonUniformScale boolean: true enables handling matrices with unnormalised columns.
+ *
+ * @remark original name: "Matrix_to_rotate2_new"?
+ *
+ * See Matrix_MtxFToYXZRot() for full inline documentation.
+ */
+void Matrix_MtxFToZYXRot(MtxF* src, Vec3s* dest, s32 nonUniformScale) {
+ f32 temp;
+ f32 temp2;
+ f32 temp3;
+ f32 temp4;
+
+ temp = src->xx;
+ temp *= temp;
+ temp += SQ(src->yx);
+ dest->y = Math_Atan2S(-src->zx, sqrtf(temp));
+
+ if ((dest->y == 0x4000) || (dest->y == -0x4000)) {
+ dest->x = 0;
+ dest->z = Math_Atan2S(-src->xy, src->yy);
+ } else {
+ dest->z = Math_Atan2S(src->yx, src->xx);
+
+ if (!nonUniformScale) {
+ dest->x = Math_Atan2S(src->zy, src->zz);
+ } else {
+ temp = src->xy;
+ temp2 = src->yy;
+ temp3 = src->yz;
+
+ temp *= temp;
+ temp += SQ(temp2);
+ temp2 = src->zy;
+ temp += SQ(temp2);
+ temp = sqrtf(temp);
+ temp = temp2 / temp;
+
+ temp2 = src->xz;
+ temp2 *= temp2;
+ temp2 += SQ(temp3);
+ temp3 = src->zz;
+ temp2 += SQ(temp3);
+ temp2 = sqrtf(temp2);
+ temp2 = temp3 / temp2;
+
+ dest->x = Math_Atan2S(temp, temp2);
+ }
+ }
+}
+
+/**
+ * @brief Rotate by `angle` radians about `axis`, which is assumed to be a unit vector.
+ *
+ * @param angle rotation angle (radians).
+ * @param axis axis about which to rotate, must be a unit vector.
+ * @param mode APPLY or NEW.
+ *
+ * @remark original name may have been "Matrix_RotateVector", but clashed with the next function.
+ */
+void Matrix_RotateAxisF(f32 angle, Vec3f* axis, MatrixMode mode) {
+ MtxF* cmf;
+ f32 sin;
+ f32 cos;
+ f32 versin;
+ f32 temp1;
+ f32 temp2;
+ f32 temp3;
+ f32 temp4;
+ f32 temp5;
+
+ if (mode == MTXMODE_APPLY) {
+ if (angle != 0) {
+ cmf = sCurrentMatrix;
+
+ sin = sinf(angle);
+ cos = cosf(angle);
+
+ temp1 = cmf->xx;
+ temp2 = cmf->xy;
+ temp3 = cmf->xz;
+ temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos);
+ cmf->xx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y);
+ cmf->xy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z);
+ cmf->xz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x);
+
+ temp1 = cmf->yx;
+ temp2 = cmf->yy;
+ temp3 = cmf->yz;
+ temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos);
+ cmf->yx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y);
+ cmf->yy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z);
+ cmf->yz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x);
+
+ temp1 = cmf->zx;
+ temp2 = cmf->zy;
+ temp3 = cmf->zz;
+ temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos);
+ cmf->zx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y);
+ cmf->zy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z);
+ cmf->zz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x);
+ }
+ } else {
+ cmf = sCurrentMatrix;
+
+ if (angle != 0) {
+ sin = sinf(angle);
+ cos = cosf(angle);
+ versin = 1.0f - cos;
+
+ cmf->xx = axis->x * axis->x * versin + cos;
+ cmf->yy = axis->y * axis->y * versin + cos;
+ cmf->zz = axis->z * axis->z * versin + cos;
+
+ if (0) {}
+
+ temp2 = axis->x * versin * axis->y;
+ temp3 = axis->z * sin;
+ cmf->yx = temp2 + temp3;
+ cmf->xy = temp2 - temp3;
+
+ temp2 = axis->x * versin * axis->z;
+ temp3 = axis->y * sin;
+ cmf->zx = temp2 - temp3;
+ cmf->xz = temp2 + temp3;
+
+ temp2 = axis->y * versin * axis->z;
+ temp3 = axis->x * sin;
+ cmf->zy = temp2 + temp3;
+ cmf->yz = temp2 - temp3;
+
+ cmf->wx = cmf->wy = cmf->wz = cmf->xw = cmf->yw = cmf->zw = 0.0f;
+ cmf->ww = 1.0f;
+ } else {
+ cmf->xx = 1.0f;
+ cmf->yx = 0.0f;
+ cmf->zx = 0.0f;
+ cmf->wx = 0.0f;
+ cmf->xy = 0.0f;
+ cmf->yy = 1.0f;
+ cmf->zy = 0.0f;
+ cmf->wy = 0.0f;
+ cmf->xz = 0.0f;
+ cmf->yz = 0.0f;
+ cmf->zz = 1.0f;
+ cmf->wz = 0.0f;
+ cmf->xw = 0.0f;
+ cmf->yw = 0.0f;
+ cmf->zw = 0.0f;
+ cmf->ww = 1.0f;
+ }
+ }
+}
+
+/**
+ * @brief Rotate by binary angle `angle` about `axis`, which is assumed to be a unit vector.
+ *
+ * @param angle rotation angle (binary).
+ * @param axis axis about which to rotate, must be a unit vector.
+ * @param mode APPLY or NEW.
+ *
+ * @remark original name: "Matrix_RotateVector"
+ */
+void Matrix_RotateAxisS(s16 angle, Vec3f* axis, MatrixMode mode) {
+ MtxF* cmf;
+ f32 cos;
+ f32 sin;
+ f32 versin;
+ f32 temp1;
+ f32 temp2;
+ f32 temp3;
+ f32 temp4;
+
+ if (mode == MTXMODE_APPLY) {
+ if (angle != 0) {
+ cmf = sCurrentMatrix;
+
+ sin = Math_SinS(angle);
+ cos = Math_CosS(angle);
+
+ temp1 = cmf->xx;
+ temp2 = cmf->xy;
+ temp3 = cmf->xz;
+ temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos);
+ cmf->xx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y);
+ cmf->xy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z);
+ cmf->xz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x);
+
+ temp1 = cmf->yx;
+ temp2 = cmf->yy;
+ temp3 = cmf->yz;
+ temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos);
+ cmf->yx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y);
+ cmf->yy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z);
+ cmf->yz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x);
+
+ temp1 = cmf->zx;
+ temp2 = cmf->zy;
+ temp3 = cmf->zz;
+ temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos);
+ cmf->zx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y);
+ cmf->zy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z);
+ cmf->zz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x);
+ }
+ } else {
+ cmf = sCurrentMatrix;
+
+ if (angle != 0) {
+ sin = Math_SinS(angle);
+ cos = Math_CosS(angle);
+ versin = 1.0f - cos;
+
+ cmf->xx = axis->x * axis->x * versin + cos;
+ cmf->yy = axis->y * axis->y * versin + cos;
+ cmf->zz = axis->z * axis->z * versin + cos;
+
+ if (0) {}
+
+ temp2 = axis->x * versin * axis->y;
+ temp3 = axis->z * sin;
+ cmf->yx = temp2 + temp3;
+ cmf->xy = temp2 - temp3;
+
+ temp2 = axis->x * versin * axis->z;
+ temp3 = axis->y * sin;
+ cmf->zx = temp2 - temp3;
+ cmf->xz = temp2 + temp3;
+
+ temp2 = axis->y * versin * axis->z;
+ temp3 = axis->x * sin;
+ cmf->zy = temp2 + temp3;
+ cmf->yz = temp2 - temp3;
+
+ cmf->wx = cmf->wy = cmf->wz = cmf->xw = cmf->yw = cmf->zw = 0.0f;
+ cmf->ww = 1.0f;
+ } else {
+ cmf->xx = 1.0f;
+ cmf->yx = 0.0f;
+ cmf->zx = 0.0f;
+ cmf->wx = 0.0f;
+ cmf->xy = 0.0f;
+ cmf->yy = 1.0f;
+ cmf->zy = 0.0f;
+ cmf->wy = 0.0f;
+ cmf->xz = 0.0f;
+ cmf->yz = 0.0f;
+ cmf->zz = 1.0f;
+ cmf->wz = 0.0f;
+ cmf->xw = 0.0f;
+ cmf->yw = 0.0f;
+ cmf->zw = 0.0f;
+ cmf->ww = 1.0f;
+ }
+ }
+}
diff --git a/src/code/z_DLF.c b/src/code/z_DLF.c
index 4c57aca01..862463b76 100644
--- a/src/code/z_DLF.c
+++ b/src/code/z_DLF.c
@@ -1,5 +1,6 @@
#include "global.h"
#include "system_malloc.h"
+#include "z64load.h"
#pragma GLOBAL_ASM("asm/non_matchings/code/z_DLF/Overlay_LoadGameState.s")
diff --git a/src/code/z_actor.c b/src/code/z_actor.c
index 24bc91a17..ddc22949b 100644
--- a/src/code/z_actor.c
+++ b/src/code/z_actor.c
@@ -4,6 +4,7 @@
*/
#include "global.h"
+#include "z64load.h"
#include "overlays/actors/ovl_En_Horse/z_en_horse.h"
#include "overlays/actors/ovl_En_Part/z_en_part.h"
#include "overlays/actors/ovl_En_Box/z_en_box.h"
@@ -92,10 +93,10 @@ void ActorShadow_Draw(Actor* actor, Lights* lights, GlobalContext* globalCtx, Gf
}
func_800C0094(actor->floorPoly, actor->world.pos.x, actor->floorHeight, actor->world.pos.z, &mtx);
- Matrix_SetCurrentState(&mtx);
+ Matrix_Put(&mtx);
if ((dlist != gCircleShadowDL) || (actor->scale.x != actor->scale.z)) {
- Matrix_RotateY(actor->shape.rot.y, MTXMODE_APPLY);
+ Matrix_RotateYS(actor->shape.rot.y, MTXMODE_APPLY);
}
shadowScale *= actor->shape.shadowScale;
@@ -151,8 +152,8 @@ void ActorShadow_DrawFoot(GlobalContext* globalCtx, Light* light, MtxF* arg2, s3
sp58 = Math_FAtan2F(dir2, dir0);
shadowScaleZ *= (4.5f - (light->l.dir[1] * 0.035f));
shadowScaleZ = CLAMP_MIN(shadowScaleZ, 1.0f);
- Matrix_SetCurrentState(arg2);
- Matrix_RotateY(sp58, MTXMODE_APPLY);
+ Matrix_Put(arg2);
+ Matrix_RotateYS(sp58, MTXMODE_APPLY);
Matrix_Scale(shadowScaleX, 1.0f, shadowScaleX * shadowScaleZ, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD);
@@ -195,7 +196,7 @@ void ActorShadow_DrawFeet(Actor* actor, Lights* mapper, GlobalContext* globalCtx
CollisionPoly* spF8;
s32 bgId;
f32 floorHeight[2];
- f32 pad;
+ Light* firstLight = &mapper->l.l[0];
f32 shadowAlpha;
f32 shadowScaleX;
f32 shadowScaleZ;
@@ -239,8 +240,6 @@ void ActorShadow_DrawFeet(Actor* actor, Lights* mapper, GlobalContext* globalCtx
IREG(88) + 80, IREG(89) + 60, IREG(90) + 40, 30000, 200, 60);
}
actor->shape.unk_17 &= ~spB8;
-
- if ((uintptr_t)mapper->l.l) {} // POSSIBLE FAKE MATCH
}
}
@@ -252,7 +251,8 @@ void ActorShadow_DrawFeet(Actor* actor, Lights* mapper, GlobalContext* globalCtx
shadowScaleZ = 1.0f - (distToFloor * (1.0f / 70.0f));
shadowScaleX = actor->shape.shadowScale * shadowScaleZ * actor->scale.x;
- for (lightPtr = mapper->l.l, j = 0; j < numLights; lightPtr++, j++) {
+ lightPtr = firstLight;
+ for (j = 0; j < numLights; j++) {
if (lightPtr->l.dir[1] > 0) {
lightNum = (lightPtr->l.col[0] + lightPtr->l.col[1] + lightPtr->l.col[2]) *
ABS_ALT(lightPtr->l.dir[1]);
@@ -263,9 +263,10 @@ void ActorShadow_DrawFeet(Actor* actor, Lights* mapper, GlobalContext* globalCtx
shadowScaleZ);
}
}
+ lightPtr++;
}
- for (j = 0; j < 2; lightPtr++, j++) {
+ for (j = 0; j < 2; j++) {
if (lightPtr->l.dir[1] > 0) {
lightNum = ((lightPtr->l.col[0] + lightPtr->l.col[1] + lightPtr->l.col[2]) *
ABS_ALT(lightPtr->l.dir[1])) -
@@ -275,6 +276,7 @@ void ActorShadow_DrawFeet(Actor* actor, Lights* mapper, GlobalContext* globalCtx
shadowScaleZ);
}
}
+ lightPtr++;
}
}
feetPosPtr++;
@@ -300,9 +302,9 @@ void ActorShadow_DrawFeet(Actor* actor, Lights* mapper, GlobalContext* globalCtx
void Actor_SetFeetPos(Actor* actor, s32 limbIndex, s32 leftFootIndex, Vec3f* leftFootPos, s32 rightFootIndex,
Vec3f* rightFootPos) {
if (limbIndex == leftFootIndex) {
- Matrix_MultiplyVector3fByState(leftFootPos, &actor->shape.feetPos[FOOT_LEFT]);
+ Matrix_MultVec3f(leftFootPos, &actor->shape.feetPos[FOOT_LEFT]);
} else if (limbIndex == rightFootIndex) {
- Matrix_MultiplyVector3fByState(rightFootPos, &actor->shape.feetPos[FOOT_RIGHT]);
+ Matrix_MultVec3f(rightFootPos, &actor->shape.feetPos[FOOT_RIGHT]);
}
}
@@ -532,22 +534,22 @@ void Actor_DrawZTarget(TargetContext* targetCtx, GlobalContext* globalCtx) {
var2 = ((entry->unkC - 120.0f) * 0.001f) + 0.15f;
}
- Matrix_InsertTranslation(entry->pos.x, entry->pos.y, 0.0f, MTXMODE_NEW);
+ Matrix_Translate(entry->pos.x, entry->pos.y, 0.0f, MTXMODE_NEW);
Matrix_Scale(var2, 0.15f, 1.0f, MTXMODE_APPLY);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, entry->color.r, entry->color.g, entry->color.b,
(u8)alpha);
- Matrix_InsertZRotation_s((targetCtx->unk4B * 512), MTXMODE_APPLY);
+ Matrix_RotateZS((targetCtx->unk4B * 512), MTXMODE_APPLY);
for (i = 0; i < 4; i++) {
- Matrix_InsertZRotation_s(0x4000, MTXMODE_APPLY);
- Matrix_StatePush();
- Matrix_InsertTranslation(entry->unkC, entry->unkC, 0.0f, MTXMODE_APPLY);
+ Matrix_RotateZS(0x4000, MTXMODE_APPLY);
+ Matrix_Push();
+ Matrix_Translate(entry->unkC, entry->unkC, 0.0f, MTXMODE_APPLY);
gSPMatrix(OVERLAY_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
G_MTX_MODELVIEW | G_MTX_LOAD);
gSPDisplayList(OVERLAY_DISP++, gZTargetLockOnTriangleDL);
- Matrix_StatePop();
+ Matrix_Pop();
}
}
@@ -565,10 +567,10 @@ void Actor_DrawZTarget(TargetContext* targetCtx, GlobalContext* globalCtx) {
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0x07);
- Matrix_InsertTranslation(actor->focus.pos.x,
- actor->focus.pos.y + (actor->targetArrowOffset * actor->scale.y) + 17.0f,
- actor->focus.pos.z, MTXMODE_NEW);
- Matrix_RotateY((globalCtx->gameplayFrames * 3000), MTXMODE_APPLY);
+ Matrix_Translate(actor->focus.pos.x,
+ actor->focus.pos.y + (actor->targetArrowOffset * actor->scale.y) + 17.0f,
+ actor->focus.pos.z, MTXMODE_NEW);
+ Matrix_RotateYS((globalCtx->gameplayFrames * 3000), MTXMODE_APPLY);
Matrix_Scale((iREG(27) + 35) / 1000.0f, (iREG(28) + 60) / 1000.0f, (iREG(29) + 50) / 1000.0f,
MTXMODE_APPLY);
@@ -2002,11 +2004,11 @@ s32 Actor_PickUp(Actor* actor, GlobalContext* globalCtx, s32 getItemId, f32 xzRa
if (!(player->stateFlags1 & 0x3C7080) && Player_GetExplosiveHeld(player) < 0) {
if ((actor->xzDistToPlayer <= xzRange) && (fabsf(actor->playerHeightRel) <= fabsf(yRange))) {
- if (((getItemId == GI_MASK_CIRCUS_LEADER) || (getItemId == GI_PENDANT_OF_MEMORIES) ||
- (getItemId == GI_DEED_LAND) ||
- (((player->heldActor != NULL) || (actor == player->targetActor)) &&
+ if ((getItemId == GI_MASK_CIRCUS_LEADER || getItemId == GI_PENDANT_OF_MEMORIES ||
+ getItemId == GI_DEED_LAND ||
+ ((player->heldActor != NULL || actor == player->targetActor) &&
(getItemId > GI_NONE && getItemId < GI_MAX))) ||
- (!(player->stateFlags1 & 0x20000800))) {
+ !(player->stateFlags1 & 0x20000800)) {
s16 yawDiff = actor->yawTowardsPlayer - player->actor.shape.rot.y;
s32 absYawDiff = ABS_ALT(yawDiff);
@@ -2510,14 +2512,13 @@ void Actor_Draw(GlobalContext* globalCtx, Actor* actor) {
Lights_Draw(light, globalCtx->state.gfxCtx);
if (actor->flags & ACTOR_FLAG_1000) {
- Matrix_SetStateRotationAndTranslation(
+ Matrix_SetTranslateRotateYXZ(
actor->world.pos.x + globalCtx->mainCamera.skyboxOffset.x,
actor->world.pos.y + ((actor->shape.yOffset * actor->scale.y) + globalCtx->mainCamera.skyboxOffset.y),
actor->world.pos.z + globalCtx->mainCamera.skyboxOffset.z, &actor->shape.rot);
} else {
- Matrix_SetStateRotationAndTranslation(actor->world.pos.x,
- actor->world.pos.y + (actor->shape.yOffset * actor->scale.y),
- actor->world.pos.z, &actor->shape.rot);
+ Matrix_SetTranslateRotateYXZ(actor->world.pos.x, actor->world.pos.y + (actor->shape.yOffset * actor->scale.y),
+ actor->world.pos.z, &actor->shape.rot);
}
Matrix_Scale(actor->scale.x, actor->scale.y, actor->scale.z, MTXMODE_APPLY);
@@ -3542,14 +3543,14 @@ void Actor_SpawnBodyParts(Actor* actor, GlobalContext* globalCtx, s32 arg2, Gfx*
MtxF* currentMatrix;
if (*dList != NULL) {
- currentMatrix = Matrix_GetCurrentState();
+ currentMatrix = Matrix_GetCurrent();
spawnedPart =
Actor_SpawnAsChild(&globalCtx->actorCtx, actor, globalCtx, ACTOR_EN_PART, currentMatrix->mf[3][0],
currentMatrix->mf[3][1], currentMatrix->mf[3][2], 0, 0, actor->objBankIndex, arg2);
if (spawnedPart != NULL) {
part = (EnPart*)spawnedPart;
- func_8018219C(currentMatrix, &part->actor.shape.rot, 0);
+ Matrix_MtxFToYXZRot(currentMatrix, &part->actor.shape.rot, false);
part->unk_150 = *dList;
Math_Vec3f_Copy(&part->actor.scale, &actor->scale);
}
@@ -3771,9 +3772,9 @@ void func_800BC620(Vec3f* arg0, Vec3f* arg1, u8 alpha, GlobalContext* globalCtx)
sp54 = BgCheck_EntityRaycastFloor2(globalCtx, &globalCtx->colCtx, &sp44, &sp48);
if (sp44 != NULL) {
func_800C0094(sp44, arg0->x, sp54, arg0->z, &sp58);
- Matrix_SetCurrentState(&sp58);
+ Matrix_Put(&sp58);
} else {
- Matrix_InsertTranslation(arg0->x, arg0->y, arg0->z, MTXMODE_NEW);
+ Matrix_Translate(arg0->x, arg0->y, arg0->z, MTXMODE_NEW);
}
Matrix_Scale(arg1->x, 1.0f, arg1->z, MTXMODE_APPLY);
@@ -3840,16 +3841,16 @@ void Actor_DrawDoorLock(GlobalContext* globalCtx, s32 frame, s32 type) {
OPEN_DISPS(globalCtx->state.gfxCtx);
- Matrix_InsertTranslation(0.0f, entry->yShift, 500.0f, MTXMODE_APPLY);
- Matrix_CopyCurrentState(&baseMtxF);
+ Matrix_Translate(0.0f, entry->yShift, 500.0f, MTXMODE_APPLY);
+ Matrix_Get(&baseMtxF);
- chainsTranslateX = __sinf(entry->chainAngle - chainRotZ) * -(10 - frame) * 0.1f * entry->chainLength;
- chainsTranslateY = __cosf(entry->chainAngle - chainRotZ) * (10 - frame) * 0.1f * entry->chainLength;
+ chainsTranslateX = sinf(entry->chainAngle - chainRotZ) * -(10 - frame) * 0.1f * entry->chainLength;
+ chainsTranslateY = cosf(entry->chainAngle - chainRotZ) * (10 - frame) * 0.1f * entry->chainLength;
for (i = 0; i < 4; i++) {
- Matrix_SetCurrentState(&baseMtxF);
- Matrix_InsertZRotation_f(chainRotZ, MTXMODE_APPLY);
- Matrix_InsertTranslation(chainsTranslateX, chainsTranslateY, 0.0f, MTXMODE_APPLY);
+ Matrix_Put(&baseMtxF);
+ Matrix_RotateZF(chainRotZ, MTXMODE_APPLY);
+ Matrix_Translate(chainsTranslateX, chainsTranslateY, 0.0f, MTXMODE_APPLY);
if (entry->chainsScale != 1.0f) {
Matrix_Scale(entry->chainsScale, entry->chainsScale, entry->chainsScale, MTXMODE_APPLY);
}
@@ -3866,7 +3867,7 @@ void Actor_DrawDoorLock(GlobalContext* globalCtx, s32 frame, s32 type) {
chainRotZ += rotZStep;
}
- Matrix_SetCurrentState(&baseMtxF);
+ Matrix_Put(&baseMtxF);
Matrix_Scale(frame * 0.1f, frame * 0.1f, frame * 0.1f, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -4280,7 +4281,7 @@ s16 func_800BDB6C(Actor* actor, GlobalContext* globalCtx, s16 arg2, f32 arg3) {
Player* player = GET_PLAYER(globalCtx);
f32 phi_f2;
- if ((globalCtx->csCtx.state != 0) || (D_801D0D50 != 0)) {
+ if ((globalCtx->csCtx.state != 0) || gDbgCamEnabled) {
phi_f2 = Math_Vec3f_DistXYZ(&actor->world.pos, &globalCtx->view.eye) * 0.25f;
} else {
phi_f2 = Math_Vec3f_DistXYZ(&actor->world.pos, &player->actor.world.pos);
@@ -4482,9 +4483,10 @@ void func_800BE5CC(Actor* actor, ColliderJntSph* collider, s32 colliderIndex) {
}
}
-s32 func_800BE63C(struct EnBox* chest) {
- if ((chest->unk_1F1 == 5) || (chest->unk_1F1 == 6) || (chest->unk_1F1 == 7) || (chest->unk_1F1 == 8) ||
- (chest->unk_1F1 == 0xC)) {
+s32 Actor_IsSmallChest(struct EnBox* chest) {
+ if (chest->type == ENBOX_TYPE_SMALL || chest->type == ENBOX_TYPE_SMALL_INVISIBLE ||
+ chest->type == ENBOX_TYPE_SMALL_ROOM_CLEAR || chest->type == ENBOX_TYPE_SMALL_SWITCH_FLAG_FALL ||
+ chest->type == ENBOX_TYPE_SMALL_SWITCH_FLAG) {
return true;
}
return false;
@@ -4515,7 +4517,7 @@ void Actor_DrawDamageEffects(GlobalContext* globalCtx, Actor* actor, Vec3f limbP
u32 gameplayFrames = globalCtx->gameplayFrames;
f32 effectAlphaScaled;
- currentMatrix = Matrix_GetCurrentState();
+ currentMatrix = Matrix_GetCurrent();
// Apply sfx along with damage effect
if ((actor != NULL) && (effectAlpha > 0.05f) && (globalCtx->gameOverCtx.state == 0)) {
@@ -4564,15 +4566,15 @@ void Actor_DrawDamageEffects(GlobalContext* globalCtx, Actor* actor, Vec3f limbP
gDPSetEnvColor(POLY_XLU_DISP++, KREG(20) + 200, KREG(21) + 200, KREG(22) + 255, (u8)alpha);
- Matrix_InsertTranslation(limbPos->x, limbPos->y, limbPos->z, MTXMODE_NEW);
+ Matrix_Translate(limbPos->x, limbPos->y, limbPos->z, MTXMODE_NEW);
Matrix_Scale(frozenScale, frozenScale, frozenScale, MTXMODE_APPLY);
if (limbIndex & 1) {
- Matrix_InsertYRotation_f(M_PI, MTXMODE_APPLY);
+ Matrix_RotateYF(M_PI, MTXMODE_APPLY);
}
if (limbIndex & 2) {
- Matrix_InsertZRotation_f(M_PI, MTXMODE_APPLY);
+ Matrix_RotateZF(M_PI, MTXMODE_APPLY);
}
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
@@ -4603,8 +4605,8 @@ void Actor_DrawDamageEffects(GlobalContext* globalCtx, Actor* actor, Vec3f limbP
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, twoTexScrollParam * 3,
twoTexScrollParam * -12, 32, 64, 1, 0, 0, 32, 32));
- Matrix_InsertTranslation(limbPos->x, limbPos->y, limbPos->z, MTXMODE_NEW);
- Matrix_NormalizeXYZ(&globalCtx->billboardMtxF);
+ Matrix_Translate(limbPos->x, limbPos->y, limbPos->z, MTXMODE_NEW);
+ Matrix_ReplaceRotation(&globalCtx->billboardMtxF);
Matrix_Scale(steamScale, steamScale, 1.0f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
@@ -4624,7 +4626,7 @@ void Actor_DrawDamageEffects(GlobalContext* globalCtx, Actor* actor, Vec3f limbP
type = 255;
}
- Matrix_SetCurrentState(&globalCtx->billboardMtxF);
+ Matrix_Put(&globalCtx->billboardMtxF);
Matrix_Scale((effectScale * 0.005f) * 1.35f, (effectScale * 0.005f), (effectScale * 0.005f) * 1.35f,
MTXMODE_APPLY);
@@ -4650,7 +4652,7 @@ void Actor_DrawDamageEffects(GlobalContext* globalCtx, Actor* actor, Vec3f limbP
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 0, 0, 32, 64, 1, 0,
((limbIndex * 10 + gameplayFrames) * -20) & 0x1FF, 32, 128));
- Matrix_InsertYRotation_f(M_PI, MTXMODE_APPLY);
+ Matrix_RotateYF(M_PI, MTXMODE_APPLY);
currentMatrix->mf[3][0] = limbPos->x;
currentMatrix->mf[3][1] = limbPos->y;
currentMatrix->mf[3][2] = limbPos->z;
@@ -4687,12 +4689,12 @@ void Actor_DrawDamageEffects(GlobalContext* globalCtx, Actor* actor, Vec3f limbP
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 100, 128);
}
- Matrix_SetCurrentState(&globalCtx->billboardMtxF);
+ Matrix_Put(&globalCtx->billboardMtxF);
Matrix_Scale(lightOrbsScale, lightOrbsScale, 1.0f, MTXMODE_APPLY);
// Apply and draw a light orb over each limb of frozen actor
for (limbIndex = 0; limbIndex < limbPosCount; limbIndex++, limbPos++) {
- Matrix_InsertZRotation_f(randPlusMinusPoint5Scaled(2 * M_PI), MTXMODE_APPLY);
+ Matrix_RotateZF(randPlusMinusPoint5Scaled(2 * M_PI), MTXMODE_APPLY);
currentMatrix->mf[3][0] = limbPos->x;
currentMatrix->mf[3][1] = limbPos->y;
currentMatrix->mf[3][2] = limbPos->z;
@@ -4725,14 +4727,14 @@ void Actor_DrawDamageEffects(GlobalContext* globalCtx, Actor* actor, Vec3f limbP
gDPSetEnvColor(POLY_XLU_DISP++, (u8)(sREG(20) + 255), (u8)(sREG(21) + 255), (u8)sREG(22), (u8)sREG(23));
- Matrix_SetCurrentState(&globalCtx->billboardMtxF);
+ Matrix_Put(&globalCtx->billboardMtxF);
Matrix_Scale(electricSparksScale, electricSparksScale, electricSparksScale, MTXMODE_APPLY);
// Every limb draws two electric sparks at random orientations
for (limbIndex = 0; limbIndex < limbPosCount; limbIndex++, limbPos++) {
// first electric spark
- Matrix_RotateStateAroundXAxis(Rand_ZeroFloat(2 * M_PI));
- Matrix_InsertZRotation_f(Rand_ZeroFloat(2 * M_PI), MTXMODE_APPLY);
+ Matrix_RotateXFApply(Rand_ZeroFloat(2 * M_PI));
+ Matrix_RotateZF(Rand_ZeroFloat(2 * M_PI), MTXMODE_APPLY);
currentMatrix->mf[3][0] = randPlusMinusPoint5Scaled((f32)sREG(24) + 30.0f) + limbPos->x;
currentMatrix->mf[3][1] = randPlusMinusPoint5Scaled((f32)sREG(24) + 30.0f) + limbPos->y;
currentMatrix->mf[3][2] = randPlusMinusPoint5Scaled((f32)sREG(24) + 30.0f) + limbPos->z;
@@ -4743,8 +4745,8 @@ void Actor_DrawDamageEffects(GlobalContext* globalCtx, Actor* actor, Vec3f limbP
gSPDisplayList(POLY_XLU_DISP++, gElectricSparkVtxDL);
// second electric spark
- Matrix_RotateStateAroundXAxis(Rand_ZeroFloat(2 * M_PI));
- Matrix_InsertZRotation_f(Rand_ZeroFloat(2 * M_PI), MTXMODE_APPLY);
+ Matrix_RotateXFApply(Rand_ZeroFloat(2 * M_PI));
+ Matrix_RotateZF(Rand_ZeroFloat(2 * M_PI), MTXMODE_APPLY);
currentMatrix->mf[3][0] = randPlusMinusPoint5Scaled((f32)sREG(24) + 30.0f) + limbPos->x;
currentMatrix->mf[3][1] = randPlusMinusPoint5Scaled((f32)sREG(24) + 30.0f) + limbPos->y;
currentMatrix->mf[3][2] = randPlusMinusPoint5Scaled((f32)sREG(24) + 30.0f) + limbPos->z;
@@ -4780,7 +4782,7 @@ void Actor_SpawnIceEffects(GlobalContext* globalCtx, Actor* actor, Vec3f limbPos
yaw = Actor_YawToPoint(actor, limbPos);
for (j = 0; j < effectsPerLimb; j++) {
- randomYaw = (Rand_Next() >> 0x13) + yaw;
+ randomYaw = ((s32)Rand_Next() >> 0x13) + yaw;
velocity.z = Rand_ZeroFloat(5.0f);
diff --git a/src/code/z_bgcheck.c b/src/code/z_bgcheck.c
index f0ebe5911..0667bd84b 100644
--- a/src/code/z_bgcheck.c
+++ b/src/code/z_bgcheck.c
@@ -248,20 +248,20 @@ void func_800C0094(CollisionPoly* poly, f32 tx, f32 ty, f32 tz, MtxF* dest) {
phi_f12 = 0.0f;
}
dest->xx = z_f14;
- dest->xy = (-nx) * phi_f14;
- dest->xz = (-nx) * phi_f12;
- dest->yx = nx;
+ dest->yx = (-nx) * phi_f14;
+ dest->zx = (-nx) * phi_f12;
+ dest->xy = nx;
dest->yy = ny;
- dest->yz = nz;
- dest->zx = 0.0f;
- dest->zy = -phi_f12;
+ dest->zy = nz;
+ dest->xz = 0.0f;
+ dest->yz = -phi_f12;
dest->zz = phi_f14;
- dest->wx = tx;
- dest->wy = ty;
- dest->wz = tz;
- dest->xw = 0.0f;
- dest->yw = 0.0f;
- dest->zw = 0.0f;
+ dest->xw = tx;
+ dest->yw = ty;
+ dest->zw = tz;
+ dest->wx = 0.0f;
+ dest->wy = 0.0f;
+ dest->wz = 0.0f;
dest->ww = 1.0f;
}
@@ -4208,9 +4208,6 @@ s32 func_800C9AE4(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) {
return (func_800C9A4C(colCtx, poly, bgId) & 4) ? true : false;
}
-/**
- * unused
- */
u32 func_800C9B18(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) {
return SurfaceType_GetData(colCtx, poly, bgId, 0) >> 26 & 0xF;
}
diff --git a/src/code/z_collision_check.c b/src/code/z_collision_check.c
index a08e3f822..7ac956e5d 100644
--- a/src/code/z_collision_check.c
+++ b/src/code/z_collision_check.c
@@ -3691,7 +3691,7 @@ void Collider_UpdateSpheres(s32 limb, ColliderJntSph* collider) {
D_801EE1C0.x = collider->elements[i].dim.modelSphere.center.x;
D_801EE1C0.y = collider->elements[i].dim.modelSphere.center.y;
D_801EE1C0.z = collider->elements[i].dim.modelSphere.center.z;
- Matrix_MultiplyVector3fByState(&D_801EE1C0, &D_801EE1D0);
+ Matrix_MultVec3f(&D_801EE1C0, &D_801EE1D0);
collider->elements[i].dim.worldSphere.center.x = D_801EE1D0.x;
collider->elements[i].dim.worldSphere.center.y = D_801EE1D0.y;
collider->elements[i].dim.worldSphere.center.z = D_801EE1D0.z;
@@ -3733,7 +3733,7 @@ void Collider_UpdateSphere(s32 limb, ColliderSphere* collider) {
D_801EE1E0.x = collider->dim.modelSphere.center.x;
D_801EE1E0.y = collider->dim.modelSphere.center.y;
D_801EE1E0.z = collider->dim.modelSphere.center.z;
- Matrix_MultiplyVector3fByState(&D_801EE1E0, &D_801EE1F0);
+ Matrix_MultVec3f(&D_801EE1E0, &D_801EE1F0);
collider->dim.worldSphere.center.x = D_801EE1F0.x;
collider->dim.worldSphere.center.y = D_801EE1F0.y;
collider->dim.worldSphere.center.z = D_801EE1F0.z;
diff --git a/src/code/z_debug_display.c b/src/code/z_debug_display.c
index ab3478fa1..fb7378751 100644
--- a/src/code/z_debug_display.c
+++ b/src/code/z_debug_display.c
@@ -68,10 +68,10 @@ void DebugDisplay_DrawSpriteI8(DebugDispObject* dispObj, void* texture, GlobalCo
func_8012C6FC(globalCtx->state.gfxCtx);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, dispObj->color.r, dispObj->color.g, dispObj->color.b, dispObj->color.a);
- Matrix_InsertTranslation(dispObj->pos.x, dispObj->pos.y, dispObj->pos.z, MTXMODE_NEW);
+ Matrix_Translate(dispObj->pos.x, dispObj->pos.y, dispObj->pos.z, MTXMODE_NEW);
Matrix_Scale(dispObj->scale.x, dispObj->scale.y, dispObj->scale.z, MTXMODE_APPLY);
- Matrix_InsertMatrix(&globalCtx->billboardMtxF, MTXMODE_APPLY);
- Matrix_InsertRotation(dispObj->rot.x, dispObj->rot.y, dispObj->rot.z, MTXMODE_APPLY);
+ Matrix_Mult(&globalCtx->billboardMtxF, MTXMODE_APPLY);
+ Matrix_RotateZYX(dispObj->rot.x, dispObj->rot.y, dispObj->rot.z, MTXMODE_APPLY);
gDPLoadTextureBlock(POLY_XLU_DISP++, texture, G_IM_FMT_I, G_IM_SIZ_8b, 16, 16, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
@@ -94,7 +94,7 @@ void DebugDisplay_DrawPolygon(DebugDispObject* dispObj, void* arg1, GlobalContex
gSPSetLights1(POLY_XLU_DISP++, sDebugDisplayLight1);
- Matrix_SetStateRotationAndTranslation(dispObj->pos.x, dispObj->pos.y, dispObj->pos.z, &dispObj->rot);
+ Matrix_SetTranslateRotateYXZ(dispObj->pos.x, dispObj->pos.y, dispObj->pos.z, &dispObj->rot);
Matrix_Scale(dispObj->scale.x, dispObj->scale.y, dispObj->scale.z, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
diff --git a/src/code/z_demo.c b/src/code/z_demo.c
index c9c6253d3..67a4d5608 100644
--- a/src/code/z_demo.c
+++ b/src/code/z_demo.c
@@ -132,7 +132,6 @@ void Cutscene_Command_Misc(GlobalContext* globalCtx2, CutsceneContext* csCtx, Cs
u8 isStartFrame = false;
f32 progress;
SceneTableEntry* loadedScene;
- u16 time;
if ((csCtx->frames < cmd->startFrame) || ((csCtx->frames >= cmd->endFrame) && (cmd->endFrame != cmd->startFrame))) {
return;
@@ -250,11 +249,9 @@ void Cutscene_Command_Misc(GlobalContext* globalCtx2, CutsceneContext* csCtx, Cs
break;
case 0x12:
if (!gSaveContext.save.isNight) {
- time = gSaveContext.save.time;
- gSaveContext.save.time = time - (u16)REG(15);
+ gSaveContext.save.time = ((void)0, gSaveContext.save.time) - (u16)REG(15);
} else {
- time = gSaveContext.save.time;
- gSaveContext.save.time = time - (u16)(2 * REG(15));
+ gSaveContext.save.time = ((void)0, gSaveContext.save.time) - (u16)(2 * REG(15));
}
break;
case 0x13:
@@ -328,10 +325,9 @@ void Cutscene_Command_Misc(GlobalContext* globalCtx2, CutsceneContext* csCtx, Cs
D_801BB15C = csCtx->frames;
if (REG(15) != 0) {
- time = gSaveContext.save.time;
- gSaveContext.save.time = (u16)REG(15) + time;
- time = gSaveContext.save.time;
- gSaveContext.save.time = (u16)gSaveContext.save.daySpeed + time;
+ gSaveContext.save.time = ((void)0, gSaveContext.save.time) + (u16)REG(15);
+ gSaveContext.save.time =
+ ((void)0, gSaveContext.save.time) + (u16)((void)0, gSaveContext.save.daySpeed);
}
}
break;
@@ -921,7 +917,7 @@ s32 Cutscene_Command_Camera(GlobalContext* globalCtx, u8* cmd) {
bcopy(cmd, &sp1C, sizeof(s32));
cmd += sizeof(s32);
- if (func_8016A168() == 0) {
+ if (!Play_IsDebugCamEnabled()) {
func_80161998(cmd, &sCutsceneCameraInfo);
}
return sp1C + sizeof(s32);
diff --git a/src/code/z_eff_footmark.c b/src/code/z_eff_footmark.c
index d246aaffa..f959867fe 100644
--- a/src/code/z_eff_footmark.c
+++ b/src/code/z_eff_footmark.c
@@ -106,7 +106,7 @@ void EffFootmark_Draw(GlobalContext* globalCtx) {
for (footmark = globalCtx->footprintInfo, i = 0; i < 100; i++, footmark++) {
if (footmark->actor != NULL) {
- Matrix_SetCurrentState(&footmark->displayMatrix);
+ Matrix_Put(&footmark->displayMatrix);
Matrix_Scale(footmark->size * (1.0f / 0x100) * 0.7f, 1, footmark->size * (1.0f / 0x100), MTXMODE_APPLY);
gSPMatrix(gfxCtx->polyXlu.p++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD);
diff --git a/src/code/z_effect_soft_sprite.c b/src/code/z_effect_soft_sprite.c
index fd1d0212c..56eab9e8a 100644
--- a/src/code/z_effect_soft_sprite.c
+++ b/src/code/z_effect_soft_sprite.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "z64load.h"
EffectSsInfo sEffectSsInfo = { NULL, 0, 0 };
diff --git a/src/code/z_effect_soft_sprite_old_init.c b/src/code/z_effect_soft_sprite_old_init.c
index 0300144e1..1e9b25573 100644
--- a/src/code/z_effect_soft_sprite_old_init.c
+++ b/src/code/z_effect_soft_sprite_old_init.c
@@ -206,21 +206,21 @@ void func_800B1598(GlobalContext* globalCtx, f32 randScale, Vec3f* srcPos) {
}
}
-void EffectSsKiraKira_SpawnSmallYellow(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel) {
+void EffectSsKirakira_SpawnSmallYellow(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel) {
Color_RGBA8 primColor = { 255, 255, 200, 255 };
Color_RGBA8 envColor = { 255, 200, 0, 0 };
- EffectSsKiraKira_SpawnDispersed(globalCtx, pos, velocity, accel, &primColor, &envColor, 1000, 16);
+ EffectSsKirakira_SpawnDispersed(globalCtx, pos, velocity, accel, &primColor, &envColor, 1000, 16);
}
-void EffectSsKiraKira_SpawnSmall(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel,
+void EffectSsKirakira_SpawnSmall(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel,
Color_RGBA8* primColor, Color_RGBA8* envColor) {
- EffectSsKiraKira_SpawnDispersed(globalCtx, pos, velocity, accel, primColor, envColor, 1000, 16);
+ EffectSsKirakira_SpawnDispersed(globalCtx, pos, velocity, accel, primColor, envColor, 1000, 16);
}
-void EffectSsKiraKira_SpawnDispersed(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel,
+void EffectSsKirakira_SpawnDispersed(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel,
Color_RGBA8* primColor, Color_RGBA8* envColor, s16 scale, s32 life) {
- EffectSsKiraKiraInitParams initParams;
+ EffectSsKirakiraInitParams initParams;
Math_Vec3f_Copy(&initParams.pos, pos);
Math_Vec3f_Copy(&initParams.velocity, velocity);
@@ -239,9 +239,9 @@ void EffectSsKiraKira_SpawnDispersed(GlobalContext* globalCtx, Vec3f* pos, Vec3f
EffectSs_Spawn(globalCtx, EFFECT_SS_KIRAKIRA, 128, &initParams);
}
-void EffectSsKiraKira_SpawnFocused(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel,
+void EffectSsKirakira_SpawnFocused(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel,
Color_RGBA8* primColor, Color_RGBA8* envColor, s16 scale, s32 life) {
- EffectSsKiraKiraInitParams initParams;
+ EffectSsKirakiraInitParams initParams;
Math_Vec3f_Copy(&initParams.pos, pos);
Math_Vec3f_Copy(&initParams.velocity, velocity);
diff --git a/src/code/z_en_item00.c b/src/code/z_en_item00.c
index b8fa0f4f1..7ba6134fb 100644
--- a/src/code/z_en_item00.c
+++ b/src/code/z_en_item00.c
@@ -68,9 +68,9 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) {
f32 shadowOffset = 980.0f;
f32 shadowScale = 6.0f;
s32 getItemId = GI_NONE;
- s32 sp30 = (this->actor.params & 0x8000) ? 1 : 0;
+ s32 sp30 = ENITEM00_GET_8000(&this->actor) ? 1 : 0;
- this->collectibleFlag = (this->actor.params & 0x7F00) >> 8;
+ this->collectibleFlag = ENITEM00_GET_7F00(&this->actor);
thisx->params &= 0xFF; // Has to be thisx to match
@@ -346,7 +346,7 @@ void func_800A6650(EnItem00* this, GlobalContext* globalCtx) {
pos.x = this->actor.world.pos.x + randPlusMinusPoint5Scaled(10.0f);
pos.y = this->actor.world.pos.y + randPlusMinusPoint5Scaled(10.0f);
pos.z = this->actor.world.pos.z + randPlusMinusPoint5Scaled(10.0f);
- EffectSsKiraKira_SpawnSmall(globalCtx, &pos, &D_801ADF18, &D_801ADF24, &D_801ADF10, &D_801ADF14);
+ EffectSsKirakira_SpawnSmall(globalCtx, &pos, &D_801ADF18, &D_801ADF24, &D_801ADF10, &D_801ADF14);
}
if ((this->actor.bgCheckFlags & 3) != 0) {
if (this->actor.velocity.y > -2.0f) {
@@ -403,7 +403,7 @@ void func_800A6780(EnItem00* this, GlobalContext* globalCtx) {
pos.x = this->actor.world.pos.x + ((Rand_ZeroOne() - 0.5f) * 10.0f);
pos.y = this->actor.world.pos.y + ((Rand_ZeroOne() - 0.5f) * 10.0f);
pos.z = this->actor.world.pos.z + ((Rand_ZeroOne() - 0.5f) * 10.0f);
- EffectSsKiraKira_SpawnSmall(globalCtx, &pos, &D_801ADF18, &D_801ADF24, &D_801ADF10, &D_801ADF14);
+ EffectSsKirakira_SpawnSmall(globalCtx, &pos, &D_801ADF18, &D_801ADF24, &D_801ADF10, &D_801ADF14);
}
if (this->actor.bgCheckFlags & 0x0003) {
@@ -815,8 +815,6 @@ void EnItem00_DrawHeartPiece(EnItem00* this, GlobalContext* globalCtx) {
}
s16 func_800A7650(s16 dropId) {
- s16 healthCapacity;
-
if ((((dropId == ITEM00_BOMBS_A) || (dropId == ITEM00_BOMBS_0) || (dropId == ITEM00_BOMBS_B)) &&
(INV_CONTENT(ITEM_BOMB) == ITEM_NONE)) ||
(((dropId == ITEM00_ARROWS_10) || (dropId == ITEM00_ARROWS_30) || (dropId == ITEM00_ARROWS_40) ||
@@ -828,8 +826,7 @@ s16 func_800A7650(s16 dropId) {
}
if (dropId == ITEM00_HEART) {
- healthCapacity = gSaveContext.save.playerData.healthCapacity;
- if (healthCapacity == gSaveContext.save.playerData.health) {
+ if (((void)0, gSaveContext.save.playerData.healthCapacity) == ((void)0, gSaveContext.save.playerData.health)) {
return ITEM00_RUPEE_GREEN;
}
}
@@ -1188,6 +1185,6 @@ s32 func_800A817C(s32 index) {
return D_801AE214[index];
}
-s32 func_800A81A4(GlobalContext* globalCtx, s32 a1, s32 a2) {
- return (func_800A8150(a1) == ITEM00_BIG_FAIRY) && (!Flags_GetCollectible(globalCtx, a2));
+s32 Item_CanDropBigFairy(GlobalContext* globalCtx, s32 index, s32 collectibleFlag) {
+ return (func_800A8150(index) == ITEM00_BIG_FAIRY) && (!Flags_GetCollectible(globalCtx, collectibleFlag));
}
diff --git a/src/code/z_fcurve_data.c b/src/code/z_fcurve_data.c
index a0bf887e1..5c0aa066a 100644
--- a/src/code/z_fcurve_data.c
+++ b/src/code/z_fcurve_data.c
@@ -1,5 +1,86 @@
+/**
+ * @file z_fcurve_data.c
+ * @brief Interpolation functions for use with Curve SkelAnime
+ */
#include "global.h"
+#include "z64curve.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data/func_800F23E0.s")
+#define FCURVE_INTERP_CUBIC 0 // Interpolate using a Hermite cubic spline
+#define FCURVE_INTERP_NONE 1 // Return the value at the left endpoint instead of interpolating
+#define FCURVE_INTERP_LINEAR 2 // Interpolate linearly
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data/func_800F2478.s")
+/**
+ * Hermite cubic spline interpolation between two endpoints, a,b. More information available at
+ * https://en.wikipedia.org/wiki/Cubic_Hermite_spline
+ *
+ * @param t interpolation parameter rescaled to lie in [0,1], (x-a)/(b-a)
+ * @param interval distance (b-a) between the endpoints
+ * @param y0 p(a)
+ * @param y1 p(b)
+ * @param m0 p'(a)
+ * @param m1 p'(b)
+ * @return f32 p(t), value of the cubic interpolating polynomial
+ */
+f32 Curve_CubicHermiteSpline(f32 t, f32 interval, f32 y0, f32 y1, f32 m0, f32 m1) {
+ f32 t2 = t * t;
+ f32 t3 = t2 * t;
+ f32 t3x2 = t3 * 2.0f;
+ f32 t2x3 = t2 * 3.0f;
+
+ // Hermite basis cubics h_{ij} satisfy h_{ij}^{(j)}(i) = 1, the other three values being 0
+ f32 h00 = t3x2 - t2x3 + 1.0f; // h_{00}(t) = 2t^3 - 3t^2 + 1
+ f32 h01 = t2x3 - t3x2; // h_{01}(t) = 3t^2 - 2t^3
+ f32 h10 = t3 - t2 * 2.0f + t; // h_{10}(t) = t^3 - 2t^2 + t
+ f32 h11 = t3 - t2; // h_{11}(t) = t^3 - t^2
+
+ f32 ret = h00 * y0;
+
+ ret += h01 * y1;
+ ret += h10 * m0 * interval;
+ ret += h11 * m1 * interval;
+
+ return ret;
+}
+
+/**
+ * Interpolates based on an array of CurveInterpKnot.
+ *
+ * @param x point at which to interpolate.
+ * @param knots Beginning of CurveInterpKnot array to use.
+ * @param knotCount number of knots to read from the array.
+ * @return f32 interpolated value
+ */
+f32 Curve_Interpolate(f32 x, CurveInterpKnot* knots, s32 knotCount) {
+ // If outside the entire interpolation interval, return the value at the near endpoint.
+ if (x <= knots[0].abscissa) {
+ return knots[0].ordinate;
+ } else if (x >= knots[knotCount - 1].abscissa) {
+ return knots[knotCount - 1].ordinate;
+ } else {
+ s32 cur;
+
+ for (cur = 0;; cur++) {
+ s32 next = cur + 1;
+
+ // Find the subinterval in which x lies
+ if (x < knots[next].abscissa) {
+ if (knots[cur].flags & FCURVE_INTERP_NONE) {
+ // No interpolation
+ return knots[cur].ordinate;
+ } else if (knots[cur].flags & FCURVE_INTERP_LINEAR) {
+ // Linear interpolation
+ return knots[cur].ordinate +
+ ((x - (f32)knots[cur].abscissa) / ((f32)knots[next].abscissa - (f32)knots[cur].abscissa)) *
+ (knots[next].ordinate - knots[cur].ordinate);
+ } else {
+ // Cubic interpolation
+ f32 diff = (f32)knots[next].abscissa - (f32)knots[cur].abscissa;
+ f32 t = (x - (f32)knots[cur].abscissa) / ((f32)knots[next].abscissa - (f32)knots[cur].abscissa);
+
+ return Curve_CubicHermiteSpline(t, diff * (1.0f / 30.0f), knots[cur].ordinate, knots[next].ordinate,
+ knots[cur].rightGradient, knots[next].leftGradient);
+ }
+ }
+ }
+ }
+}
diff --git a/src/code/z_fcurve_data_skelanime.c b/src/code/z_fcurve_data_skelanime.c
index e22b5f351..b40a1c351 100644
--- a/src/code/z_fcurve_data_skelanime.c
+++ b/src/code/z_fcurve_data_skelanime.c
@@ -1,132 +1,189 @@
+/**
+ * @file z_fcurve_data_skelanime.c
+ * @brief Curve skeleton animation system
+ *
+ * A curve skeleton has a fixed number of limbs, each of which has 9 properties that may be changed by the animation:
+ * - 3 scales,
+ * - 3 rotations,
+ * - 3 positions
+ * (note the position is stored in the animations instead of being stored in the limbs like SkelAnime would). Otherwise
+ * the structure is similar to an ordinary SkelAnime-compatible skeleton.
+ *
+ * The animations are significantly more complex than SkelAnime. A curve animation consists of 4 parts:
+ * - a header (CurveAnimationHeader)
+ * - a list of counts, one for each of the 9 properties of each limb (u8)
+ * - a list of interpolation data (CurveInterpKnot). The length is the sum of the counts.
+ * - a list of constant data (s16[9]). The length is the number of 0s in counts.
+ *
+ * If the interpolation count for a property is 0, the value of the property is copied from the next number in the
+ * constant data; there are no gaps for nonzero interpolation count.
+ * If the interpolation count N for a property is larger than 0, the next N elements of the interpolation data array
+ * are used to interpolate the value of the property, using Curve_Interpolate.
+ *
+ * Curve limbs may use LOD:
+ * - lower detail draws only the first displaylist
+ * - higher detail draws both.
+ */
+
#include "global.h"
+#include "z64curve.h"
-void SkelCurve_Clear(SkelAnimeCurve* skelCurve) {
+void SkelCurve_Clear(SkelCurve* skelCurve) {
skelCurve->limbCount = 0;
- skelCurve->limbList = NULL;
- skelCurve->transUpdIdx = NULL;
- skelCurve->animCurFrame = 0.0f;
- skelCurve->animSpeed = 0.0f;
- skelCurve->animFinalFrame = 0.0f;
- skelCurve->unk0C = 0.0f;
- skelCurve->transforms = NULL;
+ skelCurve->skeleton = NULL;
+ skelCurve->animation = NULL;
+ skelCurve->curFrame = 0.0f;
+ skelCurve->playSpeed = 0.0f;
+ skelCurve->endFrame = 0.0f;
+ skelCurve->unk_0C = 0.0f;
+ skelCurve->jointTable = NULL;
}
-s32 SkelCurve_Init(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve, SkelCurveLimbList* limbListSeg,
- TransformUpdateIndex* transUpdIdx) {
+/**
+ * Initialises the SkelCurve struct and mallocs the joint table.
+ *
+ * @return bool always true
+ */
+s32 SkelCurve_Init(GlobalContext* globalCtx, SkelCurve* skelCurve, CurveSkeletonHeader* skeletonHeaderSeg,
+ CurveAnimationHeader* animation) {
SkelCurveLimb** limbs;
- SkelCurveLimbList* limbList = Lib_SegmentedToVirtual(limbListSeg);
+ CurveSkeletonHeader* skeletonHeader = Lib_SegmentedToVirtual(skeletonHeaderSeg);
- skelCurve->limbCount = limbList->limbCount;
- skelCurve->limbList = Lib_SegmentedToVirtual(limbList->limbs);
+ skelCurve->limbCount = skeletonHeader->limbCount;
+ skelCurve->skeleton = Lib_SegmentedToVirtual(skeletonHeader->limbs);
- skelCurve->transforms = ZeldaArena_Malloc(sizeof(*skelCurve->transforms) * skelCurve->limbCount);
+ skelCurve->jointTable = ZeldaArena_Malloc(sizeof(*skelCurve->jointTable) * skelCurve->limbCount);
- do {
- skelCurve->animCurFrame = 0.0f;
- } while (0);
- return 1;
+ skelCurve->curFrame = 0.0f;
+ return true;
}
-void SkelCurve_Destroy(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve) {
- if (skelCurve->transforms != NULL) {
- ZeldaArena_Free(skelCurve->transforms);
+/**
+ * Frees the joint table.
+ */
+void SkelCurve_Destroy(GlobalContext* globalCtx, SkelCurve* skelCurve) {
+ if (skelCurve->jointTable != NULL) {
+ ZeldaArena_Free(skelCurve->jointTable);
}
}
-void SkelCurve_SetAnim(SkelAnimeCurve* skelCurve, TransformUpdateIndex* transUpdIdx, f32 arg2, f32 animFinalFrame,
- f32 animCurFrame, f32 animSpeed) {
- skelCurve->unk0C = arg2 - skelCurve->animSpeed;
- skelCurve->animFinalFrame = animFinalFrame;
- skelCurve->animCurFrame = animCurFrame;
- skelCurve->animSpeed = animSpeed;
- skelCurve->transUpdIdx = transUpdIdx;
+void SkelCurve_SetAnim(SkelCurve* skelCurve, CurveAnimationHeader* animation, f32 arg2, f32 endFrame, f32 curFrame,
+ f32 playSpeed) {
+ skelCurve->unk_0C = arg2 - skelCurve->playSpeed;
+ skelCurve->endFrame = endFrame;
+ skelCurve->curFrame = curFrame;
+ skelCurve->playSpeed = playSpeed;
+ skelCurve->animation = animation;
}
-#ifdef NON_MATCHING
-/* Should be functionally equivalent, also migrating rodata makes it a lot cleaner */
-s32 SkelCurve_Update(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve) {
- s16* transforms;
- u8* transformRefIdx;
- TransformUpdateIndex* transformIndex;
- u16* transformCopyValues;
- s32 i;
- s32 ret = 0;
- s32 k;
- TransformData* transData;
- f32 transformValue;
- s32 j;
-
- transformIndex = Lib_SegmentedToVirtual(skelCurve->transUpdIdx);
- transformRefIdx = Lib_SegmentedToVirtual(transformIndex->refIndex);
- transData = Lib_SegmentedToVirtual(transformIndex->transformData);
- transformCopyValues = Lib_SegmentedToVirtual(transformIndex->copyValues);
- transforms = (s16*)skelCurve->transforms;
-
- skelCurve->animCurFrame += skelCurve->animSpeed * (globalCtx->state.framerateDivisor * 0.5f);
-
- if ((skelCurve->animSpeed >= 0.0f && skelCurve->animCurFrame > skelCurve->animFinalFrame) ||
- (skelCurve->animSpeed < 0.0f && skelCurve->animCurFrame < skelCurve->animFinalFrame)) {
- skelCurve->animCurFrame = skelCurve->animFinalFrame;
- ret = 1;
+typedef enum {
+ /* 0 */ SKELCURVE_VEC_TYPE_SCALE,
+ /* 1 */ SKELCURVE_VEC_TYPE_ROTATION,
+ /* 2 */ SKELCURVE_VEC_TYPE_POSIITON,
+ /* 3 */ SKELCURVE_VEC_TYPE_MAX
+} SkelCurveVecType;
+
+#define SKELCURVE_SCALE_SCALE 1024.0f
+#define SKELCURVE_SCALE_POSITION 100
+
+/**
+ * The only animation updating function.
+ *
+ * @return bool true when the animation has finished.
+ */
+s32 SkelCurve_Update(GlobalContext* globalCtx, SkelCurve* skelCurve) {
+ s16* jointData;
+ u8* knotCounts;
+ CurveAnimationHeader* animation;
+ u16* constantData;
+ s32 curLimb;
+ s32 ret = false;
+ s32 coord;
+ CurveInterpKnot* startKnot;
+ s32 vecType;
+
+ animation = Lib_SegmentedToVirtual(skelCurve->animation);
+ knotCounts = Lib_SegmentedToVirtual(animation->knotCounts);
+ startKnot = Lib_SegmentedToVirtual(animation->interpolationData);
+ constantData = Lib_SegmentedToVirtual(animation->constantData);
+ jointData = *skelCurve->jointTable;
+
+ skelCurve->curFrame += skelCurve->playSpeed * ((s32)globalCtx->state.framerateDivisor * 0.5f);
+
+ if (((skelCurve->playSpeed >= 0.0f) && (skelCurve->curFrame > skelCurve->endFrame)) ||
+ ((skelCurve->playSpeed < 0.0f) && (skelCurve->curFrame < skelCurve->endFrame))) {
+ skelCurve->curFrame = skelCurve->endFrame;
+ ret = true;
}
- for (i = 0; i < skelCurve->limbCount; i++) {
- for (j = 0; j < 3; j++) {
- for (k = 0; k < 3; k++, transformRefIdx++, transforms++) {
- if (*transformRefIdx == 0) {
- transformValue = *transformCopyValues;
- *transforms = transformValue;
- transformCopyValues++;
+ for (curLimb = 0; curLimb < skelCurve->limbCount; curLimb++) {
+
+ // scale/rotation/position
+ for (vecType = SKELCURVE_VEC_TYPE_SCALE; vecType < SKELCURVE_VEC_TYPE_MAX; vecType++) {
+
+ // x/y/z
+ for (coord = 0; coord < 3; coord++) {
+ f32 transformValue;
+
+ if (*knotCounts == 0) {
+ transformValue = *constantData;
+ *jointData = transformValue;
+ constantData++;
} else {
- transformValue = func_800F2478(skelCurve->animCurFrame, transData, *transformRefIdx);
- transData += *transformRefIdx;
- if (j == 0) {
- *transforms = transformValue * 1024.0f;
- } else if (j == 1) {
- *transforms = transformValue * (32768.0f / 180.0f);
- } else {
- *transforms = transformValue * 100.0f;
+ transformValue = Curve_Interpolate(skelCurve->curFrame, startKnot, *knotCounts);
+ startKnot += *knotCounts;
+ if (vecType == SKELCURVE_VEC_TYPE_SCALE) {
+ // Rescaling allows for more refined scaling using an s16
+ *jointData = transformValue * SKELCURVE_SCALE_SCALE;
+ } else if (vecType == SKELCURVE_VEC_TYPE_ROTATION) {
+ // Convert value from degrees to a binary angle
+ *jointData = DEG_TO_BINANG(transformValue);
+ } else { // SKELCURVE_VEC_TYPE_POSIITON
+ // Model to world scale conversion
+ *jointData = transformValue * SKELCURVE_SCALE_POSITION;
}
}
+ knotCounts++;
+ jointData++;
}
}
}
return ret;
}
-#else
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data_skelanime/SkelCurve_Update.s")
-#endif
-void SkelCurve_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, SkelAnimeCurve* skelCurve,
+/**
+ * Recursively draws limbs with appropriate properties.
+ */
+void SkelCurve_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, SkelCurve* skelCurve,
OverrideCurveLimbDraw overrideLimbDraw, PostCurveLimbDraw postLimbDraw, s32 lod, Actor* thisx) {
- SkelCurveLimb* limb = Lib_SegmentedToVirtual(skelCurve->limbList[limbIndex]);
+ SkelCurveLimb* limb = Lib_SegmentedToVirtual(skelCurve->skeleton[limbIndex]);
OPEN_DISPS(globalCtx->state.gfxCtx);
- Matrix_StatePush();
+ Matrix_Push();
- if (overrideLimbDraw == NULL ||
- (overrideLimbDraw != NULL && overrideLimbDraw(globalCtx, skelCurve, limbIndex, thisx))) {
+ if ((overrideLimbDraw == NULL) ||
+ ((overrideLimbDraw != NULL) && overrideLimbDraw(globalCtx, skelCurve, limbIndex, thisx))) {
Vec3f scale;
Vec3s rot;
Vec3f pos;
Gfx* dList;
- Vec3s* transform = (Vec3s*)&skelCurve->transforms[limbIndex];
-
- scale.x = transform->x / 1024.0f;
- scale.y = transform->y / 1024.0f;
- scale.z = transform->z / 1024.0f;
- transform++;
- rot.x = transform->x;
- rot.y = transform->y;
- rot.z = transform->z;
- transform++;
- pos.x = transform->x;
- pos.y = transform->y;
- pos.z = transform->z;
-
- Matrix_JointPosition(&pos, &rot);
+ s16* jointData = skelCurve->jointTable[limbIndex];
+
+ scale.x = jointData[0] / SKELCURVE_SCALE_SCALE;
+ scale.y = jointData[1] / SKELCURVE_SCALE_SCALE;
+ scale.z = jointData[2] / SKELCURVE_SCALE_SCALE;
+ jointData += 3;
+ rot.x = jointData[0];
+ rot.y = jointData[1];
+ rot.z = jointData[2];
+ jointData += 3;
+ pos.x = jointData[0];
+ pos.y = jointData[1];
+ pos.z = jointData[2];
+
+ Matrix_TranslateRotateZYX(&pos, &rot);
Matrix_Scale(scale.x, scale.y, scale.z, MTXMODE_APPLY);
if (lod == 0) {
@@ -160,22 +217,22 @@ void SkelCurve_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, SkelAnimeCurve*
postLimbDraw(globalCtx, skelCurve, limbIndex, thisx);
}
- if (limb->firstChildIdx != LIMB_DONE) {
- SkelCurve_DrawLimb(globalCtx, limb->firstChildIdx, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
+ if (limb->child != LIMB_DONE) {
+ SkelCurve_DrawLimb(globalCtx, limb->child, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
}
- Matrix_StatePop();
+ Matrix_Pop();
- if (limb->nextLimbIdx != LIMB_DONE) {
- SkelCurve_DrawLimb(globalCtx, limb->nextLimbIdx, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
+ if (limb->sibling != LIMB_DONE) {
+ SkelCurve_DrawLimb(globalCtx, limb->sibling, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
-void SkelCurve_Draw(Actor* actor, GlobalContext* globalCtx, SkelAnimeCurve* skelCurve,
+void SkelCurve_Draw(Actor* actor, GlobalContext* globalCtx, SkelCurve* skelCurve,
OverrideCurveLimbDraw overrideLimbDraw, PostCurveLimbDraw postLimbDraw, s32 lod, Actor* thisx) {
- if (skelCurve->transforms != NULL) {
+ if (skelCurve->jointTable != NULL) {
SkelCurve_DrawLimb(globalCtx, 0, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
}
}
diff --git a/src/code/z_fireobj.c b/src/code/z_fireobj.c
index 379ebda1d..f627c6394 100644
--- a/src/code/z_fireobj.c
+++ b/src/code/z_fireobj.c
@@ -159,7 +159,7 @@ void FireObj_Draw(GlobalContext* globalCtx, FireObj* fire) {
vec.x = 0;
vec.y = Camera_GetCamDirYaw(GET_ACTIVE_CAM(globalCtx)) + 0x8000;
vec.z = 0;
- Matrix_SetStateRotationAndTranslation(fire->position.x, fire->position.y, fire->position.z, &vec);
+ Matrix_SetTranslateRotateYXZ(fire->position.x, fire->position.y, fire->position.z, &vec);
Matrix_Scale(fire->xScale, fire->yScale, 1.0f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
diff --git a/src/code/z_kaleido_manager.c b/src/code/z_kaleido_manager.c
index 5e89f49e9..73656d65d 100644
--- a/src/code/z_kaleido_manager.c
+++ b/src/code/z_kaleido_manager.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "z64load.h"
#define KALEIDO_OVERLAY(name) \
{ \
diff --git a/src/code/z_kaleido_setup.c b/src/code/z_kaleido_setup.c
index 5a234ea44..5ed36d551 100644
--- a/src/code/z_kaleido_setup.c
+++ b/src/code/z_kaleido_setup.c
@@ -60,7 +60,7 @@ void func_800F4A10(GlobalContext* globalCtx) {
}
void KaleidoSetup_Update(GlobalContext* globalCtx) {
- Input* input = CONTROLLER1(globalCtx);
+ Input* input = CONTROLLER1(&globalCtx->state);
MessageContext* msgCtx = &globalCtx->msgCtx;
Player* player = GET_PLAYER(globalCtx);
PauseContext* pauseCtx = &globalCtx->pauseCtx;
diff --git a/src/code/z_lights.c b/src/code/z_lights.c
index 5d47b4153..e9fae530a 100644
--- a/src/code/z_lights.c
+++ b/src/code/z_lights.c
@@ -431,7 +431,7 @@ void Lights_DrawGlow(GlobalContext* globalCtx) {
gDPSetPrimColor(dl++, 0, 0, params->color[0], params->color[1], params->color[2], 50);
- Matrix_InsertTranslation(params->x, params->y, params->z, MTXMODE_NEW);
+ Matrix_Translate(params->x, params->y, params->z, MTXMODE_NEW);
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
gSPMatrix(dl++, Matrix_NewMtx(globalCtx->state.gfxCtx),
diff --git a/src/code/z_message.c b/src/code/z_message.c
index f41c713f6..d8e2d5c8a 100644
--- a/src/code/z_message.c
+++ b/src/code/z_message.c
@@ -67,7 +67,7 @@ void func_80147564(GlobalContext* globalCtx) {
s32 Message_ShouldAdvance(GlobalContext* globalCtx) {
MessageContext* msgCtx = &globalCtx->msgCtx;
- Input* controller = CONTROLLER1(globalCtx);
+ Input* controller = CONTROLLER1(&globalCtx->state);
if ((msgCtx->unk12020 == 0x10) || (msgCtx->unk12020 == 0x11)) {
if (CHECK_BTN_ALL(controller->press.button, BTN_A)) {
@@ -86,7 +86,7 @@ s32 Message_ShouldAdvance(GlobalContext* globalCtx) {
s32 Message_ShouldAdvanceSilent(GlobalContext* globalCtx) {
MessageContext* msgCtx = &globalCtx->msgCtx;
- Input* controller = CONTROLLER1(globalCtx);
+ Input* controller = CONTROLLER1(&globalCtx->state);
if (msgCtx->unk12020 == 0x10 || msgCtx->unk12020 == 0x11) {
return CHECK_BTN_ALL(controller->press.button, BTN_A);
@@ -117,7 +117,7 @@ void func_801477B4(GlobalContext* globalCtx) {
void func_80148B98(GlobalContext* globalCtx, u8 arg1) {
static s16 held = 0;
MessageContext* msgCtx = &globalCtx->msgCtx;
- Input* curInput = CONTROLLER1(globalCtx);
+ Input* curInput = CONTROLLER1(&globalCtx->state);
if ((curInput->rel.stick_y > 29) && held == 0) {
held = 1;
@@ -405,23 +405,23 @@ void func_80151BB4(GlobalContext* globalCtx, u8 arg1) {
u32 func_80151C9C(GlobalContext* globalCtx) {
MessageContext* msgCtx = &globalCtx->msgCtx;
- u8 flag;
while (true) {
if (msgCtx->unk120B1 == 0) {
- return 0;
+ return false;
}
msgCtx->unk120B1--;
if ((gSaveContext.save.weekEventReg[D_801C6B28[msgCtx->unk120B2[msgCtx->unk120B1]] >> 8] &
(u8)D_801C6B28[msgCtx->unk120B2[msgCtx->unk120B1]]) == 0) {
- flag = gSaveContext.save.weekEventReg[D_801C6B28[msgCtx->unk120B2[msgCtx->unk120B1]] >> 8];
gSaveContext.save.weekEventReg[D_801C6B28[msgCtx->unk120B2[msgCtx->unk120B1]] >> 8] =
- flag | (u8)D_801C6B28[msgCtx->unk120B2[msgCtx->unk120B1]];
+ ((void)0, gSaveContext.save.weekEventReg[D_801C6B28[msgCtx->unk120B2[msgCtx->unk120B1]] >> 8]) |
+ (u8)D_801C6B28[msgCtx->unk120B2[msgCtx->unk120B1]];
+
if ((D_801C6AB8[msgCtx->unk120B2[msgCtx->unk120B1]] != 0) && CHECK_QUEST_ITEM(QUEST_BOMBERS_NOTEBOOK)) {
func_80151938(globalCtx, D_801C6AB8[msgCtx->unk120B2[msgCtx->unk120B1]]);
play_sound(NA_SE_SY_SCHEDULE_WRITE);
- return 1;
+ return true;
}
}
}
diff --git a/src/code/z_message_nes.c b/src/code/z_message_nes.c
index 1de839d68..485f016ff 100644
--- a/src/code/z_message_nes.c
+++ b/src/code/z_message_nes.c
@@ -193,29 +193,32 @@ void Message_LoadTimeNES(GlobalContext* globalCtx, u8 arg1, s32* offset, f32* ar
s16 p = *decodedBufPos;
s32 o = *offset;
f32 f = *arg3;
- u32 dayTime;
+ u32 timeLeft;
s16 digits[4];
- f32 timeInMinutes;
- s32 day;
+ f32 timeLeftInMinutes;
s16 i;
if (arg1 == 0xCF) {
- day = gSaveContext.save.day;
- dayTime = 0x40000 - ((day % 5) << 16) - (u16)(-0x4000 + gSaveContext.save.time);
+ // Calculates the time left before the moon crashes.
+ // The day begins at CLOCK_TIME(6, 0) so it must be offset.
+ timeLeft = (4 - CURRENT_DAY) * DAY_LENGTH - (u16)(((void)0, gSaveContext.save.time) - CLOCK_TIME(6, 0));
} else {
- dayTime = 0x10000 - (u16)(-0x4000 + gSaveContext.save.time);
+ // Calculates the time left before a new day.
+ // The day begins at CLOCK_TIME(6, 0) so it must be offset.
+ timeLeft = DAY_LENGTH - (u16)(((void)0, gSaveContext.save.time) - CLOCK_TIME(6, 0));
}
- timeInMinutes = TIME_TO_MINUTES_F(dayTime);
+
+ timeLeftInMinutes = TIME_TO_MINUTES_F(timeLeft);
digits[0] = 0;
- digits[1] = (timeInMinutes / 60.0f);
+ digits[1] = (timeLeftInMinutes / 60.0f);
while (digits[1] >= 10) {
digits[0]++;
digits[1] -= 10;
}
digits[2] = 0;
- digits[3] = (s32)timeInMinutes % 60;
+ digits[3] = (s32)timeLeftInMinutes % 60;
while (digits[3] >= 10) {
digits[2]++;
digits[3] -= 10;
diff --git a/src/code/z_overlay.c b/src/code/z_overlay.c
index f635331c9..a358cefe6 100644
--- a/src/code/z_overlay.c
+++ b/src/code/z_overlay.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "z64load.h"
#pragma GLOBAL_ASM("asm/non_matchings/code/z_overlay/func_801651B0.s")
diff --git a/src/code/z_play.c b/src/code/z_play.c
index aa360934e..7d13ee8ee 100644
--- a/src/code/z_play.c
+++ b/src/code/z_play.c
@@ -309,10 +309,8 @@ s32 Play_IsUnderwater(GlobalContext* globalCtx, Vec3f* pos) {
}
}
-// z_demo and EnTest4
-// This data appears to be a boolean. It is only set by Play_Init.
-s32 func_8016A168(void) {
- return D_801D0D50;
+s32 Play_IsDebugCamEnabled(void) {
+ return gDbgCamEnabled;
}
// A mapping from playerActorCsIds to sGlobalCamDataSettings indices.
diff --git a/src/code/z_rcp.c b/src/code/z_rcp.c
index f4ffd43c1..1d13be316 100644
--- a/src/code/z_rcp.c
+++ b/src/code/z_rcp.c
@@ -1239,11 +1239,11 @@ void func_8012CF0C(GraphicsContext* gfxCtx, s32 clearFb, s32 clearZb, u8 r, u8 g
gSPDisplayList(&masterGfx[0], D_0E000000.syncSegments);
gSPDisplayList(&masterGfx[1], sFillSetupDL);
- gDPSetColorImage(&masterGfx[2], G_IM_FMT_RGBA, G_IM_SIZ_16b, D_801FBBCC, &D_0F000000);
+ gDPSetColorImage(&masterGfx[2], G_IM_FMT_RGBA, G_IM_SIZ_16b, D_801FBBCC, D_0F000000);
if (zbuffer != NULL) {
gDPSetDepthImage(&masterGfx[3], zbuffer);
} else {
- gDPSetDepthImage(&masterGfx[3], &D_0F000000);
+ gDPSetDepthImage(&masterGfx[3], D_0F000000);
}
gSPEndDisplayList(&masterGfx[4]);
@@ -1267,7 +1267,7 @@ void func_8012CF0C(GraphicsContext* gfxCtx, s32 clearFb, s32 clearZb, u8 r, u8 g
gDPSetRenderMode(&masterGfx[3], G_RM_NOOP, G_RM_NOOP2);
gDPSetFillColor(&masterGfx[4], (GPACK_RGBA5551(255, 255, 240, 0) << 16) | GPACK_RGBA5551(255, 255, 240, 0));
gSPDisplayList(&masterGfx[5], D_0E000000.clearFillRect);
- gDPSetColorImage(&masterGfx[6], G_IM_FMT_RGBA, G_IM_SIZ_16b, D_801FBBCC, &D_0F000000);
+ gDPSetColorImage(&masterGfx[6], G_IM_FMT_RGBA, G_IM_SIZ_16b, D_801FBBCC, D_0F000000);
gSPEndDisplayList(&masterGfx[7]);
}
@@ -1275,7 +1275,7 @@ void func_8012CF0C(GraphicsContext* gfxCtx, s32 clearFb, s32 clearZb, u8 r, u8 g
masterGfx = gGfxMasterDL->clearFrameBuffer;
- gDPSetColorImage(&masterGfx[0], G_IM_FMT_RGBA, G_IM_SIZ_16b, D_801FBBCC, &D_0F000000);
+ gDPSetColorImage(&masterGfx[0], G_IM_FMT_RGBA, G_IM_SIZ_16b, D_801FBBCC, D_0F000000);
gDPSetCycleType(&masterGfx[1], G_CYC_FILL);
gDPSetRenderMode(&masterGfx[2], G_RM_NOOP, G_RM_NOOP2);
gDPSetFillColor(&masterGfx[3], (GPACK_RGBA5551(r, g, b, 1) << 16) | GPACK_RGBA5551(r, g, b, 1));
diff --git a/src/code/z_scene.c b/src/code/z_scene.c
index b03990702..b9dbb35dd 100644
--- a/src/code/z_scene.c
+++ b/src/code/z_scene.c
@@ -142,11 +142,9 @@ void* func_8012F73C(ObjectContext* objectCtx, s32 iParm2, s16 id) {
// SceneTableEntry Header Command 0x00: Spawn List
void Scene_HeaderCmdSpawnList(GlobalContext* globalCtx, SceneCmd* cmd) {
- GlobalContext* globalCtx2 = globalCtx;
s32 loadedCount;
- void* nextObject;
s16 playerObjectId;
- u8 playerForm;
+ void* nextObject;
globalCtx->linkActorEntry = (ActorEntry*)Lib_SegmentedToVirtual(cmd->spawnList.segment) +
globalCtx->setupEntranceList[globalCtx->curSpawn].spawn;
@@ -158,11 +156,10 @@ void Scene_HeaderCmdSpawnList(GlobalContext* globalCtx, SceneCmd* cmd) {
}
loadedCount = Object_Spawn(&globalCtx->objectCtx, OBJECT_LINK_CHILD);
- nextObject = globalCtx2->objectCtx.status[globalCtx2->objectCtx.num].segment;
+ nextObject = globalCtx->objectCtx.status[globalCtx->objectCtx.num].segment;
globalCtx->objectCtx.num = loadedCount;
globalCtx->objectCtx.spawnedObjectCount = loadedCount;
- playerForm = gSaveContext.save.playerForm;
- playerObjectId = gLinkFormObjectIndexes[playerForm];
+ playerObjectId = gLinkFormObjectIndexes[(void)0, gSaveContext.save.playerForm];
gActorOverlayTable[0].initInfo->objectId = playerObjectId;
Object_Spawn(&globalCtx->objectCtx, playerObjectId);
@@ -378,8 +375,6 @@ void Scene_HeaderCmdSkyboxDisables(GlobalContext* globalCtx, SceneCmd* cmd) {
// SceneTableEntry Header Command 0x10: Time Settings
void Scene_HeaderCmdTimeSettings(GlobalContext* globalCtx, SceneCmd* cmd) {
- u32 dayTime;
-
if (cmd->timeSettings.hour != 0xFF && cmd->timeSettings.min != 0xFF) {
gSaveContext.environmentTime = gSaveContext.save.time =
(u16)(((cmd->timeSettings.hour + (cmd->timeSettings.min / 60.0f)) * 60.0f) / 0.021972656f);
@@ -399,12 +394,9 @@ void Scene_HeaderCmdTimeSettings(GlobalContext* globalCtx, SceneCmd* cmd) {
REG(15) = globalCtx->envCtx.timeIncrement;
}
- dayTime = gSaveContext.save.time;
- globalCtx->envCtx.unk_4 = -(Math_SinS(dayTime - 0x8000) * 120.0f) * 25.0f;
- dayTime = gSaveContext.save.time;
- globalCtx->envCtx.unk_8 = (Math_CosS(dayTime - 0x8000) * 120.0f) * 25.0f;
- dayTime = gSaveContext.save.time;
- globalCtx->envCtx.unk_C = (Math_CosS(dayTime - 0x8000) * 20.0f) * 25.0f;
+ globalCtx->envCtx.unk_4 = -(Math_SinS(((void)0, gSaveContext.save.time) - 0x8000) * 120.0f) * 25.0f;
+ globalCtx->envCtx.unk_8 = (Math_CosS(((void)0, gSaveContext.save.time) - 0x8000) * 120.0f) * 25.0f;
+ globalCtx->envCtx.unk_C = (Math_CosS(((void)0, gSaveContext.save.time) - 0x8000) * 20.0f) * 25.0f;
if (globalCtx->envCtx.timeIncrement == 0 && gSaveContext.save.cutscene < 0xFFF0) {
gSaveContext.environmentTime = gSaveContext.save.time;
diff --git a/src/code/z_skelanime.c b/src/code/z_skelanime.c
index 6563eecfc..4c77b3669 100644
--- a/src/code/z_skelanime.c
+++ b/src/code/z_skelanime.c
@@ -33,7 +33,7 @@ void SkelAnime_DrawLimbLod(GlobalContext* globalCtx, s32 limbIndex, void** skele
OPEN_DISPS(globalCtx->state.gfxCtx);
- Matrix_StatePush();
+ Matrix_Push();
limb = Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
rot = jointTable[limbIndex];
@@ -44,7 +44,7 @@ void SkelAnime_DrawLimbLod(GlobalContext* globalCtx, s32 limbIndex, void** skele
dList = limb->dLists[lod];
if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, limbIndex, &dList, &pos, &rot, actor) == 0)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (dList != NULL) {
Gfx* polyTemp = POLY_OPA_DISP;
@@ -63,7 +63,7 @@ void SkelAnime_DrawLimbLod(GlobalContext* globalCtx, s32 limbIndex, void** skele
SkelAnime_DrawLimbLod(globalCtx, limb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor, lod);
}
- Matrix_StatePop();
+ Matrix_Pop();
if (limb->sibling != LIMB_DONE) {
SkelAnime_DrawLimbLod(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
@@ -91,7 +91,7 @@ void SkelAnime_DrawLod(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTa
OPEN_DISPS(globalCtx->state.gfxCtx);
- Matrix_StatePush();
+ Matrix_Push();
rootLimb = Lib_SegmentedToVirtual(skeleton[0]);
pos.x = jointTable[0].x;
@@ -102,7 +102,7 @@ void SkelAnime_DrawLod(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTa
dList = rootLimb->dLists[lod];
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &dList, &pos, &rot, actor)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (dList != NULL) {
Gfx* polyTemp = POLY_OPA_DISP;
@@ -123,7 +123,7 @@ void SkelAnime_DrawLod(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTa
lod);
}
- Matrix_StatePop();
+ Matrix_Pop();
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
@@ -143,7 +143,7 @@ void SkelAnime_DrawFlexLimbLod(GlobalContext* globalCtx, s32 limbIndex, void** s
OPEN_DISPS(globalCtx->state.gfxCtx);
- Matrix_StatePush();
+ Matrix_Push();
limb = Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
@@ -157,7 +157,7 @@ void SkelAnime_DrawFlexLimbLod(GlobalContext* globalCtx, s32 limbIndex, void** s
newDList = limbDList = limb->dLists[lod];
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &newDList, &pos, &rot, actor)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (newDList != NULL) {
Matrix_ToMtx(*mtx);
gSPMatrix(POLY_OPA_DISP++, *mtx, G_MTX_LOAD);
@@ -178,7 +178,7 @@ void SkelAnime_DrawFlexLimbLod(GlobalContext* globalCtx, s32 limbIndex, void** s
lod, mtx);
}
- Matrix_StatePop();
+ Matrix_Pop();
if (limb->sibling != LIMB_DONE) {
SkelAnime_DrawFlexLimbLod(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
@@ -211,7 +211,7 @@ void SkelAnime_DrawFlexLod(GlobalContext* globalCtx, void** skeleton, Vec3s* joi
OPEN_DISPS(globalCtx->state.gfxCtx);
gSPSegment(POLY_OPA_DISP++, 0x0D, mtx);
- Matrix_StatePush();
+ Matrix_Push();
rootLimb = Lib_SegmentedToVirtual(skeleton[0]);
pos.x = jointTable[0].x;
@@ -223,7 +223,7 @@ void SkelAnime_DrawFlexLod(GlobalContext* globalCtx, void** skeleton, Vec3s* joi
newDList = limbDList = rootLimb->dLists[lod];
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &newDList, &pos, &rot, actor)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (newDList != NULL) {
Gfx* polyTemp = POLY_OPA_DISP;
@@ -246,7 +246,7 @@ void SkelAnime_DrawFlexLod(GlobalContext* globalCtx, void** skeleton, Vec3s* joi
actor, lod, &mtx);
}
- Matrix_StatePop();
+ Matrix_Pop();
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
@@ -263,7 +263,7 @@ void SkelAnime_DrawLimbOpa(GlobalContext* globalCtx, s32 limbIndex, void** skele
OPEN_DISPS(globalCtx->state.gfxCtx);
- Matrix_StatePush();
+ Matrix_Push();
limb = Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
@@ -274,7 +274,7 @@ void SkelAnime_DrawLimbOpa(GlobalContext* globalCtx, s32 limbIndex, void** skele
dList = limb->dList;
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &dList, &pos, &rot, actor)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (dList != NULL) {
Gfx* polyTemp = POLY_OPA_DISP;
@@ -292,7 +292,7 @@ void SkelAnime_DrawLimbOpa(GlobalContext* globalCtx, s32 limbIndex, void** skele
SkelAnime_DrawLimbOpa(globalCtx, limb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor);
}
- Matrix_StatePop();
+ Matrix_Pop();
if (limb->sibling != LIMB_DONE) {
SkelAnime_DrawLimbOpa(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor);
@@ -318,7 +318,7 @@ void SkelAnime_DrawOpa(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTa
OPEN_DISPS(globalCtx->state.gfxCtx);
- Matrix_StatePush();
+ Matrix_Push();
rootLimb = Lib_SegmentedToVirtual(skeleton[0]);
pos.x = jointTable[0].x;
@@ -329,7 +329,7 @@ void SkelAnime_DrawOpa(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTa
dList = rootLimb->dList;
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &dList, &pos, &rot, actor)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (dList != NULL) {
Gfx* polyTemp = POLY_OPA_DISP;
@@ -347,7 +347,7 @@ void SkelAnime_DrawOpa(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTa
SkelAnime_DrawLimbOpa(globalCtx, rootLimb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor);
}
- Matrix_StatePop();
+ Matrix_Pop();
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
@@ -363,7 +363,7 @@ void SkelAnime_DrawFlexLimbOpa(GlobalContext* globalCtx, s32 limbIndex, void** s
OPEN_DISPS(globalCtx->state.gfxCtx);
- Matrix_StatePush();
+ Matrix_Push();
limb = Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
@@ -376,7 +376,7 @@ void SkelAnime_DrawFlexLimbOpa(GlobalContext* globalCtx, s32 limbIndex, void** s
newDList = limbDList = limb->dList;
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &newDList, &pos, &rot, actor)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (newDList != NULL) {
Matrix_ToMtx(*limbMatricies);
gSPMatrix(POLY_OPA_DISP++, *limbMatricies, G_MTX_LOAD);
@@ -397,7 +397,7 @@ void SkelAnime_DrawFlexLimbOpa(GlobalContext* globalCtx, s32 limbIndex, void** s
limbMatricies);
}
- Matrix_StatePop();
+ Matrix_Pop();
if (limb->sibling != LIMB_DONE) {
SkelAnime_DrawFlexLimbOpa(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
@@ -430,7 +430,7 @@ void SkelAnime_DrawFlexOpa(GlobalContext* globalCtx, void** skeleton, Vec3s* joi
gSPSegment(POLY_OPA_DISP++, 0x0D, mtx);
- Matrix_StatePush();
+ Matrix_Push();
rootLimb = Lib_SegmentedToVirtual(skeleton[0]);
@@ -442,7 +442,7 @@ void SkelAnime_DrawFlexOpa(GlobalContext* globalCtx, void** skeleton, Vec3s* joi
newDList = limbDList = rootLimb->dList;
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &newDList, &pos, &rot, actor)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (newDList != NULL) {
Gfx* polyTemp = POLY_OPA_DISP;
@@ -467,7 +467,7 @@ void SkelAnime_DrawFlexOpa(GlobalContext* globalCtx, void** skeleton, Vec3s* joi
actor, &mtx);
}
- Matrix_StatePop();
+ Matrix_Pop();
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
@@ -483,7 +483,7 @@ void SkelAnime_DrawTransformFlexLimbOpa(GlobalContext* globalCtx, s32 limbIndex,
OPEN_DISPS(globalCtx->state.gfxCtx);
- Matrix_StatePush();
+ Matrix_Push();
limb = Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
@@ -496,8 +496,8 @@ void SkelAnime_DrawTransformFlexLimbOpa(GlobalContext* globalCtx, s32 limbIndex,
newDList = limbDList = limb->dList;
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &newDList, &pos, &rot, actor)) {
- Matrix_JointPosition(&pos, &rot);
- Matrix_StatePush();
+ Matrix_TranslateRotateZYX(&pos, &rot);
+ Matrix_Push();
transformLimbDraw(globalCtx, limbIndex, actor);
@@ -514,7 +514,7 @@ void SkelAnime_DrawTransformFlexLimbOpa(GlobalContext* globalCtx, s32 limbIndex,
(*mtx)++;
}
}
- Matrix_StatePop();
+ Matrix_Pop();
}
if (postLimbDraw != NULL) {
@@ -526,7 +526,7 @@ void SkelAnime_DrawTransformFlexLimbOpa(GlobalContext* globalCtx, s32 limbIndex,
transformLimbDraw, actor, mtx);
}
- Matrix_StatePop();
+ Matrix_Pop();
if (limb->sibling != LIMB_DONE) {
SkelAnime_DrawTransformFlexLimbOpa(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw,
@@ -566,7 +566,7 @@ void SkelAnime_DrawTransformFlexOpa(GlobalContext* globalCtx, void** skeleton, V
gSPSegment(POLY_OPA_DISP++, 0x0D, mtx);
- Matrix_StatePush();
+ Matrix_Push();
rootLimb = Lib_SegmentedToVirtual(skeleton[0]);
@@ -578,8 +578,8 @@ void SkelAnime_DrawTransformFlexOpa(GlobalContext* globalCtx, void** skeleton, V
newDList = limbDList = rootLimb->dList;
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &newDList, &pos, &rot, actor)) {
- Matrix_JointPosition(&pos, &rot);
- Matrix_StatePush();
+ Matrix_TranslateRotateZYX(&pos, &rot);
+ Matrix_Push();
transformLimbDraw(globalCtx, 1, actor);
@@ -595,7 +595,7 @@ void SkelAnime_DrawTransformFlexOpa(GlobalContext* globalCtx, void** skeleton, V
Matrix_ToMtx(mtx++);
}
}
- Matrix_StatePop();
+ Matrix_Pop();
}
if (postLimbDraw != NULL) {
@@ -607,7 +607,7 @@ void SkelAnime_DrawTransformFlexOpa(GlobalContext* globalCtx, void** skeleton, V
postLimbDraw, transformLimbDraw, actor, &mtx);
}
- Matrix_StatePop();
+ Matrix_Pop();
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
@@ -627,9 +627,7 @@ void SkelAnime_GetFrameData(AnimationHeader* animation, s32 frame, s32 limbCount
for (i = 0; i < limbCount; i++) {
// Debug prints here, this is needed to prevent loop unrolling
- if (0) {
- if (0) {};
- }
+ if ((frameTable == NULL) || (jointIndices == NULL) || (dynamicData == NULL)) {}
frameTable->x = jointIndices->x >= staticIndexMax ? dynamicData[jointIndices->x] : frameData[jointIndices->x];
frameTable->y = jointIndices->y >= staticIndexMax ? dynamicData[jointIndices->y] : frameData[jointIndices->y];
frameTable->z = jointIndices->z >= staticIndexMax ? dynamicData[jointIndices->z] : frameData[jointIndices->z];
@@ -660,7 +658,7 @@ Gfx* SkelAnime_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, void** skeleton
Vec3f pos;
Vec3s rot;
- Matrix_StatePush();
+ Matrix_Push();
limb = Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
@@ -673,7 +671,7 @@ Gfx* SkelAnime_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, void** skeleton
dList = limb->dList;
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &dList, &pos, &rot, actor, &gfx)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (dList != NULL) {
gSPMatrix(&gfx[0], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
gSPDisplayList(&gfx[1], dList);
@@ -690,7 +688,7 @@ Gfx* SkelAnime_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, void** skeleton
gfx);
}
- Matrix_StatePop();
+ Matrix_Pop();
if (limb->sibling != LIMB_DONE) {
gfx = SkelAnime_DrawLimb(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
@@ -716,7 +714,7 @@ Gfx* SkelAnime_Draw(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable
return NULL;
}
- Matrix_StatePush();
+ Matrix_Push();
rootLimb = Lib_SegmentedToVirtual(skeleton[0]);
@@ -729,7 +727,7 @@ Gfx* SkelAnime_Draw(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable
dList = rootLimb->dList;
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &dList, &pos, &rot, actor, &gfx)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (dList != NULL) {
gSPMatrix(&gfx[0], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
gSPDisplayList(&gfx[1], dList);
@@ -746,7 +744,7 @@ Gfx* SkelAnime_Draw(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable
actor, gfx);
}
- Matrix_StatePop();
+ Matrix_Pop();
return gfx;
}
@@ -763,7 +761,7 @@ Gfx* SkelAnime_DrawFlexLimb(GlobalContext* globalCtx, s32 limbIndex, void** skel
Vec3f pos;
Vec3s rot;
- Matrix_StatePush();
+ Matrix_Push();
limb = Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
@@ -776,7 +774,7 @@ Gfx* SkelAnime_DrawFlexLimb(GlobalContext* globalCtx, s32 limbIndex, void** skel
newDList = limbDList = limb->dList;
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &newDList, &pos, &rot, actor, &gfx)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (newDList != NULL) {
gSPMatrix(&gfx[0], Matrix_ToMtx(*mtx), G_MTX_LOAD);
gSPDisplayList(&gfx[1], newDList);
@@ -799,7 +797,7 @@ Gfx* SkelAnime_DrawFlexLimb(GlobalContext* globalCtx, s32 limbIndex, void** skel
actor, mtx, gfx);
}
- Matrix_StatePop();
+ Matrix_Pop();
if (limb->sibling != LIMB_DONE) {
gfx = SkelAnime_DrawFlexLimb(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw,
@@ -832,7 +830,7 @@ Gfx* SkelAnime_DrawFlex(GlobalContext* globalCtx, void** skeleton, Vec3s* jointT
gSPSegment(gfx++, 0x0D, mtx);
- Matrix_StatePush();
+ Matrix_Push();
rootLimb = Lib_SegmentedToVirtual(skeleton[0]);
@@ -845,7 +843,7 @@ Gfx* SkelAnime_DrawFlex(GlobalContext* globalCtx, void** skeleton, Vec3s* jointT
newDList = limbDList = rootLimb->dList;
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &newDList, &pos, &rot, actor, &gfx)) {
- Matrix_JointPosition(&pos, &rot);
+ Matrix_TranslateRotateZYX(&pos, &rot);
if (newDList != NULL) {
gSPMatrix(&gfx[0], Matrix_ToMtx(mtx), G_MTX_LOAD);
gSPDisplayList(&gfx[1], newDList);
@@ -868,7 +866,7 @@ Gfx* SkelAnime_DrawFlex(GlobalContext* globalCtx, void** skeleton, Vec3s* jointT
actor, &mtx, gfx);
}
- Matrix_StatePop();
+ Matrix_Pop();
return gfx;
}
diff --git a/src/code/z_skin.c b/src/code/z_skin.c
index 808a00da0..de449c02d 100644
--- a/src/code/z_skin.c
+++ b/src/code/z_skin.c
@@ -13,13 +13,13 @@ void Skin_UpdateVertices(MtxF* mtx, SkinVertex* skinVertices, SkinLimbModif* mod
Vec3f normal;
Vec3f sp44;
- wTemp.x = mtx->wx;
- wTemp.y = mtx->wy;
- wTemp.z = mtx->wz;
+ wTemp.x = mtx->xw;
+ wTemp.y = mtx->yw;
+ wTemp.z = mtx->zw;
- mtx->wx = 0.0f;
- mtx->wy = 0.0f;
- mtx->wz = 0.0f;
+ mtx->xw = 0.0f;
+ mtx->yw = 0.0f;
+ mtx->zw = 0.0f;
for (vertexEntry = skinVertices; vertexEntry < &skinVertices[modifEntry->vtxCount]; vertexEntry++) {
vtx = &vtxBuf[vertexEntry->index];
@@ -39,9 +39,9 @@ void Skin_UpdateVertices(MtxF* mtx, SkinVertex* skinVertices, SkinLimbModif* mod
vtx->n.n[2] = normal.z;
}
- mtx->wx = wTemp.x;
- mtx->wy = wTemp.y;
- mtx->wz = wTemp.z;
+ mtx->xw = wTemp.x;
+ mtx->yw = wTemp.y;
+ mtx->zw = wTemp.z;
}
void Skin_ApplyLimbModifications(GraphicsContext* gfxCtx, Skin* skin, s32 limbIndex, s32 arg3) {
diff --git a/src/code/z_skin_matrix.c b/src/code/z_skin_matrix.c
index f355aec9b..9b30a3c0b 100644
--- a/src/code/z_skin_matrix.c
+++ b/src/code/z_skin_matrix.c
@@ -1,13 +1,11 @@
#include "global.h"
-// clang-format off
-MtxF sMtxFClear = {
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f,
-};
-// clang-format on
+MtxF sMtxFClear = { {
+ { 1.0f, 0.0f, 0.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 1.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f, 1.0f },
+} };
/**
* Multiplies a 4 component row vector [ src , 1 ] by the matrix mf and writes the resulting 4 components to xyzDest
@@ -16,10 +14,10 @@ MtxF sMtxFClear = {
* \f[ [\texttt{xyzDest}, \texttt{wDest}] = [\texttt{src}, 1] \cdot [mf] \f]
*/
void SkinMatrix_Vec3fMtxFMultXYZW(MtxF* mf, Vec3f* src, Vec3f* xyzDest, f32* wDest) {
- xyzDest->x = mf->wx + ((src->x * mf->xx) + (src->y * mf->yx) + (src->z * mf->zx));
- xyzDest->y = mf->wy + ((src->x * mf->xy) + (src->y * mf->yy) + (src->z * mf->zy));
- xyzDest->z = mf->wz + ((src->x * mf->xz) + (src->y * mf->yz) + (src->z * mf->zz));
- *wDest = mf->ww + ((src->x * mf->xw) + (src->y * mf->yw) + (src->z * mf->zw));
+ xyzDest->x = mf->xw + ((src->x * mf->xx) + (src->y * mf->xy) + (src->z * mf->xz));
+ xyzDest->y = mf->yw + ((src->x * mf->yx) + (src->y * mf->yy) + (src->z * mf->yz));
+ xyzDest->z = mf->zw + ((src->x * mf->zx) + (src->y * mf->zy) + (src->z * mf->zz));
+ *wDest = mf->ww + ((src->x * mf->wx) + (src->y * mf->wy) + (src->z * mf->wz));
}
/**
@@ -29,21 +27,22 @@ void SkinMatrix_Vec3fMtxFMultXYZW(MtxF* mf, Vec3f* src, Vec3f* xyzDest, f32* wDe
*/
void SkinMatrix_Vec3fMtxFMultXYZ(MtxF* mf, Vec3f* src, Vec3f* dest) {
f32 mx = mf->xx;
- f32 my = mf->yx;
- f32 mz = mf->zx;
- f32 mw = mf->wx;
+ f32 my = mf->xy;
+ f32 mz = mf->xz;
+ f32 mw = mf->xw;
+
dest->x = mw + ((src->x * mx) + (src->y * my) + (src->z * mz));
- mx = mf->xy;
+ mx = mf->yx;
my = mf->yy;
- mz = mf->zy;
- mw = mf->wy;
+ mz = mf->yz;
+ mw = mf->yw;
dest->y = mw + ((src->x * mx) + (src->y * my) + (src->z * mz));
- mx = mf->xz;
- my = mf->yz;
+ mx = mf->zx;
+ my = mf->zy;
mz = mf->zz;
- mw = mf->wz;
+ mw = mf->zw;
dest->z = mw + ((src->x * mx) + (src->y * my) + (src->z * mz));
}
@@ -59,122 +58,122 @@ void SkinMatrix_MtxFMtxFMult(MtxF* mfB, MtxF* mfA, MtxF* dest) {
//---COL1---
f32 cx = mfB->xx;
- f32 cy = mfB->yx;
- f32 cz = mfB->zx;
- f32 cw = mfB->wx;
+ f32 cy = mfB->xy;
+ f32 cz = mfB->xz;
+ f32 cw = mfB->xw;
//--------
rx = mfA->xx;
- ry = mfA->xy;
- rz = mfA->xz;
- rw = mfA->xw;
+ ry = mfA->yx;
+ rz = mfA->zx;
+ rw = mfA->wx;
dest->xx = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->yx;
+ rx = mfA->xy;
ry = mfA->yy;
- rz = mfA->yz;
- rw = mfA->yw;
- dest->yx = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ rz = mfA->zy;
+ rw = mfA->wy;
+ dest->xy = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->zx;
- ry = mfA->zy;
+ rx = mfA->xz;
+ ry = mfA->yz;
rz = mfA->zz;
- rw = mfA->zw;
- dest->zx = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ rw = mfA->wz;
+ dest->xz = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->wx;
- ry = mfA->wy;
- rz = mfA->wz;
+ rx = mfA->xw;
+ ry = mfA->yw;
+ rz = mfA->zw;
rw = mfA->ww;
- dest->wx = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ dest->xw = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
//---2Col---
- cx = mfB->xy;
+ cx = mfB->yx;
cy = mfB->yy;
- cz = mfB->zy;
- cw = mfB->wy;
+ cz = mfB->yz;
+ cw = mfB->yw;
//--------
rx = mfA->xx;
- ry = mfA->xy;
- rz = mfA->xz;
- rw = mfA->xw;
- dest->xy = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ ry = mfA->yx;
+ rz = mfA->zx;
+ rw = mfA->wx;
+ dest->yx = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->yx;
+ rx = mfA->xy;
ry = mfA->yy;
- rz = mfA->yz;
- rw = mfA->yw;
+ rz = mfA->zy;
+ rw = mfA->wy;
dest->yy = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->zx;
- ry = mfA->zy;
+ rx = mfA->xz;
+ ry = mfA->yz;
rz = mfA->zz;
- rw = mfA->zw;
- dest->zy = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ rw = mfA->wz;
+ dest->yz = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->wx;
- ry = mfA->wy;
- rz = mfA->wz;
+ rx = mfA->xw;
+ ry = mfA->yw;
+ rz = mfA->zw;
rw = mfA->ww;
- dest->wy = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ dest->yw = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
//---3Col---
- cx = mfB->xz;
- cy = mfB->yz;
+ cx = mfB->zx;
+ cy = mfB->zy;
cz = mfB->zz;
- cw = mfB->wz;
+ cw = mfB->zw;
//--------
rx = mfA->xx;
- ry = mfA->xy;
- rz = mfA->xz;
- rw = mfA->xw;
- dest->xz = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ ry = mfA->yx;
+ rz = mfA->zx;
+ rw = mfA->wx;
+ dest->zx = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->yx;
+ rx = mfA->xy;
ry = mfA->yy;
- rz = mfA->yz;
- rw = mfA->yw;
- dest->yz = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ rz = mfA->zy;
+ rw = mfA->wy;
+ dest->zy = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->zx;
- ry = mfA->zy;
+ rx = mfA->xz;
+ ry = mfA->yz;
rz = mfA->zz;
- rw = mfA->zw;
+ rw = mfA->wz;
dest->zz = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->wx;
- ry = mfA->wy;
- rz = mfA->wz;
+ rx = mfA->xw;
+ ry = mfA->yw;
+ rz = mfA->zw;
rw = mfA->ww;
- dest->wz = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ dest->zw = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
//---4Col---
- cx = mfB->xw;
- cy = mfB->yw;
- cz = mfB->zw;
+ cx = mfB->wx;
+ cy = mfB->wy;
+ cz = mfB->wz;
cw = mfB->ww;
//--------
rx = mfA->xx;
- ry = mfA->xy;
- rz = mfA->xz;
- rw = mfA->xw;
- dest->xw = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ ry = mfA->yx;
+ rz = mfA->zx;
+ rw = mfA->wx;
+ dest->wx = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->yx;
+ rx = mfA->xy;
ry = mfA->yy;
- rz = mfA->yz;
- rw = mfA->yw;
- dest->yw = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ rz = mfA->zy;
+ rw = mfA->wy;
+ dest->wy = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->zx;
- ry = mfA->zy;
+ rx = mfA->xz;
+ ry = mfA->yz;
rz = mfA->zz;
- rw = mfA->zw;
- dest->zw = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
+ rw = mfA->wz;
+ dest->wz = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
- rx = mfA->wx;
- ry = mfA->wy;
- rz = mfA->wz;
+ rx = mfA->xw;
+ ry = mfA->yw;
+ rz = mfA->zw;
rw = mfA->ww;
dest->ww = (cx * rx) + (cy * ry) + (cz * rz) + (cw * rw);
}
@@ -188,39 +187,39 @@ void SkinMatrix_GetClear(MtxF** mfp) {
void SkinMatrix_Clear(MtxF* mf) {
mf->xx = 1.0f;
- mf->xy = 0.0f;
- mf->xz = 0.0f;
- mf->xw = 0.0f;
mf->yx = 0.0f;
- mf->yy = 1.0f;
- mf->yz = 0.0f;
- mf->yw = 0.0f;
mf->zx = 0.0f;
- mf->zy = 0.0f;
- mf->zz = 1.0f;
- mf->zw = 0.0f;
mf->wx = 0.0f;
+ mf->xy = 0.0f;
+ mf->yy = 1.0f;
+ mf->zy = 0.0f;
mf->wy = 0.0f;
+ mf->xz = 0.0f;
+ mf->yz = 0.0f;
+ mf->zz = 1.0f;
mf->wz = 0.0f;
+ mf->xw = 0.0f;
+ mf->yw = 0.0f;
+ mf->zw = 0.0f;
mf->ww = 1.0f;
}
void SkinMatrix_MtxFCopy(MtxF* src, MtxF* dest) {
dest->xx = src->xx;
- dest->xy = src->xy;
- dest->xz = src->xz;
- dest->xw = src->xw;
dest->yx = src->yx;
- dest->yy = src->yy;
- dest->yz = src->yz;
- dest->yw = src->yw;
dest->zx = src->zx;
- dest->zy = src->zy;
- dest->zz = src->zz;
- dest->zw = src->zw;
dest->wx = src->wx;
+ dest->xy = src->xy;
+ dest->yy = src->yy;
+ dest->zy = src->zy;
dest->wy = src->wy;
+ dest->xz = src->xz;
+ dest->yz = src->yz;
+ dest->zz = src->zz;
dest->wz = src->wz;
+ dest->xw = src->xw;
+ dest->yw = src->yw;
+ dest->zw = src->zw;
dest->ww = src->ww;
}
@@ -282,18 +281,18 @@ s32 SkinMatrix_Invert(MtxF* src, MtxF* dest) {
* Produces a matrix which scales x,y,z components of vectors or x,y,z rows of matrices (when applied on LHS)
*/
void SkinMatrix_SetScale(MtxF* mf, f32 x, f32 y, f32 z) {
- mf->xy = 0.0f;
- mf->xz = 0.0f;
- mf->xw = 0.0f;
mf->yx = 0.0f;
- mf->yz = 0.0f;
- mf->yw = 0.0f;
mf->zx = 0.0f;
- mf->zy = 0.0f;
- mf->zw = 0.0f;
mf->wx = 0.0f;
+ mf->xy = 0.0f;
+ mf->zy = 0.0f;
mf->wy = 0.0f;
+ mf->xz = 0.0f;
+ mf->yz = 0.0f;
mf->wz = 0.0f;
+ mf->xw = 0.0f;
+ mf->yw = 0.0f;
+ mf->zw = 0.0f;
mf->ww = 1.0f;
mf->xx = x;
mf->yy = y;
@@ -307,16 +306,16 @@ void SkinMatrix_SetRotateRPY(MtxF* mf, s16 roll, s16 pitch, s16 yaw) {
f32 cos2;
f32 sin = Math_SinS(yaw);
f32 cos = Math_CosS(yaw);
- f32 yx;
+ f32 xy;
f32 sin2;
- f32 zx;
+ f32 xz;
f32 yy;
- f32 zy;
+ f32 yz;
mf->yy = cos;
- mf->yx = -sin;
- mf->xw = mf->yw = mf->zw = 0;
+ mf->xy = -sin;
mf->wx = mf->wy = mf->wz = 0;
+ mf->xw = mf->yw = mf->zw = 0;
mf->ww = 1;
if (pitch != 0) {
@@ -324,19 +323,19 @@ void SkinMatrix_SetRotateRPY(MtxF* mf, s16 roll, s16 pitch, s16 yaw) {
cos2 = Math_CosS(pitch);
mf->xx = cos * cos2;
- mf->zx = cos * sin2;
+ mf->xz = cos * sin2;
- mf->xy = sin * cos2;
- mf->zy = sin * sin2;
- mf->xz = -sin2;
+ mf->yx = sin * cos2;
+ mf->yz = sin * sin2;
+ mf->zx = -sin2;
mf->zz = cos2;
} else {
mf->xx = cos;
if (1) {}
if (1) {}
- zx = sin; // required to match
- mf->xy = sin;
- mf->xz = mf->zx = mf->zy = 0;
+ xz = sin; // required to match
+ mf->yx = sin;
+ mf->zx = mf->xz = mf->yz = 0;
mf->zz = 1;
}
@@ -344,22 +343,22 @@ void SkinMatrix_SetRotateRPY(MtxF* mf, s16 roll, s16 pitch, s16 yaw) {
sin2 = Math_SinS(roll);
cos2 = Math_CosS(roll);
- yx = mf->yx;
- zx = mf->zx;
- mf->yx = (yx * cos2) + (zx * sin2);
- mf->zx = (zx * cos2) - (yx * sin2);
+ xy = mf->xy;
+ xz = mf->xz;
+ mf->xy = (xy * cos2) + (xz * sin2);
+ mf->xz = (xz * cos2) - (xy * sin2);
if (1) {}
- zy = mf->zy;
+ yz = mf->yz;
yy = mf->yy;
- mf->yy = (yy * cos2) + (zy * sin2);
- mf->zy = (zy * cos2) - (yy * sin2);
+ mf->yy = (yy * cos2) + (yz * sin2);
+ mf->yz = (yz * cos2) - (yy * sin2);
if (cos2) {}
- mf->yz = mf->zz * sin2;
+ mf->zy = mf->zz * sin2;
mf->zz = mf->zz * cos2;
} else {
- mf->yz = 0;
+ mf->zy = 0;
}
}
@@ -370,23 +369,23 @@ void SkinMatrix_SetRotateYRP(MtxF* mf, s16 yaw, s16 roll, s16 pitch) {
f32 cos2;
f32 sin;
f32 cos;
- f32 xz;
+ f32 zx;
f32 sin2;
- f32 yz;
+ f32 zy;
f32 xx;
- f32 yx;
+ f32 xy;
sin = Math_SinS(roll);
cos = Math_CosS(roll);
mf->xx = cos;
- mf->xz = -sin;
- mf->zw = 0;
- mf->yw = 0;
- mf->xw = 0;
+ mf->zx = -sin;
mf->wz = 0;
mf->wy = 0;
mf->wx = 0;
+ mf->zw = 0;
+ mf->yw = 0;
+ mf->xw = 0;
mf->ww = 1;
if (yaw != 0) {
@@ -394,19 +393,19 @@ void SkinMatrix_SetRotateYRP(MtxF* mf, s16 yaw, s16 roll, s16 pitch) {
cos2 = Math_CosS(yaw);
mf->zz = cos * cos2;
- mf->yz = cos * sin2;
+ mf->zy = cos * sin2;
- mf->zx = sin * cos2;
- mf->yx = sin * sin2;
- mf->zy = -sin2;
+ mf->xz = sin * cos2;
+ mf->xy = sin * sin2;
+ mf->yz = -sin2;
mf->yy = cos2;
} else {
mf->zz = cos;
if (1) {}
if (1) {}
- yx = sin; // required to match
- mf->zx = sin;
- mf->yx = mf->yz = mf->zy = 0;
+ xy = sin; // required to match
+ mf->xz = sin;
+ mf->xy = mf->zy = mf->yz = 0;
mf->yy = 1;
}
@@ -414,19 +413,19 @@ void SkinMatrix_SetRotateYRP(MtxF* mf, s16 yaw, s16 roll, s16 pitch) {
sin2 = Math_SinS(pitch);
cos2 = Math_CosS(pitch);
xx = mf->xx;
- yx = mf->yx;
- mf->xx = (xx * cos2) + (yx * sin2);
- mf->yx = yx * cos2 - (xx * sin2);
+ xy = mf->xy;
+ mf->xx = (xx * cos2) + (xy * sin2);
+ mf->xy = xy * cos2 - (xx * sin2);
if (1) {}
- yz = mf->yz;
- xz = mf->xz;
- mf->xz = (xz * cos2) + (yz * sin2);
- mf->yz = (yz * cos2) - (xz * sin2);
+ zy = mf->zy;
+ zx = mf->zx;
+ mf->zx = (zx * cos2) + (zy * sin2);
+ mf->zy = (zy * cos2) - (zx * sin2);
if (cos2) {}
- mf->xy = mf->yy * sin2;
+ mf->yx = mf->yy * sin2;
mf->yy = mf->yy * cos2;
} else {
- mf->xy = 0;
+ mf->yx = 0;
}
}
@@ -434,22 +433,22 @@ void SkinMatrix_SetRotateYRP(MtxF* mf, s16 yaw, s16 roll, s16 pitch) {
* Produces a matrix which translates a vector by amounts in the x, y and z directions
*/
void SkinMatrix_SetTranslate(MtxF* mf, f32 x, f32 y, f32 z) {
- mf->xy = 0.0f;
- mf->xz = 0.0f;
- mf->xw = 0.0f;
mf->yx = 0.0f;
- mf->yz = 0.0f;
- mf->yw = 0.0f;
mf->zx = 0.0f;
+ mf->wx = 0.0f;
+ mf->xy = 0.0f;
mf->zy = 0.0f;
- mf->zw = 0.0f;
+ mf->wy = 0.0f;
+ mf->xz = 0.0f;
+ mf->yz = 0.0f;
+ mf->wz = 0.0f;
mf->xx = 1.0f;
mf->yy = 1.0f;
mf->zz = 1.0f;
mf->ww = 1.0f;
- mf->wx = x;
- mf->wy = y;
- mf->wz = z;
+ mf->xw = x;
+ mf->yw = y;
+ mf->zw = z;
}
/**
@@ -515,19 +514,19 @@ void SkinMatrix_MtxFToMtx(MtxF* src, Mtx* dest) {
m1[0] = (temp >> 0x10);
m1[16 + 0] = temp & 0xFFFF;
- temp = src->xy * 0x10000;
+ temp = src->yx * 0x10000;
m1[1] = (temp >> 0x10);
m1[16 + 1] = temp & 0xFFFF;
- temp = src->xz * 0x10000;
+ temp = src->zx * 0x10000;
m1[2] = (temp >> 0x10);
m1[16 + 2] = temp & 0xFFFF;
- temp = src->xw * 0x10000;
+ temp = src->wx * 0x10000;
m1[3] = (temp >> 0x10);
m1[16 + 3] = temp & 0xFFFF;
- temp = src->yx * 0x10000;
+ temp = src->xy * 0x10000;
m1[4] = (temp >> 0x10);
m1[16 + 4] = temp & 0xFFFF;
@@ -535,19 +534,19 @@ void SkinMatrix_MtxFToMtx(MtxF* src, Mtx* dest) {
m1[5] = (temp >> 0x10);
m1[16 + 5] = temp & 0xFFFF;
- temp = src->yz * 0x10000;
+ temp = src->zy * 0x10000;
m1[6] = (temp >> 0x10);
m1[16 + 6] = temp & 0xFFFF;
- temp = src->yw * 0x10000;
+ temp = src->wy * 0x10000;
m1[7] = (temp >> 0x10);
m1[16 + 7] = temp & 0xFFFF;
- temp = src->zx * 0x10000;
+ temp = src->xz * 0x10000;
m1[8] = (temp >> 0x10);
m1[16 + 8] = temp & 0xFFFF;
- temp = src->zy * 0x10000;
+ temp = src->yz * 0x10000;
m1[9] = (temp >> 0x10);
m2[9] = temp & 0xFFFF;
@@ -555,19 +554,19 @@ void SkinMatrix_MtxFToMtx(MtxF* src, Mtx* dest) {
m1[10] = (temp >> 0x10);
m2[10] = temp & 0xFFFF;
- temp = src->zw * 0x10000;
+ temp = src->wz * 0x10000;
m1[11] = (temp >> 0x10);
m2[11] = temp & 0xFFFF;
- temp = src->wx * 0x10000;
+ temp = src->xw * 0x10000;
m1[12] = (temp >> 0x10);
m2[12] = temp & 0xFFFF;
- temp = src->wy * 0x10000;
+ temp = src->yw * 0x10000;
m1[13] = (temp >> 0x10);
m2[13] = temp & 0xFFFF;
- temp = src->wz * 0x10000;
+ temp = src->zw * 0x10000;
m1[14] = (temp >> 0x10);
m2[14] = temp & 0xFFFF;
@@ -612,21 +611,21 @@ void SkinMatrix_SetRotateAroundVec(MtxF* mf, s16 a, f32 x, f32 y, f32 z) {
xz = x * z;
mf->xx = (1.0f - xx) * cosA + xx;
- mf->xy = (1.0f - cosA) * xy + z * sinA;
- mf->xz = (1.0f - cosA) * xz - y * sinA;
- mf->xw = 0.0f;
+ mf->yx = (1.0f - cosA) * xy + z * sinA;
+ mf->zx = (1.0f - cosA) * xz - y * sinA;
+ mf->wx = 0.0f;
- mf->yx = (1.0f - cosA) * xy - z * sinA;
+ mf->xy = (1.0f - cosA) * xy - z * sinA;
mf->yy = (1.0f - yy) * cosA + yy;
- mf->yz = (1.0f - cosA) * yz + x * sinA;
- mf->yw = 0.0f;
+ mf->zy = (1.0f - cosA) * yz + x * sinA;
+ mf->wy = 0.0f;
- mf->zx = (1.0f - cosA) * xz + y * sinA;
- mf->zy = (1.0f - cosA) * yz - x * sinA;
+ mf->xz = (1.0f - cosA) * xz + y * sinA;
+ mf->yz = (1.0f - cosA) * yz - x * sinA;
mf->zz = (1.0f - zz) * cosA + zz;
- mf->zw = 0.0f;
+ mf->wz = 0.0f;
- mf->wx = mf->wy = mf->wz = 0.0f;
+ mf->xw = mf->yw = mf->zw = 0.0f;
mf->ww = 1.0f;
}
@@ -642,27 +641,27 @@ void SkinMatrix_SetXRotation(MtxF* mf, s16 a) {
cosA = 1.0f;
}
- mf->xy = 0.0f;
- mf->xz = 0.0f;
- mf->xw = 0.0f;
-
mf->yx = 0.0f;
- mf->yw = 0.0f;
-
mf->zx = 0.0f;
- mf->zw = 0.0f;
-
mf->wx = 0.0f;
+
+ mf->xy = 0.0f;
mf->wy = 0.0f;
+
+ mf->xz = 0.0f;
mf->wz = 0.0f;
+ mf->xw = 0.0f;
+ mf->yw = 0.0f;
+ mf->zw = 0.0f;
+
mf->xx = 1.0f;
mf->ww = 1.0f;
mf->yy = cosA;
mf->zz = cosA;
- mf->yz = sinA;
- mf->zy = -sinA;
+ mf->zy = sinA;
+ mf->yz = -sinA;
}
void SkinMatrix_MulXRotation(MtxF* mf, s16 a) {
@@ -675,25 +674,25 @@ void SkinMatrix_MulXRotation(MtxF* mf, s16 a) {
sinA = Math_SinS(a);
cosA = Math_CosS(a);
- ry = mf->yx;
- rz = mf->zx;
- mf->yx = ry * cosA + rz * sinA;
- mf->zx = rz * cosA - ry * sinA;
+ ry = mf->xy;
+ rz = mf->xz;
+ mf->xy = ry * cosA + rz * sinA;
+ mf->xz = rz * cosA - ry * sinA;
ry = mf->yy;
- rz = mf->zy;
+ rz = mf->yz;
mf->yy = ry * cosA + rz * sinA;
- mf->zy = rz * cosA - ry * sinA;
+ mf->yz = rz * cosA - ry * sinA;
- ry = mf->yz;
+ ry = mf->zy;
rz = mf->zz;
- mf->yz = ry * cosA + rz * sinA;
+ mf->zy = ry * cosA + rz * sinA;
mf->zz = rz * cosA - ry * sinA;
- ry = mf->yw;
- rz = mf->zw;
- mf->yw = ry * cosA + rz * sinA;
- mf->zw = rz * cosA - ry * sinA;
+ ry = mf->wy;
+ rz = mf->wz;
+ mf->wy = ry * cosA + rz * sinA;
+ mf->wz = rz * cosA - ry * sinA;
}
}
@@ -709,27 +708,27 @@ void SkinMatrix_SetYRotation(MtxF* mf, s16 a) {
cosA = 1.0f;
}
- mf->xy = 0.0f;
- mf->xw = 0.0f;
-
mf->yx = 0.0f;
- mf->yz = 0.0f;
- mf->yw = 0.0f;
+ mf->wx = 0.0f;
+ mf->xy = 0.0f;
mf->zy = 0.0f;
- mf->zw = 0.0f;
-
- mf->wx = 0.0f;
mf->wy = 0.0f;
+
+ mf->yz = 0.0f;
mf->wz = 0.0f;
+ mf->xw = 0.0f;
+ mf->yw = 0.0f;
+ mf->zw = 0.0f;
+
mf->yy = 1.0f;
mf->ww = 1.0f;
mf->xx = cosA;
mf->zz = cosA;
- mf->xz = -sinA;
- mf->zx = sinA;
+ mf->zx = -sinA;
+ mf->xz = sinA;
}
void SkinMatrix_MulYRotation(MtxF* mf, s16 a) {
@@ -743,24 +742,24 @@ void SkinMatrix_MulYRotation(MtxF* mf, s16 a) {
cosA = Math_CosS(a);
rx = mf->xx;
- rz = mf->zx;
+ rz = mf->xz;
mf->xx = rx * cosA - rz * sinA;
- mf->zx = rx * sinA + rz * cosA;
+ mf->xz = rx * sinA + rz * cosA;
- rx = mf->xy;
- rz = mf->zy;
- mf->xy = rx * cosA - rz * sinA;
- mf->zy = rx * sinA + rz * cosA;
+ rx = mf->yx;
+ rz = mf->yz;
+ mf->yx = rx * cosA - rz * sinA;
+ mf->yz = rx * sinA + rz * cosA;
- rx = mf->xz;
+ rx = mf->zx;
rz = mf->zz;
- mf->xz = rx * cosA - rz * sinA;
+ mf->zx = rx * cosA - rz * sinA;
mf->zz = rx * sinA + rz * cosA;
- rx = mf->xw;
- rz = mf->zw;
- mf->xw = rx * cosA - rz * sinA;
- mf->zw = rx * sinA + rz * cosA;
+ rx = mf->wx;
+ rz = mf->wz;
+ mf->wx = rx * cosA - rz * sinA;
+ mf->wz = rx * sinA + rz * cosA;
}
}
@@ -776,25 +775,25 @@ void SkinMatrix_SetZRotation(MtxF* mf, s16 a) {
cosA = 1.0f;
}
- mf->xz = 0.0f;
- mf->xw = 0.0f;
-
- mf->yz = 0.0f;
- mf->yw = 0.0f;
-
mf->zx = 0.0f;
- mf->zy = 0.0f;
- mf->zw = 0.0f;
-
mf->wx = 0.0f;
+
+ mf->zy = 0.0f;
mf->wy = 0.0f;
+
+ mf->xz = 0.0f;
+ mf->yz = 0.0f;
mf->wz = 0.0f;
+ mf->xw = 0.0f;
+ mf->yw = 0.0f;
+ mf->zw = 0.0f;
+
mf->zz = 1.0f;
mf->ww = 1.0f;
mf->xx = cosA;
mf->yy = cosA;
- mf->xy = sinA;
- mf->yx = -sinA;
+ mf->yx = sinA;
+ mf->xy = -sinA;
}
diff --git a/src/code/z_sub_s.c b/src/code/z_sub_s.c
index b51de4897..4968185d0 100644
--- a/src/code/z_sub_s.c
+++ b/src/code/z_sub_s.c
@@ -53,7 +53,7 @@ Gfx* SubS_DrawTransformFlexLimb(GlobalContext* globalCtx, s32 limbIndex, void**
Vec3f pos;
Vec3s rot;
- Matrix_StatePush();
+ Matrix_Push();
limb = Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
rot = jointTable[limbIndex];
@@ -63,8 +63,8 @@ Gfx* SubS_DrawTransformFlexLimb(GlobalContext* globalCtx, s32 limbIndex, void**
newDList = limbDList = limb->dList;
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &newDList, &pos, &rot, actor, &gfx)) {
- Matrix_JointPosition(&pos, &rot);
- Matrix_StatePush();
+ Matrix_TranslateRotateZYX(&pos, &rot);
+ Matrix_Push();
transformLimbDraw(globalCtx, limbIndex, actor, &gfx);
@@ -77,7 +77,7 @@ Gfx* SubS_DrawTransformFlexLimb(GlobalContext* globalCtx, s32 limbIndex, void**
Matrix_ToMtx(*mtx);
(*mtx)++;
}
- Matrix_StatePop();
+ Matrix_Pop();
}
if (postLimbDraw != NULL) {
postLimbDraw(globalCtx, limbIndex, &limbDList, &rot, actor, &gfx);
@@ -86,7 +86,7 @@ Gfx* SubS_DrawTransformFlexLimb(GlobalContext* globalCtx, s32 limbIndex, void**
gfx = SubS_DrawTransformFlexLimb(globalCtx, limb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw,
transformLimbDraw, actor, mtx, gfx);
}
- Matrix_StatePop();
+ Matrix_Pop();
if (limb->sibling != LIMB_DONE) {
gfx = SubS_DrawTransformFlexLimb(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw,
transformLimbDraw, actor, mtx, gfx);
@@ -119,7 +119,7 @@ Gfx* SubS_DrawTransformFlex(GlobalContext* globalCtx, void** skeleton, Vec3s* jo
}
gSPSegment(gfx++, 0x0D, mtx);
- Matrix_StatePush();
+ Matrix_Push();
rootLimb = Lib_SegmentedToVirtual(skeleton[0]);
pos.x = jointTable->x;
pos.y = jointTable->y;
@@ -129,8 +129,8 @@ Gfx* SubS_DrawTransformFlex(GlobalContext* globalCtx, void** skeleton, Vec3s* jo
limbDList = rootLimb->dList;
if (overrideLimbDraw == NULL || !overrideLimbDraw(globalCtx, 1, &newDlist, &pos, &rot, actor, &gfx)) {
- Matrix_JointPosition(&pos, &rot);
- Matrix_StatePush();
+ Matrix_TranslateRotateZYX(&pos, &rot);
+ Matrix_Push();
transformLimbDraw(globalCtx, 1, actor, &gfx);
@@ -143,7 +143,7 @@ Gfx* SubS_DrawTransformFlex(GlobalContext* globalCtx, void** skeleton, Vec3s* jo
Matrix_ToMtx(mtx);
mtx++;
}
- Matrix_StatePop();
+ Matrix_Pop();
}
if (postLimbDraw != NULL) {
@@ -154,7 +154,7 @@ Gfx* SubS_DrawTransformFlex(GlobalContext* globalCtx, void** skeleton, Vec3s* jo
gfx = SubS_DrawTransformFlexLimb(globalCtx, rootLimb->child, skeleton, jointTable, overrideLimbDraw,
postLimbDraw, transformLimbDraw, actor, &mtx, gfx);
}
- Matrix_StatePop();
+ Matrix_Pop();
return gfx;
}
@@ -168,23 +168,318 @@ s32 SubS_InCsMode(GlobalContext* globalCtx) {
return inCsMode;
}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013AD9C.s")
+/**
+ * Computes a limb's position and rotation for use in TransformLimbDraws
+ *
+ * @param[in] newRotZ value to override newRot's Z value if override is true
+ * @param[in] newRotY value to override newRot's Y value if override is true
+ * @param[out] pos limb's computed position
+ * @param[out] rot limb's computed rotation
+ * @param[in] stepRot boolean, step towards newRot instead of setting directly
+ * @param[in] overrideRot boolean, override newRot with the specified input.
+ *
+ * @note if overrideRot is true, the rotation will automatically step instead of setting directly
+ */
+s32 SubS_UpdateLimb(s16 newRotZ, s16 newRotY, Vec3f* pos, Vec3s* rot, s32 stepRot, s32 overrideRot) {
+ Vec3f newPos;
+ Vec3f zeroVec = gZeroVec3f;
+ Vec3s newRot;
+ MtxF curState;
+
+ Matrix_MultVec3f(&zeroVec, &newPos);
+ Matrix_Get(&curState);
+ Matrix_MtxFToYXZRot(&curState, &newRot, MTXMODE_NEW);
+ *pos = newPos;
+
+ if (!stepRot && !overrideRot) {
+ rot->x = newRot.x;
+ rot->y = newRot.y;
+ rot->z = newRot.z;
+ return true;
+ }
+
+ if (overrideRot) {
+ newRot.z = newRotZ;
+ newRot.y = newRotY;
+ }
+
+ Math_SmoothStepToS(&rot->x, newRot.x, 3, 0x2AA8, 0xB6);
+ Math_SmoothStepToS(&rot->y, newRot.y, 3, 0x2AA8, 0xB6);
+ Math_SmoothStepToS(&rot->z, newRot.z, 3, 0x2AA8, 0xB6);
+ return true;
+}
void SubS_UpdateFlags(u16* flags, u16 setBits, u16 unsetBits) {
*flags = (*flags & ~unsetBits) | setBits;
}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013AF00.s")
+/**
+ * Fills the knot array to be used with time paths
+ *
+ * The default knot array just pads with `order` duplicate knots of the first knot at the front and of the last knot
+ * at the end.
+ *
+ * @param[out] knots an array of values that are used to compute the progress and the individual weights
+ * @param[in] order the order of the interpolation i.e. the number of points in the interpolation
+ * @param[in] numPoints the number of points to fill, generally the path count + order
+ *
+ * @note Same note as SubS_TimePathing_Update()
+ */
+void SubS_TimePathing_FillKnots(f32 knots[], s32 order, s32 numPoints) {
+ s32 i;
+ f32 val = 0.0f;
+
+ for (i = 0; i < numPoints; i++) {
+ if ((i >= order) && (i < (numPoints - order + 1))) {
+ val += 1.0f;
+ }
+ knots[i] = val;
+ }
+}
+
+typedef enum {
+ /* 0 */ SUBS_TIME_PATHING_PROGRESS_STATUS_ERROR,
+ /* 1 */ SUBS_TIME_PATHING_PROGRESS_STATUS_STILL_ON_PATH,
+ /* 2 */ SUBS_TIME_PATHING_PROGRESS_STATUS_SHOULD_REACH_END
+} SUBS_TIME_PATHING_PROGRESS_STATUS;
+
+/**
+ * Computes the progress to be used with time paths
+ *
+ * @param[out] progress the progress along the path, used to compute the weights
+ * @param[in] elapsedTime how much time has passed
+ * @param[in] waypointTime how much time per each waypoint
+ * @param[in] totalTime how much time the path should take to travel
+ * @param[in] pathCount the path count
+ * @param[in] order the order of the interpolation i.e. the number of points in the interpolation
+ * @param[in] knots see SubS_TimePathing_FillKnots()
+ *
+ * @return see SUBS_TIME_PATHING_PROGRESS_STATUS
+ */
+s32 SubS_TimePathing_ComputeProgress(f32* progress, s32 elapsedTime, s32 waypointTime, s32 totalTime, s32 pathCount,
+ s32 order, f32 knots[]) {
+ s32 i;
+ s32 j;
+ s32 k;
+ f32 waypointTimeInv; // The fraction of a waypoint a single unit of time contains
+
+ *progress = 0.0f;
+ if ((waypointTime <= 0) || (elapsedTime < 0)) {
+ return SUBS_TIME_PATHING_PROGRESS_STATUS_ERROR;
+ }
+
+ // When using the knots from SubS_TimePathing_FillKnots() these nested loops seem to simplify to
+ // *progress = (f32)elapsedTime / (f32)waypointTime;
+ waypointTimeInv = 1.0f / waypointTime;
+ k = 0;
+ for (i = order - 1; i < pathCount; i++) {
+ for (j = 0; j < waypointTime; j++) {
+ if (k == elapsedTime) {
+ break;
+ }
+ *progress += (knots[i + 1] - knots[i]) * waypointTimeInv;
+ k++;
+ }
+ }
+
+ return (elapsedTime == totalTime) ? SUBS_TIME_PATHING_PROGRESS_STATUS_SHOULD_REACH_END
+ : SUBS_TIME_PATHING_PROGRESS_STATUS_STILL_ON_PATH;
+}
+
+/**
+ * Computes the interpolation weights to be used with time paths
+ *
+ * Seems to use some kind of B-Spline interpolation algorithm
+ *
+ * @param[in] order the order of the interpolation i.e. the number of points in the interpolation, max is 10
+ * @param[in] progress see SubS_TimePathing_ComputeProgress()
+ * @param[in] waypoint the current waypoint
+ * @param[in] knots see SubS_TimePathing_FillKnots()
+ * @param[out] weights how much to weight each point considered
+ */
+void SubS_TimePathing_ComputeWeights(s32 order, f32 progress, s32 waypoint, f32 knots[], f32 weights[]) {
+ f32 weightsTemp[10][11];
+ s32 i;
+ s32 j;
+ s32 k;
+
+ for (i = 0; i < order; i++) {
+ for (j = 0; j < order + 1; j++) {
+ weightsTemp[i][j] = 0.0f;
+ }
+ }
+
+ weightsTemp[0][order - 1] = 1.0f;
+
+ for (i = 1; i < order; i++) {
+ for (j = waypoint - i, k = (order - 1) - i; j <= waypoint; j++, k++) {
+ if (knots[j + i] != knots[j]) {
+ weightsTemp[i][k] = ((progress - knots[j]) / (knots[j + i] - knots[j])) * weightsTemp[i - 1][k];
+ } else {
+ weightsTemp[i][k] = 0.0f;
+ }
+
+ if (knots[j + i + 1] != knots[j + 1]) {
+ weightsTemp[i][k] +=
+ ((knots[j + i + 1] - progress) / (knots[j + i + 1] - knots[j + 1])) * weightsTemp[i - 1][k + 1];
+ }
+ }
+ }
+ for (j = 0; j < order; j++) {
+ weights[j] = weightsTemp[order - 1][j];
+ }
+}
+
+/**
+ * Computes the X and Z component of the position to move to in time based paths
+ *
+ * @param[out] x computed x position
+ * @param[out] z computed z position
+ * @param[in] progress see SubS_TimePathing_ComputeProgress()
+ * @param[in] order the order of the interpolation i.e. the number of points in the interpolation, max is 10
+ * @param[in] waypoint the current waypoint
+ * @param[in] points the path's points
+ * @param[in] knots see SubS_TimePathing_FillKnots()
+ */
+void SubS_TimePathing_ComputeTargetPosXZ(f32* x, f32* z, f32 progress, s32 order, s32 waypoint, Vec3s points[],
+ f32 knots[]) {
+ f32 xPos;
+ f32 zPos;
+ f32 weights[11];
+ f32 weightedX;
+ f32 weightedZ;
+ f32 weightedTotal;
+ s32 i;
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013B010.s")
+ SubS_TimePathing_ComputeWeights(order, progress, waypoint, knots, weights);
+ weightedTotal = 0.0f;
+ weightedZ = 0.0f;
+ weightedX = 0.0f;
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013B0C8.s")
+ for (i = 0; i < order; i++) {
+ xPos = points[waypoint - order + i + 1].x;
+ zPos = points[waypoint - order + i + 1].z;
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013B350.s")
+ weightedX += weights[i] * xPos;
+ weightedZ += weights[i] * zPos;
+ weightedTotal += weights[i];
+ }
+ *x = weightedX / weightedTotal;
+ *z = weightedZ / weightedTotal;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013B6B0.s")
+/**
+ * Updates a time based path that an actor follows by:
+ * - Computing the X and Z components of the next point to move to
+ * - Updating the waypoint
+ * - Updating the time
+ *
+ * @param[in] path
+ * @param[out] progress see SubS_TimePathing_ComputeProgress()
+ * @param[in,out] elapsedTime how much time has passed
+ * @param[in] waypointTime how much time per each waypoint
+ * @param[in] totalTime how much time the path should take to travel
+ * @param[in,out] waypoint the current waypoint, this and the previous two points will be used to compute the targetPos
+ * @param[in] knots see SubS_TimePathing_FillKnots()
+ * @param[out] targetPos the computed position to move to
+ * @param[in] timeSpeed how fast time moves
+ *
+ * @return s32 returns true when the end has been reached.
+ *
+ * @note This system/function makes a couple of assumptions about the order used:
+ * 1. the order is assumed to be 3, see SUBS_TIME_PATHING_ORDER
+ * 2. even if SUBS_TIME_PATHING_ORDER is updated, the order can only be a max of 10
+ */
+s32 SubS_TimePathing_Update(Path* path, f32* progress, s32* elapsedTime, s32 waypointTime, s32 totalTime, s32* waypoint,
+ f32 knots[], Vec3f* targetPos, s32 timeSpeed) {
+ Vec3s* points = Lib_SegmentedToVirtual(path->points);
+ s32 state;
+ f32 endX;
+ f32 endZ;
+ s32 reachedEnd = false;
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013B878.s")
+ if (*waypoint >= path->count) {
+ state = SUBS_TIME_PATHING_PROGRESS_STATUS_SHOULD_REACH_END;
+ } else {
+ state = SubS_TimePathing_ComputeProgress(progress, *elapsedTime, waypointTime, totalTime, path->count,
+ SUBS_TIME_PATHING_ORDER, knots);
+ }
+
+ switch (state) {
+ case SUBS_TIME_PATHING_PROGRESS_STATUS_STILL_ON_PATH:
+ reachedEnd = false;
+ SubS_TimePathing_ComputeTargetPosXZ(&targetPos->x, &targetPos->z, *progress, SUBS_TIME_PATHING_ORDER,
+ *waypoint, points, knots);
+ break;
+ case SUBS_TIME_PATHING_PROGRESS_STATUS_SHOULD_REACH_END:
+ endX = points[path->count - 1].x;
+ endZ = points[path->count - 1].z;
+ targetPos->x = endX * 1;
+ targetPos->z = endZ * 1;
+ reachedEnd = true;
+ break;
+ }
+
+ *elapsedTime += timeSpeed;
+ if (*elapsedTime >= totalTime) {
+ *elapsedTime = totalTime;
+ } else if (*elapsedTime < 0) {
+ *elapsedTime = 0;
+ }
+ *waypoint = (*elapsedTime / waypointTime) + (SUBS_TIME_PATHING_ORDER - 1);
+
+ return reachedEnd;
+}
+
+/**
+ * Computes the initial Y component of a time based path
+ *
+ * @param[in] globalCtx
+ * @param[in] path
+ * @param[in] waypoint the current waypoint, this and the previous two points will be used to compute the target pos
+ * @param[out] targetPos the computed position to move to, only the Y component has meaning
+ *
+ * @note Same note as SubS_TimePathing_Update()
+ */
+void SubS_TimePathing_ComputeInitialY(GlobalContext* globalCtx, Path* path, s32 waypoint, Vec3f* targetPos) {
+ Vec3s* points = Lib_SegmentedToVirtual(path->points);
+ Vec3f posA;
+ Vec3f posB;
+ Vec3f posResult;
+ s32 i = waypoint - (SUBS_TIME_PATHING_ORDER - 1);
+ s16 max;
+ s16 min;
+ s32 isSetup;
+ CollisionPoly* outPoly = NULL;
+ s32 bgId = 0;
+
+ max = 0;
+ min = 0;
+ isSetup = false;
+ for (; i <= waypoint; i++) {
+ if (isSetup) {
+ if (max < points[i].y) {
+ max = points[i].y;
+ }
+ if (points[i].y < min) {
+ min = points[i].y;
+ }
+ } else {
+ max = min = points[i].y;
+ }
+ isSetup = true;
+ }
+ max += 30;
+ min -= 30;
+ posA = *targetPos;
+ posB = *targetPos;
+ posA.y = max;
+ posB.y = min;
+ if (BgCheck_EntityLineTest1(&globalCtx->colCtx, &posA, &posB, &posResult, &outPoly, true, true, true, true,
+ &bgId)) {
+ targetPos->y = posResult.y;
+ }
+}
Path* SubS_GetAdditionalPath(GlobalContext* globalCtx, u8 pathIndex, s32 max) {
Path* path;
@@ -322,9 +617,189 @@ Path* SubS_GetDayDependentPath(GlobalContext* globalCtx, u8 pathIndex, u8 max, s
return path;
}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013C068.s")
+/**
+ * Computes the point to move toward using a weight based algorithm that considers 4 points along the path
+ *
+ * @param path
+ * @param waypoint the current waypoint, this and the previous three points will be used to compute the point
+ * @param point the point computed
+ * @param progress the main weight value used to compute the weights for the points considered
+ * @param direction the direciton along the path to move, 1 for forwards, anything else for backwards
+ *
+ * @note only computes X and Z components of the point
+ */
+s32 SubS_WeightPathing_ComputePoint(Path* path, s32 waypoint, Vec3f* point, f32 progress, s32 direction) {
+ s32 i;
+ f32 weight0;
+ f32 weight1;
+ f32 weight2;
+ f32 weight3;
+ s32 lastPoint;
+ s32 secondLastPoint;
+ s32 secondPoint;
+ s32 firstPoint;
+ f32 xPoints[4];
+ f32 zPoints[4];
+ f32 oneMinusProgress;
+ f32 squared;
+ f32 cubed;
+ Vec3s* points;
+ s32 count = path->count;
+ s32 pointIndex;
+ s32 tmp;
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013C624.s")
+ if (path == NULL) {
+ return false;
+ }
+ if (direction == 1) {
+ if (waypoint <= 2) {
+ pointIndex = 2;
+ } else {
+ pointIndex = (waypoint == 3) ? 3 : waypoint;
+ }
+ for (i = 0; i < 4; i++, pointIndex--) {
+ if (pointIndex <= 0) {
+ pointIndex = 0;
+ }
+ points = Lib_SegmentedToVirtual(path->points);
+ points = &points[pointIndex];
+ xPoints[i] = points->x;
+ zPoints[i] = points->z;
+ }
+ lastPoint = count - 1;
+ secondLastPoint = count - 2;
+ secondPoint = 3;
+ firstPoint = 2;
+ } else {
+ if (waypoint >= count - 3) {
+ pointIndex = count - 3;
+ } else {
+ tmp = waypoint + 4;
+ pointIndex = (count == tmp) ? count - 4 : waypoint;
+ }
+ for (i = 0; i < 4; i++, pointIndex++) {
+ if (pointIndex >= path->count) {
+ pointIndex = path->count - 1;
+ }
+ points = Lib_SegmentedToVirtual(path->points);
+ points = &points[pointIndex];
+ xPoints[i] = points->x;
+ zPoints[i] = points->z;
+ }
+ lastPoint = 0;
+ secondLastPoint = 1;
+ secondPoint = count - 4;
+ firstPoint = count - 3;
+ }
+ if (waypoint == lastPoint) {
+ oneMinusProgress = 1.0f - progress;
+ squared = progress * progress;
+ cubed = progress * squared;
+ weight0 = oneMinusProgress * oneMinusProgress * oneMinusProgress;
+ weight1 = (1.75f * cubed) - (4.5f * squared) + (3.0f * progress);
+ weight2 = ((-11.0f / 12.0f) * cubed) + (1.5f * squared);
+ weight3 = (1.0f / 6.0f) * cubed;
+ } else if (waypoint == secondLastPoint) {
+ oneMinusProgress = 1.0f - progress;
+ squared = progress * progress;
+ cubed = progress * squared;
+ weight0 = oneMinusProgress * oneMinusProgress * oneMinusProgress * ((void)0, 0.25f); //! FAKE:
+ weight1 = ((7.0f / 12.0f) * cubed) - (1.25f * squared) + (0.25f * progress) + (7.0f / 12.0f);
+ weight2 = (-0.5f * cubed) + (0.5f * squared) + (progress * 0.5f) + (1.0f / 6.0f);
+ weight3 = cubed * (1.0f / 6.0f);
+ } else if (waypoint == secondPoint) {
+ oneMinusProgress = 1.0f - progress;
+ squared = oneMinusProgress * oneMinusProgress;
+ cubed = oneMinusProgress * squared;
+ weight0 = (1.0f / 6.0f) * cubed;
+ weight1 = (-0.5f * cubed) + (0.5f * squared) + (0.5f * oneMinusProgress) + (1.0f / 6.0f);
+ weight2 = ((7.0f / 12.0f) * cubed) - (1.25f * squared) + (0.25f * oneMinusProgress) + (7.0f / 12.0f);
+ weight3 = progress * progress * progress * 0.25f;
+ } else if (((direction == 1) && (firstPoint >= waypoint)) || ((direction != 1) && (waypoint >= firstPoint))) {
+ oneMinusProgress = 1.0f - progress;
+ squared = oneMinusProgress * oneMinusProgress;
+ cubed = oneMinusProgress * squared;
+ weight0 = (1.0f / 6.0f) * cubed;
+ weight1 = ((-11.0f / 12.0f) * cubed) + (1.5f * squared);
+ weight2 = (1.75f * cubed) - (4.5f * squared) + (3.0f * oneMinusProgress);
+ weight3 = progress * progress * progress;
+ } else {
+ oneMinusProgress = 1.0f - progress;
+ squared = progress * progress;
+ cubed = squared * progress;
+ weight0 = oneMinusProgress * oneMinusProgress;
+ weight0 = oneMinusProgress * weight0 / 6.0f;
+ weight1 = (cubed * 0.5f) - squared + (2.0f / 3.0f);
+ weight2 = (cubed / -2.0f) + (squared * 0.5f) + (progress * 0.5f) + (1.0f / 6.0f);
+ weight3 = cubed / 6.0f;
+ }
+ point->x = (weight0 * xPoints[0]) + (weight1 * xPoints[1]) + (weight2 * xPoints[2]) + (weight3 * xPoints[3]);
+ point->z = (weight0 * zPoints[0]) + (weight1 * zPoints[1]) + (weight2 * zPoints[2]) + (weight3 * zPoints[3]);
+
+ return true;
+}
+
+// WeightPathing System is completely unused
+/**
+ * Moves an actor based on a weight based algorithm that takes into account 4 points along the path
+ *
+ * @param actor
+ * @param path
+ * @param waypoint the current waypoint, this and the previous three points will be used to move forward
+ * @param progress the progress towards a given waypoint, used to compute the weights
+ * @param direction the direction along the path to move, 1 for forwards, anything else for backwards
+ * @param returnStart boolean, true if the actor should wrap back to start when reaching the end
+ *
+ * @return s32 true if actor reached the end of the path in this iteration, false otherwise
+ */
+s32 SubS_WeightPathing_Move(Actor* actor, Path* path, s32* waypoint, f32* progress, s32 direction, s32 returnStart) {
+ Vec3f worldPos = actor->world.pos;
+ Vec3f velocity = actor->velocity;
+ Vec3f point;
+ f32 dist;
+
+ if (((direction != 1) && (*waypoint >= (path->count - 2))) || ((direction == 1) && (*waypoint < 2))) {
+ return false;
+ }
+ while (true) {
+ if (!SubS_WeightPathing_ComputePoint(path, *waypoint, &point, *progress, direction) ||
+ ((s32)(actor->speedXZ * 10000.0f) == 0)) {
+ return false;
+ }
+ dist = Math_Vec3f_DistXZ(&actor->world.pos, &point);
+ actor->world.rot.y = Math_Vec3f_Yaw(&actor->world.pos, &point);
+ Actor_MoveWithGravity(actor);
+ if (Math_Vec3f_DistXZ(&actor->world.pos, &point) < dist) {
+ break;
+ }
+ *progress += 0.1f;
+ if (*progress >= 1.1f) {
+ if (direction != 1) {
+ (*waypoint)++;
+ if (*waypoint >= (path->count - 2)) {
+ if (returnStart) {
+ *waypoint = 0;
+ } else {
+ return true;
+ }
+ }
+ } else {
+ (*waypoint)--;
+ if (*waypoint < 2) {
+ if (returnStart) {
+ *waypoint = path->count - 2;
+ } else {
+ return true;
+ }
+ }
+ }
+ *progress = 0.0f;
+ }
+ actor->world.pos = worldPos;
+ actor->velocity = velocity;
+ }
+ return false;
+}
s32 SubS_CopyPointFromPathCheckBounds(Path* path, s32 pointIndex, Vec3f* dst) {
Vec3s* point;
@@ -498,7 +973,7 @@ void SubS_GenShadowTex(Vec3f bodyPartsPos[], Vec3f* worldPos, u8* tex, f32 tween
pos.z = bodyPartPos->z - worldPos->z;
}
- Matrix_MultiplyVector3fByState(&pos, &startVec);
+ Matrix_MultVec3f(&pos, &startVec);
startCol = 64.0f + startVec.x;
startRow = 64.0f - startVec.z;
SubS_FillShadowTex(startCol >> 1, startRow >> 1, tex, sizes[i]);
@@ -514,20 +989,102 @@ void SubS_DrawShadowTex(Actor* actor, GameState* gameState, u8* tex) {
func_8012C28C(gfxCtx);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 0, 0, 100);
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
- Matrix_InsertTranslation(actor->world.pos.x, 0.0f, actor->world.pos.z, MTXMODE_NEW);
+ Matrix_Translate(actor->world.pos.x, 0.0f, actor->world.pos.z, MTXMODE_NEW);
Matrix_Scale(0.6f, 1.0f, 0.6f, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_OPA_DISP++, gShadowDL);
+ gSPDisplayList(POLY_OPA_DISP++, gShadowMaterialDL);
gDPLoadTextureBlock(POLY_OPA_DISP++, tex, G_IM_FMT_I, G_IM_SIZ_8b, SUBS_SHADOW_TEX_WIDTH, SUBS_SHADOW_TEX_HEIGHT, 0,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD);
- gSPDisplayList(POLY_OPA_DISP++, gShadowVtxDL);
+ gSPDisplayList(POLY_OPA_DISP++, gShadowModelDL);
CLOSE_DISPS(gfxCtx);
}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013D0E0.s")
+/**
+ * Computes the rotation based on the options and target rotation value
+ *
+ * @param[in,out] rot the computed rotation
+ * @param[in] rotMax the max rotation in binary angles
+ * @param[in] target the target rotation value
+ * @param[in] slowness how slow to rotate, the larger the number the slower the rotation, cannot be 0
+ * @param[in] stepMin the minimun step in degrees
+ * @param[in] stepMax the maximum step in degrees
+ */
+s16 SubS_ComputeTrackPointRot(s16* rot, s16 rotMax, s16 target, f32 slowness, f32 stepMin, f32 stepMax) {
+ s16 prevRot = *rot;
+ f32 step;
+ f32 prevRotStep;
+
+ step = (f32)(target - *rot) * (360.0f / (f32)0x10000);
+ step *= gFramerateDivisorHalf;
+ prevRotStep = step;
+ if (step >= 0.0f) {
+ step /= slowness;
+ step = CLAMP(step, stepMin, stepMax);
+ *rot += (s16)((step * (f32)0x10000) / 360.0f);
+ if (prevRotStep < stepMin) {
+ *rot = target;
+ }
+ if (rotMax != 0) {
+ *rot = CLAMP(*rot, -rotMax, rotMax);
+ }
+ } else {
+ step = (step / slowness) * -1.0f;
+ step = CLAMP(step, stepMin, stepMax);
+ *rot -= (s16)((step * (f32)0x10000) / 360.0f);
+ if (-stepMin < prevRotStep) {
+ *rot = target;
+ }
+ if (rotMax != 0) {
+ *rot = CLAMP(*rot, -rotMax, rotMax);
+ }
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013D2E0.s")
+ return prevRot - *rot;
+}
+
+/**
+ * Computes the necessary HeadRot and TorsoRot to smoothly turn an actors's head and torso to a point
+ *
+ * @param[in] target the point to turn to
+ * @param[in] focusPos the actor's focus postion
+ * @param[in] shapeRot the actor's shape rotation
+ * @param[in,out] trackTarget the intermediate target step that headRot and torsoRot step towards
+ * @param[in,out] headRot the computed head rotation
+ * @param[in,out] torsoRot the computed torso rotation
+ * @param[in] options various options to adjust how the actor turns, see SubS_ComputeTrackPointRot()
+ */
+s32 SubS_TrackPoint(Vec3f* target, Vec3f* focusPos, Vec3s* shapeRot, Vec3s* trackTarget, Vec3s* headRot,
+ Vec3s* torsoRot, TrackOptionsSet* options) {
+ s16 pitch;
+ s16 yaw;
+ s16 pad;
+ s16 targetY;
+ f32 diffX = target->x - focusPos->x;
+ s16 targetX;
+ f32 diffZ = target->z - focusPos->z;
+
+ yaw = Math_FAtan2F(diffZ, diffX);
+ pitch = Math_FAtan2F(sqrtf(SQ(diffX) + SQ(diffZ)), target->y - focusPos->y);
+ Math_SmoothStepToS(&trackTarget->x, pitch, 4, 0x2710, 0);
+ Math_SmoothStepToS(&trackTarget->y, yaw, 4, 0x2710, 0);
+
+ targetX =
+ SubS_ComputeTrackPointRot(&headRot->x, options->headRotX.rotMax, trackTarget->x, options->headRotX.slowness,
+ options->headRotX.rotStepMin, options->headRotX.rotStepMax);
+ //! @bug: torsoRotX uses headRotX slowness
+ SubS_ComputeTrackPointRot(&torsoRot->x, options->torsoRotX.rotMax, targetX, options->headRotX.slowness,
+ options->torsoRotX.rotStepMin, options->torsoRotX.rotStepMax);
+
+ targetY = trackTarget->y - shapeRot->y;
+ SubS_ComputeTrackPointRot(&headRot->y, options->headRotY.rotMax, targetY - torsoRot->y, options->headRotY.slowness,
+ options->headRotY.rotStepMin, options->headRotY.rotStepMax);
+ SubS_ComputeTrackPointRot(&torsoRot->y, options->torsoRotY.rotMax, targetY - headRot->y,
+ options->torsoRotY.slowness, options->torsoRotY.rotStepMin,
+ options->torsoRotY.rotStepMax);
+
+ return true;
+}
s32 SubS_AngleDiffLessEqual(s16 angleA, s16 threshold, s16 angleB) {
return (ABS_ALT(BINANG_SUB(angleB, angleA)) <= threshold) ? true : false;
@@ -657,8 +1214,8 @@ s32 SubS_CopyPointFromPathList(Path* paths, s32 pathIndex, s32 pointIndex, Vec3f
return false;
}
-u8 SubS_GetPathCount(Path* paths, s32 index) {
- Path* path = &paths[index];
+u8 SubS_GetPathCountFromPathList(Path* paths, s32 pathIndex) {
+ Path* path = &paths[pathIndex];
return path->count;
}
@@ -880,9 +1437,7 @@ s32 SubS_FillCutscenesList(Actor* actor, s16 cutscenes[], s16 numCutscenes) {
* @param[in] rot the angles to rotate with, uses just the x and y components
* @param[out] plane the computed plane
*
- * Notes:
- * The unit input vector is expected to already be normalized (only uses are with the z unit vector)
- *
+ * @note the unit input vector is expected to already be normalized (only uses are with the z unit vector)
*/
void SubS_ConstructPlane(Vec3f* point, Vec3f* unitVec, Vec3s* rot, Plane* plane) {
f32 sin;
@@ -987,4 +1542,51 @@ s32 func_8013E8F8(Actor* actor, GlobalContext* globalCtx, f32 xzRange, f32 yRang
return func_8013E748(actor, globalCtx, xzRange, yRange, exhangeItemId, &yawTols, SubS_ActorAndPlayerFaceEachOther);
}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013E950.s")
+/**
+ * Computes the necessary HeadRot and TorsoRot steps to be added to the normal rotation to smoothly turn an actors's
+ * head and torso to a point
+ *
+ * @param[in] worldPos the actor's world position
+ * @param[in] focusPos the actor's focus position
+ * @param[in] shapeYRot the actor's shape's Y rotation
+ * @param[in] yawTarget the target point to determine desired yaw
+ * @param[in] pitchTarget the target point to determine desired pitch
+ * @param[in,out] headZRotStep the computed actors' head's Z rotation step
+ * @param[in,out] headXRotStep the computed actors' head's X rotation step
+ * @param[in,out] torsoZRotStep the computed actors' torso's Z rotation step
+ * @param[in,out] torsoXRotStep the computed actors' torso's X rotation step
+ * @param[in] headZRotStepMax the max head's Z rotation step
+ * @param[in] headXRotStepMax the max head's X rotation step
+ * @param[in] torsoZRotStepMax the max torso's Z rotation step
+ * @param[in] torsoXRotStepMax the max torso's X rotation step
+ */
+s32 SubS_TrackPointStep(Vec3f* worldPos, Vec3f* focusPos, s16 shapeYRot, Vec3f* yawTarget, Vec3f* pitchTarget,
+ s16* headZRotStep, s16* headXRotStep, s16* torsoZRotStep, s16* torsoXRotStep,
+ u16 headZRotStepMax, u16 headXRotStepMax, u16 torsoZRotStepMax, u16 torsoXRotStepMax) {
+ s16 yaw = Math_Vec3f_Yaw(worldPos, yawTarget) - shapeYRot;
+ s16 pad;
+ s16 pad2;
+ s16 pitch = Math_Vec3f_Pitch(focusPos, pitchTarget);
+
+ if (BINANG_ADD(headXRotStepMax, torsoXRotStepMax) >= (s16)ABS(yaw)) {
+ Math_ApproachS(headXRotStep, yaw - *torsoXRotStep, 4, 0x2AA8);
+ *headXRotStep = CLAMP(*headXRotStep, -headXRotStepMax, headXRotStepMax);
+ Math_ApproachS(torsoXRotStep, yaw - *headXRotStep, 4, 0x2AA8);
+ *torsoXRotStep = CLAMP(*torsoXRotStep, -torsoXRotStepMax, torsoXRotStepMax);
+ } else {
+ Math_ApproachS(headXRotStep, 0, 4, 0x2AA8);
+ Math_ApproachS(torsoXRotStep, 0, 4, 0x2AA8);
+ }
+
+ if (BINANG_ADD(headZRotStepMax, torsoZRotStepMax) >= (s16)ABS(pitch)) {
+ Math_ApproachS(headZRotStep, pitch - *torsoZRotStep, 4, 0x2AA8);
+ *headZRotStep = CLAMP(*headZRotStep, -headZRotStepMax, headZRotStepMax);
+ Math_ApproachS(torsoZRotStep, pitch - *headZRotStep, 4, 0x2AA8);
+ *torsoZRotStep = CLAMP(*torsoZRotStep, -torsoZRotStepMax, torsoZRotStepMax);
+ } else {
+ Math_ApproachS(headZRotStep, 0, 4, 0x2AA8);
+ Math_ApproachS(torsoZRotStep, 0, 4, 0x2AA8);
+ }
+
+ return true;
+}
diff --git a/src/code/z_view.c b/src/code/z_view.c
index d11a18201..915c196b7 100644
--- a/src/code/z_view.c
+++ b/src/code/z_view.c
@@ -262,15 +262,15 @@ s32 View_StepDistortion(View* view, Mtx* projectionMtx) {
F32_LERPIMP(view->curDistortionScale.z, view->distortionScale.z, view->distortionSpeed);
}
- Matrix_FromRSPMatrix(projectionMtx, &projectionMtxF);
- Matrix_SetCurrentState(&projectionMtxF);
- Matrix_RotateStateAroundXAxis(view->curDistortionDirRot.x);
- Matrix_InsertYRotation_f(view->curDistortionDirRot.y, MTXMODE_APPLY);
- Matrix_InsertZRotation_f(view->curDistortionDirRot.z, MTXMODE_APPLY);
+ Matrix_MtxToMtxF(projectionMtx, &projectionMtxF);
+ Matrix_Put(&projectionMtxF);
+ Matrix_RotateXFApply(view->curDistortionDirRot.x);
+ Matrix_RotateYF(view->curDistortionDirRot.y, MTXMODE_APPLY);
+ Matrix_RotateZF(view->curDistortionDirRot.z, MTXMODE_APPLY);
Matrix_Scale(view->curDistortionScale.x, view->curDistortionScale.y, view->curDistortionScale.z, MTXMODE_APPLY);
- Matrix_InsertZRotation_f(-view->curDistortionDirRot.z, MTXMODE_APPLY);
- Matrix_InsertYRotation_f(-view->curDistortionDirRot.y, MTXMODE_APPLY);
- Matrix_RotateStateAroundXAxis(-view->curDistortionDirRot.x);
+ Matrix_RotateZF(-view->curDistortionDirRot.z, MTXMODE_APPLY);
+ Matrix_RotateYF(-view->curDistortionDirRot.y, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-view->curDistortionDirRot.x);
Matrix_ToMtx(projectionMtx);
return true;
diff --git a/src/code/z_vismono.c b/src/code/z_vismono.c
index 6c0d1ef22..b28ed2aa6 100644
--- a/src/code/z_vismono.c
+++ b/src/code/z_vismono.c
@@ -1,14 +1,179 @@
+/*
+ * File: z_vismono.c
+ * Description: Color frame buffer effect to desaturate the colors.
+ */
+
#include "global.h"
#include "system_malloc.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_vismono/func_801418B0.s")
+// Height of the fragments the color frame buffer (CFB) is split into.
+// It is the maximum amount of lines such that all rgba16 SCREEN_WIDTH-long lines fit into
+// the half of tmem (0x800 bytes) dedicated to color-indexed data.
+#define VISMONO_CFBFRAG_HEIGHT (0x800 / (SCREEN_WIDTH * G_IM_SIZ_16b_BYTES))
+
+// Maximum size of the dlist written by `VisMono_DesaturateDList`.
+// `VisMono_DesaturateDList` consistently uses `VISMONO_DLSIZE - 2` double words, so this can be 2 less.
+#define VISMONO_DLSIZE (3 + SCREEN_HEIGHT / VISMONO_CFBFRAG_HEIGHT * (7 + 2 + 2 + 3) + 2 + 2)
+
+// How much each color component contributes to the desaturated result.
+// These coefficients are close to what the YUV color space defines Y (luminance) as:
+// https://en.wikipedia.org/wiki/YUV#Conversion_to/from_RGB
+#define VISMONO_FAC_RED 2
+#define VISMONO_FAC_GREEN 4
+#define VISMONO_FAC_BLUE 1
+#define VISMONO_FAC_NORM (0x1F * VISMONO_FAC_RED + 0x1F * VISMONO_FAC_GREEN + 0x1F * VISMONO_FAC_BLUE)
+
+void VisMono_Init(VisMono* this) {
+ bzero(this, sizeof(VisMono));
+ this->unk_00 = 0;
+ this->setScissor = false;
+ this->primColor.r = 255;
+ this->primColor.g = 255;
+ this->primColor.b = 255;
+ this->primColor.a = 255;
+ this->envColor.r = 0;
+ this->envColor.g = 0;
+ this->envColor.b = 0;
+ this->envColor.a = 0;
+}
+
+void VisMono_Destroy(VisMono* this) {
+ SystemArena_Free(this->dList);
+}
+
+void VisMono_DesaturateTLUT(u16* tlut) {
+ s32 i;
+
+ for (i = 0; i < 256; i++) {
+ // `tlut[i]` is a IA16 color
+ // `i` corresponds to either byte of a RGBA16 color RRRR_RGGG GGBB_BBBA from the color frame buffer
+
+ // The high byte I (intensity) corresponds to `i` being interpreted as the high byte RRRR_RGGG
+ // I = (RRRRR * FAC_RED + GGG00 * FAC_GREEN) * (255 / FAC_NORM)
+
+ // The low byte A (alpha) corresponds to `i` being interpreted as the low byte GGBB_BBBA
+ // A = (000GG * FAC_GREEN + BBBBB * FAC_BLUE) * (255 / FAC_NORM)
+
+ // Note: I + A = (RRRRR * FAC_RED + GGGGG * FAC_GREEN + BBBBB * FAC_BLUE) * (255 / FAC_NORM)
+
+ tlut[i] = GPACK_IA16(
+ (((i >> 3) & 0x1F) * VISMONO_FAC_RED + ((i << 2) & 0x1F) * VISMONO_FAC_GREEN) * 255 / VISMONO_FAC_NORM,
+ (((i >> 6) & 0x1F) * VISMONO_FAC_GREEN + ((i >> 1) & 0x1F) * VISMONO_FAC_BLUE) * 255 / VISMONO_FAC_NORM);
+ }
+}
+
+Gfx* VisMono_DesaturateDList(Gfx* gfx) {
+ s32 y;
+ s32 height = VISMONO_CFBFRAG_HEIGHT;
+ u16* cfbFrag = D_0F000000;
+
+ gDPPipeSync(gfx++);
+ // `G_TT_IA16`: use color-indexed images, and IA16 palettes
+ gDPSetOtherMode(gfx++,
+ G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_IA16 | G_TL_TILE |
+ G_TD_CLAMP | G_TP_NONE | G_CYC_2CYCLE | G_PM_1PRIMITIVE,
+ G_AC_NONE | G_ZS_PRIM | GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) | G_RM_CLD_SURF2);
+ // First color cycle sums texel 1 alpha and texel 0 color
+ // By using IA16 palettes, this means summing A (from the IA16 color texel 1 maps to)
+ // with I (from the IA16 color texel 0 maps to)
+ gDPSetCombineLERP(gfx++, 1, 0, TEXEL1_ALPHA, TEXEL0, 0, 0, 0, 1, PRIMITIVE, ENVIRONMENT, COMBINED, ENVIRONMENT, 0,
+ 0, 0, PRIMITIVE);
+
+ for (y = 0; y <= SCREEN_HEIGHT - height; y += height) {
+ // Load a few lines of the color frame buffer
+ gDPLoadTextureBlock(gfx++, cfbFrag, G_IM_FMT_CI, G_IM_SIZ_8b, SCREEN_WIDTH * 2, height, 0,
+ G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK,
+ G_TX_NOLOD, G_TX_NOLOD);
+
+ // Set texel 0 to be a CI8 image with width `SCREEN_WIDTH * 2` and height `VISMONO_CFBFRAG_HEIGHT`
+ // Its position in texture image space is shifted along +S by 2
+ gDPSetTile(gfx++, G_IM_FMT_CI, G_IM_SIZ_8b, SCREEN_WIDTH * 2 * G_IM_SIZ_8b_LINE_BYTES / 8, 0x0, G_TX_RENDERTILE,
+ 0, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0);
+ gDPSetTileSize(gfx++, G_TX_RENDERTILE, 2 << 2, 0, (SCREEN_WIDTH * 2 + 1) << 2,
+ (VISMONO_CFBFRAG_HEIGHT - 1) << 2);
+
+ // Set texel 1 to be a CI8 image with width `SCREEN_WIDTH * 2` and height `VISMONO_CFBFRAG_HEIGHT`
+ // Its position in texture image space is shifted along +S by 1
+ gDPSetTile(gfx++, G_IM_FMT_CI, G_IM_SIZ_8b, SCREEN_WIDTH * 2 * G_IM_SIZ_8b_LINE_BYTES / 8, 0x0, 1, 1,
+ G_TX_NOMIRROR | G_TX_CLAMP, 0, 0, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0);
+ gDPSetTileSize(gfx++, 1, 1 << 2, 0, (SCREEN_WIDTH * 2) << 2, (VISMONO_CFBFRAG_HEIGHT - 1) << 2);
+
+ // Draw a `SCREEN_WIDTH` wide, `height` high rectangle.
+ // Texture coordinate T (vertical) starts at 0 and changes by one each line (dtdy = 1)
+ // Texture coordinate S (horizontal) starts at 2 and changes by two each column (dsdx = 2)
+
+ // Because texel 0 is shifted by 2 and texel 1 only by 1 along +S,
+ // a pixel at S coordinates s = 2+2*n will look at the 2*n-th byte of texel 0 and the 2*n+1-th byte of texel 1.
+ // (in "s = 2+2*n" the first "2" is the starting S coordinate and the second "2" is the dsdx value)
+
+ // The 2*n-th byte of texel 0 is the high byte of the n-th RGBA16 color of the color frame buffer.
+ // The 2*n+1-th byte of texel 1 is the low byte of the n-th RGBA16 color of the color frame buffer.
+
+ // With the TLUT computed by `VisMono_DesaturateTLUT`:
+ // The 2*n-th byte of texel 0 maps to a IA16 color where the high byte I (intensity) corresponds to
+ // the high byte of the n-th RGBA16 color of the color frame buffer.
+ // The 2*n+1-th byte of texel 1 maps to a IA16 color where the low byte A (alpha) corresponds to
+ // the low byte of the n-th RGBA16 color of the color frame buffer.
+
+ // Since the combiner is in part set up to sum texel 0 color (I, intensity) with texel 1 alpha (A, alpha),
+ // the resulting color in the drawn rectangle is a desaturated color as defined by the `VISMONO_FAC_*` values.
+
+ gSPTextureRectangle(gfx++, 0, y << 2, SCREEN_WIDTH << 2, (y + height) << 2, G_TX_RENDERTILE, 2 << 5, 0, 2 << 10,
+ 1 << 10);
+ cfbFrag += SCREEN_WIDTH * height;
+ }
+
+ gDPPipeSync(gfx++);
+ gSPEndDisplayList(gfx++);
+ return gfx;
+}
+
+void VisMono_Draw(VisMono* this, Gfx** gfxp) {
+ Gfx* gfx = *gfxp;
+ u16* tlut;
+ Gfx* dList;
+ Gfx* dListEnd;
+
+ if (this->tlut) {
+ tlut = this->tlut;
+ } else {
+ tlut = Graph_DlistAlloc(&gfx, 256 * G_IM_SIZ_16b_BYTES);
+ VisMono_DesaturateTLUT(tlut);
+ }
+
+ if (this->dList) {
+ dList = this->dList;
+ } else {
+ dList = Graph_DlistAlloc(&gfx, VISMONO_DLSIZE * sizeof(Gfx));
+ dListEnd = VisMono_DesaturateDList(dList);
+ }
+
+ gDPPipeSync(gfx++);
+
+ if (this->setScissor == true) {
+ gSPDisplayList(gfx++, D_0E000000.setScissor);
+ }
+
+ gDPSetColor(gfx++, G_SETPRIMCOLOR, this->primColor.rgba);
+ gDPSetColor(gfx++, G_SETENVCOLOR, this->envColor.rgba);
+
+ gDPLoadTLUT_pal256(gfx++, tlut);
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_vismono/func_80141900.s")
+ gSPDisplayList(gfx++, dList);
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_vismono/func_80141924.s")
+ gDPPipeSync(gfx++);
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_vismono/func_80141C34.s")
+ *gfxp = gfx;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_vismono/VisMono_Draw.s")
+void VisMono_DrawOld(VisMono* this) {
+ if (this->tlut == NULL) {
+ this->tlut = SystemArena_Malloc(256 * G_IM_SIZ_16b_BYTES);
+ VisMono_DesaturateTLUT(this->tlut);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_vismono/func_8014204C.s")
+ if (this->dList == NULL) {
+ this->dList = SystemArena_Malloc(VISMONO_DLSIZE * sizeof(Gfx));
+ VisMono_DesaturateDList(this->dList);
+ }
+}
diff --git a/src/code/z_vr_box_draw.c b/src/code/z_vr_box_draw.c
index d7f99eed9..326fcb3e2 100644
--- a/src/code/z_vr_box_draw.c
+++ b/src/code/z_vr_box_draw.c
@@ -3,11 +3,11 @@
Mtx* sSkyboxDrawMatrix;
Mtx* SkyboxDraw_UpdateMatrix(SkyboxContext* skyboxCtx, f32 x, f32 y, f32 z) {
- Matrix_InsertTranslation(x, y, z, MTXMODE_NEW);
+ Matrix_Translate(x, y, z, MTXMODE_NEW);
Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY);
- Matrix_RotateStateAroundXAxis(skyboxCtx->rotX);
- Matrix_InsertYRotation_f(skyboxCtx->rotY, MTXMODE_APPLY);
- Matrix_InsertZRotation_f(skyboxCtx->rotZ, MTXMODE_APPLY);
+ Matrix_RotateXFApply(skyboxCtx->rotX);
+ Matrix_RotateYF(skyboxCtx->rotY, MTXMODE_APPLY);
+ Matrix_RotateZF(skyboxCtx->rotZ, MTXMODE_APPLY);
return Matrix_ToMtx(sSkyboxDrawMatrix);
}
@@ -30,11 +30,11 @@ void SkyboxDraw_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyb
sSkyboxDrawMatrix = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
- Matrix_InsertTranslation(x, y, z, MTXMODE_NEW);
+ Matrix_Translate(x, y, z, MTXMODE_NEW);
Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY);
- Matrix_RotateStateAroundXAxis(skyboxCtx->rotX);
- Matrix_InsertYRotation_f(skyboxCtx->rotY, MTXMODE_APPLY);
- Matrix_InsertZRotation_f(skyboxCtx->rotZ, MTXMODE_APPLY);
+ Matrix_RotateXFApply(skyboxCtx->rotX);
+ Matrix_RotateYF(skyboxCtx->rotY, MTXMODE_APPLY);
+ Matrix_RotateZF(skyboxCtx->rotZ, MTXMODE_APPLY);
Matrix_ToMtx(sSkyboxDrawMatrix);
gSPMatrix(POLY_OPA_DISP++, sSkyboxDrawMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);