diff --git a/assets/xml/objects/object_bal.xml b/assets/xml/objects/object_bal.xml index 15b9971fc4..a31c0e29f3 100644 --- a/assets/xml/objects/object_bal.xml +++ b/assets/xml/objects/object_bal.xml @@ -76,6 +76,6 @@ - + diff --git a/include/functions.h b/include/functions.h index 27c11bbe71..5c71053227 100644 --- a/include/functions.h +++ b/include/functions.h @@ -2551,9 +2551,11 @@ void SpeedMeter_DrawTimeEntries(void* displayList, GraphicsContext* gfxCtx); // void func_80177A84(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5, UNK_TYPE4 param_6, UNK_TYPE4 param_7, UNK_TYPE4 param_8, UNK_TYPE4 param_9); //void func_80177AC8(void); void SpeedMeter_DrawAllocEntries(void* displayList, GraphicsContext* gfxCtx, GameState* gameState); -void func_801780F0(Mtx* param_1, f32 param_2, f32 param_3, f32 param_4, f32 param_5, f32 param_6, f32 param_7); -// void func_801781EC(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5); -void func_8017842C(MtxF* arg0, f32 arg1, f32 arg2, f32 arg3, s16 arg4, f32 arg5, f32 arg6, f32 arg7, f32 arg8, f32 arg9, f32 arg10); + +void Mtx_SetTranslateScaleMtx(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, f32 translateX, f32 translateY, f32 translateZ); +void Mtx_SetRotationMtx(Mtx* mtx, s32 angle, f32 axisX, f32 axisY, f32 axisZ); +void Mtx_SetTranslationRotationScaleMtx(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, s32 angle, f32 axisX, f32 axisY, f32 axisZ,f32 translateX, f32 translateY, f32 translateZ); + // void func_80178750(void); // void func_80178818(void); void func_80178978(void); diff --git a/spec b/spec index d923922359..9a29b7fcfe 100644 --- a/spec +++ b/spec @@ -528,7 +528,8 @@ beginseg include "build/src/code/z_rumble.o" include "build/src/code/z_view.o" include "build/src/code/z_vimode.o" - include "build/data/code/z_vimode.data.o" + include "build/src/code/code_80140CE0.o" + include "build/data/code/code_80140CE0.data.o" include "build/src/code/code_80140E80.o" include "build/src/code/z_vismono.o" include "build/src/code/code_801420C0.o" @@ -580,6 +581,7 @@ beginseg include "build/src/code/speed_meter.o" include "build/data/code/speed_meter.data.o" include "build/data/code/speed_meter.bss.o" + include "build/src/code/su_mtx.o" include "build/data/code/sys_cfb.bss.o" include "build/src/code/sys_cmpdma.o" include "build/data/code/sys_cmpdma.bss.o" diff --git a/src/code/code_80140CE0.c b/src/code/code_80140CE0.c new file mode 100644 index 0000000000..f3d487fabc --- /dev/null +++ b/src/code/code_80140CE0.c @@ -0,0 +1,7 @@ +#include "global.h" + +#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140CE0/func_80140CE0.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140CE0/func_80140D04.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140CE0/func_80140D10.s") diff --git a/src/code/speed_meter.c b/src/code/speed_meter.c index 5ad1cdbe0e..780a02c62f 100644 --- a/src/code/speed_meter.c +++ b/src/code/speed_meter.c @@ -15,9 +15,3 @@ #pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/func_80177AC8.s") #pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/SpeedMeter_DrawAllocEntries.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/func_801780F0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/func_801781EC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/func_8017842C.s") diff --git a/src/code/su_mtx.c b/src/code/su_mtx.c new file mode 100644 index 0000000000..09cbda90e2 --- /dev/null +++ b/src/code/su_mtx.c @@ -0,0 +1,361 @@ +/** + * @file su_mtx.c + * @brief "Fast" functions for constructing RSP-compatible matrices directly + * + * The three functions in this file construct scaling, rotation, and translation matrices, and combinations thereof. The + * intention appears to be to exploit the peculiar structure of the RSP's fixed-point matrix format, which we recall is + * + * typedef long int Mtx_t[4][4]; + * typedef union { + * Mtx_t m; + * struct { + * u16 intPart[4][4]; + * u16 fracPart[4][4]; + * }; + * long long int forc_structure_alignment; + * } Mtx; // size = 0x40 + * + * This means it can be written to as either words or two sets of shorts; the latter is the correct format for + * interpreting it the way the RSP does, but the first is likely faster to access and write to. The functions save + * writing halves by + * + * - writing a word 0 if two adjacent elements are 0 in a convenient place, or 1 if they are 0 and 1, + * - writing a word using a shift and overwriting the dirty half afterwards. + * + * Examples of both of these are seen in Mtx_SetTranslateScaleMtx(); we explain there in full detail due to the + * function's relative simplicity. The other two functions we merely point out the interesting parts rather than + * explaining the whole process. + * + * We use the following notation throughout: round brackets denote the word-sized elements, square the pairs they cover. + * The integer and fractional parts of a fixed-point number are denoted by i and f respectively, and these letters are + * also used to represent which half each of the pairs belongs to. + * + * (00) [i00,i01], (01) [i02,i03] + * (02) [i10,i11], (03) [i12,i13] + * (10) [i20,i21], (11) [i22,i23] + * (12) [i30,i31], (13) [i32,i33] + * (20) [f00,f01], (21) [f02,f03] + * (22) [f10,f11], (23) [f12,f13] + * (30) [f20,f21], (31) [f22,f23] + * (32) [f30,f31], (33) [f32,f33] + * + * We keep the RSP's column-major convention; this file is confusing enough without attempting to transpose everything. + * Bear in mind therefore that we are acting on *row vectors* on the *right*. + * + * @warning The behaviour of the output of the functions in this file is undefined in C89, since both members of the + * union are used to set the mtxs. (C99+ allow type-punning, but the behaviour is still implementation-defined because + * it relies on the storage being big-endian.) + * + * @remark Name inferred from shared Animal Forest functions, meaning of "su" is unclear. + */ + +#include "global.h" + +/** + * Constructs a matrix \$f ST \$f, i.e. a scaling \$f S \$f followed by a translation \$f T \$f. + * + * The final result is + * + * \f[ + * \begin{bmatrix} + * s_x & 0 & 0 & 0 \\ + * 0 & s_y & 0 & 0 \\ + * 0 & 0 & s_z & 0 \\ + * t_x & t_y & t_z & 1 + * \end{bmatrix} + * \f] + * + * @param[out] mtx Fixed-point matrix pointer to output to + * @param[in] scaleX Scale in the X direction + * @param[in] scaleY Scale in the Y direction + * @param[in] scaleZ Scale in the Z direction + * @param[in] translateX X component of translation + * @param[in] translateY Y component of translation + * @param[in] translateZ Z component of translation + * + * @remark Original name: "suMtxMakeTS" + */ +void Mtx_SetTranslateScaleMtx(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, f32 translateX, f32 translateY, + f32 translateZ) { + Mtx* m = mtx; + s32 fixedPoint; + + m->m[0][1] = 0; // [i02, i03] == [0, 0] + m->m[2][1] = 0; // [f02, f03] == [0, 0] + m->m[0][3] = 0; // [i12, i13] == [0, 0] + m->m[2][3] = 0; // [f22, f23] == [0, 0] + m->m[1][0] = 0; // [i20, i21] == [0, 0] + // + fixedPoint = scaleX * 0x10000; // + m->m[0][0] = fixedPoint; // [i00, i01] == [scaleX.i, scaleX.f]; i01 is now "dirty" + m->intPart[0][1] = 0; // Clean i01 by zeroing it: [i00, i01] == [scaleX.i, 0] + m->m[2][0] = (u32)fixedPoint << 16; // [f00, f01] == [scaleX.f, 0] + // + fixedPoint = scaleY * 0x10000; // + m->m[0][2] = (u32)fixedPoint >> 16; // [i10, i11] == [0, scaleY.i] + m->m[2][2] = fixedPoint & 0xFFFF; // [f10, f11] == [0, scaleY.f] + // + fixedPoint = scaleZ * 0x10000; // + m->m[1][1] = fixedPoint; // [i22, i23] == [scaleZ.i, scaleZ.f] + m->intPart[2][3] = 0; // [i22, i23] == [scaleZ.i, 0] + m->m[3][1] = (u32)fixedPoint << 16; // [f22, f23] == [scaleZ.f, 0] + // + m->m[3][0] = 0; // [f20, f21] == [0, 0] + // + fixedPoint = translateX * 0x10000; // + m->intPart[3][0] = ((u32)fixedPoint >> 16) & 0xFFFF; // [i30, i31] == [translateX.i, ?] + m->fracPart[3][0] = fixedPoint & 0xFFFF; // [f30, f31] == [translateX.f, ?] + // + fixedPoint = translateY * 0x10000; // + m->intPart[3][1] = ((u32)fixedPoint >> 16) & 0xFFFF; // [i30, i31] == [translateX.i, translateY.i] + m->fracPart[3][1] = fixedPoint & 0xFFFF; // [f30, f31] == [translateX.f, translateY.f] + // + fixedPoint = translateZ * 0x10000; // + m->intPart[3][2] = ((u32)fixedPoint >> 16) & 0xFFFF; // [i30, i31] == [translateZ.i, ?] + m->intPart[3][3] = 1; // [i32, i33] == [translateZ.i, 1] + m->m[3][3] = (u32)fixedPoint << 16; // [f32, f33] == [translateZ.f, 0] + + // So we end up with + // [scaleX.i, 0], [0, 0], + // [0, scaleY.i], [0, 0], + // [0, 0], [scaleZ.i, 0], + // [translateX.i, translateY.i], [translateZ.i, 1] + // + // [scaleX.f, 0], [0, 0], + // [0, scaleY.f], [0, 0], + // [0, 0], [scaleZ.f, 0] + // [translateX.f, translateY.f], [translateZ.f, 0] +} + +// Unused +/** + * Should create an axis-angle rotation matrix. + * + * @note The axis vector is expected to be normalised. + * + * The result should be: + * + * \f[ + * \begin{bmatrix} + * (1-a_x^2) \cos \theta + a_x^2 & a_x a_y (1 - \cos \theta) + a_z \sin \theta & a_z a_x (1 - \cos \theta) - a_y + * \sin \theta & 0 \\ + * a_x a_y (1 - \cos \theta) - a_z \sin \theta & (1-a_y^2) \cos \theta + a_y^2 & a_y a_z (1 - \cos \theta) + a_x + * \sin \theta & 0 \\ + * a_z a_x (1 - \cos \theta) + a_y \sin \theta & a_y a_z (1 - \cos \theta) - a_x \sin \theta & (1-a_z^2) \cos + * \theta + * + a_z^2 & 0 \\ + * t_x & t_y & t_z & 1 + * \end{bmatrix} + * \f] + * + * @warning There is a significant bug in this function, which means it does not actually produce this correct rotation + * matrix; see inline for details. + * + * @param[out] mtx Fixed-point matrix pointer to output to + * @param[in] angle angle to rotate about axis + * @param[in] axisX X component of axis to rotate about + * @param[in] axisY Y component of axis to rotate about + * @param[in] axisZ Z component of axis to rotate about + * + * @remark Original name: probably something like "suMtxMakeR" or "suMtxMakeRotateVector" + */ +void Mtx_SetRotationMtx(Mtx* mtx, s32 angle, f32 axisX, f32 axisY, f32 axisZ) { + //! FAKE? The somewhat peculiar distribution of temps in this function seems necessary to match? + f32 tempX; + f32 tempZ; + f32 tempY; + f32 sin = Math_SinS(angle); + f32 cos = Math_CosS(angle); + f32 tempXX; + f32 tempYY; + f32 tempZZ; + + s32 fixedPoint; + + mtx->m[1][2] = 0; // [i30, i31] == [0, 0] + mtx->m[1][3] = 1; // [i32, i33] == [0, 1] + mtx->m[3][2] = 0; // [f30, f31] == [0, 0] + mtx->m[3][3] = 0; // [f31, f32] == [0, 0] + + tempXX = axisX * axisX; + tempX = (axisY * axisZ) * (1.0f - cos); + + // i00 and f00 + fixedPoint = (((1.0f - tempXX) * cos) + tempXX) * 0x10000; + mtx->intPart[0][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[0][0] = fixedPoint & 0xFFFF; + + tempZ = ((axisX * axisY) * (1.0f - cos)); + tempZZ = axisZ * axisZ; + + // i21 and f21 + fixedPoint = (tempX - (axisX * sin)) * 0x10000; + mtx->intPart[2][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[2][1] = fixedPoint & 0xFFFF; + + tempY = (axisZ * axisX) * (1.0f - cos); + tempYY = axisY * axisY; + + // [i12, i13] and [f12, f13] + fixedPoint = (tempX + (axisX * sin)) * 0x10000; + mtx->m[0][3] = fixedPoint; // i13 dirty + mtx->intPart[1][3] = 0; // clean i13 + mtx->m[2][3] = fixedPoint << 0x10; + + // i11 and f11 + fixedPoint = ((((1.0f - tempYY) * cos) + tempYY) * 0x10000); + mtx->intPart[1][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[1][1] = fixedPoint & 0xFFFF; + + //! @bug The sign of the `axisY * sin` term is wrong on the next two elements (i/f20 and i/f02), which causes the + //! matrix to not be a rotation matrix (and indeed not even necessarily invertible). + // i20 and f20 + fixedPoint = (tempY - (axisY * sin)) * 0x10000; + mtx->intPart[2][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[2][0] = fixedPoint & 0xFFFF; + + // [i02, i03] and [f02, f03] + fixedPoint = (tempY + (axisY * sin)) * 0x10000; + mtx->m[0][1] = fixedPoint; // i03 dirty + mtx->intPart[0][3] = 0; // clean i03 + mtx->m[2][1] = fixedPoint << 0x10; + + // [i22, i23] and [f22, f23] + fixedPoint = ((((1.0f - tempZZ) * cos) + tempZZ) * 0x10000); + mtx->m[1][1] = fixedPoint; // i23 dirty + mtx->intPart[2][3] = 0; // clean i23 + mtx->m[3][1] = fixedPoint << 0x10; + + // i10 and f10 + fixedPoint = (tempZ - axisZ * sin) * 0x10000; + mtx->intPart[1][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[1][0] = fixedPoint & 0xFFFF; + + // i01 and f01 + fixedPoint = (tempZ + axisZ * sin) * 0x10000; + mtx->intPart[0][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[0][1] = fixedPoint & 0xFFFF; +} + +/** + * Creates a general scale, rotation, translation matrix. + * + * @note The axis vector is expected to be normalised. + * + * The transformations are applied in the order scale, rotate, translate: \$f SRT \$f + * + * The result should be + * \f[ + * \begin{bmatrix} + * s_x((1-a_x^2) \cos \theta + a_x^2) & s_x(a_x a_y (1 - \cos \theta) + a_z \sin \theta) & s_x(a_z a_x (1 - \cos + * \theta) - a_y \sin \theta & 0) \\ + * s_y(a_x a_y (1 - \cos \theta) - a_z \sin \theta) & s_y((1-a_y^2) \cos \theta + a_y^2) & s_z(a_y a_z (1 - \cos + * \theta) + a_x \sin \theta) & 0 \\ + * s_z(a_z a_x (1 - \cos \theta) + a_y \sin \theta) & s_z(a_y a_z (1 - \cos \theta) - a_x \sin \theta) & + * s_z((1-a_z^2) \cos \theta + a_z^2) & 0 \\ + * 0 & 0 & 0 & 1 + * \end{bmatrix} . + * \f] + * + * @warning There is a significant bug in this function, which means it does not actually produce a proper rotation + * matrix; see inline for details. + * + * @param[out] mtx Fixed-point matrix pointer to output to + * @param[in] scaleX Scale in the X direction + * @param[in] scaleY Scale in the Y direction + * @param[in] scaleZ Scale in the Z direction + * @param[in] angle angle to rotate about axis + * @param[in] axisX X component of axis to rotate about + * @param[in] axisY Y component of axis to rotate about + * @param[in] axisZ Z component of axis to rotate about + * @param[in] translateX X component of translation + * @param[in] translateY Y component of translation + * @param[in] translateZ Z component of translation + * + * @remark Original name: probably something like "suMtxMakeSRT", although Animal Forest function is a Tait-Bryan + * rotation rather than axis-angle. + */ +void Mtx_SetTranslationRotationScaleMtx(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, s32 angle, f32 axisX, f32 axisY, + f32 axisZ, f32 translateX, f32 translateY, f32 translateZ) { + f32 tempX; + f32 tempY; + f32 tempZ; + f32 sin = Math_SinS(angle); + f32 cos = Math_CosS(angle); + f32 tempXX = axisX * axisX; + f32 tempYY = axisY * axisY; + f32 tempZZ = axisZ * axisZ; + s32 fixedPoint; + + tempX = axisY * axisZ * (1.0f - cos); + + // i00 and f00 + fixedPoint = (tempXX + (1.0f - tempXX) * cos) * scaleX * 0x10000; + mtx->intPart[0][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[0][0] = fixedPoint & 0xFFFF; + + tempY = axisZ * axisX * (1.0f - cos); + + // i21 and f21 + fixedPoint = (tempX - axisX * sin) * scaleZ * 0x10000; + mtx->intPart[2][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[2][1] = fixedPoint & 0xFFFF; + + tempZ = axisX * axisY * (1.0f - cos); + + // [i12, i13] and [f12, f13] + fixedPoint = (tempX + axisX * sin) * scaleY * 0x10000; + mtx->m[0][3] = fixedPoint; // i13 dirty + mtx->intPart[1][3] = 0; // clean i13 + mtx->m[2][3] = fixedPoint << 0x10; + + // i11 and f11 + fixedPoint = (tempYY + (1.0f - tempYY) * cos) * scaleY * 0x10000; + mtx->intPart[1][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[1][1] = fixedPoint & 0xFFFF; + + //! @bug The sign of the `axisY * sin` term is wrong on the next two elements (i/f20 and i/f02), which causes the + //! matrix to not be a rotation matrix (and indeed not even necessarily invertible). + // i20, f20 + fixedPoint = (tempY - axisY * sin) * scaleZ * 0x10000; + mtx->intPart[2][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[2][0] = fixedPoint & 0xFFFF; + + // [i02, i03] and [f02, f03] + fixedPoint = (tempY + axisY * sin) * scaleX * 0x10000; + mtx->m[0][1] = fixedPoint; // [i03, i03], i03 dirty + mtx->intPart[0][3] = 0; // clean i03 + mtx->m[2][1] = fixedPoint << 0x10; // [f02, f03] + + // [i22, i23] and [f22, f23] + fixedPoint = (tempZZ + (1.0f - tempZZ) * cos) * scaleZ * 0x10000; + mtx->m[1][1] = fixedPoint; + mtx->intPart[2][3] = 0; + mtx->m[3][1] = fixedPoint << 0x10; + + // i10 and f10 + fixedPoint = (tempZ - axisZ * sin) * scaleY * 0x10000; + mtx->intPart[1][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[1][0] = fixedPoint & 0xFFFF; + + // i01 and f01 + fixedPoint = (tempZ + axisZ * sin) * scaleX * 0x10000; + mtx->intPart[0][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF; + mtx->fracPart[0][1] = fixedPoint & 0xFFFF; + + // [i30, i31] and f30 + fixedPoint = translateX * 0x10000; + mtx->m[1][2] = fixedPoint; // [i30, i31], i31 dirty + mtx->fracPart[3][0] = fixedPoint & 0xFFFF; // f30 + + // i31 and f31 + fixedPoint = translateY * 0x10000; + mtx->intPart[3][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF; // overwrite i31 + mtx->fracPart[3][1] = fixedPoint & 0xFFFF; // overwrite f31 + + // [i32, i33] and [f32, f33] + fixedPoint = translateZ * 0x10000; + mtx->m[1][3] = fixedPoint; // [i32, i33] + mtx->intPart[3][3] = 1; // clean i33 + mtx->m[3][3] = (fixedPoint << 0x10); // [f32, f33] +} diff --git a/src/code/z_actor.c b/src/code/z_actor.c index 0483d097e9..919752d748 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -2353,10 +2353,8 @@ Actor* Actor_UpdateActor(UpdateActor_Params* params) { if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) { Actor_Kill(actor); } else { - s32 tmp = (params->unk_08 == 0); - if (((params->unk_08) && !(actor->flags & params->unk_08)) || - ((tmp = (params->unk_08 == 0)) && + ((((!params->unk_08) != 0)) && (!(actor->flags & ACTOR_FLAG_100000) || ((actor->category == ACTORCAT_EXPLOSIVES) && (params->player->stateFlags1 & PLAYER_STATE1_200))) && (params->unkC != 0) && (actor != params->unk10) && ((actor != params->player->heldActor)) && diff --git a/src/code/z_lifemeter.c b/src/code/z_lifemeter.c index 669aa338ab..b123baab69 100644 --- a/src/code/z_lifemeter.c +++ b/src/code/z_lifemeter.c @@ -235,6 +235,7 @@ void LifeMeter_Draw(PlayState* play) { if ((gSaveContext.save.playerData.health % 0x10) == 0) { fullHeartCount--; } + offsetY = 0.0f; offsetX = 0.0f; curColorSet = -1; @@ -381,12 +382,13 @@ void LifeMeter_Draw(PlayState* play) { } } mtx = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); - func_801780F0(mtx, 1.0f - (0.32f * lifesize), 1.0f - (0.32f * lifesize), 1.0f - (0.32f * lifesize), - -130.0f + offsetX, 94.5f - offsetY, 0.0f); + Mtx_SetTranslateScaleMtx(mtx, 1.0f - (0.32f * lifesize), 1.0f - (0.32f * lifesize), + 1.0f - (0.32f * lifesize), -130.0f + offsetX, 94.5f - offsetY, 0.0f); gSPMatrix(OVERLAY_DISP++, mtx, G_MTX_LOAD | G_MTX_MODELVIEW); gSPVertex(OVERLAY_DISP++, beatingHeartVtx, 4, 0); gSP1Quadrangle(OVERLAY_DISP++, 0, 2, 3, 1, 0); } + offsetX += 10.0f; if (i == 9) { offsetY += 10.0f; @@ -423,10 +425,8 @@ u32 LifeMeter_IsCritical(void) { if (gSaveContext.save.playerData.healthCapacity <= 0x50) { criticalThreshold = 0x10; - } else if (gSaveContext.save.playerData.healthCapacity <= 0xA0) { criticalThreshold = 0x18; - } else if (gSaveContext.save.playerData.healthCapacity <= 0xF0) { criticalThreshold = 0x20; } else { diff --git a/src/code/z_vimode.c b/src/code/z_vimode.c index 76479a0287..b7d2dea64a 100644 --- a/src/code/z_vimode.c +++ b/src/code/z_vimode.c @@ -15,9 +15,3 @@ #pragma GLOBAL_ASM("asm/non_matchings/code/z_vimode/func_8014090C.s") #pragma GLOBAL_ASM("asm/non_matchings/code/z_vimode/func_80140970.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_vimode/func_80140CE0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_vimode/func_80140D04.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_vimode/func_80140D10.s") diff --git a/src/overlays/actors/ovl_Dm_Bal/z_dm_bal.c b/src/overlays/actors/ovl_Dm_Bal/z_dm_bal.c index e2dc0daa71..b9c4cb33c0 100644 --- a/src/overlays/actors/ovl_Dm_Bal/z_dm_bal.c +++ b/src/overlays/actors/ovl_Dm_Bal/z_dm_bal.c @@ -15,8 +15,8 @@ void DmBal_Destroy(Actor* thisx, PlayState* play); void DmBal_Update(Actor* thisx, PlayState* play); void DmBal_Draw(Actor* thisx, PlayState* play); -void func_80C1EAC4(DmBal* this); -void func_80C1EAD8(DmBal* this, PlayState* play); +void DmBal_SetupDoNothing(DmBal* this); +void DmBal_DoNothing(DmBal* this, PlayState* play); ActorInit Dm_Bal_InitVars = { ACTOR_DM_BAL, @@ -59,18 +59,18 @@ void DmBal_Init(Actor* thisx, PlayState* play) { Actor_UpdateBgCheckInfo(play, &this->actor, 0.0f, 0.0f, 0.0f, 4); this->timer = 60; this->eyeIndex = 0; - this->unk_336 = 0; - func_80C1EAC4(this); + this->keepEyesShut = false; + DmBal_SetupDoNothing(this); } void DmBal_Destroy(Actor* thisx, PlayState* play) { } -void func_80C1EAC4(DmBal* this) { - this->actionFunc = func_80C1EAD8; +void DmBal_SetupDoNothing(DmBal* this) { + this->actionFunc = DmBal_DoNothing; } -void func_80C1EAD8(DmBal* this, PlayState* play) { +void DmBal_DoNothing(DmBal* this, PlayState* play) { } void func_80C1EAE8(DmBal* this, PlayState* play) { @@ -84,12 +84,12 @@ void func_80C1EAE8(DmBal* this, PlayState* play) { D_80C1F2C0 = play->csCtx.actorActions[actionIndex]->action; switch (play->csCtx.actorActions[actionIndex]->action) { case 1: - this->unk_336 = 0; + this->keepEyesShut = false; this->eyeIndex = 0; Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 0); break; case 2: - this->unk_336 = 1; + this->keepEyesShut = true; Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 12); break; case 3: @@ -98,34 +98,34 @@ void func_80C1EAE8(DmBal* this, PlayState* play) { } } else if (D_80C1F2C0 == 3) { if (Animation_OnFrame(&this->skelAnime, 0.0f)) { - this->unk_336 = 1; + this->keepEyesShut = true; } else if (Animation_OnFrame(&this->skelAnime, 29.0f)) { - this->unk_336 = 0; + this->keepEyesShut = false; this->eyeIndex = 0; } } Cutscene_ActorTranslateAndYaw(&this->actor, play, actionIndex); this->actor.home.pos = this->actor.world.pos; } else { - this->unk_336 = 0; + this->keepEyesShut = false; this->eyeIndex = 0; D_80C1F2C0 = 0x63; } } void func_80C1EC60(DmBal* this, PlayState* play) { - f32 temp_fv1_2; + f32 scaleX; this->unk_338 += 0x320; this->unk_33A += 0x3E8; this->scale.y = this->scale.z = Math_CosS(this->unk_338) * 0.1f + 1.0f; - temp_fv1_2 = (Math_SinS(this->unk_338) * 0.1f) + 1.0f; - this->scale.x = SQ(temp_fv1_2); + scaleX = (Math_SinS(this->unk_338) * 0.1f) + 1.0f; + this->scale.x = SQ(scaleX); this->actor.world.pos.y = this->actor.home.pos.y + (Math_SinS(this->unk_338) * 25.0f); } -void func_80C1ED0C(DmBal* this) { - if (this->unk_336 == 1) { +void DmBal_UpdateEyes(DmBal* this) { + if (this->keepEyesShut == true) { this->eyeIndex = 1; } else if (this->timer >= 4) { this->timer--; @@ -138,38 +138,36 @@ void func_80C1ED0C(DmBal* this) { } } -void func_80C1ED64(DmBal* this, PlayState* play, Vec3f* arg2, Vec3f* arg3, f32 arg4) { - Actor* paper = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PAPER, arg2->x, arg2->y, arg2->z, 0, 0, 0, 0); +void DmBal_SpawnPaper(DmBal* this, PlayState* play, Vec3f* pos, Vec3f* vel, f32 gravity) { + Actor* paper = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PAPER, pos->x, pos->y, pos->z, 0, 0, 0, 0); if (paper != NULL) { - paper->velocity = *arg3; - paper->gravity = arg4; + paper->velocity = *vel; + paper->gravity = gravity; } } -Vec3f D_80C1F2C4 = { 0.0f, 9.0f, 0.0f }; - void DmBal_Update(Actor* thisx, PlayState* play) { s32 pad; DmBal* this = THIS; - Vec3f sp3C; - Vec3f sp30; + // Throw confetti if (Animation_OnFrame(&this->skelAnime, 29.0f) && (this->skelAnime.animation == &object_bal_Anim_001804)) { - sp3C = this->actor.world.pos; - sp30 = D_80C1F2C4; - sp3C.x += 7.0f * Math_SinS(this->actor.shape.rot.y); - sp3C.y += 2.5f; - sp3C.z += 7.0f * Math_CosS(this->actor.shape.rot.y); - sp30.x = Math_SinS(this->actor.shape.rot.y) * 5.0f; - sp30.z = Math_CosS(this->actor.shape.rot.y) * 5.0f; - func_80C1ED64(this, play, &sp3C, &sp30, -0.4f); - func_80C1ED64(this, play, &sp3C, &sp30, -0.5f); + Vec3f pos = this->actor.world.pos; + Vec3f vel = { 0.0f, 9.0f, 0.0f }; + + pos.x += 7.0f * Math_SinS(this->actor.shape.rot.y); + pos.y += 2.5f; + pos.z += 7.0f * Math_CosS(this->actor.shape.rot.y); + vel.x = Math_SinS(this->actor.shape.rot.y) * 5.0f; + vel.z = Math_CosS(this->actor.shape.rot.y) * 5.0f; + DmBal_SpawnPaper(this, play, &pos, &vel, -0.4f); + DmBal_SpawnPaper(this, play, &pos, &vel, -0.5f); } this->actionFunc(this, play); func_80C1EAE8(this, play); func_80C1EC60(this, play); - func_80C1ED0C(this); + DmBal_UpdateEyes(this); SkelAnime_Update(&this->skelAnime); } @@ -178,8 +176,8 @@ s32 DmBal_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p Vec3s rots; if (limbIndex == 6) { - rots.x = Math_SinS(this->unk_33A) * 3640.0f; - rots.z = Math_CosS(this->unk_33A) * 3640.0f; + rots.x = Math_SinS(this->unk_33A) * (0x10000 / 18); + rots.z = Math_CosS(this->unk_33A) * (0x10000 / 18); Matrix_RotateZYX(rots.x, 0, rots.z, MTXMODE_APPLY); Matrix_Scale(this->scale.x, this->scale.y, this->scale.z, MTXMODE_APPLY); Matrix_RotateZS(-rots.z, MTXMODE_APPLY); diff --git a/src/overlays/actors/ovl_Dm_Bal/z_dm_bal.h b/src/overlays/actors/ovl_Dm_Bal/z_dm_bal.h index 7b38356538..01f10d4c92 100644 --- a/src/overlays/actors/ovl_Dm_Bal/z_dm_bal.h +++ b/src/overlays/actors/ovl_Dm_Bal/z_dm_bal.h @@ -18,7 +18,7 @@ typedef struct DmBal { /* 0x19C */ Vec3s morphTable[OBJECT_BAL_LIMB_MAX]; /* 0x328 */ UNK_TYPE1 pad_328[12]; /* 0x334 */ s16 timer; - /* 0x336 */ s16 unk_336; + /* 0x336 */ s16 keepEyesShut; /* 0x338 */ s16 unk_338; /* 0x33A */ s16 unk_33A; } DmBal; /* size = 0x33C */ diff --git a/src/overlays/actors/ovl_En_Paper/z_en_paper.c b/src/overlays/actors/ovl_En_Paper/z_en_paper.c index 47d97e1c2f..a3f158cbdc 100644 --- a/src/overlays/actors/ovl_En_Paper/z_en_paper.c +++ b/src/overlays/actors/ovl_En_Paper/z_en_paper.c @@ -1,7 +1,11 @@ -/* - * File: z_en_paper.c +/** + * @file z_en_paper.c * Overlay: ovl_En_Paper - * Description: Tingle Confetti + * Description: Tingle confetti group + * + * Complex actor for its length, that creates and manages a group of confetti effects. Each is a triangle of a + * particular colour, that rotates around a fixed axis at a randomly-chosen fixed velocity, and is subject to gravity, + * drag and wind forces. */ #include "z_en_paper.h" @@ -16,12 +20,12 @@ void EnPaper_Destroy(Actor* thisx, PlayState* play); void EnPaper_Update(Actor* thisx, PlayState* play); void EnPaper_Draw(Actor* thisx, PlayState* play); -void func_80C1F480(EnPaper* this, PlayState* play); -void func_80C1F4FC(EnPaper* this, PlayState* play); -void func_80C1F46C(EnPaper* this); -void func_80C1F4E8(EnPaper* this); -void func_80C1F55C(EnPaper* this, EnPaperStruct* arg1); -void func_80C1F6E0(EnPaper* this, EnPaperStruct* arg1); +void EnPaper_SetupSpreadConfettiGroup(EnPaper* this); +void EnPaper_SpreadConfettiGroup(EnPaper* this, PlayState* play); +void EnPaper_SetupFlyConfettiGroup(EnPaper* this); +void EnPaper_FlyConfettiGroup(EnPaper* this, PlayState* play); +void EnPaper_InitConfettiPiece(EnPaper* this, EnPaperConfetto* piece); +void EnPaper_FlyConfettiPiece(EnPaper* this, EnPaperConfetto* piece); ActorInit En_Paper_InitVars = { ACTOR_EN_PAPER, @@ -35,114 +39,155 @@ ActorInit En_Paper_InitVars = { (ActorFunc)EnPaper_Draw, }; -Vec3f D_80C1FC60 = { 0.0f, 0.0f, 1.0f }; +static Vec3f sUnitVecZ = { 0.0f, 0.0f, 1.0f }; void EnPaper_Init(Actor* thisx, PlayState* play) { EnPaper* this = THIS; Actor_SetScale(&this->actor, 0.01f); this->timer = 70; - this->unk_D78 = D_80C1FC60; + this->windForce = sUnitVecZ; Actor_UpdateBgCheckInfo(play, &this->actor, 0.0f, 0.0f, 0.0f, 4); - func_80C1F46C(this); + EnPaper_SetupSpreadConfettiGroup(this); } void EnPaper_Destroy(Actor* thisx, PlayState* play) { } -void func_80C1F46C(EnPaper* this) { - this->actionFunc = func_80C1F480; +void EnPaper_SetupSpreadConfettiGroup(EnPaper* this) { + this->actionFunc = EnPaper_SpreadConfettiGroup; } -void func_80C1F480(EnPaper* this, PlayState* play) { +/** + * Set up the pieces of confetti. + */ +void EnPaper_SpreadConfettiGroup(EnPaper* this, PlayState* play) { s32 i; - for (i = 0; i < ARRAY_COUNT(this->unk_148); i++) { - func_80C1F55C(this, &this->unk_148[i]); + for (i = 0; i < ARRAY_COUNT(this->pieces); i++) { + EnPaper_InitConfettiPiece(this, &this->pieces[i]); } - func_80C1F4E8(this); + EnPaper_SetupFlyConfettiGroup(this); } -void func_80C1F4E8(EnPaper* this) { - this->actionFunc = func_80C1F4FC; +void EnPaper_SetupFlyConfettiGroup(EnPaper* this) { + this->actionFunc = EnPaper_FlyConfettiGroup; } -void func_80C1F4FC(EnPaper* this, PlayState* play) { +/** + * Main action function for the group. + */ +void EnPaper_FlyConfettiGroup(EnPaper* this, PlayState* play) { s32 i; - for (i = 0; i < ARRAY_COUNT(this->unk_148); i++) { - func_80C1F6E0(this, &this->unk_148[i]); + for (i = 0; i < ARRAY_COUNT(this->pieces); i++) { + EnPaper_FlyConfettiPiece(this, &this->pieces[i]); } } -void func_80C1F55C(EnPaper* this, EnPaperStruct* arg1) { +void EnPaper_InitConfettiPiece(EnPaper* this, EnPaperConfetto* piece) { + // Pick rotation axis randomly (significantly biased towards the z = 0 plane) Matrix_RotateZYX(Rand_Next(), Rand_Next(), Rand_Next(), MTXMODE_NEW); - Matrix_MultVec3f(&D_80C1FC60, &arg1->unk_0C); + Matrix_MultVec3f(&sUnitVecZ, &piece->rotAxis); - arg1->unk_18 = this->actor.world.pos; + // copy actor position and distribute uniformly in a cube of side 2 around it + piece->pos = this->actor.world.pos; + piece->pos.x += Rand_Centered() * 4.0f; + piece->pos.y += Rand_Centered() * 4.0f; + piece->pos.z += Rand_Centered() * 4.0f; - arg1->unk_18.x += Rand_Centered() * 4.0f; - arg1->unk_18.y += Rand_Centered() * 4.0f; - arg1->unk_18.z += Rand_Centered() * 4.0f; + // copy actor velocity and distrbute uniformly in a cuboid with sides 9, 6, 9 with actor.velocity in the middle + // of the base. + piece->vel = this->actor.velocity; + piece->vel.x += Rand_Centered() * 9.0f; + piece->vel.y += Rand_ZeroOne() * 6.0f; + piece->vel.z += Rand_Centered() * 9.0f; - arg1->unk_24 = this->actor.velocity; + // Choose random starting angle and angular velocity + piece->angle = Rand_Next(); + piece->angVel = (Rand_Next() >> 4) + (0x10000 / 180); - arg1->unk_24.x += Rand_Centered() * 9.0f; - arg1->unk_24.y += Rand_ZeroOne() * 6.0f; - arg1->unk_24.z += Rand_Centered() * 9.0f; - - arg1->unk_30 = Rand_Next(); - arg1->unk_32 = (Rand_Next() >> 4) + 0x16C; - - Matrix_RotateAxisS(arg1->unk_30, &arg1->unk_0C, MTXMODE_NEW); - Matrix_MultVec3f(&D_80C1FC60, &arg1->unk_00); + // Rotate the unit Z-vector by the random starting axis and angle + Matrix_RotateAxisS(piece->angle, &piece->rotAxis, MTXMODE_NEW); + Matrix_MultVec3f(&sUnitVecZ, &piece->normal); } -void func_80C1F6E0(EnPaper* this, EnPaperStruct* arg1) { - f32 sp1C = Math_CosS(arg1->unk_30); - f32 sp18 = Math_SinS(arg1->unk_30); - f32 temp_ft4 = 1.0f - sp1C; +/** + * Main falling function for a single piece, handles dynamics. + * + * Position \f$ \mathbf{x} \f$ essentially satisfies discretised version of the equation + * + * \f[ + * \ddot{\mathbf{x}} = -0.2 \mathbf{n} (\dot{\mathbf{x}} + \mathbf{W}) + \mathbf{g} , + * \f] + * + * where + * + * - \f$ \mathbf{n} \f$ is the unit normal to the confetti triangle's plane + * - \f$ \mathbf{W} \f$ is the random wind pressure + * - \f$ \mathbf{g} \f$ is gravity + * + * and the product is componentwise: the normal is being used as a cross-sectional area measure rather than vectorially. + */ +void EnPaper_FlyConfettiPiece(EnPaper* this, EnPaperConfetto* piece) { + f32 cos = Math_CosS(piece->angle); + f32 sin = Math_SinS(piece->angle); + f32 versin = 1.0f - cos; - if (arg1->unk_18.y < (this->actor.floorHeight - 40.0f)) { + if (piece->pos.y < (this->actor.floorHeight - 40.0f)) { return; } - arg1->unk_24.y += this->actor.gravity; + // acceleration due to gravity + piece->vel.y += this->actor.gravity; - arg1->unk_24.x -= 0.2f * fabsf(arg1->unk_00.x) * (arg1->unk_24.x + this->unk_D78.x); - arg1->unk_24.y -= 0.2f * fabsf(arg1->unk_00.y) * (arg1->unk_24.y + this->unk_D78.y); - arg1->unk_24.z -= 0.2f * fabsf(arg1->unk_00.z) * (arg1->unk_24.z + this->unk_D78.z); + // drag and wind force: normal is used to simulate cross-section size of piece, although + piece->vel.x -= 0.2f * fabsf(piece->normal.x) * (piece->vel.x + this->windForce.x); + piece->vel.y -= 0.2f * fabsf(piece->normal.y) * (piece->vel.y + this->windForce.y); + piece->vel.z -= 0.2f * fabsf(piece->normal.z) * (piece->vel.z + this->windForce.z); - arg1->unk_30 += arg1->unk_32; + // rotate around axis + piece->angle += piece->angVel; - arg1->unk_18.x += arg1->unk_24.x; - arg1->unk_18.y += arg1->unk_24.y; - arg1->unk_18.z += arg1->unk_24.z; + // move + piece->pos.x += piece->vel.x; + piece->pos.y += piece->vel.y; + piece->pos.z += piece->vel.z; - arg1->unk_00.x = (arg1->unk_0C.x * temp_ft4 * arg1->unk_0C.z) - (arg1->unk_0C.y * sp18); - arg1->unk_00.y = (arg1->unk_0C.y * temp_ft4 * arg1->unk_0C.z) + (arg1->unk_0C.x * sp18); - arg1->unk_00.z = (arg1->unk_0C.z * temp_ft4 * arg1->unk_0C.z) + sp1C; + // Rotate unit Z vector about `axis` by `angle` to get forward direction. This is the same calculation as at the + // bottom of EnPaper_InitConfettiPiece(), but done manually instead of using any matrix functions. + piece->normal.x = (versin * piece->rotAxis.x * piece->rotAxis.z) - (piece->rotAxis.y * sin); + piece->normal.y = (versin * piece->rotAxis.y * piece->rotAxis.z) + (piece->rotAxis.x * sin); + piece->normal.z = (versin * piece->rotAxis.z * piece->rotAxis.z) + cos; } -void func_80C1F87C(EnPaper* this) { - f32 sp2C = (Rand_Centered() * 4.0f) + 6.0f; - f32 sp28; +#define WIND_PITCH_BOUND (0x10000 / 12) - this->unk_D78.y = Math_SinS(this->actor.shape.rot.x) * -sp2C; +/** + * Sets the wind force for the whole group, using the shape.rot from the previous frame, and picks a new random one + * for the next frame. + */ +void EnPaper_UpdateWind(EnPaper* this) { + f32 strength = (Rand_Centered() * 4.0f) + 6.0f; + f32 cosX; - sp28 = Math_CosS(this->actor.shape.rot.x) * -sp2C; - this->unk_D78.x = Math_SinS(this->actor.shape.rot.y) * sp28; - this->unk_D78.z = Math_CosS(this->actor.shape.rot.y) * sp28; + this->windForce.y = Math_SinS(this->actor.shape.rot.x) * -strength; + cosX = Math_CosS(this->actor.shape.rot.x) * -strength; + this->windForce.x = Math_SinS(this->actor.shape.rot.y) * cosX; + this->windForce.z = Math_CosS(this->actor.shape.rot.y) * cosX; + // New random wind direction. A uniform distribution of the angles in spherical coordinates is not uniformly + // distributed on the sphere, so this is biased more towards up and down. this->actor.shape.rot.x += (s16)(Rand_Next() >> 8); this->actor.shape.rot.y += (s16)(Rand_Next() >> 6); - if (ABS_ALT(this->actor.shape.rot.x) > 0x1555) { + // Essentially a clamp + if (ABS_ALT(this->actor.shape.rot.x) > WIND_PITCH_BOUND) { if (this->actor.shape.rot.x > 0) { - this->actor.shape.rot.x = 0x1555; + this->actor.shape.rot.x = WIND_PITCH_BOUND; } else { - this->actor.shape.rot.x = -0x1555; + this->actor.shape.rot.x = -WIND_PITCH_BOUND; } } } @@ -151,8 +196,8 @@ void EnPaper_Update(Actor* thisx, PlayState* play) { EnPaper* this = THIS; this->actionFunc(this, play); + EnPaper_UpdateWind(this); - func_80C1F87C(this); if (this->timer == 0) { Actor_Kill(&this->actor); return; @@ -163,7 +208,7 @@ void EnPaper_Update(Actor* thisx, PlayState* play) { void EnPaper_Draw(Actor* thisx, PlayState* play) { EnPaper* this = THIS; - EnPaperStruct* ptr = this->unk_148; + EnPaperConfetto* piece = this->pieces; s32 i; OPEN_DISPS(play->state.gfxCtx); @@ -174,7 +219,8 @@ void EnPaper_Draw(Actor* thisx, PlayState* play) { gDPSetCombineLERP(POLY_OPA_DISP++, 0, 0, 0, SHADE, 0, 0, 0, SHADE, PRIMITIVE, 0, COMBINED, 0, 0, 0, 0, COMBINED); gSPLoadGeometryMode(POLY_OPA_DISP++, G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_LIGHTING | G_SHADING_SMOOTH); - for (i = 0; i < ARRAY_COUNT(this->unk_148); i++, ptr++) { + for (i = 0; i < ARRAY_COUNT(this->pieces); i++, piece++) { + // colour the first 30 white and 10 each of the other 3 colours if (i == 0) { gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); } else if (i == 30) { @@ -185,14 +231,15 @@ void EnPaper_Draw(Actor* thisx, PlayState* play) { gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 64, 255, 128, 255); } - if ((this->actor.floorHeight - 40.0f) < ptr->unk_18.y) { - MtxF* mf = GRAPH_ALLOC(play->state.gfxCtx, sizeof(MtxF)); + if ((this->actor.floorHeight - 40.0f) < piece->pos.y) { + Mtx* mtx = GRAPH_ALLOC(play->state.gfxCtx, sizeof(Mtx)); - func_8017842C(mf, this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, ptr->unk_30, ptr->unk_0C.x, - ptr->unk_0C.y, ptr->unk_0C.z, ptr->unk_18.x, ptr->unk_18.y, ptr->unk_18.z); + Mtx_SetTranslationRotationScaleMtx(mtx, this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, + piece->angle, piece->rotAxis.x, piece->rotAxis.y, piece->rotAxis.z, + piece->pos.x, piece->pos.y, piece->pos.z); - gSPMatrix(POLY_OPA_DISP++, mf, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, object_bal_DL_00D5A0); + gSPMatrix(POLY_OPA_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gTingleConfettiDL); } } diff --git a/src/overlays/actors/ovl_En_Paper/z_en_paper.h b/src/overlays/actors/ovl_En_Paper/z_en_paper.h index 5e8450722a..a48c6ae881 100644 --- a/src/overlays/actors/ovl_En_Paper/z_en_paper.h +++ b/src/overlays/actors/ovl_En_Paper/z_en_paper.h @@ -7,20 +7,22 @@ struct EnPaper; typedef void (*EnPaperActionFunc)(struct EnPaper*, PlayState*); +#define ENPAPER_PIECES_COUNT 60 + typedef struct { - /* 0x00 */ Vec3f unk_00; - /* 0x0C */ Vec3f unk_0C; - /* 0x18 */ Vec3f unk_18; - /* 0x24 */ Vec3f unk_24; - /* 0x30 */ s16 unk_30; - /* 0x32 */ s16 unk_32; -} EnPaperStruct; // size = 0x34 + /* 0x00 */ Vec3f normal; // normal to the plane of the confetti piece + /* 0x0C */ Vec3f rotAxis; // axis to spin around + /* 0x18 */ Vec3f pos; + /* 0x24 */ Vec3f vel; + /* 0x30 */ s16 angle; // angle to rotate around `rotAxis` + /* 0x32 */ s16 angVel; // angular velocity of `angle` +} EnPaperConfetto; // size = 0x34 typedef struct EnPaper { /* 0x000 */ Actor actor; /* 0x144 */ EnPaperActionFunc actionFunc; - /* 0x148 */ EnPaperStruct unk_148[60]; - /* 0xD78 */ Vec3f unk_D78; + /* 0x148 */ EnPaperConfetto pieces[ENPAPER_PIECES_COUNT]; + /* 0xD78 */ Vec3f windForce; /* 0xD84 */ s16 timer; } EnPaper; // size = 0xD88 diff --git a/tools/disasm/files.txt b/tools/disasm/files.txt index c546c1f69b..3f2d082775 100644 --- a/tools/disasm/files.txt +++ b/tools/disasm/files.txt @@ -428,6 +428,7 @@ 0x8013EC10 : "z_rumble", 0x8013EE60 : "z_view", 0x80140260 : "z_vimode", + 0x80140CE0 : "code_80140CE0", 0x80140E80 : "code_80140E80", 0x801418B0 : "z_vismono", 0x801420C0 : "code_801420C0", @@ -464,6 +465,7 @@ 0x80174F10 : "padmgr", 0x80176280 : "sched", 0x80177390 : "speed_meter", + 0x801780F0 : "su_mtx", 0x80178750 : "sys_cmpdma", 0x80178F30 : "sys_initial_check", 0x80179300 : "sys_math", @@ -558,7 +560,7 @@ 0x801C5CB0 : "z_skelanime", 0x801C5CD0 : "z_skin_matrix", 0x801C5D10 : "z_sub_s", - 0x801C5DD0 : "z_vimode", + 0x801C5DD0 : "code_80140CE0", 0x801C5E30 : "z_vr_box", 0x801C5FC0 : "z_sram_NES", 0x801C6A70 : "z_message", diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index ac39602196..988fbde6bb 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -3222,9 +3222,9 @@ 0x80177A84:("func_80177A84",), 0x80177AC8:("func_80177AC8",), 0x80177E58:("SpeedMeter_DrawAllocEntries",), - 0x801780F0:("func_801780F0",), - 0x801781EC:("func_801781EC",), - 0x8017842C:("func_8017842C",), + 0x801780F0:("Mtx_SetTranslateScaleMtx",), + 0x801781EC:("Mtx_SetRotationMtx",), + 0x8017842C:("Mtx_SetTranslationRotationScaleMtx",), 0x80178750:("func_80178750",), 0x80178818:("func_80178818",), 0x80178978:("func_80178978",), @@ -16990,25 +16990,25 @@ 0x80C1E84C:("EnEndingHero_Draw",), 0x80C1E9E0:("DmBal_Init",), 0x80C1EAB4:("DmBal_Destroy",), - 0x80C1EAC4:("func_80C1EAC4",), - 0x80C1EAD8:("func_80C1EAD8",), + 0x80C1EAC4:("DmBal_SetupDoNothing",), + 0x80C1EAD8:("DmBal_DoNothing",), 0x80C1EAE8:("func_80C1EAE8",), 0x80C1EC60:("func_80C1EC60",), - 0x80C1ED0C:("func_80C1ED0C",), - 0x80C1ED64:("func_80C1ED64",), + 0x80C1ED0C:("DmBal_UpdateEyes",), + 0x80C1ED64:("DmBal_SpawnPaper",), 0x80C1EDE4:("DmBal_Update",), 0x80C1EF80:("DmBal_OverrideLimbDraw",), 0x80C1F060:("DmBal_PostLimbDraw",), 0x80C1F078:("DmBal_Draw",), 0x80C1F3D0:("EnPaper_Init",), 0x80C1F45C:("EnPaper_Destroy",), - 0x80C1F46C:("func_80C1F46C",), - 0x80C1F480:("func_80C1F480",), - 0x80C1F4E8:("func_80C1F4E8",), - 0x80C1F4FC:("func_80C1F4FC",), - 0x80C1F55C:("func_80C1F55C",), - 0x80C1F6E0:("func_80C1F6E0",), - 0x80C1F87C:("func_80C1F87C",), + 0x80C1F46C:("EnPaper_SetupSpreadConfettiGroup",), + 0x80C1F480:("EnPaper_SpreadConfettiGroup",), + 0x80C1F4E8:("EnPaper_SetupFlyConfettiGroup",), + 0x80C1F4FC:("EnPaper_FlyConfettiGroup",), + 0x80C1F55C:("EnPaper_InitConfettiPiece",), + 0x80C1F6E0:("EnPaper_FlyConfettiPiece",), + 0x80C1F87C:("EnPaper_UpdateWind",), 0x80C1F97C:("EnPaper_Update",), 0x80C1F9D0:("EnPaper_Draw",), 0x80C1FCF0:("EnHintSkb_Init",),