From 60cbb52ba4bdf0ba997489ca098642b90abf5e04 Mon Sep 17 00:00:00 2001 From: j3lee Date: Mon, 12 Oct 2026 12:07:27 +0930 Subject: [PATCH 1/6] hadoho: import and decompile the overlay --- CMakeLists.txt | 1 + config/symbols.magic-hadoho.us.txt | 19 + config/us.yaml | 13 + src/magic/hadoho.c | 575 +++++++++++++++++++++++++++++ src/magic/hadoho.h | 6 + tools/builder/builder/objdiff.go | 1 + 6 files changed, 615 insertions(+) create mode 100644 config/symbols.magic-hadoho.us.txt create mode 100644 src/magic/hadoho.c create mode 100644 src/magic/hadoho.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 14280eff..3e9106bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,6 +89,7 @@ set(FF7_MINI set(FF7_MAGIC src/magic/barrier.c src/magic/brizad.c + src/magic/hadoho.c src/magic/lv5deth.c src/magic/mabaria.c src/magic/sennkoku.c diff --git a/config/symbols.magic-hadoho.us.txt b/config/symbols.magic-hadoho.us.txt new file mode 100644 index 00000000..5fc1ba73 --- /dev/null +++ b/config/symbols.magic-hadoho.us.txt @@ -0,0 +1,19 @@ +func_801B0000 = 0x801B0000; +func_801B0020 = 0x801B0020; +func_801B01CC = 0x801B01CC; +func_801B02FC = 0x801B02FC; +HadohoDoubleBufferFlip = 0x801B045C; +func_801B04C8 = 0x801B04C8; +func_801B05B0 = 0x801B05B0; +func_801B066C = 0x801B066C; +func_801B0888 = 0x801B0888; +func_801B09E8 = 0x801B09E8; +func_801B0B44 = 0x801B0B44; +func_801B0CC8 = 0x801B0CC8; +func_801B0DB4 = 0x801B0DB4; +func_801B0EB4 = 0x801B0EB4; +func_801B10A8 = 0x801B10A8; +func_801B1598 = 0x801B1598; +func_801B1978 = 0x801B1978; +g_HadohoPrimBuffer = 0x801D5648; +g_HadohoBufferPtr = 0x801ED648; diff --git a/config/us.yaml b/config/us.yaml index 69eaa150..858466a0 100644 --- a/config/us.yaml +++ b/config/us.yaml @@ -807,3 +807,16 @@ overlays: - [0, c, sennkoku] - [0x930, data, sennkoku_model] - [0x559C, data, sennkoku_buffers] + # HADOHO.BIN -- effect overlay + - name: hadoho + disk_path: disks/us/MAGIC/HADOHO.BIN + sha1: 850cc7b46911dd9c300f4c0a7928a55cd097d84c + base_path: magic + imports: [main, battle] + vram_start: 0x801B0000 + symbol_addrs_path: + - config/symbols.magic-hadoho.us.txt + segments: + - [0, c, hadoho] + - [0x1B40, data, hadoho_model] + - [0x25648, data, hadoho_buffers] diff --git a/src/magic/hadoho.c b/src/magic/hadoho.c new file mode 100644 index 00000000..283a725a --- /dev/null +++ b/src/magic/hadoho.c @@ -0,0 +1,575 @@ +//! PSYQ=3.3 CC1=2.6.3 + +#include "common.h" +#include "magic.h" +#include "hadoho.h" +#include "../battle/battle.h" + +u_long* func_800C4FC8(); + +// Effect HADOHO. + +void func_801B1978(s32 targetMask, s32 callbackArg); + +// Primitive buffer pages, one 0xC000 page per double-buffered frame. +extern u8 g_HadohoPrimBuffer[2][0xC000]; +extern void* g_HadohoBufferPtr; + +// Only StartFrame/AnimationFrame are common to every magic overlay; the +// rest is payload this effect lays out for itself. +typedef struct { + /* 0x00 */ s16 StartFrame; + /* 0x02 */ s16 AnimationFrame; + /* 0x04 */ SVECTOR Pos; + /* 0x0C */ SVECTOR PartPos; + /* 0x14 */ s16 unk14; + /* 0x16 */ s16 unk16; + /* 0x18 */ s16 unk18; + /* 0x1A */ s16 unk1A; + /* 0x1C */ s16 unk1C; + /* 0x1E */ s16 unk1E; +} HadohoData; // size:0x20 + +extern MATRIX D_801D561C; +extern ModelRenderDesc D_801D555C; +extern ModelRenderDesc D_801D5584; +extern ModelRenderDesc D_801D559C; +extern ModelRenderDesc D_801D55C8; +extern ModelRenderDesc D_801D55F4; +extern SVECTOR D_801D557C; +extern SVECTOR D_801D5594; +extern SVECTOR D_801D55D8; +extern SVECTOR D_801D5610; +extern SVECTOR D_801D5640; +extern SpriteRenderDesc D_801D5534; +extern SpriteRenderDesc D_801D5540; +extern SpriteRenderDesc D_801D55AC; +extern SpriteRenderDesc D_801D55B8; +extern SpriteRenderDesc D_801D5604; +extern VECTOR D_801D554C; +extern VECTOR D_801D55E4; +extern HadohoData g_BattleEffectSlots[]; +extern HadohoData g_BattleDetachedSlots[]; +extern s16 g_BattleDetachedCursor; +extern s16 D_801D5530; +extern s16 D_801D55C4; +extern s16 D_801D55E0; +extern s16 D_801D5618; +extern s16 D_801D563C; +extern s32 D_801D5174; +extern s32 D_801D53AC; +extern s32 D_801D1C40[]; +extern s32 D_801D2244[]; +extern s32 D_801D2848[]; +extern s32 D_801D37EC[]; +extern s32 D_801D4790[]; +extern s32* D_801D556C[]; +extern u16 D_801031EA; +extern u8 D_800F5B70; +extern u8 D_800F5B71; +extern u8 D_800F5B72; +extern u_long D_801B1B40[]; +extern void* D_80163C74; +s32 BattleDetachedRegister(void (*func)(void)); +void func_800BBA84(u16 arg0, s32 arg1, s32 arg2); +void func_801B04C8(void); +void func_801B066C(void); +void func_801B0888(void); +void func_801B0B44(void); +void func_801B10A8(void); +void func_801B1598(void); + +// Same as MAGIC_Biora. +void func_801B0000(s32 targetMask, s32 callbackArg) { func_801B1978(targetMask, callbackArg); } + +void func_801B0020(s16 targetMask, SVECTOR* out) { + VECTOR sum; + SVECTOR pos; + s16 i; + s16 count; + + count = 0; + sum.vx = sum.vy = sum.vz = 0; + for (i = 0; i < 10; i++) { + if ((targetMask >> i) & 1) { + BattleGetPartPosition(i, g_BattleModels[i].boneIndices[0], &pos); + count++; + sum.vx += pos.vx; + sum.vy += pos.vy; + sum.vz += pos.vz; + } + } + out->vx = sum.vx / count; + out->vy = sum.vy / count; + out->vz = sum.vz / count; +} + +void func_801B01CC(s32 offset, s16 spread, SVECTOR* out) { + SVECTOR in; + SVECTOR rot; + MATRIX matrix; + + in.vz = 0; + in.vx = 0; + in.vy = offset + (rand() % spread * 2 - spread); + rot.vy = 0; + rot.vx = rand() % 800 - 400; + rot.vz = rand() % 800 - 400; + RotMatrix(&rot, &matrix); + ApplyMatrixSV(&matrix, &in, out); +} + +void func_801B02FC(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) { + MATRIX matrix; + MATRIX rotated; + VECTOR dir; + s32 flag; + s16 i; + + for (i = 0; i < 3; i++) { + matrix.m[2][i] = 0; + matrix.m[1][i] = 0; + matrix.m[0][i] = 0; + } + SetRotMatrix(&g_BattleWorldView.m); + SetTransMatrix(&g_BattleWorldView.m); + RotTrans(pos, (VECTOR*)matrix.t, &flag); + if (offset != 0) { + VectorNormal((VECTOR*)matrix.t, &dir); + matrix.t[0] += offset * dir.vx >> 12; + matrix.t[1] += offset * dir.vy >> 12; + matrix.t[2] += offset * dir.vz >> 12; + } + matrix.m[0][0] = matrix.m[1][1] = matrix.m[2][2] = scale; + RotMatrixYXZ(rot, &rotated); + MulMatrix(&matrix, &rotated); + SetRotMatrix(&matrix); + SetTransMatrix(&matrix); +} + +// Same as BioraDoubleBufferFlip. +static void HadohoDoubleBufferFlip(void) { + HadohoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + g_HadohoBufferPtr = g_HadohoPrimBuffer[effect->AnimationFrame]; + effect->AnimationFrame ^= 1; + if (g_BattleEffectCount < 2) { + effect->StartFrame = -1; + } +} + +void func_801B04C8(void) { + HadohoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + D_80163C74 = func_800C4FC8(D_801D5530, D_801D5530 >> 1, 0); + if (D_80062D98 == 0) { + if (effect->AnimationFrame < 16) { + D_801D5530 += 15; + } + if (effect->AnimationFrame >= 35) { + D_801D5530 -= 15; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 50) { + effect->StartFrame = -1; + } + } +} + +void func_801B05B0(void) { + HadohoData* effect; + + effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; + BattleSetBillboardMatrix(&effect->Pos, 0x2800, 0); + D_801D5534.frameIndex = effect->AnimationFrame; + D_80163C74 = func_800D4D90(&D_801D5534, (u_long**)&g_cDb->unk70, 12, D_80163C74); + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame >= D_801D5174) { + effect->StartFrame = -1; + } + } +} + +void func_801B066C(void) { + MATRIX rotated; + MATRIX matrix; + SVECTOR rot; + s32 flag; + HadohoData* effect; + s16 fade; + s16 i; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + for (i = 0; i < 3; i++) { + matrix.m[2][i] = 0; + matrix.m[1][i] = 0; + matrix.m[0][i] = 0; + } + fade = 8; + if (effect->AnimationFrame >= 12) { + fade = 20 - effect->AnimationFrame; + } + rot.vy = 0; + rot.vx = 0; + rot.vz = effect->unk14; + SetRotMatrix(&g_BattleWorldView.m); + SetTransMatrix(&g_BattleWorldView.m); + RotTrans(&effect->Pos, (VECTOR*)matrix.t, &flag); + matrix.m[0][0] = matrix.m[1][1] = matrix.m[2][2] = 0x2000; + RotMatrixYXZ(&rot, &rotated); + MulMatrix(&matrix, &rotated); + SetRotMatrix(&matrix); + SetTransMatrix(&matrix); + D_801D5540.frameIndex = effect->unk16; + D_801D5540.color.cd = fade == 8 ? 0x2C : 0x2E; + D_801D5540.color.r = D_801D5540.color.g = D_801D5540.color.b = fade << 4; + D_80163C74 = func_800D4D90(&D_801D5540, (u_long**)&g_cDb->unk70, 12, D_80163C74); + if (D_80062D98 == 0) { + effect->Pos.vx += effect->PartPos.vx; + effect->Pos.vy += effect->PartPos.vy; + effect->Pos.vz += effect->PartPos.vz; + if (effect->Pos.vy > 0) { + effect->Pos.vy = 0; + effect->PartPos.vy *= -1; + } + effect->PartPos.vy += 0x14; + effect->unk14 += 0x200; + effect->AnimationFrame++; + if (effect->AnimationFrame == 0x14) { + effect->StartFrame = -1; + } + } +} + +void func_801B0888(void) { + MATRIX matrix; + MATRIX composed; + SVECTOR rot; + HadohoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + rot.vy = 0; + rot.vx = 0; + rot.vz = effect->unk14; + RotMatrix(&rot, &matrix); + ScaleMatrix(&matrix, &D_801D554C); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + D_801D555C.color = 0x80 - effect->AnimationFrame * 6; + D_801D555C.model = D_801D556C[effect->unk16]; + g_HadohoBufferPtr = func_800D29D4(&D_801D555C, g_cDb->unk70, 12, g_HadohoBufferPtr); + if (D_80062D98 == 0) { + effect->Pos.vy -= 200; + effect->unk14 += 0x100; + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B09E8(void) { + MATRIX matrix; + MATRIX composed; + VECTOR scale; + HadohoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + RotMatrixYXZ(&D_801D557C, &matrix); + MulMatrix0(&D_801D561C, &matrix, &matrix); + scale.vx = scale.vy = scale.vz = effect->AnimationFrame * 1500; + ScaleMatrix(&matrix, &scale); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + SetFarColor(0, 0, 0); + D_801D5584.color = effect->AnimationFrame * 256; + g_HadohoBufferPtr = func_800D29D4(&D_801D5584, g_cDb->unk70, 12, g_HadohoBufferPtr); + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B0B44(void) { + MATRIX matrix; + MATRIX composed; + VECTOR scale; + HadohoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + if (effect->AnimationFrame >= 3) { + RotMatrixYXZ(&D_801D5594, &matrix); + MulMatrix0(&D_801D561C, &matrix, &matrix); + scale.vx = scale.vy = scale.vz = 0x4000 - effect->AnimationFrame * 400; + ScaleMatrix(&matrix, &scale); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + SetFarColor(0, 0, 0); + D_801D559C.color = effect->AnimationFrame * 200; + g_HadohoBufferPtr = func_800D29D4(&D_801D559C, g_cDb->unk70, 12, g_HadohoBufferPtr); + } + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B0CC8(void) { + HadohoData* effect; + + effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; + BattleSetBillboardMatrix(&effect->Pos, 0x4000, 0); + D_801D55AC.frameIndex = effect->AnimationFrame; + D_80163C74 = func_800D4D90(&D_801D55AC, (u_long**)&g_cDb->unk70, 12, D_80163C74); + if (D_80062D98 == 0) { + effect->Pos.vx += effect->PartPos.vx; + effect->Pos.vy += effect->PartPos.vy; + effect->Pos.vz += effect->PartPos.vz; + effect->AnimationFrame++; + if (effect->AnimationFrame >= D_801D53AC) { + effect->StartFrame = -1; + } + } +} + +void func_801B0DB4(void) { + HadohoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + BattleSetBillboardMatrix(&effect->Pos, (s16)(0x1000 + ((rsin(effect->AnimationFrame * 51) << 11) >> 16 << 7)), 0); + D_801D55B8.frameIndex = effect->AnimationFrame % 2; + g_HadohoBufferPtr = func_800D4D90(&D_801D55B8, (u_long**)&g_cDb->unk70, 12, g_HadohoBufferPtr); + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame == 40) { + effect->StartFrame = -1; + } + } +} + +void func_801B0EB4(void) { + MATRIX matrix; + MATRIX composed; + VECTOR scale; + HadohoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + RotMatrixYXZ(&D_801D55D8, &matrix); + MulMatrix0(&D_801D561C, &matrix, &matrix); + scale.vx = scale.vz = 0x4000 - effect->AnimationFrame * 300; + scale.vy = effect->AnimationFrame * 900; + ScaleMatrix(&matrix, &scale); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + SetFarColor(0, 0, 0); + D_801D55C8.color = 0x1000 - D_801D55C4 * 256; + D_801D55C8.model = D_801D1C40; + g_HadohoBufferPtr = func_800D29D4(&D_801D55C8, g_cDb->unk70, 12, g_HadohoBufferPtr); + D_801D55C8.model = D_801D2244; + g_HadohoBufferPtr = func_800D29D4(&D_801D55C8, g_cDb->unk70, 12, g_HadohoBufferPtr); + if (D_80062D98 == 0) { + if (effect->AnimationFrame >= 13) { + D_801D55C4 -= 1; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B10A8(void) { + MATRIX matrix; + MATRIX composed; + HadohoData* effect; + HadohoData* child; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + RotMatrixYXZ(&D_801D5610, &matrix); + MulMatrix0(&D_801D561C, &matrix, &matrix); + ScaleMatrix(&matrix, &D_801D55E4); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + D_801D55F4.color = (u16)D_801D55E0 * 16; + D_801D55F4.model = D_801D2848; + g_HadohoBufferPtr = func_800D29D4(&D_801D55F4, g_cDb->unk70, 12, g_HadohoBufferPtr); + D_801D55F4.model = D_801D37EC; + g_HadohoBufferPtr = func_800D29D4(&D_801D55F4, g_cDb->unk70, 12, g_HadohoBufferPtr); + D_801D55F4.model = D_801D4790; + g_HadohoBufferPtr = func_800D29D4(&D_801D55F4, g_cDb->unk70, 12, g_HadohoBufferPtr); + BattleSetBillboardMatrix(&effect->Pos, 0x4000, 0); + D_801D5604.color.r = D_801D5604.color.g = D_801D5604.color.b = D_801D55E0 * 20; + D_801D5604.frameIndex = effect->AnimationFrame % 2; + g_HadohoBufferPtr = func_800D4D90(&D_801D5604, (u_long**)&g_cDb->unk70, 12, g_HadohoBufferPtr); + if (D_80062D98 == 0) { + effect->Pos.vx += effect->PartPos.vx; + effect->Pos.vy += effect->PartPos.vy; + effect->Pos.vz += effect->PartPos.vz; + if ((effect->AnimationFrame & 1) == 0) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0B44)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + } + if (effect->Pos.vy < 0) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B066C)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vz = effect->Pos.vz; + child->Pos.vy = 0; + D_801D5618 = rand() % 4096; + child->PartPos.vx = (u32)(rcos(D_801D5618) * 15) >> 9; + child->PartPos.vz = (u32)(rsin(D_801D5618) * 15) >> 9; + child->PartPos.vy = -rand() % 300 - 50; + child->unk16 = rand() % 7; + if (effect->AnimationFrame % 3 == 0) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0888)]; + child->Pos.vx = effect->Pos.vx + rand() % 4000 - 2000; + child->Pos.vz = effect->Pos.vz + rand() % 4000 - 2000; + child->Pos.vy = 0; + child->unk16 = rand() % 4; + } + } + if (effect->AnimationFrame >= 13) { + D_801D55E0 -= 1; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} +void func_801B1598(void) { + SVECTOR in; + SVECTOR rot; + MATRIX matrix; + s32 flag; + HadohoData* effect; + HadohoData* child; + s16 i; + u16* u16p; + u16 t; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + if (D_80062D98 == 0) { + if (effect->AnimationFrame == 0) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B09E8)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0DB4)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + func_800BBA84(0x174, effect->unk1E, 0x40); + } + if (effect->AnimationFrame == 20) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0EB4)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B10A8)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + child->PartPos.vx = effect->PartPos.vx; + child->PartPos.vy = effect->PartPos.vy; + child->PartPos.vz = effect->PartPos.vz; + func_800BBA84(0x176, effect->unk1E, 0x40); + } + if (effect->AnimationFrame == 20) { + BattleEffectRegister(func_801B04C8); + } + if (effect->AnimationFrame == 54) { + BattleFixedPointRampUpdateInit(0, 16); + } + if (effect->AnimationFrame >= 37 && effect->AnimationFrame < 44) { + for (i = 0; i < 10; i++) { + if ((D_801D563C >> i) & 1) { + child = &g_BattleDetachedSlots[BattleDetachedRegister(func_801B0CC8)]; + BattleGetPartPosition(i, g_BattleModels[i].boneIndices[0], &child->Pos); + in.vy = 0x50; + in.vz = 0; + in.vx = 0; + rot.vx = rand() % 4096; + rot.vz = rand() % 4096; + rot.vy = 0; + RotMatrixYXZ(&rot, &matrix); + matrix.t[2] = 0; + matrix.t[1] = 0; + matrix.t[0] = 0; + SetRotMatrix(&matrix); + SetTransMatrix(&matrix); + RotTransSV(&in, &child->PartPos, &flag); + } + } + } + if (effect->AnimationFrame == 40) { + for (i = 0; i < 10; i++) { + if ((D_801D563C >> i) & 1) { + func_800D5774(i); + } + } + func_800BBA84(0xFA, -1, 0x40); + } + if (effect->AnimationFrame >= 21) { + u16p = &D_801031EA; + t = *u16p + 0x10; + *u16p = t - (effect->AnimationFrame % 2) * 32; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 75) { + effect->StartFrame = -1; + } + } +} + +void func_801B1978(s32 targetMask, s32 callbackArg) { + VECTOR vec; + SVECTOR dir; + HadohoData* effect; + + BattleEffectRegister(HadohoDoubleBufferFlip); + D_801D563C = targetMask; + effect = &g_BattleEffectSlots[BattleEffectRegister(func_801B1598)]; + BattleGetPartPosition(callbackArg, g_BattleModels[callbackArg].boneIndices[8], &effect->Pos); + func_801B0020(targetMask, &D_801D5640); + vec.vx = dir.vx = D_801D5640.vx - effect->Pos.vx; + vec.vy = dir.vy = D_801D5640.vy - effect->Pos.vy; + vec.vz = dir.vz = D_801D5640.vz - effect->Pos.vz; + BattleMatrixFromDirection(&dir, &D_801D561C); + VectorNormal(&vec, &vec); + effect->PartPos.vx = (u32)(vec.vx * 75) >> 9; + effect->PartPos.vy = (u32)(vec.vy * 75) >> 9; + effect->PartPos.vz = (u32)(vec.vz * 75) >> 9; + effect->unk1E = callbackArg; + BattleSetLoadTimToVram(D_801B1B40, 0, 0, 0); + D_800F5B70 = D_800F5B71 = D_800F5B72 = 0; + BattleFixedPointRampUpdateInit(0x1000, 0x10); +} diff --git a/src/magic/hadoho.h b/src/magic/hadoho.h new file mode 100644 index 00000000..bb012511 --- /dev/null +++ b/src/magic/hadoho.h @@ -0,0 +1,6 @@ +#ifndef HADOHO_H +#define HADOHO_H + +#include "magic.h" + +#endif diff --git a/tools/builder/builder/objdiff.go b/tools/builder/builder/objdiff.go index 23967455..ea9ecae5 100644 --- a/tools/builder/builder/objdiff.go +++ b/tools/builder/builder/objdiff.go @@ -113,6 +113,7 @@ var metaOverlays = map[string]metaOverlay{ "lv5deth": {"lv5deth", "magic", "LV.5 Death"}, "choco0": {"choco0", "magic", "choco0"}, "sennkoku": {"sennkoku", "magic", "Death Sentence / Roulette"}, + "hadoho": {"hadoho", "magic", "HADOHO"}, } func makeObjdiffConfig(b BuildConfig) objdiffConfig { From b9e4c098b8575d31a7e1e553a26c7a38c57b4ac4 Mon Sep 17 00:00:00 2001 From: j3lee Date: Mon, 12 Oct 2026 12:07:32 +0930 Subject: [PATCH 2/6] shaku: import and decompile the overlay --- CMakeLists.txt | 1 + config/symbols.magic-shaku.us.txt | 19 + config/us.yaml | 13 + src/magic/shaku.c | 576 ++++++++++++++++++++++++++++++ src/magic/shaku.h | 6 + tools/builder/builder/objdiff.go | 1 + 6 files changed, 616 insertions(+) create mode 100644 config/symbols.magic-shaku.us.txt create mode 100644 src/magic/shaku.c create mode 100644 src/magic/shaku.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e9106bb..e39f0100 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,7 @@ set(FF7_MAGIC src/magic/lv5deth.c src/magic/mabaria.c src/magic/sennkoku.c + src/magic/shaku.c src/magic/thunder.c ) diff --git a/config/symbols.magic-shaku.us.txt b/config/symbols.magic-shaku.us.txt new file mode 100644 index 00000000..90894c37 --- /dev/null +++ b/config/symbols.magic-shaku.us.txt @@ -0,0 +1,19 @@ +func_801B0000 = 0x801B0000; +func_801B0020 = 0x801B0020; +func_801B01CC = 0x801B01CC; +func_801B02FC = 0x801B02FC; +ShakuDoubleBufferFlip = 0x801B045C; +func_801B04C8 = 0x801B04C8; +func_801B05A8 = 0x801B05A8; +func_801B0664 = 0x801B0664; +func_801B0880 = 0x801B0880; +func_801B09E0 = 0x801B09E0; +func_801B0B3C = 0x801B0B3C; +func_801B0CC0 = 0x801B0CC0; +func_801B0DAC = 0x801B0DAC; +func_801B0EAC = 0x801B0EAC; +func_801B10A0 = 0x801B10A0; +func_801B1590 = 0x801B1590; +func_801B1970 = 0x801B1970; +g_ShakuPrimBuffer = 0x801D5768; +g_ShakuBufferPtr = 0x801ED768; diff --git a/config/us.yaml b/config/us.yaml index 858466a0..15d80148 100644 --- a/config/us.yaml +++ b/config/us.yaml @@ -820,3 +820,16 @@ overlays: - [0, c, hadoho] - [0x1B40, data, hadoho_model] - [0x25648, data, hadoho_buffers] + # SHAKU.BIN -- effect overlay + - name: shaku + disk_path: disks/us/MAGIC/SHAKU.BIN + sha1: fe2958f8b1b2ac815ba968c1e9979e88daa943c2 + base_path: magic + imports: [main, battle] + vram_start: 0x801B0000 + symbol_addrs_path: + - config/symbols.magic-shaku.us.txt + segments: + - [0, c, shaku] + - [0x1B38, data, shaku_model] + - [0x25768, data, shaku_buffers] diff --git a/src/magic/shaku.c b/src/magic/shaku.c new file mode 100644 index 00000000..9241d4f7 --- /dev/null +++ b/src/magic/shaku.c @@ -0,0 +1,576 @@ +//! PSYQ=3.3 CC1=2.6.3 + +#include "common.h" +#include "magic.h" +#include "shaku.h" +#include "../battle/battle.h" + +u_long* func_800C4FC8(); + +// Effect SHAKU. + +void func_801B1970(s32 targetMask, s32 callbackArg); + +// Primitive buffer pages, one 0xC000 page per double-buffered frame. +extern u8 g_ShakuPrimBuffer[2][0xC000]; +extern void* g_ShakuBufferPtr; + +// Only StartFrame/AnimationFrame are common to every magic overlay; the +// rest is payload this effect lays out for itself. +typedef struct { + /* 0x00 */ s16 StartFrame; + /* 0x02 */ s16 AnimationFrame; + /* 0x04 */ SVECTOR Pos; + /* 0x0C */ SVECTOR PartPos; + /* 0x14 */ s16 unk14; + /* 0x16 */ s16 unk16; + /* 0x18 */ s16 unk18; + /* 0x1A */ s16 unk1A; + /* 0x1C */ s16 unk1C; + /* 0x1E */ s16 unk1E; +} ShakuData; // size:0x20 + +extern MATRIX D_801D573C; +extern ModelRenderDesc D_801D567C; +extern ModelRenderDesc D_801D56A4; +extern ModelRenderDesc D_801D56BC; +extern ModelRenderDesc D_801D56E8; +extern ModelRenderDesc D_801D5714; +extern SVECTOR D_801D569C; +extern SVECTOR D_801D56B4; +extern SVECTOR D_801D56F8; +extern SVECTOR D_801D5730; +extern SVECTOR D_801D5760; +extern SpriteRenderDesc D_801D5654; +extern SpriteRenderDesc D_801D5660; +extern SpriteRenderDesc D_801D56CC; +extern SpriteRenderDesc D_801D56D8; +extern SpriteRenderDesc D_801D5724; +extern VECTOR D_801D566C; +extern VECTOR D_801D5704; +extern ShakuData g_BattleEffectSlots[]; +extern ShakuData g_BattleDetachedSlots[]; +extern s16 g_BattleDetachedCursor; +extern s16 D_801D5650; +extern s16 D_801D56E4; +extern s16 D_801D5700; +extern s16 D_801D5738; +extern s16 D_801D575C; +extern s32 D_801D5294; +extern s32 D_801D54CC; +extern s32 D_801D1C38[]; +extern s32 D_801D223C[]; +extern s32 D_801D2840[]; +extern s32 D_801D37E4[]; +extern s32 D_801D4788[]; +extern s32* D_801D568C[]; +extern u16 D_801031EA; +extern u8 D_800F5B70; +extern u8 D_800F5B71; +extern u8 D_800F5B72; +extern u_long D_801B1B38[]; +extern void* D_80163C74; +s32 BattleDetachedRegister(void (*func)(void)); +void func_800BBA84(u16 arg0, s32 arg1, s32 arg2); +void func_801B04C8(void); +void func_801B0664(void); +void func_801B0880(void); +void func_801B0B3C(void); +void func_801B10A0(void); +void func_801B1590(void); + +// Same as MAGIC_Biora. +void func_801B0000(s32 targetMask, s32 callbackArg) { func_801B1970(targetMask, callbackArg); } + +void func_801B0020(s16 targetMask, SVECTOR* out) { + VECTOR sum; + SVECTOR pos; + s16 i; + s16 count; + + count = 0; + sum.vx = sum.vy = sum.vz = 0; + for (i = 0; i < 10; i++) { + if ((targetMask >> i) & 1) { + BattleGetPartPosition(i, g_BattleModels[i].boneIndices[0], &pos); + count++; + sum.vx += pos.vx; + sum.vy += pos.vy; + sum.vz += pos.vz; + } + } + out->vx = sum.vx / count; + out->vy = sum.vy / count; + out->vz = sum.vz / count; +} + +void func_801B01CC(s32 offset, s16 spread, SVECTOR* out) { + SVECTOR in; + SVECTOR rot; + MATRIX matrix; + + in.vz = 0; + in.vx = 0; + in.vy = offset + (rand() % spread * 2 - spread); + rot.vy = 0; + rot.vx = rand() % 800 - 400; + rot.vz = rand() % 800 - 400; + RotMatrix(&rot, &matrix); + ApplyMatrixSV(&matrix, &in, out); +} + +void func_801B02FC(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) { + MATRIX matrix; + MATRIX rotated; + VECTOR dir; + s32 flag; + s16 i; + + for (i = 0; i < 3; i++) { + matrix.m[2][i] = 0; + matrix.m[1][i] = 0; + matrix.m[0][i] = 0; + } + SetRotMatrix(&g_BattleWorldView.m); + SetTransMatrix(&g_BattleWorldView.m); + RotTrans(pos, (VECTOR*)matrix.t, &flag); + if (offset != 0) { + VectorNormal((VECTOR*)matrix.t, &dir); + matrix.t[0] += offset * dir.vx >> 12; + matrix.t[1] += offset * dir.vy >> 12; + matrix.t[2] += offset * dir.vz >> 12; + } + matrix.m[0][0] = matrix.m[1][1] = matrix.m[2][2] = scale; + RotMatrixYXZ(rot, &rotated); + MulMatrix(&matrix, &rotated); + SetRotMatrix(&matrix); + SetTransMatrix(&matrix); +} + +// Same as BioraDoubleBufferFlip. +static void ShakuDoubleBufferFlip(void) { + ShakuData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + g_ShakuBufferPtr = g_ShakuPrimBuffer[effect->AnimationFrame]; + effect->AnimationFrame ^= 1; + if (g_BattleEffectCount < 2) { + effect->StartFrame = -1; + } +} + +void func_801B04C8(void) { + ShakuData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + D_80163C74 = func_800C4FC8(D_801D5650, 0, 0); + if (D_80062D98 == 0) { + if (effect->AnimationFrame < 16) { + D_801D5650 += 15; + } + if (effect->AnimationFrame >= 35) { + D_801D5650 -= 15; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 50) { + effect->StartFrame = -1; + } + } +} + +void func_801B05A8(void) { + ShakuData* effect; + + effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; + BattleSetBillboardMatrix(&effect->Pos, 0x2800, 0); + D_801D5654.frameIndex = effect->AnimationFrame; + D_80163C74 = func_800D4D90(&D_801D5654, (u_long**)&g_cDb->unk70, 12, D_80163C74); + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame >= D_801D5294) { + effect->StartFrame = -1; + } + } +} + +void func_801B0664(void) { + MATRIX rotated; + MATRIX matrix; + SVECTOR rot; + s32 flag; + ShakuData* effect; + s16 fade; + s16 i; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + for (i = 0; i < 3; i++) { + matrix.m[2][i] = 0; + matrix.m[1][i] = 0; + matrix.m[0][i] = 0; + } + fade = 8; + if (effect->AnimationFrame >= 12) { + fade = 20 - effect->AnimationFrame; + } + rot.vy = 0; + rot.vx = 0; + rot.vz = effect->unk14; + SetRotMatrix(&g_BattleWorldView.m); + SetTransMatrix(&g_BattleWorldView.m); + RotTrans(&effect->Pos, (VECTOR*)matrix.t, &flag); + matrix.m[0][0] = matrix.m[1][1] = matrix.m[2][2] = 0x2000; + RotMatrixYXZ(&rot, &rotated); + MulMatrix(&matrix, &rotated); + SetRotMatrix(&matrix); + SetTransMatrix(&matrix); + D_801D5660.frameIndex = effect->unk16; + D_801D5660.color.cd = fade == 8 ? 0x2C : 0x2E; + D_801D5660.color.r = D_801D5660.color.g = D_801D5660.color.b = fade << 4; + D_80163C74 = func_800D4D90(&D_801D5660, (u_long**)&g_cDb->unk70, 12, D_80163C74); + if (D_80062D98 == 0) { + effect->Pos.vx += effect->PartPos.vx; + effect->Pos.vy += effect->PartPos.vy; + effect->Pos.vz += effect->PartPos.vz; + if (effect->Pos.vy > 0) { + effect->Pos.vy = 0; + effect->PartPos.vy *= -1; + } + effect->PartPos.vy += 0x14; + effect->unk14 += 0x200; + effect->AnimationFrame++; + if (effect->AnimationFrame == 0x14) { + effect->StartFrame = -1; + } + } +} + +void func_801B0880(void) { + MATRIX matrix; + MATRIX composed; + SVECTOR rot; + ShakuData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + rot.vy = 0; + rot.vx = 0; + rot.vz = effect->unk14; + RotMatrix(&rot, &matrix); + ScaleMatrix(&matrix, &D_801D566C); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + D_801D567C.color = 0x80 - effect->AnimationFrame * 6; + D_801D567C.model = D_801D568C[effect->unk16]; + g_ShakuBufferPtr = func_800D29D4(&D_801D567C, g_cDb->unk70, 12, g_ShakuBufferPtr); + if (D_80062D98 == 0) { + effect->Pos.vy -= 200; + effect->unk14 += 0x100; + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B09E0(void) { + MATRIX matrix; + MATRIX composed; + VECTOR scale; + ShakuData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + RotMatrixYXZ(&D_801D569C, &matrix); + MulMatrix0(&D_801D573C, &matrix, &matrix); + scale.vx = scale.vy = scale.vz = effect->AnimationFrame * 1500; + ScaleMatrix(&matrix, &scale); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + SetFarColor(0, 0, 0); + D_801D56A4.color = effect->AnimationFrame * 256; + g_ShakuBufferPtr = func_800D29D4(&D_801D56A4, g_cDb->unk70, 12, g_ShakuBufferPtr); + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B0B3C(void) { + MATRIX matrix; + MATRIX composed; + VECTOR scale; + ShakuData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + if (effect->AnimationFrame >= 3) { + RotMatrixYXZ(&D_801D56B4, &matrix); + MulMatrix0(&D_801D573C, &matrix, &matrix); + scale.vx = scale.vy = scale.vz = 0x4000 - effect->AnimationFrame * 400; + ScaleMatrix(&matrix, &scale); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + SetFarColor(0, 0, 0); + D_801D56BC.color = effect->AnimationFrame * 200; + g_ShakuBufferPtr = func_800D29D4(&D_801D56BC, g_cDb->unk70, 12, g_ShakuBufferPtr); + } + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B0CC0(void) { + ShakuData* effect; + + effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; + BattleSetBillboardMatrix(&effect->Pos, 0x4000, 0); + D_801D56CC.frameIndex = effect->AnimationFrame; + D_80163C74 = func_800D4D90(&D_801D56CC, (u_long**)&g_cDb->unk70, 12, D_80163C74); + if (D_80062D98 == 0) { + effect->Pos.vx += effect->PartPos.vx; + effect->Pos.vy += effect->PartPos.vy; + effect->Pos.vz += effect->PartPos.vz; + effect->AnimationFrame++; + if (effect->AnimationFrame >= D_801D54CC) { + effect->StartFrame = -1; + } + } +} + +void func_801B0DAC(void) { + ShakuData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + BattleSetBillboardMatrix(&effect->Pos, (s16)(0x1000 + ((rsin(effect->AnimationFrame * 51) << 11) >> 16 << 7)), 0); + D_801D56D8.frameIndex = effect->AnimationFrame % 2; + g_ShakuBufferPtr = func_800D4D90(&D_801D56D8, (u_long**)&g_cDb->unk70, 12, g_ShakuBufferPtr); + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame == 40) { + effect->StartFrame = -1; + } + } +} + +void func_801B0EAC(void) { + MATRIX matrix; + MATRIX composed; + VECTOR scale; + ShakuData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + RotMatrixYXZ(&D_801D56F8, &matrix); + MulMatrix0(&D_801D573C, &matrix, &matrix); + scale.vx = scale.vz = 0x4000 - effect->AnimationFrame * 300; + scale.vy = effect->AnimationFrame * 900; + ScaleMatrix(&matrix, &scale); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + SetFarColor(0, 0, 0); + D_801D56E8.color = 0x1000 - D_801D56E4 * 256; + D_801D56E8.model = D_801D1C38; + g_ShakuBufferPtr = func_800D29D4(&D_801D56E8, g_cDb->unk70, 12, g_ShakuBufferPtr); + D_801D56E8.model = D_801D223C; + g_ShakuBufferPtr = func_800D29D4(&D_801D56E8, g_cDb->unk70, 12, g_ShakuBufferPtr); + if (D_80062D98 == 0) { + if (effect->AnimationFrame >= 13) { + D_801D56E4 -= 1; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B10A0(void) { + MATRIX matrix; + MATRIX composed; + ShakuData* effect; + ShakuData* child; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + RotMatrixYXZ(&D_801D5730, &matrix); + MulMatrix0(&D_801D573C, &matrix, &matrix); + ScaleMatrix(&matrix, &D_801D5704); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + D_801D5714.color = (u16)D_801D5700 * 16; + D_801D5714.model = D_801D2840; + g_ShakuBufferPtr = func_800D29D4(&D_801D5714, g_cDb->unk70, 12, g_ShakuBufferPtr); + D_801D5714.model = D_801D37E4; + g_ShakuBufferPtr = func_800D29D4(&D_801D5714, g_cDb->unk70, 12, g_ShakuBufferPtr); + D_801D5714.model = D_801D4788; + g_ShakuBufferPtr = func_800D29D4(&D_801D5714, g_cDb->unk70, 12, g_ShakuBufferPtr); + BattleSetBillboardMatrix(&effect->Pos, 0x4000, 0); + D_801D5724.color.r = D_801D5724.color.g = D_801D5724.color.b = D_801D5700 * 20; + D_801D5724.frameIndex = effect->AnimationFrame % 2; + g_ShakuBufferPtr = func_800D4D90(&D_801D5724, (u_long**)&g_cDb->unk70, 12, g_ShakuBufferPtr); + if (D_80062D98 == 0) { + effect->Pos.vx += effect->PartPos.vx; + effect->Pos.vy += effect->PartPos.vy; + effect->Pos.vz += effect->PartPos.vz; + if ((effect->AnimationFrame & 1) == 0) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0B3C)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + } + if (effect->Pos.vy < 0) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0664)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vz = effect->Pos.vz; + child->Pos.vy = 0; + D_801D5738 = rand() % 4096; + child->PartPos.vx = (u32)(rcos(D_801D5738) * 15) >> 9; + child->PartPos.vz = (u32)(rsin(D_801D5738) * 15) >> 9; + child->PartPos.vy = -rand() % 300 - 50; + child->unk16 = rand() % 7; + if (effect->AnimationFrame % 3 == 0) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0880)]; + child->Pos.vx = effect->Pos.vx + rand() % 4000 - 2000; + child->Pos.vz = effect->Pos.vz + rand() % 4000 - 2000; + child->Pos.vy = 0; + child->unk16 = rand() % 4; + } + } + if (effect->AnimationFrame >= 13) { + D_801D5700 -= 1; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B1590(void) { + SVECTOR in; + SVECTOR rot; + MATRIX matrix; + s32 flag; + ShakuData* effect; + ShakuData* child; + s16 i; + u16* u16p; + u16 t; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + if (D_80062D98 == 0) { + if (effect->AnimationFrame == 0) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B09E0)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0DAC)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + func_800BBA84(0x174, effect->unk1E, 0x40); + } + if (effect->AnimationFrame == 20) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0EAC)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B10A0)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + child->PartPos.vx = effect->PartPos.vx; + child->PartPos.vy = effect->PartPos.vy; + child->PartPos.vz = effect->PartPos.vz; + func_800BBA84(0x176, effect->unk1E, 0x40); + } + if (effect->AnimationFrame == 20) { + BattleEffectRegister(func_801B04C8); + } + if (effect->AnimationFrame == 54) { + BattleFixedPointRampUpdateInit(0, 16); + } + if (effect->AnimationFrame >= 37 && effect->AnimationFrame < 44) { + for (i = 0; i < 10; i++) { + if ((D_801D575C >> i) & 1) { + child = &g_BattleDetachedSlots[BattleDetachedRegister(func_801B0CC0)]; + BattleGetPartPosition(i, g_BattleModels[i].boneIndices[0], &child->Pos); + in.vy = 0x50; + in.vz = 0; + in.vx = 0; + rot.vx = rand() % 4096; + rot.vz = rand() % 4096; + rot.vy = 0; + RotMatrixYXZ(&rot, &matrix); + matrix.t[2] = 0; + matrix.t[1] = 0; + matrix.t[0] = 0; + SetRotMatrix(&matrix); + SetTransMatrix(&matrix); + RotTransSV(&in, &child->PartPos, &flag); + } + } + } + if (effect->AnimationFrame == 40) { + for (i = 0; i < 10; i++) { + if ((D_801D575C >> i) & 1) { + func_800D5774(i); + } + } + func_800BBA84(0xFA, -1, 0x40); + } + if (effect->AnimationFrame >= 21) { + u16p = &D_801031EA; + t = *u16p + 0x10; + *u16p = t - (effect->AnimationFrame % 2) * 32; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 70) { + effect->StartFrame = -1; + } + } +} + +void func_801B1970(s32 targetMask, s32 callbackArg) { + VECTOR vec; + SVECTOR dir; + ShakuData* effect; + + BattleEffectRegister(ShakuDoubleBufferFlip); + D_801D575C = targetMask; + effect = &g_BattleEffectSlots[BattleEffectRegister(func_801B1590)]; + BattleGetPartPosition(callbackArg, g_BattleModels[callbackArg].boneIndices[8], &effect->Pos); + func_801B0020(targetMask, &D_801D5760); + vec.vx = dir.vx = D_801D5760.vx - effect->Pos.vx; + vec.vy = dir.vy = D_801D5760.vy - effect->Pos.vy; + vec.vz = dir.vz = D_801D5760.vz - effect->Pos.vz; + BattleMatrixFromDirection(&dir, &D_801D573C); + VectorNormal(&vec, &vec); + effect->PartPos.vx = (u32)(vec.vx * 75) >> 9; + effect->PartPos.vy = (u32)(vec.vy * 75) >> 9; + effect->PartPos.vz = (u32)(vec.vz * 75) >> 9; + effect->unk1E = callbackArg; + BattleSetLoadTimToVram(D_801B1B38, 0, 0, 0); + D_800F5B70 = D_800F5B71 = D_800F5B72 = 0; + BattleFixedPointRampUpdateInit(0x1000, 0x10); +} diff --git a/src/magic/shaku.h b/src/magic/shaku.h new file mode 100644 index 00000000..9992fee7 --- /dev/null +++ b/src/magic/shaku.h @@ -0,0 +1,6 @@ +#ifndef SHAKU_H +#define SHAKU_H + +#include "magic.h" + +#endif diff --git a/tools/builder/builder/objdiff.go b/tools/builder/builder/objdiff.go index ea9ecae5..e41def58 100644 --- a/tools/builder/builder/objdiff.go +++ b/tools/builder/builder/objdiff.go @@ -114,6 +114,7 @@ var metaOverlays = map[string]metaOverlay{ "choco0": {"choco0", "magic", "choco0"}, "sennkoku": {"sennkoku", "magic", "Death Sentence / Roulette"}, "hadoho": {"hadoho", "magic", "HADOHO"}, + "shaku": {"shaku", "magic", "SHAKU"}, } func makeObjdiffConfig(b BuildConfig) objdiffConfig { From cf1ac4539bc1a8d9eaf68113d003e0805e9e0756 Mon Sep 17 00:00:00 2001 From: j3lee Date: Mon, 12 Oct 2026 12:07:36 +0930 Subject: [PATCH 3/6] re_do: import and decompile the overlay --- CMakeLists.txt | 1 + config/symbols.magic-re_do.us.txt | 19 + config/us.yaml | 13 + src/magic/re_do.c | 576 ++++++++++++++++++++++++++++++ src/magic/re_do.h | 6 + tools/builder/builder/objdiff.go | 1 + 6 files changed, 616 insertions(+) create mode 100644 config/symbols.magic-re_do.us.txt create mode 100644 src/magic/re_do.c create mode 100644 src/magic/re_do.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e39f0100..9f401eb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,7 @@ set(FF7_MAGIC src/magic/hadoho.c src/magic/lv5deth.c src/magic/mabaria.c + src/magic/re_do.c src/magic/sennkoku.c src/magic/shaku.c src/magic/thunder.c diff --git a/config/symbols.magic-re_do.us.txt b/config/symbols.magic-re_do.us.txt new file mode 100644 index 00000000..9d46e56c --- /dev/null +++ b/config/symbols.magic-re_do.us.txt @@ -0,0 +1,19 @@ +func_801B0000 = 0x801B0000; +func_801B0020 = 0x801B0020; +func_801B01CC = 0x801B01CC; +func_801B02FC = 0x801B02FC; +ReDoDoubleBufferFlip = 0x801B045C; +func_801B04C8 = 0x801B04C8; +func_801B05A8 = 0x801B05A8; +func_801B0664 = 0x801B0664; +func_801B0880 = 0x801B0880; +func_801B09E0 = 0x801B09E0; +func_801B0B3C = 0x801B0B3C; +func_801B0CC0 = 0x801B0CC0; +func_801B0DAC = 0x801B0DAC; +func_801B0EAC = 0x801B0EAC; +func_801B10A0 = 0x801B10A0; +func_801B1590 = 0x801B1590; +func_801B1A54 = 0x801B1A54; +g_ReDoPrimBuffer = 0x801D5738; +g_ReDoBufferPtr = 0x801ED738; diff --git a/config/us.yaml b/config/us.yaml index 15d80148..11180dfb 100644 --- a/config/us.yaml +++ b/config/us.yaml @@ -833,3 +833,16 @@ overlays: - [0, c, shaku] - [0x1B38, data, shaku_model] - [0x25768, data, shaku_buffers] + # RE_DO.BIN -- effect overlay + - name: re_do + disk_path: disks/us/MAGIC/RE_DO.BIN + sha1: f27b56b6b0666873bb632a35d345ecbf6b15b52f + base_path: magic + imports: [main, battle] + vram_start: 0x801B0000 + symbol_addrs_path: + - config/symbols.magic-re_do.us.txt + segments: + - [0, c, re_do] + - [0x1B08, data, re_do_model] + - [0x25738, data, re_do_buffers] diff --git a/src/magic/re_do.c b/src/magic/re_do.c new file mode 100644 index 00000000..c46dfa2e --- /dev/null +++ b/src/magic/re_do.c @@ -0,0 +1,576 @@ +//! PSYQ=3.3 CC1=2.6.3 + +#include "common.h" +#include "magic.h" +#include "re_do.h" +#include "../battle/battle.h" + +u_long* func_800C4FC8(); + +// Effect RE_DO. + +void func_801B1A54(s32 targetMask, s32 callbackArg); + +// Primitive buffer pages, one 0xC000 page per double-buffered frame. +extern u8 g_ReDoPrimBuffer[2][0xC000]; +extern void* g_ReDoBufferPtr; + +// Only StartFrame/AnimationFrame are common to every magic overlay; the +// rest is payload this effect lays out for itself. +typedef struct { + /* 0x00 */ s16 StartFrame; + /* 0x02 */ s16 AnimationFrame; + /* 0x04 */ SVECTOR Pos; + /* 0x0C */ SVECTOR PartPos; + /* 0x14 */ s16 unk14; + /* 0x16 */ s16 unk16; + /* 0x18 */ s16 unk18; + /* 0x1A */ s16 unk1A; + /* 0x1C */ s16 unk1C; + /* 0x1E */ s16 unk1E; +} ReDoData; // size:0x20 + +extern MATRIX D_801D570C; +extern ModelRenderDesc D_801D564C; +extern ModelRenderDesc D_801D5674; +extern ModelRenderDesc D_801D568C; +extern ModelRenderDesc D_801D56B8; +extern ModelRenderDesc D_801D56E4; +extern ReDoData g_BattleEffectSlots[]; +extern ReDoData g_BattleDetachedSlots[]; +extern SVECTOR D_801D566C; +extern SVECTOR D_801D5684; +extern SVECTOR D_801D56C8; +extern SVECTOR D_801D5700; +extern SVECTOR D_801D5730; +extern SpriteRenderDesc D_801D5624; +extern SpriteRenderDesc D_801D5630; +extern SpriteRenderDesc D_801D569C; +extern SpriteRenderDesc D_801D56A8; +extern SpriteRenderDesc D_801D56F4; +extern VECTOR D_801D563C; +extern VECTOR D_801D56D4; +extern s16 g_BattleDetachedCursor; +extern s16 D_801D5620; +extern s16 D_801D56B4; +extern s16 D_801D56D0; +extern s16 D_801D5708; +extern s16 D_801D572C; +extern s32 D_801D5264; +extern s32 D_801D549C; +extern s32 D_801D1C08[]; +extern s32 D_801D220C[]; +extern s32 D_801D2810[]; +extern s32 D_801D37B4[]; +extern s32 D_801D4758[]; +extern s32* D_801D565C[]; +extern u16 D_801031EA; +extern u8 D_800F5B70; +extern u8 D_800F5B71; +extern u8 D_800F5B72; +extern u_long D_801B1B08[]; +extern u_long D_801B1B38[]; +extern void* D_80163C74; +s32 BattleDetachedRegister(void (*func)(void)); +void func_800BBA84(u16 arg0, s32 arg1, s32 arg2); +void func_801B04C8(void); +void func_801B0664(void); +void func_801B0880(void); +void func_801B0B3C(void); +void func_801B10A0(void); +void func_801B1590(void); + +// Same as MAGIC_Biora. +void func_801B0000(s32 targetMask, s32 callbackArg) { func_801B1A54(targetMask, callbackArg); } + +void func_801B0020(s16 targetMask, SVECTOR* out) { + VECTOR sum; + SVECTOR pos; + s16 i; + s16 count; + + count = 0; + sum.vx = sum.vy = sum.vz = 0; + for (i = 0; i < 10; i++) { + if ((targetMask >> i) & 1) { + BattleGetPartPosition(i, g_BattleModels[i].boneIndices[0], &pos); + count++; + sum.vx += pos.vx; + sum.vy += pos.vy; + sum.vz += pos.vz; + } + } + out->vx = sum.vx / count; + out->vy = sum.vy / count; + out->vz = sum.vz / count; +} + +void func_801B01CC(s32 offset, s16 spread, SVECTOR* out) { + SVECTOR in; + SVECTOR rot; + MATRIX matrix; + + in.vz = 0; + in.vx = 0; + in.vy = offset + (rand() % spread * 2 - spread); + rot.vy = 0; + rot.vx = rand() % 800 - 400; + rot.vz = rand() % 800 - 400; + RotMatrix(&rot, &matrix); + ApplyMatrixSV(&matrix, &in, out); +} + +void func_801B02FC(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) { + MATRIX matrix; + MATRIX rotated; + VECTOR dir; + s32 flag; + s16 i; + + for (i = 0; i < 3; i++) { + matrix.m[2][i] = 0; + matrix.m[1][i] = 0; + matrix.m[0][i] = 0; + } + SetRotMatrix(&g_BattleWorldView.m); + SetTransMatrix(&g_BattleWorldView.m); + RotTrans(pos, (VECTOR*)matrix.t, &flag); + if (offset != 0) { + VectorNormal((VECTOR*)matrix.t, &dir); + matrix.t[0] += offset * dir.vx >> 12; + matrix.t[1] += offset * dir.vy >> 12; + matrix.t[2] += offset * dir.vz >> 12; + } + matrix.m[0][0] = matrix.m[1][1] = matrix.m[2][2] = scale; + RotMatrixYXZ(rot, &rotated); + MulMatrix(&matrix, &rotated); + SetRotMatrix(&matrix); + SetTransMatrix(&matrix); +} + +// Same as BioraDoubleBufferFlip. +static void ReDoDoubleBufferFlip(void) { + ReDoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + g_ReDoBufferPtr = g_ReDoPrimBuffer[effect->AnimationFrame]; + effect->AnimationFrame ^= 1; + if (g_BattleEffectCount < 2) { + effect->StartFrame = -1; + } +} + +void func_801B04C8(void) { + ReDoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + D_80163C74 = func_800C4FC8(0, 0, D_801D5620); + if (D_80062D98 == 0) { + if (effect->AnimationFrame < 16) { + D_801D5620 += 15; + } + if (effect->AnimationFrame >= 35) { + D_801D5620 -= 15; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 50) { + effect->StartFrame = -1; + } + } +} + +void func_801B05A8(void) { + ReDoData* effect; + + effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; + BattleSetBillboardMatrix(&effect->Pos, 0x2800, 0); + D_801D5624.frameIndex = effect->AnimationFrame; + D_80163C74 = func_800D4D90(&D_801D5624, (u_long**)&g_cDb->unk70, 12, D_80163C74); + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame >= D_801D5264) { + effect->StartFrame = -1; + } + } +} + +void func_801B0664(void) { + MATRIX rotated; + MATRIX matrix; + SVECTOR rot; + s32 flag; + ReDoData* effect; + s16 fade; + s16 i; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + for (i = 0; i < 3; i++) { + matrix.m[2][i] = 0; + matrix.m[1][i] = 0; + matrix.m[0][i] = 0; + } + fade = 8; + if (effect->AnimationFrame >= 12) { + fade = 20 - effect->AnimationFrame; + } + rot.vy = 0; + rot.vx = 0; + rot.vz = effect->unk14; + SetRotMatrix(&g_BattleWorldView.m); + SetTransMatrix(&g_BattleWorldView.m); + RotTrans(&effect->Pos, (VECTOR*)matrix.t, &flag); + matrix.m[0][0] = matrix.m[1][1] = matrix.m[2][2] = 0x2000; + RotMatrixYXZ(&rot, &rotated); + MulMatrix(&matrix, &rotated); + SetRotMatrix(&matrix); + SetTransMatrix(&matrix); + D_801D5630.frameIndex = effect->unk16; + D_801D5630.color.cd = fade == 8 ? 0x2C : 0x2E; + D_801D5630.color.r = D_801D5630.color.g = D_801D5630.color.b = fade << 4; + D_80163C74 = func_800D4D90(&D_801D5630, (u_long**)&g_cDb->unk70, 12, D_80163C74); + if (D_80062D98 == 0) { + effect->Pos.vx += effect->PartPos.vx; + effect->Pos.vy += effect->PartPos.vy; + effect->Pos.vz += effect->PartPos.vz; + if (effect->Pos.vy > 0) { + effect->Pos.vy = 0; + effect->PartPos.vy *= -1; + } + effect->PartPos.vy += 0x14; + effect->unk14 += 0x200; + effect->AnimationFrame++; + if (effect->AnimationFrame == 0x14) { + effect->StartFrame = -1; + } + } +} + +void func_801B0880(void) { + MATRIX matrix; + MATRIX composed; + SVECTOR rot; + ReDoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + rot.vy = 0; + rot.vx = 0; + rot.vz = effect->unk14; + RotMatrix(&rot, &matrix); + ScaleMatrix(&matrix, &D_801D563C); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + D_801D564C.color = 0x80 - effect->AnimationFrame * 6; + D_801D564C.model = D_801D565C[effect->unk16]; + g_ReDoBufferPtr = func_800D29D4(&D_801D564C, g_cDb->unk70, 12, g_ReDoBufferPtr); + if (D_80062D98 == 0) { + effect->Pos.vy -= 200; + effect->unk14 += 0x100; + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B09E0(void) { + MATRIX matrix; + MATRIX composed; + VECTOR scale; + ReDoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + RotMatrixYXZ(&D_801D566C, &matrix); + MulMatrix0(&D_801D570C, &matrix, &matrix); + scale.vx = scale.vy = scale.vz = effect->AnimationFrame * 1500; + ScaleMatrix(&matrix, &scale); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + SetFarColor(0, 0, 0); + D_801D5674.color = effect->AnimationFrame * 256; + g_ReDoBufferPtr = func_800D29D4(&D_801D5674, g_cDb->unk70, 12, g_ReDoBufferPtr); + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B0B3C(void) { + MATRIX matrix; + MATRIX composed; + VECTOR scale; + ReDoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + if (effect->AnimationFrame >= 3) { + RotMatrixYXZ(&D_801D5684, &matrix); + MulMatrix0(&D_801D570C, &matrix, &matrix); + scale.vx = scale.vy = scale.vz = 0x4000 - effect->AnimationFrame * 400; + ScaleMatrix(&matrix, &scale); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + SetFarColor(0, 0, 0); + D_801D568C.color = effect->AnimationFrame * 200; + g_ReDoBufferPtr = func_800D29D4(&D_801D568C, g_cDb->unk70, 12, g_ReDoBufferPtr); + } + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B0CC0(void) { + ReDoData* effect; + + effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; + BattleSetBillboardMatrix(&effect->Pos, 0x4000, 0); + D_801D569C.frameIndex = effect->AnimationFrame; + D_80163C74 = func_800D4D90(&D_801D569C, (u_long**)&g_cDb->unk70, 12, D_80163C74); + if (D_80062D98 == 0) { + effect->Pos.vx += effect->PartPos.vx; + effect->Pos.vy += effect->PartPos.vy; + effect->Pos.vz += effect->PartPos.vz; + effect->AnimationFrame++; + if (effect->AnimationFrame >= D_801D549C) { + effect->StartFrame = -1; + } + } +} + +void func_801B0DAC(void) { + ReDoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + BattleSetBillboardMatrix( + &effect->Pos, (s16)(0x1000 + ((rsin(effect->AnimationFrame * 51) << 11) >> 16 << 7)), -500); + D_801D56A8.frameIndex = effect->AnimationFrame % 2; + g_ReDoBufferPtr = func_800D4D90(&D_801D56A8, (u_long**)&g_cDb->unk70, 12, g_ReDoBufferPtr); + if (D_80062D98 == 0) { + effect->AnimationFrame++; + if (effect->AnimationFrame == 40) { + effect->StartFrame = -1; + } + } +} + +void func_801B0EAC(void) { + MATRIX matrix; + MATRIX composed; + VECTOR scale; + ReDoData* effect; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + RotMatrixYXZ(&D_801D56C8, &matrix); + MulMatrix0(&D_801D570C, &matrix, &matrix); + scale.vx = scale.vz = 0x4000 - effect->AnimationFrame * 300; + scale.vy = effect->AnimationFrame * 900; + ScaleMatrix(&matrix, &scale); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + SetFarColor(0, 0, 0); + D_801D56B8.color = 0x1000 - D_801D56B4 * 256; + D_801D56B8.model = D_801D1C08; + g_ReDoBufferPtr = func_800D29D4(&D_801D56B8, g_cDb->unk70, 12, g_ReDoBufferPtr); + D_801D56B8.model = D_801D220C; + g_ReDoBufferPtr = func_800D29D4(&D_801D56B8, g_cDb->unk70, 12, g_ReDoBufferPtr); + if (D_80062D98 == 0) { + if (effect->AnimationFrame >= 13) { + D_801D56B4 -= 1; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B10A0(void) { + MATRIX matrix; + MATRIX composed; + ReDoData* effect; + ReDoData* child; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + RotMatrixYXZ(&D_801D5700, &matrix); + MulMatrix0(&D_801D570C, &matrix, &matrix); + ScaleMatrix(&matrix, &D_801D56D4); + matrix.t[0] = effect->Pos.vx; + matrix.t[1] = effect->Pos.vy; + matrix.t[2] = effect->Pos.vz; + CompMatrix(&g_BattleWorldView.m, &matrix, &composed); + SetRotMatrix(&composed); + SetTransMatrix(&composed); + D_801D56E4.color = (u16)D_801D56D0 * 16; + D_801D56E4.model = D_801D2810; + g_ReDoBufferPtr = func_800D29D4(&D_801D56E4, g_cDb->unk70, 12, g_ReDoBufferPtr); + D_801D56E4.model = D_801D37B4; + g_ReDoBufferPtr = func_800D29D4(&D_801D56E4, g_cDb->unk70, 12, g_ReDoBufferPtr); + D_801D56E4.model = D_801D4758; + g_ReDoBufferPtr = func_800D29D4(&D_801D56E4, g_cDb->unk70, 12, g_ReDoBufferPtr); + BattleSetBillboardMatrix(&effect->Pos, 0x4000, 0); + D_801D56F4.color.r = D_801D56F4.color.g = D_801D56F4.color.b = D_801D56D0 * 20; + D_801D56F4.frameIndex = effect->AnimationFrame % 2; + g_ReDoBufferPtr = func_800D4D90(&D_801D56F4, (u_long**)&g_cDb->unk70, 12, g_ReDoBufferPtr); + if (D_80062D98 == 0) { + effect->Pos.vx += effect->PartPos.vx; + effect->Pos.vy += effect->PartPos.vy; + effect->Pos.vz += effect->PartPos.vz; + if ((effect->AnimationFrame & 1) == 0) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0B3C)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + } + if (effect->Pos.vy < 0) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0664)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vz = effect->Pos.vz; + child->Pos.vy = 0; + D_801D5708 = rand() % 4096; + child->PartPos.vx = (u32)(rcos(D_801D5708) * 15) >> 9; + child->PartPos.vz = (u32)(rsin(D_801D5708) * 15) >> 9; + child->PartPos.vy = -rand() % 300 - 50; + child->unk16 = rand() % 7; + if (effect->AnimationFrame % 3 == 0) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0880)]; + child->Pos.vx = effect->Pos.vx + rand() % 4000 - 2000; + child->Pos.vz = effect->Pos.vz + rand() % 4000 - 2000; + child->Pos.vy = 0; + child->unk16 = rand() % 4; + } + } + if (effect->AnimationFrame >= 13) { + D_801D56D0 -= 1; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 20) { + effect->StartFrame = -1; + } + } +} + +void func_801B1590(void) { + SVECTOR in; + SVECTOR rot; + MATRIX matrix; + s32 flag; + ReDoData* effect; + ReDoData* child; + s16 i; + u16* u16p; + u16 t; + + effect = &g_BattleEffectSlots[g_BattleEffectCursor]; + if (D_80062D98 == 0) { + if (effect->AnimationFrame == 4) { + BattleGetPartPosition(effect->unk1E, g_BattleModels[effect->unk1E].boneIndices[8], &effect->Pos); + in.vx = D_801D5730.vx - effect->Pos.vx; + in.vy = D_801D5730.vy - effect->Pos.vy; + in.vz = D_801D5730.vz - effect->Pos.vz; + BattleMatrixFromDirection(&in, &D_801D570C); + VectorNormalSS(&in, &in); + effect->PartPos.vx = in.vx * 75 >> 9; + effect->PartPos.vy = in.vy * 75 >> 9; + effect->PartPos.vz = in.vz * 75 >> 9; + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B09E0)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0DAC)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + func_800BBA84(0x174, effect->unk1E, 0x40); + } + if (effect->AnimationFrame == 20) { + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0EAC)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + child = &g_BattleEffectSlots[BattleEffectRegister(func_801B10A0)]; + child->Pos.vx = effect->Pos.vx; + child->Pos.vy = effect->Pos.vy; + child->Pos.vz = effect->Pos.vz; + child->PartPos.vx = effect->PartPos.vx; + child->PartPos.vy = effect->PartPos.vy; + child->PartPos.vz = effect->PartPos.vz; + func_800BBA84(0x164, effect->unk1E, 0x40); + } + if (effect->AnimationFrame == 20) { + BattleEffectRegister(func_801B04C8); + } + if (effect->AnimationFrame == 54) { + BattleFixedPointRampUpdateInit(0, 16); + } + if (effect->AnimationFrame >= 37 && effect->AnimationFrame < 44) { + for (i = 0; i < 10; i++) { + if ((D_801D572C >> i) & 1) { + child = &g_BattleDetachedSlots[BattleDetachedRegister(func_801B0CC0)]; + BattleGetPartPosition(i, g_BattleModels[i].boneIndices[0], &child->Pos); + in.vy = 0x50; + in.vz = 0; + in.vx = 0; + rot.vx = rand() % 4096; + rot.vz = rand() % 4096; + rot.vy = 0; + RotMatrixYXZ(&rot, &matrix); + matrix.t[2] = 0; + matrix.t[1] = 0; + matrix.t[0] = 0; + SetRotMatrix(&matrix); + SetTransMatrix(&matrix); + RotTransSV(&in, &child->PartPos, &flag); + } + } + } + if (effect->AnimationFrame == 40) { + for (i = 0; i < 10; i++) { + if ((D_801D572C >> i) & 1) { + func_800D5774(i); + } + } + } + if (effect->AnimationFrame >= 21) { + u16p = &D_801031EA; + t = *u16p + 0x10; + *u16p = t - (effect->AnimationFrame % 2) * 32; + } + effect->AnimationFrame++; + if (effect->AnimationFrame == 70) { + effect->StartFrame = -1; + } + } +} + +void func_801B1A54(s32 targetMask, s32 callbackArg) { + // pad0 and pad1 are unused; they only reproduce the original 0x38 stack frame. + VECTOR pad0; + SVECTOR pad1; + + BattleEffectRegister(ReDoDoubleBufferFlip); + D_801D572C = targetMask; + g_BattleEffectSlots[BattleEffectRegister(func_801B1590)].unk1E = callbackArg; + func_801B0020(targetMask, &D_801D5730); + BattleSetLoadTimToVram(D_801B1B08, 0, 0, 0); + D_800F5B70 = D_800F5B71 = D_800F5B72 = 0; + BattleFixedPointRampUpdateInit(0x1000, 0x10); +} diff --git a/src/magic/re_do.h b/src/magic/re_do.h new file mode 100644 index 00000000..7a8f41f8 --- /dev/null +++ b/src/magic/re_do.h @@ -0,0 +1,6 @@ +#ifndef RE_DO_H +#define RE_DO_H + +#include "magic.h" + +#endif diff --git a/tools/builder/builder/objdiff.go b/tools/builder/builder/objdiff.go index e41def58..4fe76b03 100644 --- a/tools/builder/builder/objdiff.go +++ b/tools/builder/builder/objdiff.go @@ -115,6 +115,7 @@ var metaOverlays = map[string]metaOverlay{ "sennkoku": {"sennkoku", "magic", "Death Sentence / Roulette"}, "hadoho": {"hadoho", "magic", "HADOHO"}, "shaku": {"shaku", "magic", "SHAKU"}, + "re_do": {"re_do", "magic", "RE_DO"}, } func makeObjdiffConfig(b BuildConfig) objdiffConfig { From b563d184ee9dede7c36b9a9a381367b7890e739d Mon Sep 17 00:00:00 2001 From: j3lee Date: Mon, 12 Oct 2026 12:30:26 +0930 Subject: [PATCH 4/6] magic: name the effects in the file headers --- src/magic/hadoho.c | 3 ++- src/magic/re_do.c | 2 +- src/magic/shaku.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/magic/hadoho.c b/src/magic/hadoho.c index 283a725a..c6f368c9 100644 --- a/src/magic/hadoho.c +++ b/src/magic/hadoho.c @@ -7,7 +7,8 @@ u_long* func_800C4FC8(); -// Effect HADOHO. +// Dragon Cannon (怒龍砲 / Doryuho). +// The file name (波動砲, Wave Artillery) is the attack that uses SHAKU. void func_801B1978(s32 targetMask, s32 callbackArg); diff --git a/src/magic/re_do.c b/src/magic/re_do.c index c46dfa2e..e2b2e370 100644 --- a/src/magic/re_do.c +++ b/src/magic/re_do.c @@ -7,7 +7,7 @@ u_long* func_800C4FC8(); -// Effect RE_DO. +// Big Breath (大口ブレス / Oguchi Buresu). void func_801B1A54(s32 targetMask, s32 callbackArg); diff --git a/src/magic/shaku.c b/src/magic/shaku.c index 9241d4f7..5f4a6841 100644 --- a/src/magic/shaku.c +++ b/src/magic/shaku.c @@ -7,7 +7,7 @@ u_long* func_800C4FC8(); -// Effect SHAKU. +// Effect shared by Wave Artillery (波動砲) and Golem Laser (ゴーレムレーザー). void func_801B1970(s32 targetMask, s32 callbackArg); From f8ff8da1035d539df6928148c1333592e42cf8ec Mon Sep 17 00:00:00 2001 From: j3lee Date: Mon, 12 Oct 2026 12:34:23 +0930 Subject: [PATCH 5/6] magic: name the effect functions Names from the label walker's table (labels-quest/NAMES-bundles.tsv, sure rows only); renames only. --- config/symbols.magic-hadoho.us.txt | 32 +++++++------- config/symbols.magic-re_do.us.txt | 32 +++++++------- config/symbols.magic-shaku.us.txt | 32 +++++++------- src/magic/hadoho.c | 68 +++++++++++++++--------------- src/magic/re_do.c | 68 +++++++++++++++--------------- src/magic/shaku.c | 68 +++++++++++++++--------------- 6 files changed, 150 insertions(+), 150 deletions(-) diff --git a/config/symbols.magic-hadoho.us.txt b/config/symbols.magic-hadoho.us.txt index 5fc1ba73..28920089 100644 --- a/config/symbols.magic-hadoho.us.txt +++ b/config/symbols.magic-hadoho.us.txt @@ -1,19 +1,19 @@ -func_801B0000 = 0x801B0000; -func_801B0020 = 0x801B0020; -func_801B01CC = 0x801B01CC; -func_801B02FC = 0x801B02FC; +MAGIC_Hadoho = 0x801B0000; +HadohoTargetCenterCalc = 0x801B0020; +HadohoSprayVectorCalc = 0x801B01CC; +HadohoSpriteMatrixSetup = 0x801B02FC; HadohoDoubleBufferFlip = 0x801B045C; -func_801B04C8 = 0x801B04C8; -func_801B05B0 = 0x801B05B0; -func_801B066C = 0x801B066C; -func_801B0888 = 0x801B0888; -func_801B09E8 = 0x801B09E8; -func_801B0B44 = 0x801B0B44; -func_801B0CC8 = 0x801B0CC8; -func_801B0DB4 = 0x801B0DB4; -func_801B0EB4 = 0x801B0EB4; -func_801B10A8 = 0x801B10A8; -func_801B1598 = 0x801B1598; -func_801B1978 = 0x801B1978; +HadohoViewportFlashTick = 0x801B04C8; +HadohoSparkSpriteTick = 0x801B05B0; +HadohoEmberTick = 0x801B066C; +HadohoRisingModelTick = 0x801B0888; +HadohoGrowingModelTick = 0x801B09E8; +HadohoShrinkingModelTick = 0x801B0B44; +HadohoDriftSpriteTick = 0x801B0CC8; +HadohoPulseSpriteTick = 0x801B0DB4; +HadohoBeamColumnTick = 0x801B0EB4; +HadohoBeamHeadTick = 0x801B10A8; +HadohoMainTick = 0x801B1598; +HadohoStart = 0x801B1978; g_HadohoPrimBuffer = 0x801D5648; g_HadohoBufferPtr = 0x801ED648; diff --git a/config/symbols.magic-re_do.us.txt b/config/symbols.magic-re_do.us.txt index 9d46e56c..d67aa2f6 100644 --- a/config/symbols.magic-re_do.us.txt +++ b/config/symbols.magic-re_do.us.txt @@ -1,19 +1,19 @@ -func_801B0000 = 0x801B0000; -func_801B0020 = 0x801B0020; -func_801B01CC = 0x801B01CC; -func_801B02FC = 0x801B02FC; +MAGIC_ReDo = 0x801B0000; +ReDoTargetCenterCalc = 0x801B0020; +ReDoSprayVectorCalc = 0x801B01CC; +ReDoSpriteMatrixSetup = 0x801B02FC; ReDoDoubleBufferFlip = 0x801B045C; -func_801B04C8 = 0x801B04C8; -func_801B05A8 = 0x801B05A8; -func_801B0664 = 0x801B0664; -func_801B0880 = 0x801B0880; -func_801B09E0 = 0x801B09E0; -func_801B0B3C = 0x801B0B3C; -func_801B0CC0 = 0x801B0CC0; -func_801B0DAC = 0x801B0DAC; -func_801B0EAC = 0x801B0EAC; -func_801B10A0 = 0x801B10A0; -func_801B1590 = 0x801B1590; -func_801B1A54 = 0x801B1A54; +ReDoViewportFlashTick = 0x801B04C8; +ReDoSparkSpriteTick = 0x801B05A8; +ReDoEmberTick = 0x801B0664; +ReDoRisingModelTick = 0x801B0880; +ReDoGrowingModelTick = 0x801B09E0; +ReDoShrinkingModelTick = 0x801B0B3C; +ReDoDriftSpriteTick = 0x801B0CC0; +ReDoPulseSpriteTick = 0x801B0DAC; +ReDoBeamColumnTick = 0x801B0EAC; +ReDoBeamHeadTick = 0x801B10A0; +ReDoMainTick = 0x801B1590; +ReDoStart = 0x801B1A54; g_ReDoPrimBuffer = 0x801D5738; g_ReDoBufferPtr = 0x801ED738; diff --git a/config/symbols.magic-shaku.us.txt b/config/symbols.magic-shaku.us.txt index 90894c37..0d7b564e 100644 --- a/config/symbols.magic-shaku.us.txt +++ b/config/symbols.magic-shaku.us.txt @@ -1,19 +1,19 @@ -func_801B0000 = 0x801B0000; -func_801B0020 = 0x801B0020; -func_801B01CC = 0x801B01CC; -func_801B02FC = 0x801B02FC; +MAGIC_Shaku = 0x801B0000; +ShakuTargetCenterCalc = 0x801B0020; +ShakuSprayVectorCalc = 0x801B01CC; +ShakuSpriteMatrixSetup = 0x801B02FC; ShakuDoubleBufferFlip = 0x801B045C; -func_801B04C8 = 0x801B04C8; -func_801B05A8 = 0x801B05A8; -func_801B0664 = 0x801B0664; -func_801B0880 = 0x801B0880; -func_801B09E0 = 0x801B09E0; -func_801B0B3C = 0x801B0B3C; -func_801B0CC0 = 0x801B0CC0; -func_801B0DAC = 0x801B0DAC; -func_801B0EAC = 0x801B0EAC; -func_801B10A0 = 0x801B10A0; -func_801B1590 = 0x801B1590; -func_801B1970 = 0x801B1970; +ShakuViewportFlashTick = 0x801B04C8; +ShakuSparkSpriteTick = 0x801B05A8; +ShakuEmberTick = 0x801B0664; +ShakuRisingModelTick = 0x801B0880; +ShakuGrowingModelTick = 0x801B09E0; +ShakuShrinkingModelTick = 0x801B0B3C; +ShakuDriftSpriteTick = 0x801B0CC0; +ShakuPulseSpriteTick = 0x801B0DAC; +ShakuBeamColumnTick = 0x801B0EAC; +ShakuBeamHeadTick = 0x801B10A0; +ShakuMainTick = 0x801B1590; +ShakuStart = 0x801B1970; g_ShakuPrimBuffer = 0x801D5768; g_ShakuBufferPtr = 0x801ED768; diff --git a/src/magic/hadoho.c b/src/magic/hadoho.c index c6f368c9..7462207a 100644 --- a/src/magic/hadoho.c +++ b/src/magic/hadoho.c @@ -10,7 +10,7 @@ u_long* func_800C4FC8(); // Dragon Cannon (怒龍砲 / Doryuho). // The file name (波動砲, Wave Artillery) is the attack that uses SHAKU. -void func_801B1978(s32 targetMask, s32 callbackArg); +void HadohoStart(s32 targetMask, s32 callbackArg); // Primitive buffer pages, one 0xC000 page per double-buffered frame. extern u8 g_HadohoPrimBuffer[2][0xC000]; @@ -73,17 +73,17 @@ extern u_long D_801B1B40[]; extern void* D_80163C74; s32 BattleDetachedRegister(void (*func)(void)); void func_800BBA84(u16 arg0, s32 arg1, s32 arg2); -void func_801B04C8(void); -void func_801B066C(void); -void func_801B0888(void); -void func_801B0B44(void); -void func_801B10A8(void); -void func_801B1598(void); +void HadohoViewportFlashTick(void); +void HadohoEmberTick(void); +void HadohoRisingModelTick(void); +void HadohoShrinkingModelTick(void); +void HadohoBeamHeadTick(void); +void HadohoMainTick(void); // Same as MAGIC_Biora. -void func_801B0000(s32 targetMask, s32 callbackArg) { func_801B1978(targetMask, callbackArg); } +void MAGIC_Hadoho(s32 targetMask, s32 callbackArg) { HadohoStart(targetMask, callbackArg); } -void func_801B0020(s16 targetMask, SVECTOR* out) { +void HadohoTargetCenterCalc(s16 targetMask, SVECTOR* out) { VECTOR sum; SVECTOR pos; s16 i; @@ -105,7 +105,7 @@ void func_801B0020(s16 targetMask, SVECTOR* out) { out->vz = sum.vz / count; } -void func_801B01CC(s32 offset, s16 spread, SVECTOR* out) { +void HadohoSprayVectorCalc(s32 offset, s16 spread, SVECTOR* out) { SVECTOR in; SVECTOR rot; MATRIX matrix; @@ -120,7 +120,7 @@ void func_801B01CC(s32 offset, s16 spread, SVECTOR* out) { ApplyMatrixSV(&matrix, &in, out); } -void func_801B02FC(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) { +void HadohoSpriteMatrixSetup(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) { MATRIX matrix; MATRIX rotated; VECTOR dir; @@ -160,7 +160,7 @@ static void HadohoDoubleBufferFlip(void) { } } -void func_801B04C8(void) { +void HadohoViewportFlashTick(void) { HadohoData* effect; effect = &g_BattleEffectSlots[g_BattleEffectCursor]; @@ -179,7 +179,7 @@ void func_801B04C8(void) { } } -void func_801B05B0(void) { +void HadohoSparkSpriteTick(void) { HadohoData* effect; effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; @@ -194,7 +194,7 @@ void func_801B05B0(void) { } } -void func_801B066C(void) { +void HadohoEmberTick(void) { MATRIX rotated; MATRIX matrix; SVECTOR rot; @@ -245,7 +245,7 @@ void func_801B066C(void) { } } -void func_801B0888(void) { +void HadohoRisingModelTick(void) { MATRIX matrix; MATRIX composed; SVECTOR rot; @@ -276,7 +276,7 @@ void func_801B0888(void) { } } -void func_801B09E8(void) { +void HadohoGrowingModelTick(void) { MATRIX matrix; MATRIX composed; VECTOR scale; @@ -304,7 +304,7 @@ void func_801B09E8(void) { } } -void func_801B0B44(void) { +void HadohoShrinkingModelTick(void) { MATRIX matrix; MATRIX composed; VECTOR scale; @@ -334,7 +334,7 @@ void func_801B0B44(void) { } } -void func_801B0CC8(void) { +void HadohoDriftSpriteTick(void) { HadohoData* effect; effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; @@ -352,7 +352,7 @@ void func_801B0CC8(void) { } } -void func_801B0DB4(void) { +void HadohoPulseSpriteTick(void) { HadohoData* effect; effect = &g_BattleEffectSlots[g_BattleEffectCursor]; @@ -367,7 +367,7 @@ void func_801B0DB4(void) { } } -void func_801B0EB4(void) { +void HadohoBeamColumnTick(void) { MATRIX matrix; MATRIX composed; VECTOR scale; @@ -402,7 +402,7 @@ void func_801B0EB4(void) { } } -void func_801B10A8(void) { +void HadohoBeamHeadTick(void) { MATRIX matrix; MATRIX composed; HadohoData* effect; @@ -434,13 +434,13 @@ void func_801B10A8(void) { effect->Pos.vy += effect->PartPos.vy; effect->Pos.vz += effect->PartPos.vz; if ((effect->AnimationFrame & 1) == 0) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0B44)]; + child = &g_BattleEffectSlots[BattleEffectRegister(HadohoShrinkingModelTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; } if (effect->Pos.vy < 0) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B066C)]; + child = &g_BattleEffectSlots[BattleEffectRegister(HadohoEmberTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vz = effect->Pos.vz; child->Pos.vy = 0; @@ -450,7 +450,7 @@ void func_801B10A8(void) { child->PartPos.vy = -rand() % 300 - 50; child->unk16 = rand() % 7; if (effect->AnimationFrame % 3 == 0) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0888)]; + child = &g_BattleEffectSlots[BattleEffectRegister(HadohoRisingModelTick)]; child->Pos.vx = effect->Pos.vx + rand() % 4000 - 2000; child->Pos.vz = effect->Pos.vz + rand() % 4000 - 2000; child->Pos.vy = 0; @@ -466,7 +466,7 @@ void func_801B10A8(void) { } } } -void func_801B1598(void) { +void HadohoMainTick(void) { SVECTOR in; SVECTOR rot; MATRIX matrix; @@ -480,22 +480,22 @@ void func_801B1598(void) { effect = &g_BattleEffectSlots[g_BattleEffectCursor]; if (D_80062D98 == 0) { if (effect->AnimationFrame == 0) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B09E8)]; + child = &g_BattleEffectSlots[BattleEffectRegister(HadohoGrowingModelTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0DB4)]; + child = &g_BattleEffectSlots[BattleEffectRegister(HadohoPulseSpriteTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; func_800BBA84(0x174, effect->unk1E, 0x40); } if (effect->AnimationFrame == 20) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0EB4)]; + child = &g_BattleEffectSlots[BattleEffectRegister(HadohoBeamColumnTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B10A8)]; + child = &g_BattleEffectSlots[BattleEffectRegister(HadohoBeamHeadTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; @@ -505,7 +505,7 @@ void func_801B1598(void) { func_800BBA84(0x176, effect->unk1E, 0x40); } if (effect->AnimationFrame == 20) { - BattleEffectRegister(func_801B04C8); + BattleEffectRegister(HadohoViewportFlashTick); } if (effect->AnimationFrame == 54) { BattleFixedPointRampUpdateInit(0, 16); @@ -513,7 +513,7 @@ void func_801B1598(void) { if (effect->AnimationFrame >= 37 && effect->AnimationFrame < 44) { for (i = 0; i < 10; i++) { if ((D_801D563C >> i) & 1) { - child = &g_BattleDetachedSlots[BattleDetachedRegister(func_801B0CC8)]; + child = &g_BattleDetachedSlots[BattleDetachedRegister(HadohoDriftSpriteTick)]; BattleGetPartPosition(i, g_BattleModels[i].boneIndices[0], &child->Pos); in.vy = 0x50; in.vz = 0; @@ -551,16 +551,16 @@ void func_801B1598(void) { } } -void func_801B1978(s32 targetMask, s32 callbackArg) { +void HadohoStart(s32 targetMask, s32 callbackArg) { VECTOR vec; SVECTOR dir; HadohoData* effect; BattleEffectRegister(HadohoDoubleBufferFlip); D_801D563C = targetMask; - effect = &g_BattleEffectSlots[BattleEffectRegister(func_801B1598)]; + effect = &g_BattleEffectSlots[BattleEffectRegister(HadohoMainTick)]; BattleGetPartPosition(callbackArg, g_BattleModels[callbackArg].boneIndices[8], &effect->Pos); - func_801B0020(targetMask, &D_801D5640); + HadohoTargetCenterCalc(targetMask, &D_801D5640); vec.vx = dir.vx = D_801D5640.vx - effect->Pos.vx; vec.vy = dir.vy = D_801D5640.vy - effect->Pos.vy; vec.vz = dir.vz = D_801D5640.vz - effect->Pos.vz; diff --git a/src/magic/re_do.c b/src/magic/re_do.c index e2b2e370..0b9c9456 100644 --- a/src/magic/re_do.c +++ b/src/magic/re_do.c @@ -9,7 +9,7 @@ u_long* func_800C4FC8(); // Big Breath (大口ブレス / Oguchi Buresu). -void func_801B1A54(s32 targetMask, s32 callbackArg); +void ReDoStart(s32 targetMask, s32 callbackArg); // Primitive buffer pages, one 0xC000 page per double-buffered frame. extern u8 g_ReDoPrimBuffer[2][0xC000]; @@ -73,17 +73,17 @@ extern u_long D_801B1B38[]; extern void* D_80163C74; s32 BattleDetachedRegister(void (*func)(void)); void func_800BBA84(u16 arg0, s32 arg1, s32 arg2); -void func_801B04C8(void); -void func_801B0664(void); -void func_801B0880(void); -void func_801B0B3C(void); -void func_801B10A0(void); -void func_801B1590(void); +void ReDoViewportFlashTick(void); +void ReDoEmberTick(void); +void ReDoRisingModelTick(void); +void ReDoShrinkingModelTick(void); +void ReDoBeamHeadTick(void); +void ReDoMainTick(void); // Same as MAGIC_Biora. -void func_801B0000(s32 targetMask, s32 callbackArg) { func_801B1A54(targetMask, callbackArg); } +void MAGIC_ReDo(s32 targetMask, s32 callbackArg) { ReDoStart(targetMask, callbackArg); } -void func_801B0020(s16 targetMask, SVECTOR* out) { +void ReDoTargetCenterCalc(s16 targetMask, SVECTOR* out) { VECTOR sum; SVECTOR pos; s16 i; @@ -105,7 +105,7 @@ void func_801B0020(s16 targetMask, SVECTOR* out) { out->vz = sum.vz / count; } -void func_801B01CC(s32 offset, s16 spread, SVECTOR* out) { +void ReDoSprayVectorCalc(s32 offset, s16 spread, SVECTOR* out) { SVECTOR in; SVECTOR rot; MATRIX matrix; @@ -120,7 +120,7 @@ void func_801B01CC(s32 offset, s16 spread, SVECTOR* out) { ApplyMatrixSV(&matrix, &in, out); } -void func_801B02FC(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) { +void ReDoSpriteMatrixSetup(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) { MATRIX matrix; MATRIX rotated; VECTOR dir; @@ -160,7 +160,7 @@ static void ReDoDoubleBufferFlip(void) { } } -void func_801B04C8(void) { +void ReDoViewportFlashTick(void) { ReDoData* effect; effect = &g_BattleEffectSlots[g_BattleEffectCursor]; @@ -179,7 +179,7 @@ void func_801B04C8(void) { } } -void func_801B05A8(void) { +void ReDoSparkSpriteTick(void) { ReDoData* effect; effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; @@ -194,7 +194,7 @@ void func_801B05A8(void) { } } -void func_801B0664(void) { +void ReDoEmberTick(void) { MATRIX rotated; MATRIX matrix; SVECTOR rot; @@ -245,7 +245,7 @@ void func_801B0664(void) { } } -void func_801B0880(void) { +void ReDoRisingModelTick(void) { MATRIX matrix; MATRIX composed; SVECTOR rot; @@ -276,7 +276,7 @@ void func_801B0880(void) { } } -void func_801B09E0(void) { +void ReDoGrowingModelTick(void) { MATRIX matrix; MATRIX composed; VECTOR scale; @@ -304,7 +304,7 @@ void func_801B09E0(void) { } } -void func_801B0B3C(void) { +void ReDoShrinkingModelTick(void) { MATRIX matrix; MATRIX composed; VECTOR scale; @@ -334,7 +334,7 @@ void func_801B0B3C(void) { } } -void func_801B0CC0(void) { +void ReDoDriftSpriteTick(void) { ReDoData* effect; effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; @@ -352,7 +352,7 @@ void func_801B0CC0(void) { } } -void func_801B0DAC(void) { +void ReDoPulseSpriteTick(void) { ReDoData* effect; effect = &g_BattleEffectSlots[g_BattleEffectCursor]; @@ -368,7 +368,7 @@ void func_801B0DAC(void) { } } -void func_801B0EAC(void) { +void ReDoBeamColumnTick(void) { MATRIX matrix; MATRIX composed; VECTOR scale; @@ -403,7 +403,7 @@ void func_801B0EAC(void) { } } -void func_801B10A0(void) { +void ReDoBeamHeadTick(void) { MATRIX matrix; MATRIX composed; ReDoData* effect; @@ -435,13 +435,13 @@ void func_801B10A0(void) { effect->Pos.vy += effect->PartPos.vy; effect->Pos.vz += effect->PartPos.vz; if ((effect->AnimationFrame & 1) == 0) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0B3C)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ReDoShrinkingModelTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; } if (effect->Pos.vy < 0) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0664)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ReDoEmberTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vz = effect->Pos.vz; child->Pos.vy = 0; @@ -451,7 +451,7 @@ void func_801B10A0(void) { child->PartPos.vy = -rand() % 300 - 50; child->unk16 = rand() % 7; if (effect->AnimationFrame % 3 == 0) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0880)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ReDoRisingModelTick)]; child->Pos.vx = effect->Pos.vx + rand() % 4000 - 2000; child->Pos.vz = effect->Pos.vz + rand() % 4000 - 2000; child->Pos.vy = 0; @@ -468,7 +468,7 @@ void func_801B10A0(void) { } } -void func_801B1590(void) { +void ReDoMainTick(void) { SVECTOR in; SVECTOR rot; MATRIX matrix; @@ -491,22 +491,22 @@ void func_801B1590(void) { effect->PartPos.vx = in.vx * 75 >> 9; effect->PartPos.vy = in.vy * 75 >> 9; effect->PartPos.vz = in.vz * 75 >> 9; - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B09E0)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ReDoGrowingModelTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0DAC)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ReDoPulseSpriteTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; func_800BBA84(0x174, effect->unk1E, 0x40); } if (effect->AnimationFrame == 20) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0EAC)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ReDoBeamColumnTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B10A0)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ReDoBeamHeadTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; @@ -516,7 +516,7 @@ void func_801B1590(void) { func_800BBA84(0x164, effect->unk1E, 0x40); } if (effect->AnimationFrame == 20) { - BattleEffectRegister(func_801B04C8); + BattleEffectRegister(ReDoViewportFlashTick); } if (effect->AnimationFrame == 54) { BattleFixedPointRampUpdateInit(0, 16); @@ -524,7 +524,7 @@ void func_801B1590(void) { if (effect->AnimationFrame >= 37 && effect->AnimationFrame < 44) { for (i = 0; i < 10; i++) { if ((D_801D572C >> i) & 1) { - child = &g_BattleDetachedSlots[BattleDetachedRegister(func_801B0CC0)]; + child = &g_BattleDetachedSlots[BattleDetachedRegister(ReDoDriftSpriteTick)]; BattleGetPartPosition(i, g_BattleModels[i].boneIndices[0], &child->Pos); in.vy = 0x50; in.vz = 0; @@ -561,15 +561,15 @@ void func_801B1590(void) { } } -void func_801B1A54(s32 targetMask, s32 callbackArg) { +void ReDoStart(s32 targetMask, s32 callbackArg) { // pad0 and pad1 are unused; they only reproduce the original 0x38 stack frame. VECTOR pad0; SVECTOR pad1; BattleEffectRegister(ReDoDoubleBufferFlip); D_801D572C = targetMask; - g_BattleEffectSlots[BattleEffectRegister(func_801B1590)].unk1E = callbackArg; - func_801B0020(targetMask, &D_801D5730); + g_BattleEffectSlots[BattleEffectRegister(ReDoMainTick)].unk1E = callbackArg; + ReDoTargetCenterCalc(targetMask, &D_801D5730); BattleSetLoadTimToVram(D_801B1B08, 0, 0, 0); D_800F5B70 = D_800F5B71 = D_800F5B72 = 0; BattleFixedPointRampUpdateInit(0x1000, 0x10); diff --git a/src/magic/shaku.c b/src/magic/shaku.c index 5f4a6841..34d80901 100644 --- a/src/magic/shaku.c +++ b/src/magic/shaku.c @@ -9,7 +9,7 @@ u_long* func_800C4FC8(); // Effect shared by Wave Artillery (波動砲) and Golem Laser (ゴーレムレーザー). -void func_801B1970(s32 targetMask, s32 callbackArg); +void ShakuStart(s32 targetMask, s32 callbackArg); // Primitive buffer pages, one 0xC000 page per double-buffered frame. extern u8 g_ShakuPrimBuffer[2][0xC000]; @@ -72,17 +72,17 @@ extern u_long D_801B1B38[]; extern void* D_80163C74; s32 BattleDetachedRegister(void (*func)(void)); void func_800BBA84(u16 arg0, s32 arg1, s32 arg2); -void func_801B04C8(void); -void func_801B0664(void); -void func_801B0880(void); -void func_801B0B3C(void); -void func_801B10A0(void); -void func_801B1590(void); +void ShakuViewportFlashTick(void); +void ShakuEmberTick(void); +void ShakuRisingModelTick(void); +void ShakuShrinkingModelTick(void); +void ShakuBeamHeadTick(void); +void ShakuMainTick(void); // Same as MAGIC_Biora. -void func_801B0000(s32 targetMask, s32 callbackArg) { func_801B1970(targetMask, callbackArg); } +void MAGIC_Shaku(s32 targetMask, s32 callbackArg) { ShakuStart(targetMask, callbackArg); } -void func_801B0020(s16 targetMask, SVECTOR* out) { +void ShakuTargetCenterCalc(s16 targetMask, SVECTOR* out) { VECTOR sum; SVECTOR pos; s16 i; @@ -104,7 +104,7 @@ void func_801B0020(s16 targetMask, SVECTOR* out) { out->vz = sum.vz / count; } -void func_801B01CC(s32 offset, s16 spread, SVECTOR* out) { +void ShakuSprayVectorCalc(s32 offset, s16 spread, SVECTOR* out) { SVECTOR in; SVECTOR rot; MATRIX matrix; @@ -119,7 +119,7 @@ void func_801B01CC(s32 offset, s16 spread, SVECTOR* out) { ApplyMatrixSV(&matrix, &in, out); } -void func_801B02FC(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) { +void ShakuSpriteMatrixSetup(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) { MATRIX matrix; MATRIX rotated; VECTOR dir; @@ -159,7 +159,7 @@ static void ShakuDoubleBufferFlip(void) { } } -void func_801B04C8(void) { +void ShakuViewportFlashTick(void) { ShakuData* effect; effect = &g_BattleEffectSlots[g_BattleEffectCursor]; @@ -178,7 +178,7 @@ void func_801B04C8(void) { } } -void func_801B05A8(void) { +void ShakuSparkSpriteTick(void) { ShakuData* effect; effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; @@ -193,7 +193,7 @@ void func_801B05A8(void) { } } -void func_801B0664(void) { +void ShakuEmberTick(void) { MATRIX rotated; MATRIX matrix; SVECTOR rot; @@ -244,7 +244,7 @@ void func_801B0664(void) { } } -void func_801B0880(void) { +void ShakuRisingModelTick(void) { MATRIX matrix; MATRIX composed; SVECTOR rot; @@ -275,7 +275,7 @@ void func_801B0880(void) { } } -void func_801B09E0(void) { +void ShakuGrowingModelTick(void) { MATRIX matrix; MATRIX composed; VECTOR scale; @@ -303,7 +303,7 @@ void func_801B09E0(void) { } } -void func_801B0B3C(void) { +void ShakuShrinkingModelTick(void) { MATRIX matrix; MATRIX composed; VECTOR scale; @@ -333,7 +333,7 @@ void func_801B0B3C(void) { } } -void func_801B0CC0(void) { +void ShakuDriftSpriteTick(void) { ShakuData* effect; effect = &g_BattleDetachedSlots[g_BattleDetachedCursor]; @@ -351,7 +351,7 @@ void func_801B0CC0(void) { } } -void func_801B0DAC(void) { +void ShakuPulseSpriteTick(void) { ShakuData* effect; effect = &g_BattleEffectSlots[g_BattleEffectCursor]; @@ -366,7 +366,7 @@ void func_801B0DAC(void) { } } -void func_801B0EAC(void) { +void ShakuBeamColumnTick(void) { MATRIX matrix; MATRIX composed; VECTOR scale; @@ -401,7 +401,7 @@ void func_801B0EAC(void) { } } -void func_801B10A0(void) { +void ShakuBeamHeadTick(void) { MATRIX matrix; MATRIX composed; ShakuData* effect; @@ -433,13 +433,13 @@ void func_801B10A0(void) { effect->Pos.vy += effect->PartPos.vy; effect->Pos.vz += effect->PartPos.vz; if ((effect->AnimationFrame & 1) == 0) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0B3C)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ShakuShrinkingModelTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; } if (effect->Pos.vy < 0) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0664)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ShakuEmberTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vz = effect->Pos.vz; child->Pos.vy = 0; @@ -449,7 +449,7 @@ void func_801B10A0(void) { child->PartPos.vy = -rand() % 300 - 50; child->unk16 = rand() % 7; if (effect->AnimationFrame % 3 == 0) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0880)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ShakuRisingModelTick)]; child->Pos.vx = effect->Pos.vx + rand() % 4000 - 2000; child->Pos.vz = effect->Pos.vz + rand() % 4000 - 2000; child->Pos.vy = 0; @@ -466,7 +466,7 @@ void func_801B10A0(void) { } } -void func_801B1590(void) { +void ShakuMainTick(void) { SVECTOR in; SVECTOR rot; MATRIX matrix; @@ -480,22 +480,22 @@ void func_801B1590(void) { effect = &g_BattleEffectSlots[g_BattleEffectCursor]; if (D_80062D98 == 0) { if (effect->AnimationFrame == 0) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B09E0)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ShakuGrowingModelTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0DAC)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ShakuPulseSpriteTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; func_800BBA84(0x174, effect->unk1E, 0x40); } if (effect->AnimationFrame == 20) { - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B0EAC)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ShakuBeamColumnTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; - child = &g_BattleEffectSlots[BattleEffectRegister(func_801B10A0)]; + child = &g_BattleEffectSlots[BattleEffectRegister(ShakuBeamHeadTick)]; child->Pos.vx = effect->Pos.vx; child->Pos.vy = effect->Pos.vy; child->Pos.vz = effect->Pos.vz; @@ -505,7 +505,7 @@ void func_801B1590(void) { func_800BBA84(0x176, effect->unk1E, 0x40); } if (effect->AnimationFrame == 20) { - BattleEffectRegister(func_801B04C8); + BattleEffectRegister(ShakuViewportFlashTick); } if (effect->AnimationFrame == 54) { BattleFixedPointRampUpdateInit(0, 16); @@ -513,7 +513,7 @@ void func_801B1590(void) { if (effect->AnimationFrame >= 37 && effect->AnimationFrame < 44) { for (i = 0; i < 10; i++) { if ((D_801D575C >> i) & 1) { - child = &g_BattleDetachedSlots[BattleDetachedRegister(func_801B0CC0)]; + child = &g_BattleDetachedSlots[BattleDetachedRegister(ShakuDriftSpriteTick)]; BattleGetPartPosition(i, g_BattleModels[i].boneIndices[0], &child->Pos); in.vy = 0x50; in.vz = 0; @@ -551,16 +551,16 @@ void func_801B1590(void) { } } -void func_801B1970(s32 targetMask, s32 callbackArg) { +void ShakuStart(s32 targetMask, s32 callbackArg) { VECTOR vec; SVECTOR dir; ShakuData* effect; BattleEffectRegister(ShakuDoubleBufferFlip); D_801D575C = targetMask; - effect = &g_BattleEffectSlots[BattleEffectRegister(func_801B1590)]; + effect = &g_BattleEffectSlots[BattleEffectRegister(ShakuMainTick)]; BattleGetPartPosition(callbackArg, g_BattleModels[callbackArg].boneIndices[8], &effect->Pos); - func_801B0020(targetMask, &D_801D5760); + ShakuTargetCenterCalc(targetMask, &D_801D5760); vec.vx = dir.vx = D_801D5760.vx - effect->Pos.vx; vec.vy = dir.vy = D_801D5760.vy - effect->Pos.vy; vec.vz = dir.vz = D_801D5760.vz - effect->Pos.vz; From cc0ba7314d4682619b8a79c3e9af134717ae233c Mon Sep 17 00:00:00 2001 From: j3lee Date: Mon, 12 Oct 2026 13:13:34 +0930 Subject: [PATCH 6/6] magic: point the "same as" comments at upstream functions Cites functions that exist on origin/main (or in this PR); comments that named draft-only functions are repointed or dropped. --- src/magic/hadoho.c | 3 +-- src/magic/re_do.c | 3 +-- src/magic/shaku.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/magic/hadoho.c b/src/magic/hadoho.c index 7462207a..46a6c37f 100644 --- a/src/magic/hadoho.c +++ b/src/magic/hadoho.c @@ -80,7 +80,6 @@ void HadohoShrinkingModelTick(void); void HadohoBeamHeadTick(void); void HadohoMainTick(void); -// Same as MAGIC_Biora. void MAGIC_Hadoho(s32 targetMask, s32 callbackArg) { HadohoStart(targetMask, callbackArg); } void HadohoTargetCenterCalc(s16 targetMask, SVECTOR* out) { @@ -148,7 +147,7 @@ void HadohoSpriteMatrixSetup(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) SetTransMatrix(&matrix); } -// Same as BioraDoubleBufferFlip. +// Same as BarrierDoubleBufferFlip. static void HadohoDoubleBufferFlip(void) { HadohoData* effect; diff --git a/src/magic/re_do.c b/src/magic/re_do.c index 0b9c9456..366f69c3 100644 --- a/src/magic/re_do.c +++ b/src/magic/re_do.c @@ -80,7 +80,6 @@ void ReDoShrinkingModelTick(void); void ReDoBeamHeadTick(void); void ReDoMainTick(void); -// Same as MAGIC_Biora. void MAGIC_ReDo(s32 targetMask, s32 callbackArg) { ReDoStart(targetMask, callbackArg); } void ReDoTargetCenterCalc(s16 targetMask, SVECTOR* out) { @@ -148,7 +147,7 @@ void ReDoSpriteMatrixSetup(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) { SetTransMatrix(&matrix); } -// Same as BioraDoubleBufferFlip. +// Same as BarrierDoubleBufferFlip. static void ReDoDoubleBufferFlip(void) { ReDoData* effect; diff --git a/src/magic/shaku.c b/src/magic/shaku.c index 34d80901..beacaaa2 100644 --- a/src/magic/shaku.c +++ b/src/magic/shaku.c @@ -79,7 +79,6 @@ void ShakuShrinkingModelTick(void); void ShakuBeamHeadTick(void); void ShakuMainTick(void); -// Same as MAGIC_Biora. void MAGIC_Shaku(s32 targetMask, s32 callbackArg) { ShakuStart(targetMask, callbackArg); } void ShakuTargetCenterCalc(s16 targetMask, SVECTOR* out) { @@ -147,7 +146,7 @@ void ShakuSpriteMatrixSetup(SVECTOR* pos, SVECTOR* rot, s16 scale, s32 offset) { SetTransMatrix(&matrix); } -// Same as BioraDoubleBufferFlip. +// Same as BarrierDoubleBufferFlip. static void ShakuDoubleBufferFlip(void) { ShakuData* effect;