diff --git a/assets/xml/objects/gameplay_keep.xml b/assets/xml/objects/gameplay_keep.xml
index 86f48d61dd..22626d302f 100644
--- a/assets/xml/objects/gameplay_keep.xml
+++ b/assets/xml/objects/gameplay_keep.xml
@@ -1287,27 +1287,27 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
diff --git a/include/z64effect.h b/include/z64effect.h
index d9211ef5e1..0b848a478f 100644
--- a/include/z64effect.h
+++ b/include/z64effect.h
@@ -257,6 +257,7 @@ typedef struct {
/* 0x18 */ u8 unk18; // Always 1?
} EffectSsOverlay; // size = 0x1C
+//! TODO: Review reuse of vec/gfx/actor fields across all effects
typedef struct EffectSs {
/* 0x00 */ Vec3f pos;
/* 0x0C */ Vec3f velocity;
diff --git a/spec b/spec
index 9fc8e73276..3a3d2f8ff8 100644
--- a/spec
+++ b/spec
@@ -3411,8 +3411,7 @@ beginseg
name "ovl_Effect_Ss_Sbn"
compress
include "build/src/overlays/effects/ovl_Effect_Ss_Sbn/z_eff_ss_sbn.o"
- include "build/data/ovl_Effect_Ss_Sbn/ovl_Effect_Ss_Sbn.data.o"
- include "build/data/ovl_Effect_Ss_Sbn/ovl_Effect_Ss_Sbn.reloc.o"
+ include "build/src/overlays/effects/ovl_Effect_Ss_Sbn/ovl_Effect_Ss_Sbn_reloc.o"
endseg
beginseg
diff --git a/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c b/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c
index d3286f5451..f1dc5c6f6a 100644
--- a/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c
+++ b/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c
@@ -357,10 +357,10 @@ void func_8088ACE0(EnArrow* this, GlobalContext* globalCtx) {
if ((this->unk_262 != 0) && (this->actor.wallBgId == BG_ACTOR_MAX)) {
- Math_Vec3f_Copy(&sp84.unk_00, &this->actor.world.pos);
- sp84.unk_0C = this->actor.wallPoly;
- sp84.unk_10 = this->bubble.unk_144;
- EffectSs_Spawn(globalCtx, EFFECT_SS_SBN, 128, &sp84.unk_00);
+ Math_Vec3f_Copy(&sp84.pos, &this->actor.world.pos);
+ sp84.colPoly = this->actor.wallPoly;
+ sp84.scale = this->bubble.unk_144;
+ EffectSs_Spawn(globalCtx, EFFECT_SS_SBN, 128, &sp84);
}
}
Actor_MarkForDeath(&this->actor);
diff --git a/src/overlays/effects/ovl_Effect_Ss_Sbn/z_eff_ss_sbn.c b/src/overlays/effects/ovl_Effect_Ss_Sbn/z_eff_ss_sbn.c
index b09dca0142..26901bac56 100644
--- a/src/overlays/effects/ovl_Effect_Ss_Sbn/z_eff_ss_sbn.c
+++ b/src/overlays/effects/ovl_Effect_Ss_Sbn/z_eff_ss_sbn.c
@@ -1,30 +1,208 @@
/*
* File: z_eff_ss_sbn.c
* Overlay: ovl_Effect_Ss_Sbn
- * Description:
+ * Description: Popped Deku Bubble
+ *
+ * Note: The gfx field is used to store the colPoly, not anything gfx related
+ * This is not a problem since gfx is already void*
*/
#include "z_eff_ss_sbn.h"
+#include "objects/gameplay_keep/gameplay_keep.h"
+
+#define rScrollStep regs[0]
+#define rScroll regs[1]
+#define rTexIndex regs[2]
+#define rAlpha regs[3]
+#define rReg4 regs[4]
+#define rReg4Step regs[5]
+#define rRotAngle regs[6]
+#define rScale regs[7]
+#define rReg8 regs[8]
#define PARAMS ((EffectSsSbnInitParams*)initParamsx)
-s32 EffectSsSbn_Init(GlobalContext* globalCtx, u32 index, EffectSs* this, void* initParamsx);
+u32 EffectSsSbn_Init(GlobalContext* globalCtx, u32 index, EffectSs* this, void* initParamsx);
void EffectSsSbn_Update(GlobalContext* globalCtx, u32 index, EffectSs* this);
-void func_80AC8ECC(GlobalContext* globalCtx, u32 index, EffectSs* this);
-void func_80AC9164(GlobalContext* globalCtx, u32 index, EffectSs* this);
+void EffectSsSbn_DrawSliding(GlobalContext* globalCtx, u32 index, EffectSs* this);
+void EffectSsSbn_Draw(GlobalContext* globalCtx, u32 index, EffectSs* this);
-#if 0
const EffectSsInit Effect_Ss_Sbn_InitVars = {
EFFECT_SS_SBN,
EffectSsSbn_Init,
};
-#endif
+static TexturePtr sSlidingTextures[] = {
+ gEffPoppedDekuBubbleSliding1Tex, gEffPoppedDekuBubbleSliding2Tex, gEffPoppedDekuBubbleSliding3Tex,
+ gEffPoppedDekuBubbleSliding4Tex, gEffPoppedDekuBubbleSliding5Tex, gEffPoppedDekuBubbleSliding6Tex,
+ gEffPoppedDekuBubbleSliding7Tex, gEffPoppedDekuBubbleSliding8Tex, gEffPoppedDekuBubbleSliding9Tex,
+ gEffPoppedDekuBubbleSliding10Tex, gEffPoppedDekuBubbleSliding11Tex, gEffPoppedDekuBubbleSliding12Tex,
+};
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Sbn/EffectSsSbn_Init.s")
+static TexturePtr sTextures[] = {
+ gEffPoppedDekuBubble1Tex, gEffPoppedDekuBubble2Tex, gEffPoppedDekuBubble3Tex,
+ gEffPoppedDekuBubble4Tex, gEffPoppedDekuBubble5Tex,
+};
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Sbn/func_80AC8ECC.s")
+u32 EffectSsSbn_Init(GlobalContext* globalCtx, u32 index, EffectSs* this, void* initParamsx) {
+ EffectSsSbnInitParams* initParams = PARAMS;
+ CollisionPoly* colPoly;
+ MtxF mtx;
+ Vec3f normal;
+ Vec3f colPolyVec;
+ Vec3f bubbleVec;
+ f32 angle;
+ f32 opposite;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Sbn/func_80AC9164.s")
+ Math_Vec3f_Copy(&this->pos, &initParams->pos);
+ Math_Vec3f_Copy(&this->velocity, &gZeroVec3f);
+ Math_Vec3f_Copy(&this->accel, &gZeroVec3f);
+ this->flags = 0;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Sbn/EffectSsSbn_Update.s")
+ this->gfx = initParams->colPoly;
+
+ this->rScroll = 0;
+ this->rScrollStep = 7;
+ this->rTexIndex = 0;
+ this->rAlpha = 200;
+ this->rReg4 = 250;
+ this->rReg4Step = 30;
+
+ this->rScale = randPlusMinusPoint5Scaled(100.0f) + (initParams->scale * 120.0f);
+ if (this->rScale < 600) {
+ this->rScale = 600;
+ } else if (this->rScale > 1500) {
+ this->rScale = 1500;
+ }
+
+ this->rReg8 = 1000;
+ this->rRotAngle = 0;
+ this->life = 93;
+ this->draw = EffectSsSbn_DrawSliding;
+ this->update = EffectSsSbn_Update;
+
+ if (this->gfx != NULL) {
+ colPoly = this->gfx;
+ func_800C0094(colPoly, this->pos.x, this->pos.y, this->pos.z, &mtx);
+ normal.x = COLPOLY_GET_NORMAL(colPoly->normal.x);
+ normal.y = COLPOLY_GET_NORMAL(colPoly->normal.y);
+ normal.z = COLPOLY_GET_NORMAL(colPoly->normal.z);
+ if ((normal.y > 0.95f) || (normal.y < -0.95f)) {
+ this->draw = EffectSsSbn_Draw;
+ return 1;
+ }
+ if (normal.y > 0.05f) {
+ colPolyVec.x = normal.x * 10.0f;
+ colPolyVec.y = (-(SQ(normal.x) + SQ(normal.z)) * 10.0f) / normal.y;
+ colPolyVec.z = normal.z * 10.0f;
+ } else if (normal.y < -0.05f) {
+ colPolyVec.x = -normal.x * 10.0f;
+ colPolyVec.y = (-(SQ(normal.x) + SQ(normal.z)) * 10.0f) / -normal.y;
+ colPolyVec.z = -normal.z * 10.0f;
+ } else {
+ colPolyVec.x = 0.0f;
+ colPolyVec.y = -10.0f;
+ colPolyVec.z = 0.0f;
+ }
+ bubbleVec.x = -mtx.mf[2][0] * 10.0f;
+ bubbleVec.y = -mtx.mf[2][1] * 10.0f;
+ bubbleVec.z = -mtx.mf[2][2] * 10.0f;
+ Math3D_AngleBetweenVectors(&colPolyVec, &bubbleVec, &angle);
+
+ opposite = (SQ(angle) >= 1.0f) ? 0.0f : sqrtf(1.0f - SQ(angle));
+ if (((mtx.mf[0][0] * colPolyVec.x) + (mtx.mf[0][1] * colPolyVec.y) + (mtx.mf[0][2] * colPolyVec.z)) < 0.0f) {
+ this->rRotAngle = Math_FAtan2F(angle, opposite);
+ } else {
+ this->rRotAngle = -Math_FAtan2F(angle, opposite);
+ }
+ }
+
+ return 1;
+}
+
+void EffectSsSbn_DrawSliding(GlobalContext* globalCtx, u32 index, EffectSs* this) {
+ GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
+ MtxF mtx;
+ f32 scale = this->rScale * 0.001f;
+ s32 pad;
+
+ func_800C0094(this->gfx, this->pos.x, this->pos.y, this->pos.z, &mtx);
+ SkinMatrix_MulYRotation(&mtx, this->rRotAngle);
+ Matrix_InsertMatrix(&mtx, MTXMODE_NEW);
+ Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
+ Matrix_Scale(0.05f, 0.05f, 0.05f, MTXMODE_APPLY);
+
+ OPEN_DISPS(gfxCtx);
+
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ func_8012C2DC(gfxCtx);
+ gDPSetRenderMode(POLY_XLU_DISP++, G_RM_FOG_SHADE_A, G_RM_ZB_XLU_DECAL2);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 255, this->rAlpha);
+
+ if (this->rTexIndex < ARRAY_COUNT(sSlidingTextures)) {
+ {
+ TexturePtr tex = sSlidingTextures[this->rTexIndex];
+
+ gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(tex));
+ }
+ this->rTexIndex++;
+ this->rScroll += this->rScrollStep;
+ } else {
+ gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gEffPoppedDekuBubbleSliding12Tex));
+ if ((this->rScrollStep >= 2) && ((globalCtx->state.frames % 2) == 0)) {
+ this->rScrollStep--;
+ }
+ this->rScroll += this->rScrollStep;
+ }
+ gSPSegment(POLY_XLU_DISP++, 0x09,
+ Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 0, 0, 0x20, 0x40, 1, 0, this->rScroll, 0x20, 0x20));
+ gSPDisplayList(POLY_XLU_DISP++, gEffPoppedDekuBubbleSlidingDL);
+
+ CLOSE_DISPS(gfxCtx);
+}
+
+void EffectSsSbn_Draw(GlobalContext* globalCtx, u32 index, EffectSs* this) {
+ GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
+ MtxF mtx;
+ f32 scale = this->rScale * 0.001f;
+
+ func_800C0094(this->gfx, this->pos.x, this->pos.y, this->pos.z, &mtx);
+ SkinMatrix_MulYRotation(&mtx, this->rRotAngle);
+ Matrix_InsertMatrix(&mtx, MTXMODE_NEW);
+ Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
+ Matrix_Scale(0.05f, 0.05f, 0.05f, MTXMODE_APPLY);
+
+ OPEN_DISPS(gfxCtx);
+
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ func_8012C2DC(gfxCtx);
+ gDPSetRenderMode(POLY_XLU_DISP++, G_RM_FOG_SHADE_A, G_RM_ZB_XLU_DECAL2);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 255, this->rAlpha);
+
+ if (this->rTexIndex < ARRAY_COUNT(sTextures)) {
+ {
+ TexturePtr tex = sTextures[this->rTexIndex];
+
+ gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(tex));
+ }
+ this->rTexIndex++;
+ } else {
+ gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gEffPoppedDekuBubble5Tex));
+ }
+ gSPDisplayList(POLY_XLU_DISP++, gEffPoppedDekuBubbleDL);
+
+ CLOSE_DISPS(gfxCtx);
+}
+
+void EffectSsSbn_Update(GlobalContext* globalCtx, u32 index, EffectSs* this) {
+ if (this->life < 10) {
+ this->rAlpha -= 20;
+ } else if (this->life >= 45) {
+ if (this->life < 85) {
+ this->rReg8 += 12;
+ this->rReg4 -= this->rReg4Step;
+ } else {
+ this->rReg8 = 1000;
+ }
+ }
+}
diff --git a/src/overlays/effects/ovl_Effect_Ss_Sbn/z_eff_ss_sbn.h b/src/overlays/effects/ovl_Effect_Ss_Sbn/z_eff_ss_sbn.h
index ba2355d232..439ef88a01 100644
--- a/src/overlays/effects/ovl_Effect_Ss_Sbn/z_eff_ss_sbn.h
+++ b/src/overlays/effects/ovl_Effect_Ss_Sbn/z_eff_ss_sbn.h
@@ -4,11 +4,10 @@
#include "global.h"
typedef struct {
- /* 0x00 */ Vec3f unk_00;
- /* 0x0C */ CollisionPoly* unk_0C;
- /* 0x10 */ f32 unk_10;
- /* 0x14 */ char unk_14[UNK_SIZE];
-} EffectSsSbnInitParams; // size = ?
+ /* 0x00 */ Vec3f pos;
+ /* 0x0C */ CollisionPoly* colPoly;
+ /* 0x10 */ f32 scale;
+} EffectSsSbnInitParams; // size = 0x14
extern const EffectSsInit Effect_Ss_Sbn_InitVars;
diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt
index 73c959b32b..6a7b926838 100644
--- a/tools/disasm/functions.txt
+++ b/tools/disasm/functions.txt
@@ -11997,8 +11997,8 @@
0x80AC8A94:("TransitionWipe5_SetColor",),
0x80AC8AA0:("TransitionWipe5_SetEnvColor",),
0x80AC8B50:("EffectSsSbn_Init",),
- 0x80AC8ECC:("func_80AC8ECC",),
- 0x80AC9164:("func_80AC9164",),
+ 0x80AC8ECC:("EffectSsSbn_DrawSliding",),
+ 0x80AC9164:("EffectSsSbn_Draw",),
0x80AC933C:("EffectSsSbn_Update",),
0x80AC94C0:("func_80AC94C0",),
0x80AC94FC:("ObjOcarinalift_Init",),
diff --git a/undefined_syms.txt b/undefined_syms.txt
index ca9dfd0a8e..296d6273e8 100644
--- a/undefined_syms.txt
+++ b/undefined_syms.txt
@@ -470,10 +470,6 @@ D_0406F380 = 0x0406F380;
D_0406F9F0 = 0x0406F9F0;
D_0406FAE0 = 0x0406FAE0;
D_040706E0 = 0x040706E0;
-D_04071230 = 0x04071230;
-D_04073F00 = 0x04073F00;
-D_04074330 = 0x04074330;
-D_04075400 = 0x04075400;
D_04075A40 = 0x04075A40;
D_04076BC0 = 0x04076BC0;
D_04079B10 = 0x04079B10;