diff options
| author | EllipticEllipsis <elliptic.ellipsis@gmail.com> | 2022-12-08 19:33:21 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-08 16:33:21 -0300 |
| commit | bbbe0b1821febc653233c48e47fd492f95e5bc0d (patch) | |
| tree | e94dfcc6055e78e25085b54f9246277772a9216c /src/code | |
| parent | b73d18b1541b39f99fcbc085f3119b73777fea89 (diff) | |
code_801780F0 OK and documented, EnPaper documented (#1061)
* File split
* Split, OK and documented
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
Co-authored-by: engineer124 <engineer124engineer124@gmail.com>
Co-authored-by: Synray <31429825+Synray@users.noreply.github.com>
* Document relevant parts of DmBal
* Some EnPaper docs
* Document EnPaper
* Name functions
* Defake Actor_UpdateActor a bit
* Reword
* \cdot
* Fiddle with the description of the DE again
* Actually force is probably more correct
* Probably time to stop fiddling
* Format?
* Review
* Remove bug comment
* Review
* Rename to su_mtx, split off code_80140CE0
* Format
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
Co-authored-by: engineer124 <engineer124engineer124@gmail.com>
Co-authored-by: Synray <31429825+Synray@users.noreply.github.com>
Co-authored-by: angie <angheloalf95@gmail.com>
Diffstat (limited to 'src/code')
| -rw-r--r-- | src/code/code_80140CE0.c | 7 | ||||
| -rw-r--r-- | src/code/speed_meter.c | 6 | ||||
| -rw-r--r-- | src/code/su_mtx.c | 361 | ||||
| -rw-r--r-- | src/code/z_actor.c | 4 | ||||
| -rw-r--r-- | src/code/z_lifemeter.c | 8 | ||||
| -rw-r--r-- | src/code/z_vimode.c | 6 |
6 files changed, 373 insertions, 19 deletions
diff --git a/src/code/code_80140CE0.c b/src/code/code_80140CE0.c new file mode 100644 index 000000000..f3d487fab --- /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 5ad1cdbe0..780a02c62 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 000000000..09cbda90e --- /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 0483d097e..919752d74 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 669aa338a..b123baab6 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 76479a028..b7d2dea64 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") |
