diff --git a/include/PR/ultratypes.h b/include/PR/ultratypes.h index 59db81ccba..faa5b51a66 100644 --- a/include/PR/ultratypes.h +++ b/include/PR/ultratypes.h @@ -27,7 +27,7 @@ typedef long int Mtx_t[4][4]; typedef union { Mtx_t m; long long int forc_structure_alignment; -} Mtx; +} Mtx; // size = 0x40 typedef float MtxF_t[4][4]; typedef union { @@ -38,6 +38,6 @@ typedef union { zx, zy, zz, zw, wx, wy, wz, ww; }; -} MtxF; +} MtxF; // size = 0x40 #endif diff --git a/include/functions.h b/include/functions.h index 1d12d55565..3131c34a5e 100644 --- a/include/functions.h +++ b/include/functions.h @@ -3391,6 +3391,7 @@ void SysMatrix_RotateAndTranslateState(Vec3f* translation, Vec3s* rotation); void SysMatrix_SetStateRotationAndTranslation(f32 x, f32 y, f32 z, Vec3s* rotation); RSPMatrix* SysMatrix_ToRSPMatrix(MtxF* src, RSPMatrix* dst); RSPMatrix* SysMatrix_GetStateAsRSPMatrix(RSPMatrix* matrix); +Mtx* Matrix_NewMtx(GraphicsContext* gfxCtx); RSPMatrix* SysMatrix_AppendStateToPolyOpaDisp(GraphicsContext* gCtxt); void SysMatrix_AppendToPolyOpaDisp(MtxF* ctxt, GraphicsContext* gCtxt); void SysMatrix_MultiplyVector3fByState(Vec3f* src, Vec3f* dst); diff --git a/include/z64actor.h b/include/z64actor.h index 8255b176ee..064d734af9 100644 --- a/include/z64actor.h +++ b/include/z64actor.h @@ -258,7 +258,9 @@ typedef struct { /* 0xAE3 */ s8 unkAE3; /* 0xAE4 */ UNK_TYPE1 padAE4[0x3]; /* 0xAE7 */ s8 unkAE7; - /* 0xAE8 */ UNK_TYPE1 padAE8[0x40]; + /* 0xAE8 */ UNK_TYPE1 padAE8[0x20]; + /* 0xB08 */ f32 unkB08; + /* 0xB0C */ UNK_TYPE1 padB0C[0x1C]; /* 0xB28 */ s16 unkB28; /* 0xB2A */ UNK_TYPE1 padB2A[0x56]; /* 0xB80 */ f32 unk_B80; @@ -267,9 +269,9 @@ typedef struct { /* 0xB9C */ Vec3f unkB9C; /* 0xBA8 */ UNK_TYPE1 padBA8[0x44]; /* 0xBEC */ Vec3f bodyPartsPos[18]; - /* 0xCC4 */ UNK_TYPE1 padCC4[0x40]; + /* 0xCC4 */ MtxF mf_CC4; /* 0xD04 */ MtxF unkD04; - /* 0xD44 */ UNK_TYPE1 padD08[0x34]; + /* 0xD44 */ UNK_TYPE1 padD44[0x34]; } ActorPlayer; // size = 0xD78 typedef enum { diff --git a/linker_scripts/code_script.txt b/linker_scripts/code_script.txt index c48f66b7d8..a3afc53baf 100644 --- a/linker_scripts/code_script.txt +++ b/linker_scripts/code_script.txt @@ -1923,9 +1923,9 @@ SECTIONS ovl_Eff_Dust : AT(RomLocation) { build/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.o(.text) - build/asm/overlays/ovl_Eff_Dust_data.o(.data) + build/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.o(.data) build/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.o(.rodata) - build/asm/overlays/ovl_Eff_Dust_rodata.o(.rodata) + build/src/overlays/actors/ovl_Eff_Dust/z_eff_dust_overlay.o(.ovl) } SegmentEnd = .; SegmentSize = SegmentEnd - SegmentStart; diff --git a/linker_scripts/object_script.txt b/linker_scripts/object_script.txt index d63e4a5327..42b8acad88 100644 --- a/linker_scripts/object_script.txt +++ b/linker_scripts/object_script.txt @@ -203,6 +203,9 @@ D_06009278 = 0x06009278; D_06012B70 = 0x06012B70; D_06013EA8 = 0x06013EA8; +/* z_eff_dust */ +D_04054A90 = 0x04054A90; + /* z_obj_visiblock */ D_06000AD0 = 0x06000AD0; D_06000140 = 0x06000140; diff --git a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c index 51c6cdd762..a90ec2f719 100644 --- a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c +++ b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c @@ -1,3 +1,9 @@ +/** + * File z_eff_dust.c + * Overlay: ovl_Eff_Dust + * Description: Dust effects + */ + #include "z_eff_dust.h" #define FLAGS 0x00000030 @@ -9,7 +15,15 @@ void EffDust_Destroy(Actor* thisx, GlobalContext* globalCtx); void EffDust_Update(Actor* thisx, GlobalContext* globalCtx); void EffDust_Draw(Actor* thisx, GlobalContext* globalCtx); -/* +void func_80918D64(EffDust* this, GlobalContext* globalCtx); +void func_80918FE4(EffDust* this, GlobalContext* globalCtx); +void func_80919230(EffDust* this, GlobalContext* globalCtx); + +void func_80919768(Actor* thisx, GlobalContext* globalCtx); +void func_809199FC(Actor* thisx, GlobalContext* globalCtx); + +extern Gfx D_04054A90[]; + const ActorInit Eff_Dust_InitVars = { ACTOR_EFF_DUST, ACTORCAT_NPC, @@ -21,24 +35,336 @@ const ActorInit Eff_Dust_InitVars = { (ActorFunc)EffDust_Update, (ActorFunc)EffDust_Draw, }; -*/ -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Eff_Dust_0x80918B40/func_80918B40.asm") +void func_80918B40(EffDust* this) { + s32 i; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Eff_Dust_0x80918B40/EffDust_Init.asm") + for (i = 0; i < ARRAY_COUNT(this->distanceTraveled); i++) { + this->initialPositions[i].z = 0.0f; + this->initialPositions[i].y = 0.0f; + this->initialPositions[i].x = 0.0f; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Eff_Dust_0x80918B40/EffDust_Destroy.asm") + this->distanceTraveled[i] = 1.0f; + } + this->index = 0; +} -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Eff_Dust_0x80918B40/func_80918D64.asm") +void EffDust_Init(Actor* thisx, GlobalContext* globalCtx) { + EffDust* this = THIS; + u32 type = this->actor.params; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Eff_Dust_0x80918B40/func_80918FE4.asm") + func_80918B40(this); + switch (type) { + case EFF_DUST_TYPE_0: + this->actionFunc = func_80918D64; + this->actor.draw = func_80919768; + this->dx = 1.0f; + this->dy = 1.0f; + this->dz = 1.0f; + this->scalingFactor = 0.2f; + break; + case EFF_DUST_TYPE_1: + this->actionFunc = func_80918FE4; + this->actor.draw = func_80919768; + this->dy = 1.0f; + this->dx = 0.8f; + this->dz = 0.8f; + this->scalingFactor = 0.5f; + break; + case EFF_DUST_TYPE_2: + case EFF_DUST_TYPE_3: + this->actionFunc = func_80919230; + this->actor.draw = func_809199FC; + this->actor.room = -1; + this->dx = 0.5f; + this->scalingFactor = 15.0f; + break; + case EFF_DUST_TYPE_4: + this->actionFunc = func_80919230; + this->actor.draw = func_809199FC; + this->actor.room = -1; + this->dx = 0.5f; + this->scalingFactor = 10.0f; + break; + case EFF_DUST_TYPE_5: + this->actionFunc = func_80919230; + this->actor.draw = func_809199FC; + this->actor.room = -1; + this->dx = 0.5f; + this->scalingFactor = 20.0f; + break; + default: + StartHeap_Free(this); + break; + } + this->life = 10; +} -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Eff_Dust_0x80918B40/func_80919230.asm") +void EffDust_Destroy(Actor* thisx, GlobalContext* globalCtx) { +} -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Eff_Dust_0x80918B40/EffDust_Update.asm") +void func_80918D64(EffDust* this, GlobalContext* globalCtx) { + s16 theta; + s16 fi; + s32 i; + s32 j; + f32* distanceTraveled = this->distanceTraveled; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Eff_Dust_0x80918B40/func_80919768.asm") + for (i = 0; i < ARRAY_COUNT(this->distanceTraveled); i++) { + if (*distanceTraveled < 1.0f) { + *distanceTraveled += 0.05f; + } + distanceTraveled++; + } -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Eff_Dust_0x80918B40/func_809199FC.asm") + if (this->actor.home.rot.z != 0) { + for (j = 0; j < 3; j++) { + i = this->index & 0x3F; + if (this->distanceTraveled[i] >= 1.0f) { + // Spherical coordinate system. + fi = randPlusMinusPoint5Scaled(0x10000); + theta = Rand_ZeroFloat(0x1000); + this->initialPositions[i].x = -(f32)this->actor.home.rot.z * Math_CosS(fi) * Math_CosS(theta); + this->initialPositions[i].y = -(f32)this->actor.home.rot.z * Math_SinS(fi) * Math_CosS(theta); + this->initialPositions[i].z = -(f32)this->actor.home.rot.z * Math_SinS(theta); + this->distanceTraveled[i] = 0.0f; + this->index++; + } + } + } +} -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Eff_Dust_0x80918B40/EffDust_Draw.asm") +void func_80918FE4(EffDust* this, GlobalContext* globalCtx) { + s16 theta; + s16 fi; + f32* distanceTraveled = this->distanceTraveled; + s32 i; + s32 j; + + for (i = 0; i < ARRAY_COUNT(this->distanceTraveled); i++) { + if (*distanceTraveled < 1.0f) { + *distanceTraveled += 0.03f; + } + distanceTraveled++; + } + + for (j = 0; j < 2; j++) { + i = this->index & 0x3F; + if (this->distanceTraveled[i] >= 1.0f) { + // Spherical coordinate system. + fi = randPlusMinusPoint5Scaled(0x10000); + theta = Rand_ZeroFloat(0x2000); + this->initialPositions[i].x = 400.0f * Math_CosS(fi) * Math_CosS(theta); + this->initialPositions[i].y = 400.0f * Math_SinS(theta); + this->initialPositions[i].z = 400.0f * Math_SinS(fi) * Math_CosS(theta); + this->distanceTraveled[i] = 0.0f; + this->index++; + } + } +} + +void func_80919230(EffDust* this, GlobalContext* globalCtx) { + s16 theta; + ActorPlayer* player = PLAYER; + Actor* parent = this->actor.parent; + f32* distanceTraveled = this->distanceTraveled; + s32 i; + s32 j; + + if (parent == NULL || parent->update == NULL || !(player->stateFlags1 & 0x1000)) { + if (this->life != 0) { + this->life--; + } else { + Actor_MarkForDeath(&this->actor); + } + + for (i = 0; i < ARRAY_COUNT(this->distanceTraveled); i++) { + if (*distanceTraveled < 1.0f) { + *distanceTraveled += 0.2f; + } + distanceTraveled++; + } + + return; + } + + for (i = 0; i < ARRAY_COUNT(this->distanceTraveled); i++) { + if (*distanceTraveled < 1.0f) { + *distanceTraveled += 0.1f; + } + distanceTraveled++; + } + + this->actor.world.pos = parent->world.pos; + + for (j = 0; j < 3; j++) { + i = this->index & 0x3F; + + if (this->distanceTraveled[i] >= 1.0f) { + theta = randPlusMinusPoint5Scaled(0x10000); + switch (this->actor.params) { + case EFF_DUST_TYPE_2: + this->initialPositions[i].x = (Rand_ZeroOne() * 4500.0f) + 700.0f; + if (this->initialPositions[i].x > 3000.0f) { + this->initialPositions[i].y = (3000.0f * Rand_ZeroOne()) * Math_SinS(theta); + this->initialPositions[i].z = (3000.0f * Rand_ZeroOne()) * Math_CosS(theta); + } else { + this->initialPositions[i].y = 3000.0f * Math_SinS(theta); + this->initialPositions[i].z = 3000.0f * Math_CosS(theta); + } + break; + + case EFF_DUST_TYPE_3: + this->initialPositions[i].x = (Rand_ZeroOne() * 2500.0f) + 700.0f; + if (this->initialPositions[i].x > 2000.0f) { + this->initialPositions[i].y = (2000.0f * Rand_ZeroOne()) * Math_SinS(theta); + this->initialPositions[i].z = (2000.0f * Rand_ZeroOne()) * Math_CosS(theta); + } else { + this->initialPositions[i].y = 2000.0f * Math_SinS(theta); + this->initialPositions[i].z = 2000.0f * Math_CosS(theta); + } + break; + + case EFF_DUST_TYPE_4: + this->initialPositions[i].x = (Rand_ZeroOne() * 8500.0f) + 1700.0f; + if (this->initialPositions[i].x > 5000.0f) { + this->initialPositions[i].y = (4000.0f * Rand_ZeroOne()) * Math_SinS(theta); + this->initialPositions[i].z = (4000.0f * Rand_ZeroOne()) * Math_CosS(theta); + } else { + this->initialPositions[i].y = 4000.0f * Math_SinS(theta); + this->initialPositions[i].z = 4000.0f * Math_CosS(theta); + } + break; + } + + this->distanceTraveled[i] = 0.0f; + this->index++; + } + } +} + +void EffDust_Update(Actor* thisx, GlobalContext* globalCtx) { + EffDust* this = THIS; + + this->actionFunc(this, globalCtx); +} + +Gfx D_80919DB0[] = { + gsSPEndDisplayList(), +}; + +void func_80919768(Actor* thisx, GlobalContext* globalCtx2) { + EffDust* this = THIS; + GlobalContext* globalCtx = globalCtx2; + GraphicsContext* gfxCtx = globalCtx2->state.gfxCtx; + f32* distanceTraveled; + Vec3f* initialPositions; + s32 i; + f32 aux; + s16 sp92; + Vec3f activeCamEye; + + activeCamEye = ACTIVE_CAM->eye; + sp92 = Math_Vec3f_Yaw(&activeCamEye, &thisx->world.pos); + + OPEN_DISPS(gfxCtx); + func_8012C28C(gfxCtx); + + gDPPipeSync(POLY_XLU_DISP++); + + initialPositions = this->initialPositions; + distanceTraveled = this->distanceTraveled; + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 255); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 255, 0); + + gSPSegment(POLY_XLU_DISP++, 0x08, D_80919DB0); + + for (i = 0; i < ARRAY_COUNT(this->distanceTraveled); i++) { + if (*distanceTraveled < 1.0f) { + aux = 1.0f - SQ(*distanceTraveled); + SysMatrix_InsertTranslation(thisx->world.pos.x, thisx->world.pos.y, thisx->world.pos.z, MTXMODE_NEW); + Matrix_RotateY(sp92, MTXMODE_APPLY); + SysMatrix_InsertTranslation(initialPositions->x * ((this->dx * aux) + (1.0f - this->dx)), + initialPositions->y * ((this->dy * aux) + (1.0f - this->dy)), + initialPositions->z * ((this->dz * aux) + (1.0f - this->dz)), MTXMODE_APPLY); + Matrix_Scale(this->scalingFactor, this->scalingFactor, this->scalingFactor, 1); + + SysMatrix_NormalizeXYZ(&globalCtx->unk187FC); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPClearGeometryMode(POLY_XLU_DISP++, G_FOG | G_LIGHTING); + + gSPDisplayList(POLY_XLU_DISP++, D_04054A90); + + gSPSetGeometryMode(POLY_XLU_DISP++, G_FOG | G_LIGHTING); + } + initialPositions++; + distanceTraveled++; + } + + CLOSE_DISPS(gfxCtx); +} + +void func_809199FC(Actor* thisx, GlobalContext* globalCtx2) { + EffDust* this = THIS; + GlobalContext* globalCtx = globalCtx2; + GraphicsContext* gfxCtx = globalCtx2->state.gfxCtx; + f32* distanceTraveled; + Vec3f* initialPositions; + s32 i; + f32 aux; + ActorPlayer* player = PLAYER; + + OPEN_DISPS(gfxCtx); + func_8012C28C(gfxCtx); + + gDPPipeSync(POLY_XLU_DISP++); + + initialPositions = this->initialPositions; + distanceTraveled = this->distanceTraveled; + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 255); + if (player->unkB08 >= 0.85f) { + gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 0, 0); + } else { + gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 255, 0); + } + + gSPSegment(POLY_XLU_DISP++, 0x08, D_80919DB0); + + for (i = 0; i < ARRAY_COUNT(this->distanceTraveled); i++) { + if (*distanceTraveled < 1.0f) { + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (*distanceTraveled * 255.0f)); + + aux = 1.0f - SQ(*distanceTraveled); + SysMatrix_InsertMatrix(&player->mf_CC4, MTXMODE_NEW); + SysMatrix_InsertTranslation(initialPositions->x * ((this->dx * aux) + (1.0f - this->dx)), + (initialPositions->y * (1.0f - *distanceTraveled)) + 320.0f, + (initialPositions->z * (1.0f - *distanceTraveled)) + -20.0f, MTXMODE_APPLY); + + Matrix_Scale(*distanceTraveled * this->scalingFactor, *distanceTraveled * this->scalingFactor, + *distanceTraveled * this->scalingFactor, MTXMODE_APPLY); + + SysMatrix_NormalizeXYZ(&globalCtx->unk187FC); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPClearGeometryMode(POLY_XLU_DISP++, G_FOG | G_LIGHTING); + + gSPDisplayList(POLY_XLU_DISP++, D_04054A90); + gSPSetGeometryMode(POLY_XLU_DISP++, G_FOG | G_LIGHTING); + } + + initialPositions++; + distanceTraveled++; + } + + CLOSE_DISPS(gfxCtx); +} + +void EffDust_Draw(Actor* thisx, GlobalContext* globalCtx) { + EffDust* this = THIS; + + this->drawFunc(thisx, globalCtx); +} diff --git a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h index 1db346907f..d6421066aa 100644 --- a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h +++ b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h @@ -5,11 +5,31 @@ struct EffDust; +typedef void (*EffDustActionFunc)(struct EffDust*, GlobalContext*); + typedef struct EffDust { - /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x41C]; + /* 0x0000 */ Actor actor; + /* 0x0144 */ f32 distanceTraveled[64]; // For each particle. Normalized. From 0.0f to 1.0f + /* 0x0244 */ Vec3f initialPositions[64]; // Array of position for each dust particle. + /* 0x0544 */ u8 index; + /* 0x0545 */ u8 life; // Only considered if actor.params is 2, 3 or 4. + /* 0x0548 */ f32 dx; // Normalized. 0.0f to 1.0f + /* 0x054C */ f32 dy; // Normalized. 0.0f to 1.0f + /* 0x0550 */ f32 dz; // Normalized. 0.0f to 1.0f + /* 0x0554 */ f32 scalingFactor; + /* 0x0558 */ EffDustActionFunc actionFunc; + /* 0x055C */ ActorFunc drawFunc; } EffDust; // size = 0x560 +typedef enum { + /* 0x00 */ EFF_DUST_TYPE_0, + /* 0x01 */ EFF_DUST_TYPE_1, + /* 0x02 */ EFF_DUST_TYPE_2, + /* 0x03 */ EFF_DUST_TYPE_3, + /* 0x04 */ EFF_DUST_TYPE_4, + /* 0x05 */ EFF_DUST_TYPE_5 +} EffDustType; + extern const ActorInit Eff_Dust_InitVars; #endif // Z_EFF_DUST_H diff --git a/tools/permuter_settings.toml b/tools/permuter_settings.toml new file mode 100644 index 0000000000..11ef7d726e --- /dev/null +++ b/tools/permuter_settings.toml @@ -0,0 +1,12 @@ +[preserve_macros] +"g[DS]P.*" = "void" +"gDma.*" = "void" +"G_IM_SIZ_.*" = "int" +"G_[AC]C.*" = "int" +LOG = "void" +SET_FULLSCREEN_VIEWPORT = "void" +OPEN_DISPS = "void" +CLOSE_DISPS = "void" +ABS = "int" +SQ = "int" +CLAMP = "int"