From 60f96c1b7782788fa2d03e13c2d40c49cb971209 Mon Sep 17 00:00:00 2001 From: rengstrom Date: Wed, 9 Sep 2026 17:14:00 +0000 Subject: [PATCH 1/5] Decompile the effect_052 overlay X-Potion runs the engine Curaga already carries, so 99 of its 118 functions are the library: nineteen units, listed in its own link order, and a symbol file that maps their names onto its addresses. Deriving that map is the whole of the work -- align unit by unit and position by position, because two functions of one unit can hash alike when they differ only in which sibling they call, and pair the relocation streams off against each other. 244 addresses paired with nothing left in conflict. What is X-Potion's own is the entry, a root dispatcher and seventeen script functions, and all but one of those are byte-identical to Curaga's or Cure's, so they came across with the addresses rewritten. Only the bank carve was written here. Its rings are Curaga's sizes, so its parameter header is the same two counts; what differs is the pool: X-Potion has no trailing-spark pool, which is why its entry sets up three where Curaga sets up four and its dispatcher drains three. Three things the overlay needed from its config. splat does not carve out a lone `jr ra` no-op, and three of them sit between script functions, so they are named in the symbol file or the binary comes out short and every later address shifts. The asset blob was declared from 0x9BF0, which swallowed the script dispatch tables; it starts at 0x9C68. And the jump tables carry the tail pad ASFLAGS suppress, so the pad between particlestep's and list's is declared. --- Makefile | 2 +- config/ff8.yaml | 32 +- config/symbols.effect_052.txt | 116 +++++ include/effect/effect_052.h | 60 +++ .../effect/params/effect_052/effect_params.h | 13 + src/effect/effect_052.c | 448 +++++++++--------- src/effect/effect_052_entry.c | 61 +++ 7 files changed, 512 insertions(+), 220 deletions(-) create mode 100644 config/symbols.effect_052.txt create mode 100644 include/effect/effect_052.h create mode 100644 include/effect/params/effect_052/effect_params.h create mode 100644 src/effect/effect_052_entry.c diff --git a/Makefile b/Makefile index 113aee26..929082e8 100644 --- a/Makefile +++ b/Makefile @@ -140,7 +140,7 @@ CODE_OVERLAYS := field_init intro field \ tripletriad battle_render battle world ALL_EFFECT_OVERLAYS := $(filter effect_%,$(SPLAT_BINARIES)) -EFFECTS ?= effect_001 effect_025 effect_028 +EFFECTS ?= effect_001 effect_025 effect_028 effect_052 EFFECT_OVERLAYS := $(if $(filter all,$(EFFECTS)),$(ALL_EFFECT_OVERLAYS),$(EFFECTS)) OVERLAYS := $(MENU_OVERLAYS) $(CODE_OVERLAYS) $(EFFECT_OVERLAYS) ALL_OVERLAYS := $(MENU_OVERLAYS) $(CODE_OVERLAYS) $(ALL_EFFECT_OVERLAYS) diff --git a/config/ff8.yaml b/config/ff8.yaml index ae67bb81..53db92e2 100644 --- a/config/ff8.yaml +++ b/config/ff8.yaml @@ -1496,15 +1496,41 @@ binaries: options: target_path: original/effect/effect_052.bin src_path: src/effect + section_order: [.text, .rodata, .data, .bss] segments: - name: effect_052 type: code start: 0x0 vram: 0x801A0000 subsegments: - - [0x0, c, effect_052] - - [0x9BDC, .rodata, effect_052] - - [0x9BF0, bin, effect_052] + - [0x0, c, effect_052_entry] + - [0x1EC, c, lib/common] + - [0x95C, c, lib/rotz] + - [0xAE8, c, lib/heading] + - [0xB18, c, lib/entity] + - [0x1688, c, lib/tint] + - [0x1964, c, lib/vector] + - [0x20D0, c, lib/emit] + - [0x3F04, c, lib/packet] + - [0x410C, c, lib/particlestep] + - [0x5400, c, lib/particlealloc] + - [0x551C, c, lib/draw] + - [0x6178, c, lib/emitteralloc] + - [0x6298, c, lib/spawn] + - [0x804C, c, lib/list] + - [0x8668, c, lib/trail] + - [0x87DC, c, lib/strands] + - [0x8CC8, c, lib/tables] + - [0x8FDC, c, lib/bankclear] + - [0x9034, c, lib/drawscript] + - [0x9498, c, effect_052] + # particlestep's jump table, then the pad its section end carried, then + # list's two, then the script dispatch tables. + - [0x9BDC, .rodata, lib/particlestep] + - [0x9BF0, pad] + - [0x9BF4, .rodata, lib/list] + - [0x9C20, .rodata, effect_052] + - [0x9C68, bin, effect_052] - [0x3C6D8] - name: effect_053 sha1: 738b1bb7de8b266db68995f925e9602f88fca51f diff --git a/config/symbols.effect_052.txt b/config/symbols.effect_052.txt new file mode 100644 index 00000000..4601a392 --- /dev/null +++ b/config/symbols.effect_052.txt @@ -0,0 +1,116 @@ +effectTextInit = 0x801A01EC; // type:func +effectTextHex = 0x801A033C; // type:func +effectTextNewline = 0x801A03E8; // type:func +effectNop = 0x801A0408; // type:func +effectDrawQuad128 = 0x801A0410; // type:func +effectDrawQuad256 = 0x801A050C; // type:func +effectMatrixIdentity = 0x801A0608; // type:func +effectMatrixRotX = 0x801A0640; // type:func +effectMatrixRotY = 0x801A07D0; // type:func +effectMatrixRotZ = 0x801A095C; // type:func +effectMatrixHeading = 0x801A0AE8; // type:func +effectReleaseWait = 0x801A0B18; // type:func +effectSpawnTask = 0x801A0B40; // type:func +effectCacheSlotAnchors = 0x801A0CCC; // type:func +effectSlotAnchor0 = 0x801A0E00; // type:func +effectSlotAnchor1 = 0x801A0E30; // type:func +effectSlotAnchorMid = 0x801A0E60; // type:func +effectCacheAnimSlotAnchors = 0x801A0E90; // type:func +effectAnimSlotAnchor0 = 0x801A0FCC; // type:func +effectAnimSlotAnchor1 = 0x801A0FFC; // type:func +effectAnimSlotAnchorMid = 0x801A102C; // type:func +effectUpdateModelBounds = 0x801A105C; // type:func +effectGetModelBounds = 0x801A12A8; // type:func +effectModelRadius = 0x801A12F8; // type:func +effectModelHalfHeight = 0x801A139C; // type:func +effectModelHalfWidth = 0x801A13CC; // type:func +effectModelHeight = 0x801A1424; // type:func +effectModelTop = 0x801A1448; // type:func +effectModelBottom = 0x801A1490; // type:func +effectModelRandomY = 0x801A14D8; // type:func +effectModelCentreY = 0x801A1590; // type:func +effectModelCentre = 0x801A15E4; // type:func +effectZeroWords = 0x801A1650; // type:func +effectTintPlay = 0x801A1688; // type:func +effectRandBetween = 0x801A1964; // type:func +effectRandProduct = 0x801A19E8; // type:func +effectRandVector = 0x801A1A8C; // type:func +effectMatrixFromAngles = 0x801A1B04; // type:func +effectJitterAngle = 0x801A1BD0; // type:func +effectJitterVector = 0x801A1C64; // type:func +effectJitterAngleS = 0x801A1CDC; // type:func +effectJitterSVector = 0x801A1D6C; // type:func +effectCopyVector = 0x801A1DE4; // type:func +effectFadeValue = 0x801A1E14; // type:func +effectFadeVector = 0x801A1E70; // type:func +effectBlendPointSets = 0x801A1F3C; // type:func +effectEmitTris = 0x801A20D0; // type:func +effectEmitQuads = 0x801A239C; // type:func +effectEmitTexTris = 0x801A26C0; // type:func +effectEmitTexQuads = 0x801A2A48; // type:func +effectEmitGouraudTris = 0x801A2E2C; // type:func +effectEmitGouraudQuads = 0x801A3134; // type:func +effectEmitGouraudTexTris = 0x801A34BC; // type:func +effectEmitGouraudTexQuads = 0x801A3878; // type:func +effectEmitStream = 0x801A3CC0; // type:func +effectBuildMeshPacket = 0x801A3F04; // type:func +effectParticleLateStep = 0x801A410C; // type:func +effectParticleAdvance = 0x801A41C4; // type:func +effectParticleAgeHold = 0x801A49CC; // type:func +effectParticlePose = 0x801A4AC0; // type:func +effectParticleAlloc = 0x801A5400; // type:func +effectStepRunKind = 0x801A551C; // type:func +effectStepFire = 0x801A5554; // type:func +effectParticleStep = 0x801A5600; // type:func +effectEmitterCountStep = 0x801A56EC; // type:func +effectSpriteEmit = 0x801A5704; // type:func +effectSpritePacket = 0x801A5D30; // type:func +effectParticleDrawPacket = 0x801A5F98; // type:func +effectDrawParticles = 0x801A6058; // type:func +effectEmitterAlloc = 0x801A6178; // type:func +effectEmitterAge = 0x801A6298; // type:func +effectEmitterSpawn = 0x801A6300; // type:func +effectEmitterSpawnShare = 0x801A6D9C; // type:func +effectEmitterStep = 0x801A6E9C; // type:func +effectEmitterOnStrand = 0x801A6F3C; // type:func +effectEmitterOnTrail = 0x801A71C4; // type:func +effectEmitterOnOwner = 0x801A73CC; // type:func +effectEmitterSlide = 0x801A75DC; // type:func +effectListAppend = 0x801A804C; // type:func +effectListRemove = 0x801A8088; // type:func +effectListClear = 0x801A80C8; // type:func +effectListRun = 0x801A80E0; // type:func +effectEmitterSetup = 0x801A8168; // type:func +effectStepFireSlots = 0x801A839C; // type:func +effectEmittersOnCue = 0x801A8450; // type:func +effectTrailPush = 0x801A858C; // type:func +effectTrailAim = 0x801A8668; // type:func +effectStrandsSeed = 0x801A87DC; // type:func +effectStrandsPush = 0x801A88E8; // type:func +effectStrandsAim = 0x801A8A00; // type:func +effectPoseTablesRelocate = 0x801A8CC8; // type:func +effectStartChildScript = 0x801A8F6C; // type:func +effectBanksClear = 0x801A8FDC; // type:func +effectDrawScriptStart = 0x801A9034; // type:func +effectDrawScriptRun = 0x801A92DC; // type:func +effectDrawListSpan = 0x801A9404; // type:func +func_801A953C = 0x801A953C; // type:func +func_801A96F8 = 0x801A96F8; // type:func +func_801A99E4 = 0x801A99E4; // type:func +g_effectStackBase = 0x801D399C; +g_effectStackTop = 0x801D39A0; +g_effectEmitterBank = 0x801D39A8; +g_effectParticleBank = 0x801D39AC; +g_effectDrawList = 0x801D39B0; +g_effectEmitterCursor = 0x801D39B4; +g_effectParticleCursor = 0x801D39B6; +g_effectParticleTotal = 0x801D39B8; +g_effectLiveTotal = 0x801D39BA; +g_effectBankUnk90 = 0x801D39BC; +g_effectBankUnk92 = 0x801D39BE; +g_effectChildPool = 0x801D41B4; +g_effectPrimCursor = 0x801D41C4; +g_effectHexGlyphs = 0x801D4504; +g_effectTextX = 0x801D4518; +g_effectTextY = 0x801D451C; +g_effectTextColour = 0x801D4520; diff --git a/include/effect/effect_052.h b/include/effect/effect_052.h new file mode 100644 index 00000000..7992fead --- /dev/null +++ b/include/effect/effect_052.h @@ -0,0 +1,60 @@ +#ifndef EFFECT_EFFECT_052_H +#define EFFECT_EFFECT_052_H + +#include "effect.h" +#include "effect/lib/particle.h" +#include "effect/lib/tint.h" + +/** + * @file effect_052.h + * @brief X-Potion: the overlay's own storage. + */ + +/** @brief Argument the frame-20 child is started with. */ +extern EffectTintStep D_801A9C68[]; + +/** @brief Sound cue the take-model script fires on its first frame. */ +extern u8 D_801A9C74[]; + +/** @brief Pool the trailing sparks are allocated from. */ +extern s32 D_801D4424; + +/** @brief Pool the frame-20 child is allocated from. */ +extern s32 D_801D44F4; + +/** @brief Pose script the model-taking handler runs. */ +extern EffectPoseTables D_801D4524; + +/** @brief Cleared when the effect starts. */ +extern s32 D_801D3994; +extern s32 D_801D3998; + +/** @brief Task pools the script's children run in. */ +extern s32 D_801D42B4; +extern s32 D_801D41E4; +extern s32 D_801D42C4; +extern s32 D_801D4434; +extern s32 D_801D39C4; + +/** @brief Table of two offsets battle.bin resolves when the effect starts. */ +extern u8 D_801A9DD4; + +/** @brief TIM uploaded to VRAM when the effect starts; also the first bank. */ +extern u8 D_801AA974; + +/** @brief Cursor the record banks are carved off, moving up as they are taken. */ +extern u8 *D_801D39A4; + +/** @brief Cursor the effect's second prim buffer is written through. */ +extern void *D_801D41C8; + +/** @brief The four bank pointers the emitters and the renderer read. */ +extern void *D_801D41CC; +extern void *D_801D41D0; +extern void *D_801D41D4; +extern void *D_801D41D8; + +/** @brief Run one frame of the effect: its opcode, then every task pool it owns. */ +s32 func_801A99EC(EffectEntity *entity); + +#endif /* EFFECT_EFFECT_052_H */ diff --git a/include/effect/params/effect_052/effect_params.h b/include/effect/params/effect_052/effect_params.h new file mode 100644 index 00000000..3ce28748 --- /dev/null +++ b/include/effect/params/effect_052/effect_params.h @@ -0,0 +1,13 @@ +#ifndef EFFECT_PARAMS_H +#define EFFECT_PARAMS_H + +/** + * @file effect_params.h + * @brief X-Potion: the ring sizes its particle engine is built with. + */ + +/** @brief Highest index each ring reaches before it wraps. */ +#define EFFECT_EMITTER_COUNT 0x59 +#define EFFECT_PARTICLE_COUNT 0x8B + +#endif /* EFFECT_PARAMS_H */ diff --git a/src/effect/effect_052.c b/src/effect/effect_052.c index ce370ca6..ba8bc84c 100644 --- a/src/effect/effect_052.c +++ b/src/effect/effect_052.c @@ -3,243 +3,259 @@ * @brief X-Potion */ #include "common.h" - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0000); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A01EC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A033C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A03E8); - -void func_801A0408(void) { +#include "game.h" +#include "effect.h" +#include "effect/effect_052.h" +#include "effect/lib/particle.h" +#include "effect/lib/entity.h" +#include "effect/lib/tint.h" +#include "psxsdk/libgte.h" +#include "effect/lib/bankclear.h" +#include "effect/lib/tables.h" +#include "effect/lib/drawscript.h" +#include "effect/lib/common.h" +#include "btl_entity.h" + +/** @brief Where in the scratchpad the effect keeps its view matrix. */ +#define EFFECT_SCRATCHPAD ((MATRIX *)0x1F8002E0) + +/** @brief @ref EffectEntity::unk05C -- the frame counter's low bit picks a bank. */ +#define EFFECT_FRAME_ODD 0x1 + +static void func_801A9498(EffectEntity *entity); +static void func_801A94F4(EffectEntity *entity); +static void func_801A953C(EffectEntity *entity); +static s32 func_801A9544(EffectEntity *entity); +static void func_801A95E4(EffectEntity *entity); +static void func_801A963C(EffectEntity *entity); +static void func_801A9670(EffectEntity *entity); +static void func_801A96F8(EffectEntity *entity); +static s32 func_801A9700(EffectEntity *entity); +static void func_801A9810(EffectEntity *entity); +static void func_801A9824(EffectEntity *entity); +static void func_801A9838(EffectEntity *entity); +static void func_801A98AC(EffectEntity *entity); +static void func_801A9904(EffectEntity *entity); +static void func_801A9964(EffectEntity *entity); +static void func_801A9978(EffectEntity *entity); +static void func_801A99A0(EffectEntity *entity); +static void func_801A99B4(EffectEntity *entity); +static void func_801A99C8(EffectEntity *entity); +static void func_801A99E4(EffectEntity *entity); + +/** @brief Opcode handler: draw and retire once the frame count is reached. */ +static void func_801A9498(EffectEntity *entity) { + EffectDrawScript *script = (EffectDrawScript *)entity; + + if (entity->unk024 >= script->stopFrame) { + /* Called with no argument: the entity is already in $a0 and stays there. */ + ((void (*)())effectDrawScriptStart)(); + effectDrawScriptRun(script); + entity->pc++; + } } -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0410); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A050C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0608); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0640); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A07D0); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A095C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0AE8); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0B18); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0B40); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0CCC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0E00); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0E30); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0E60); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0E90); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0FCC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A0FFC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A102C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A105C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A12A8); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A12F8); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A139C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A13CC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1424); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1448); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1490); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A14D8); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1590); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A15E4); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1650); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1688); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1964); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A19E8); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1A8C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1B04); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1BD0); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1C64); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1CDC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1D6C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1DE4); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1E14); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1E70); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A1F3C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A20D0); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A239C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A26C0); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A2A48); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A2E2C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A3134); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A34BC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A3878); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A3CC0); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A3F04); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A410C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A41C4); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A49CC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A4AC0); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A5400); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A551C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A5554); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A5600); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A56EC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A5704); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A5D30); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A5F98); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A6058); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A6178); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A6298); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A6300); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A6D9C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A6E9C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A6F3C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A71C4); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A73CC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A75DC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A804C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A8088); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A80C8); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A80E0); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A8168); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A839C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A8450); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A858C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A8668); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A87DC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A88E8); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A8A00); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A8CC8); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A8F6C); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A8FDC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9034); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A92DC); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9404); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9498); - -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A94F4); +/** @brief Opcode handler: hold still until the count runs out. */ +static void func_801A94F4(EffectEntity *entity) { + if (effectDrawScriptRun((EffectDrawScript *)entity) != 0) { + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } +} -void func_801A953C(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A953C(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9544); +/** + * @brief Script dispatcher: run this frame's step, draw, and retire the entity. + * + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ +static s32 func_801A9544(EffectEntity *entity) { + EffectHandler handlers[3] = { func_801A9498, func_801A94F4, func_801A953C }; + + handlers[entity->pc](entity); + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait != 0) { + return 0; + } + effectReleaseWait(entity); + return 2; + } + return 0; +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A95E4); +/** @brief Opcode handler: start the pose script on the taken model. */ +static void func_801A95E4(EffectEntity *entity) { + effectStartChildScript(entity, func_801A9544, &D_801D4524, 0, 0x2D, 0); + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A963C); +/** @brief Opcode handler: release the model once the count reaches 30. */ +static void func_801A963C(EffectEntity *entity) { + if (entity->unk024 == 30) { + entity->unk010->unk063 = 0; + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9670); +/** @brief Opcode handler: hand the current part to battle, then stop. */ +static void func_801A9670(EffectEntity *entity) { + if (entity->unk024 >= 30) { + func_800BFE1C(&entity->animSet->anims[entity->unk02A].parts[entity->unk02B]); + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } +} -void func_801A96F8(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A96F8(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9700); +/** @brief Script dispatcher: the take-model script, with its two timed cues. */ +static s32 func_801A9700(EffectEntity *entity) { + EffectHandler handlers[4] = { func_801A95E4, func_801A963C, func_801A9670, func_801A96F8 }; + + effectCacheSlotAnchors(entity); + effectUpdateModelBounds(entity); + handlers[entity->pc](entity); + if (entity->unk024 == 0) { + func_800C4764(D_801A9C74, 0, 0x80); + } + if (entity->unk024 == 20) { + EffectTintScript *child = + effectSpawnTask(&D_801D44F4, effectTintPlay, sizeof(EffectTintScript), entity); + + child->steps = D_801A9C68; + } + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait != 0) { + return 0; + } + effectReleaseWait(entity); + return 2; + } + return 0; +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9810); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9810(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9824); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9824(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9838); +/** @brief Opcode handler: carve both record banks and start the draw script. */ +static void func_801A9838(EffectEntity *entity) { + if (entity->wait == 0) { + /* Both banks are carved out of the same byte arena behind the TIM. */ + g_effectEmitterBank = (EffectEmitter *)D_801D39A4; + D_801D39A4 += EFFECT_EMITTER_BANK_BYTES; + g_effectParticleBank = (EffectParticle *)D_801D39A4; + D_801D39A4 += EFFECT_PARTICLE_BANK_BYTES; + effectBanksClear(); + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A98AC); +/** @brief Opcode handler: start a task running @ref func_801A9700. */ +static void func_801A98AC(EffectEntity *entity) { + entity->unk063 = 1; + effectSpawnTask(&D_801D4424, func_801A9700, 0x58, entity); + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9904); +/** @brief Opcode handler: repeat the preceding opcode until the count runs out. */ +static void func_801A9904(EffectEntity *entity) { + if (entity->unk063 != 0) { + return; + } + if (entity->unk02A < entity->unk058) { + entity->unk02A++; + entity->unk02E++; + entity->pc--; + } else { + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9964); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9964(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A9978); +/** @brief Opcode handler: stall here until @c unk05E reaches zero. */ +static void func_801A9978(EffectEntity *entity) { + if (entity->unk05E == 0) { + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A99A0); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A99A0(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A99B4); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A99B4(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A99C8); +/** @brief Opcode handler: raise @ref EFFECT_FLAG_STOP and consume the opcode. */ +static void func_801A99C8(EffectEntity *entity) { + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; +} -void func_801A99E4(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A99E4(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_052/nonmatchings/effect_052", func_801A99EC); +/** + * @brief Run one frame of the effect: its opcode, then every task pool it owns. + * + * @return 2 once the script has stopped and its children have drained. + */ +s32 func_801A99EC(EffectEntity *entity) { + EffectHandler handlers[11] = { + func_801A9810, func_801A9824, func_801A9838, func_801A98AC, func_801A9904, + func_801A9964, func_801A9978, func_801A99A0, func_801A99B4, func_801A99C8, + func_801A99E4 + }; + MATRIX *view = EFFECT_SCRATCHPAD; + + *view = D_800F02C8; + g_effectStackTop = (u8 *)view; + g_effectStackBase = view; + if (entity->unk05C & EFFECT_FRAME_ODD) { + g_effectPrimCursor = D_801D41CC; + D_801D41C8 = D_801D41D4; + } else { + g_effectPrimCursor = D_801D41D0; + D_801D41C8 = D_801D41D8; + } + effectCacheAnimSlotAnchors(entity); + handlers[entity->pc](entity); + g_effectParticleTotal = 0; + entity->unk05E = 0; + g_effectLiveTotal = 0; + entity->unk05E += func_800B2B68(&D_801D4424); + entity->unk05E += func_800B2B68(&D_801D44F4); + entity->unk05E += func_800B2B68(&g_effectChildPool); + entity->unk05C++; + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait == 0) { + effectReleaseWait(entity); + return 2; + } + } + return 0; +} diff --git a/src/effect/effect_052_entry.c b/src/effect/effect_052_entry.c new file mode 100644 index 00000000..f3edd25d --- /dev/null +++ b/src/effect/effect_052_entry.c @@ -0,0 +1,61 @@ +/** + * @file effect_052_entry.c + * @brief X-Potion: the overlay entry point. + */ +#include "common.h" +#include "effect.h" +#include "effect/lib/entity.h" +#include "effect/lib/tables.h" +#include "effect/effect_052.h" +#include "effect/effect_028_entry.h" + +/** @brief Stride between the prim and frame banks carved out of the TIM. */ +#define EFFECT_BANK_SIZE 0x6000 + +/** + * @brief Start the effect's script and hand back its task pool. + * + * @param animSet Animation set the effect plays. + * @return The pool the root entity lives in. + */ +void *func_801A0000(EffectAnimSet *animSet) { + u8 *bank0; + EffectEntity *entity; + u8 *bank1; + u8 *frames; + + D_801D3994 = 0; + D_801D3998 = 0; + func_800B2A00(&D_801D42B4, &D_801D41E4, 0x64, 2); + entity = effectSpawnTask(&D_801D42B4, func_801A99EC, 0x64, NULL); + entity->animSet = animSet; + entity->unk02C = animSet->anims[entity->unk02A].unk000; + entity->unk02D = + entity->animSet->anims[entity->unk02A].parts[entity->unk02B].unk000; + entity->pc = 0; + entity->unk05A = animSet->anims->unk010; + entity->unk058 = animSet->anims->unk011; + entity->unk02F = entity->unk05A - 1; + if (entity->unk02F < entity->unk058) { + entity->unk02F = entity->unk058; + } + if (!(animSet->flags & EFFECT_ANIMSET_FLAG_LOADED)) { + func_800C3BE0(&D_801A9DD4); + func_800BB084(&D_801AA974); + } + D_801D39A4 = &D_801AA974; + bank0 = &D_801AA974; + D_801D41CC = bank0; + bank1 = bank0 + EFFECT_BANK_SIZE; + D_801D41D4 = bank0 + EFFECT_BANK_SIZE; + D_801D39A4 = bank0 + EFFECT_BANK_SIZE; + frames = bank1; + D_801D41D0 = frames; + frames += EFFECT_BANK_SIZE; + D_801D39A4 = frames; + D_801D41D8 = frames; + func_800B2A00(&D_801D4424, &D_801D42C4, 0x58, 4); + func_800B2A00(&D_801D44F4, &D_801D4434, 0x3C, 3); + func_800B2A00(&g_effectChildPool, &D_801D39C4, 0x2A4, 3); + return &D_801D42B4; +} From 612fa36317c124c9f4e9e3c61e0140f46e3702dd Mon Sep 17 00:00:00 2001 From: rengstrom Date: Wed, 9 Sep 2026 17:15:19 +0000 Subject: [PATCH 2/5] effect_052: give the entry its own header The port left the entry taking its prototype from effect_028_entry.h, the overlay it was copied from. Both overlays declare the same signature under the same name, so it compiled and the binary matched -- nothing but reading the include would have shown it. X-Potion's entry now owns its declaration, the way the other three overlays' do. --- include/effect/effect_052_entry.h | 19 +++++++++++++++++++ src/effect/effect_052_entry.c | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 include/effect/effect_052_entry.h diff --git a/include/effect/effect_052_entry.h b/include/effect/effect_052_entry.h new file mode 100644 index 00000000..1f582804 --- /dev/null +++ b/include/effect/effect_052_entry.h @@ -0,0 +1,19 @@ +#ifndef EFFECT_EFFECT_052_ENTRY_H +#define EFFECT_EFFECT_052_ENTRY_H + +#include "effect.h" + +/** + * @file effect_052_entry.h + * @brief X-Potion: the overlay entry point. + */ + +/** + * @brief Start the effect's script and hand back its task pool. + * + * @param animSet Animation set the effect plays. + * @return The pool the root entity lives in. + */ +void *func_801A0000(EffectAnimSet *animSet); + +#endif /* EFFECT_EFFECT_052_ENTRY_H */ diff --git a/src/effect/effect_052_entry.c b/src/effect/effect_052_entry.c index f3edd25d..e2294ce6 100644 --- a/src/effect/effect_052_entry.c +++ b/src/effect/effect_052_entry.c @@ -7,7 +7,7 @@ #include "effect/lib/entity.h" #include "effect/lib/tables.h" #include "effect/effect_052.h" -#include "effect/effect_028_entry.h" +#include "effect/effect_052_entry.h" /** @brief Stride between the prim and frame banks carved out of the TIM. */ #define EFFECT_BANK_SIZE 0x6000 From f6ec986e19a1d827d273580fc0fc1ce9e808a3a4 Mon Sep 17 00:00:00 2001 From: rengstrom Date: Wed, 9 Sep 2026 19:25:57 +0000 Subject: [PATCH 3/5] Decompile the effect_039 overlay Drain runs Curaga's engine at Curaga's own offsets: all twenty library units land where they do there, and 276 addresses pair off the aligned relocation streams with nothing in conflict. Its script block lines up with Curaga's function for function, so twenty-eight of its thirty came across by position with the addresses rewritten. One function is Drain's own. Its take-model dispatcher spawns a screen tint at frame 4 as well as frame 20, each from its own step table, where Curaga spawns one. The bank carve looked new too but is not: it differs only in the addresses and the emitter bank's size, which its parameter header supplies -- Drain runs thirty-nine emitters where Curaga runs eighty-nine. That difference found a bug in the library. Both pool allocators bounded their search with a literal, `n < 0x5A`, which is Curaga's ring size rather than the ring's, so Drain built one byte wrong at the emitter's wrap test. The bound is the ring's own size now, and the doc says why it is one more than the ring holds: the search starts where the last one left off, so the slot it began on is the last it examines. --- Makefile | 2 +- config/ff8.yaml | 32 +- config/symbols.effect_039.txt | 114 ++++ include/effect/effect_039.h | 85 +++ include/effect/effect_039_entry.h | 19 + .../effect/params/effect_039/effect_params.h | 13 + src/effect/effect_039.c | 578 +++++++++++------- src/effect/effect_039_entry.c | 62 ++ src/effect/lib/emitteralloc.c | 5 +- src/effect/lib/particlealloc.c | 5 +- 10 files changed, 684 insertions(+), 231 deletions(-) create mode 100644 config/symbols.effect_039.txt create mode 100644 include/effect/effect_039.h create mode 100644 include/effect/effect_039_entry.h create mode 100644 include/effect/params/effect_039/effect_params.h create mode 100644 src/effect/effect_039_entry.c diff --git a/Makefile b/Makefile index 929082e8..10f5d97c 100644 --- a/Makefile +++ b/Makefile @@ -140,7 +140,7 @@ CODE_OVERLAYS := field_init intro field \ tripletriad battle_render battle world ALL_EFFECT_OVERLAYS := $(filter effect_%,$(SPLAT_BINARIES)) -EFFECTS ?= effect_001 effect_025 effect_028 effect_052 +EFFECTS ?= effect_001 effect_025 effect_028 effect_052 effect_039 EFFECT_OVERLAYS := $(if $(filter all,$(EFFECTS)),$(ALL_EFFECT_OVERLAYS),$(EFFECTS)) OVERLAYS := $(MENU_OVERLAYS) $(CODE_OVERLAYS) $(EFFECT_OVERLAYS) ALL_OVERLAYS := $(MENU_OVERLAYS) $(CODE_OVERLAYS) $(ALL_EFFECT_OVERLAYS) diff --git a/config/ff8.yaml b/config/ff8.yaml index 53db92e2..59980b5d 100644 --- a/config/ff8.yaml +++ b/config/ff8.yaml @@ -1301,15 +1301,41 @@ binaries: options: target_path: original/effect/effect_039.bin src_path: src/effect + section_order: [.text, .rodata, .data, .bss] segments: - name: effect_039 type: code start: 0x0 vram: 0x801A0000 subsegments: - - [0x0, c, effect_039] - - [0x9F34, .rodata, effect_039] - - [0x9F48, bin, effect_039] + - [0x0, c, effect_039_entry] + - [0x208, c, lib/common] + - [0x978, c, lib/rotz] + - [0xB04, c, lib/heading] + - [0xB34, c, lib/entity] + - [0x16A4, c, lib/tint] + - [0x1980, c, lib/vector] + - [0x20EC, c, lib/emit] + - [0x3F20, c, lib/packet] + - [0x4128, c, lib/particlestep] + - [0x541C, c, lib/particlealloc] + - [0x5538, c, lib/draw] + - [0x6194, c, lib/emitteralloc] + - [0x62B4, c, lib/spawn] + - [0x8068, c, lib/list] + - [0x8684, c, lib/trail] + - [0x87F8, c, lib/strands] + - [0x8CE4, c, lib/tables] + - [0x8FF8, c, lib/bankclear] + - [0x9050, c, lib/drawscript] + - [0x94B4, c, effect_039] + # particlestep's jump table, then the pad its section end carried, then + # list's two, then the script dispatch tables. + - [0x9F34, .rodata, lib/particlestep] + - [0x9F48, pad] + - [0x9F4C, .rodata, lib/list] + - [0x9F78, .rodata, effect_039] + - [0x9FD8, bin, effect_039] - [0x39744] - name: effect_040 sha1: 71c17ed17dd7557405ab4a9ef1ca1eb46383dddf diff --git a/config/symbols.effect_039.txt b/config/symbols.effect_039.txt new file mode 100644 index 00000000..9a2f0f7d --- /dev/null +++ b/config/symbols.effect_039.txt @@ -0,0 +1,114 @@ +func_801A0000 = 0x801A0000; // type:func +effectTextInit = 0x801A0208; // type:func +effectTextHex = 0x801A0358; // type:func +effectTextNewline = 0x801A0404; // type:func +effectNop = 0x801A0424; // type:func +effectDrawQuad128 = 0x801A042C; // type:func +effectDrawQuad256 = 0x801A0528; // type:func +effectMatrixIdentity = 0x801A0624; // type:func +effectMatrixRotX = 0x801A065C; // type:func +effectMatrixRotY = 0x801A07EC; // type:func +effectMatrixRotZ = 0x801A0978; // type:func +effectMatrixHeading = 0x801A0B04; // type:func +effectReleaseWait = 0x801A0B34; // type:func +effectSpawnTask = 0x801A0B5C; // type:func +effectCacheSlotAnchors = 0x801A0CE8; // type:func +effectSlotAnchor0 = 0x801A0E1C; // type:func +effectSlotAnchor1 = 0x801A0E4C; // type:func +effectSlotAnchorMid = 0x801A0E7C; // type:func +effectCacheAnimSlotAnchors = 0x801A0EAC; // type:func +effectAnimSlotAnchor0 = 0x801A0FE8; // type:func +effectAnimSlotAnchor1 = 0x801A1018; // type:func +effectAnimSlotAnchorMid = 0x801A1048; // type:func +effectUpdateModelBounds = 0x801A1078; // type:func +effectGetModelBounds = 0x801A12C4; // type:func +effectModelRadius = 0x801A1314; // type:func +effectModelHalfHeight = 0x801A13B8; // type:func +effectModelHalfWidth = 0x801A13E8; // type:func +effectModelHeight = 0x801A1440; // type:func +effectModelTop = 0x801A1464; // type:func +effectModelBottom = 0x801A14AC; // type:func +effectModelRandomY = 0x801A14F4; // type:func +effectModelCentreY = 0x801A15AC; // type:func +effectModelCentre = 0x801A1600; // type:func +effectZeroWords = 0x801A166C; // type:func +effectTintPlay = 0x801A16A4; // type:func +effectRandBetween = 0x801A1980; // type:func +effectRandProduct = 0x801A1A04; // type:func +effectRandVector = 0x801A1AA8; // type:func +effectMatrixFromAngles = 0x801A1B20; // type:func +effectJitterAngle = 0x801A1BEC; // type:func +effectJitterVector = 0x801A1C80; // type:func +effectJitterAngleS = 0x801A1CF8; // type:func +effectJitterSVector = 0x801A1D88; // type:func +effectCopyVector = 0x801A1E00; // type:func +effectFadeValue = 0x801A1E30; // type:func +effectFadeVector = 0x801A1E8C; // type:func +effectBlendPointSets = 0x801A1F58; // type:func +effectEmitTris = 0x801A20EC; // type:func +effectEmitQuads = 0x801A23B8; // type:func +effectEmitTexTris = 0x801A26DC; // type:func +effectEmitTexQuads = 0x801A2A64; // type:func +effectEmitGouraudTris = 0x801A2E48; // type:func +effectEmitGouraudQuads = 0x801A3150; // type:func +effectEmitGouraudTexTris = 0x801A34D8; // type:func +effectEmitGouraudTexQuads = 0x801A3894; // type:func +effectEmitStream = 0x801A3CDC; // type:func +effectBuildMeshPacket = 0x801A3F20; // type:func +effectParticleLateStep = 0x801A4128; // type:func +effectParticleAdvance = 0x801A41E0; // type:func +effectParticleAgeHold = 0x801A49E8; // type:func +effectParticlePose = 0x801A4ADC; // type:func +effectParticleAlloc = 0x801A541C; // type:func +effectStepRunKind = 0x801A5538; // type:func +effectStepFire = 0x801A5570; // type:func +effectParticleStep = 0x801A561C; // type:func +effectEmitterCountStep = 0x801A5708; // type:func +effectSpriteEmit = 0x801A5720; // type:func +effectSpritePacket = 0x801A5D4C; // type:func +effectParticleDrawPacket = 0x801A5FB4; // type:func +effectDrawParticles = 0x801A6074; // type:func +effectEmitterAlloc = 0x801A6194; // type:func +effectEmitterAge = 0x801A62B4; // type:func +effectEmitterSpawn = 0x801A631C; // type:func +effectEmitterSpawnShare = 0x801A6DB8; // type:func +effectEmitterStep = 0x801A6EB8; // type:func +effectEmitterOnStrand = 0x801A6F58; // type:func +effectEmitterOnTrail = 0x801A71E0; // type:func +effectEmitterOnOwner = 0x801A73E8; // type:func +effectEmitterSlide = 0x801A75F8; // type:func +effectListAppend = 0x801A8068; // type:func +effectListRemove = 0x801A80A4; // type:func +effectListClear = 0x801A80E4; // type:func +effectListRun = 0x801A80FC; // type:func +effectEmitterSetup = 0x801A8184; // type:func +effectStepFireSlots = 0x801A83B8; // type:func +effectEmittersOnCue = 0x801A846C; // type:func +effectTrailPush = 0x801A85A8; // type:func +effectTrailAim = 0x801A8684; // type:func +effectStrandsSeed = 0x801A87F8; // type:func +effectStrandsPush = 0x801A8904; // type:func +effectStrandsAim = 0x801A8A1C; // type:func +effectPoseTablesRelocate = 0x801A8CE4; // type:func +effectStartChildScript = 0x801A8F88; // type:func +effectBanksClear = 0x801A8FF8; // type:func +effectDrawScriptStart = 0x801A9050; // type:func +effectDrawScriptRun = 0x801A92F8; // type:func +effectDrawListSpan = 0x801A9420; // type:func +g_effectStackBase = 0x801D974C; +g_effectStackTop = 0x801D9750; +g_effectEmitterBank = 0x801D99F4; +g_effectParticleBank = 0x801D99F8; +g_effectDrawList = 0x801D99FC; +g_effectEmitterCursor = 0x801D9A00; +g_effectParticleCursor = 0x801D9A02; +g_effectParticleTotal = 0x801D9A04; +g_effectLiveTotal = 0x801D9A06; +g_effectBankUnk90 = 0x801D9A08; +g_effectBankUnk92 = 0x801D9A0A; +g_effectChildPool = 0x801DA204; +g_effectPrimCursor = 0x801DA214; +g_effectHexGlyphs = 0x801DA554; +g_effectTextX = 0x801DA568; +g_effectTextY = 0x801DA56C; +g_effectTextColour = 0x801DA570; diff --git a/include/effect/effect_039.h b/include/effect/effect_039.h new file mode 100644 index 00000000..14ae20e8 --- /dev/null +++ b/include/effect/effect_039.h @@ -0,0 +1,85 @@ +#ifndef EFFECT_EFFECT_039_H +#define EFFECT_EFFECT_039_H + +#include "effect.h" +#include "effect/lib/particle.h" +#include "effect/lib/tint.h" + +/** + * @file + * @brief Drain: the overlay's own storage. + */ + +extern s32 D_801DA474; + +/** @brief Pose script the model-taking handler runs. */ +extern EffectPoseTables D_801AC3C8; + +/** @brief Pool the trailing sparks are allocated from. */ +extern s32 D_801D99E4; + +/** @brief Cursor the record banks are carved off, moving up as they are taken. */ +extern u8 *D_801D9754; + +/** + * @name Overlay blob + * + * The data carried in the overlay image behind the code. + * @{ + */ + +/** @brief Table of two offsets battle.bin resolves when the effect starts. */ +extern u8 D_801B01EC; + +/** + * @brief TIM uploaded to VRAM when the effect starts. + * + * Once it is in VRAM the image memory is reused: the three prim and frame + * banks the renderer double-buffers through start at this address. + */ +extern u8 D_801B0924; +/** @} */ + +/** @brief Task pools the script's children run in. */ +extern s32 D_801DA304; +extern s32 D_801DA234; +extern s32 D_801DA314; +extern s32 D_801DA484; +extern s32 D_801D9A14; +extern s32 D_801D9764; + +/** @brief Cleared when the effect starts. */ +extern s32 D_801D9744; +extern s32 D_801D9748; + +/** + * @name Prim buffers + * + * Two of each, so the frame being built and the frame being drawn never share. + * @{ + */ +extern void *D_801DA21C; +extern void *D_801DA220; +extern void *D_801DA224; +extern void *D_801DA228; +/** @} */ + +/** @brief Cursor the effect's second prim buffer is written through. */ +extern void *D_801DA218; + +/** @brief Sound cue the take-model script fires on its first frame. */ +extern u8 D_801AA010[]; + +/** @brief Argument the frame-20 child is started with. */ +extern EffectTintStep D_801A9FE4[]; +extern EffectTintStep D_801A9FF0[]; + +/** @brief Pool the frame-20 child is allocated from. */ +extern s32 D_801DA544; + +/** + * @brief Run one frame of the effect: its opcode, then every task pool it owns. + */ +s32 func_801A9D2C(EffectEntity *entity); + +#endif /* EFFECT_EFFECT_039_H */ diff --git a/include/effect/effect_039_entry.h b/include/effect/effect_039_entry.h new file mode 100644 index 00000000..f7e5aeac --- /dev/null +++ b/include/effect/effect_039_entry.h @@ -0,0 +1,19 @@ +#ifndef EFFECT_EFFECT_039_ENTRY_H +#define EFFECT_EFFECT_039_ENTRY_H + +#include "effect.h" + +/** + * @file effect_039_entry.h + * @brief Drain: the overlay entry point. + */ + +/** + * @brief Start the effect's script and hand back its task pool. + * + * @param animSet Animation set the effect plays. + * @return The pool the root entity lives in. + */ +void *func_801A0000(EffectAnimSet *animSet); + +#endif /* EFFECT_EFFECT_039_ENTRY_H */ diff --git a/include/effect/params/effect_039/effect_params.h b/include/effect/params/effect_039/effect_params.h new file mode 100644 index 00000000..013d275c --- /dev/null +++ b/include/effect/params/effect_039/effect_params.h @@ -0,0 +1,13 @@ +#ifndef EFFECT_PARAMS_H +#define EFFECT_PARAMS_H + +/** + * @file effect_params.h + * @brief Drain: the ring sizes its particle engine is built with. + */ + +/** @brief Highest index each ring reaches before it wraps. */ +#define EFFECT_EMITTER_COUNT 0x27 +#define EFFECT_PARTICLE_COUNT 0x8B + +#endif /* EFFECT_PARAMS_H */ diff --git a/src/effect/effect_039.c b/src/effect/effect_039.c index e22f86cb..c7af5bf2 100644 --- a/src/effect/effect_039.c +++ b/src/effect/effect_039.c @@ -3,261 +3,393 @@ * @brief Drain */ #include "common.h" - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0000); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0208); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0358); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0404); - -void func_801A0424(void) { +#include "game.h" +#include "effect.h" +#include "psxsdk/libgte.h" +#include "psxsdk/libgpu.h" +#include "effect/effect_039.h" +#include "effect/lib/particle.h" +#include "effect/lib/entity.h" +#include "effect/lib/tint.h" +#include "effect/lib/bankclear.h" +#include "effect/lib/tables.h" +#include "effect/lib/drawscript.h" +#include "effect/lib/common.h" +#include "effect_params.h" +#include "btl_entity.h" + +/** @brief Where in the scratchpad the effect keeps its view matrix. */ +#define EFFECT_SCRATCHPAD ((MATRIX *)0x1F8002E0) + +/** @brief @ref EffectEntity::unk05C -- the frame counter's low bit picks a bank. */ +#define EFFECT_FRAME_ODD 0x1 + +static s32 func_801A9994(EffectEntity *entity); +static void func_801A94B4(EffectEntity *entity); +static void func_801A9500(EffectEntity *entity); +static void func_801A9568(EffectEntity *entity); +static s32 func_801A9570(EffectEntity *entity); +static void func_801A9610(EffectEntity *entity); +static void func_801A9628(EffectEntity *entity); +static void func_801A9684(EffectEntity *entity); +static s32 func_801A968C(EffectEntity *entity); +static void func_801A972C(EffectEntity *entity); +static void func_801A9788(EffectEntity *entity); +static void func_801A97D0(EffectEntity *entity); +static s32 func_801A97D8(EffectEntity *entity); +static void func_801A9878(EffectEntity *entity); +static void func_801A98D0(EffectEntity *entity); +static void func_801A9904(EffectEntity *entity); +static void func_801A998C(EffectEntity *entity); +static void func_801A9ADC(EffectEntity *entity); +static void func_801A9AF0(EffectEntity *entity); +static void func_801A9B04(EffectEntity *entity); +static void func_801A9B94(EffectEntity *entity); +static void func_801A9BEC(EffectEntity *entity); +static void func_801A9C50(EffectEntity *entity); +static void func_801A9CB8(EffectEntity *entity); +static void func_801A9CE0(EffectEntity *entity); +static void func_801A9CF4(EffectEntity *entity); +static void func_801A9D08(EffectEntity *entity); +static void func_801A9D24(EffectEntity *entity); + +/** @brief Opcode handler: clear the screen tint. */ +static void func_801A94B4(EffectEntity *entity) { + BattleTint *tint = D_800EF738; + s32 i; + + entity->pos.vx = 0; + for (i = 0; i < 4; i++) { + tint->level = entity->pos.vx; + tint->b = 0; + tint->g = 0; + tint->r = 0; + tint++; + } + entity->pc++; } -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A042C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0528); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0624); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A065C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A07EC); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0978); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0B04); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0B34); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0B5C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0CE8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0E1C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0E4C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0E7C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0EAC); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A0FE8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1018); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1048); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1078); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A12C4); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1314); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A13B8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A13E8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1440); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1464); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A14AC); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A14F4); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A15AC); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1600); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A166C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A16A4); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1980); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1A04); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1AA8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1B20); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1BEC); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1C80); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1CF8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1D88); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1E00); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1E30); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1E8C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A1F58); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A20EC); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A23B8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A26DC); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A2A64); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A2E48); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A3150); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A34D8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A3894); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A3CDC); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A3F20); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A4128); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A41E0); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A49E8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A4ADC); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A541C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A5538); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A5570); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A561C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A5708); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A5720); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A5D4C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A5FB4); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A6074); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A6194); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A62B4); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A631C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A6DB8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A6EB8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A6F58); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A71E0); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A73E8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A75F8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A8068); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A80A4); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A80E4); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A80FC); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A8184); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A83B8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A846C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A85A8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A8684); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A87F8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A8904); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A8A1C); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A8CE4); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A8F88); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A8FF8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9050); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A92F8); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9420); - -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A94B4); +/** @brief Opcode handler: fade the screen tint up to full, then stop. */ +static void func_801A9500(EffectEntity *entity) { + BattleTint *tint = D_800EF738; + s32 i; + + entity->pos.vx += 0x100; + if (entity->pos.vx >= 0x400) { + entity->pos.vx = 0x400; + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } + for (i = 3; i >= 0; i--) { + tint->level = entity->pos.vx; + tint++; + } +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9500); +/** @brief Opcode handler: no-op. */ +static void func_801A9568(EffectEntity *entity) { +} -void func_801A9568(void) { +/** + * @brief Script dispatcher: run this frame's step, draw, and retire the entity. + * + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ +static s32 func_801A9570(EffectEntity *entity) { + EffectHandler handlers[3] = { func_801A94B4, func_801A9500, func_801A9568 }; + + handlers[entity->pc](entity); + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait != 0) { + return 0; + } + effectReleaseWait(entity); + return 2; + } + return 0; } -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9570); +/** @brief Opcode handler: hold the tint at a quarter. */ +static void func_801A9610(EffectEntity *entity) { + entity->pos.vx = 0x400; + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9610); +/** @brief Opcode handler: fade the screen tint back out, then stop. */ +static void func_801A9628(EffectEntity *entity) { + BattleTint *tint = D_800EF738; + s32 i; + + entity->pos.vx -= 0x100; + if (entity->pos.vx <= 0) { + entity->pos.vx = 0; + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } + for (i = 3; i >= 0; i--) { + tint->level = entity->pos.vx; + tint++; + } +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9628); +/** @brief Opcode handler: no-op. */ +static void func_801A9684(EffectEntity *entity) { +} -void func_801A9684(void) { +/** + * @brief Script dispatcher: run this frame's step, draw, and retire the entity. + * + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ +static s32 func_801A968C(EffectEntity *entity) { + EffectHandler handlers[3] = { func_801A9610, func_801A9628, func_801A9684 }; + + handlers[entity->pc](entity); + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait != 0) { + return 0; + } + effectReleaseWait(entity); + return 2; + } + return 0; } -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A968C); +/** @brief Opcode handler: draw and retire once the frame count is reached. */ +static void func_801A972C(EffectEntity *entity) { + EffectDrawScript *script = (EffectDrawScript *)entity; -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A972C); + if (entity->unk024 >= script->stopFrame) { + /* Called with no argument: the entity is already in $a0 and stays there. */ + ((void (*)())effectDrawScriptStart)(); + effectDrawScriptRun(script); + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9788); +/** @brief Opcode handler: hold still until the count runs out. */ +static void func_801A9788(EffectEntity *entity) { + if (effectDrawScriptRun((EffectDrawScript *)entity) != 0) { + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } +} -void func_801A97D0(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A97D0(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A97D8); +/** + * @brief Script dispatcher: run this frame's step, draw, and retire the entity. + * + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ +static s32 func_801A97D8(EffectEntity *entity) { + EffectHandler handlers[3] = { func_801A972C, func_801A9788, func_801A97D0 }; + + handlers[entity->pc](entity); + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait != 0) { + return 0; + } + effectReleaseWait(entity); + return 2; + } + return 0; +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9878); +/** @brief Opcode handler: start the pose script on the taken model. */ +static void func_801A9878(EffectEntity *entity) { + effectStartChildScript(entity, func_801A97D8, &D_801AC3C8, 0, 0x2D, 0); + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A98D0); +/** @brief Opcode handler: release the model once the count reaches 30. */ +static void func_801A98D0(EffectEntity *entity) { + if (entity->unk024 == 30) { + entity->unk010->unk063 = 0; + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9904); +/** @brief Opcode handler: hand the current part to battle, then stop. */ +static void func_801A9904(EffectEntity *entity) { + if (entity->unk024 >= 30) { + func_800BFE1C(&entity->animSet->anims[entity->unk02A].parts[entity->unk02B]); + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } +} -void func_801A998C(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A998C(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9994); +/** + * @brief Script dispatcher: the take-model script, with its three timed cues. + * + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ +static s32 func_801A9994(EffectEntity *entity) { + EffectHandler handlers[4] = { func_801A9878, func_801A98D0, func_801A9904, func_801A998C }; + + effectCacheSlotAnchors(entity); + effectUpdateModelBounds(entity); + handlers[entity->pc](entity); + if (entity->unk024 == 0) { + func_800C4764(D_801AA010, 0, 0x80); + } + if (entity->unk024 == 4) { + EffectTintScript *child = + effectSpawnTask(&D_801DA544, effectTintPlay, sizeof(EffectTintScript), entity); + + child->steps = D_801A9FE4; + } + if (entity->unk024 == 20) { + EffectTintScript *child = + effectSpawnTask(&D_801DA544, effectTintPlay, sizeof(EffectTintScript), entity); + + child->steps = D_801A9FF0; + } + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait != 0) { + return 0; + } + effectReleaseWait(entity); + return 2; + } + return 0; +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9ADC); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9ADC(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9AF0); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9AF0(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9B04); +/** @brief Opcode handler: carve both record banks and start the draw script. */ +static void func_801A9B04(EffectEntity *entity) { + if (entity->wait == 0) { + /* Both banks are carved out of the same byte arena behind the TIM. */ + g_effectEmitterBank = (EffectEmitter *)D_801D9754; + D_801D9754 += EFFECT_EMITTER_BANK_BYTES; + g_effectParticleBank = (EffectParticle *)D_801D9754; + D_801D9754 += EFFECT_PARTICLE_BANK_BYTES; + effectBanksClear(); + effectSpawnTask(&D_801D99E4, func_801A9570, 0x40, entity); + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9B94); +/** @brief Opcode handler: start a task running @ref func_801A9994. */ +static void func_801A9B94(EffectEntity *entity) { + entity->unk063 = 1; + effectSpawnTask(&D_801DA474, func_801A9994, 0x58, entity); + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9BEC); +/** @brief Opcode handler: repeat the step until the loop counter runs out. */ +static void func_801A9BEC(EffectEntity *entity) { + if (entity->unk063 == 0) { + if (entity->unk02A < entity->unk058) { + entity->unk02A++; + entity->unk02E++; + entity->pc--; + } else { + /* The byte trio at unk060 is this script's countdown, one halfword wide. */ + *(s16 *)entity->unk060 = 10; + entity->pc++; + } + } +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9C50); +/** @brief Opcode handler: spawn the trailing spark once the wait runs out. */ +static void func_801A9C50(EffectEntity *entity) { + /* The byte trio at unk060 is this script's countdown, one halfword wide. */ + if (--*(s16 *)entity->unk060 <= 0) { + effectSpawnTask(&D_801D99E4, func_801A968C, 0x40, entity); + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9CB8); +/** @brief Opcode handler: stall here until @c unk05E reaches zero. */ +static void func_801A9CB8(EffectEntity *entity) { + if (entity->unk05E == 0) { + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9CE0); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9CE0(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9CF4); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9CF4(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9D08); +/** @brief Opcode handler: raise @ref EFFECT_FLAG_STOP and consume the opcode. */ +static void func_801A9D08(EffectEntity *entity) { + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; +} -void func_801A9D24(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A9D24(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_039/nonmatchings/effect_039", func_801A9D2C); +/** + * @brief Run one frame of the effect: its opcode, then every task pool it owns. + * + * @return 2 once the script has stopped and its children have drained. + */ +s32 func_801A9D2C(EffectEntity *entity) { + EffectHandler handlers[11] = { + func_801A9ADC, func_801A9AF0, func_801A9B04, func_801A9B94, func_801A9BEC, + func_801A9C50, func_801A9CB8, func_801A9CE0, func_801A9CF4, func_801A9D08, + func_801A9D24 + }; + MATRIX *view = EFFECT_SCRATCHPAD; + + *view = D_800F02C8; + g_effectStackTop = (u8 *)view; + g_effectStackBase = view; + if (entity->unk05C & EFFECT_FRAME_ODD) { + g_effectPrimCursor = D_801DA21C; + D_801DA218 = D_801DA224; + } else { + g_effectPrimCursor = D_801DA220; + D_801DA218 = D_801DA228; + } + effectCacheAnimSlotAnchors(entity); + handlers[entity->pc](entity); + g_effectParticleTotal = 0; + entity->unk05E = 0; + g_effectLiveTotal = 0; + entity->unk05E += func_800B2B68(&D_801DA474); + entity->unk05E += func_800B2B68(&D_801DA544); + entity->unk05E += func_800B2B68(&g_effectChildPool); + entity->unk05E += func_800B2B68(&D_801D99E4); + entity->unk05C++; + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait == 0) { + effectReleaseWait(entity); + return 2; + } + } + return 0; +} diff --git a/src/effect/effect_039_entry.c b/src/effect/effect_039_entry.c new file mode 100644 index 00000000..7389ba95 --- /dev/null +++ b/src/effect/effect_039_entry.c @@ -0,0 +1,62 @@ +/** + * @file effect_039_entry.c + * @brief Drain: the overlay entry point. + */ +#include "common.h" +#include "effect.h" +#include "effect/lib/entity.h" +#include "effect/lib/tables.h" +#include "effect/effect_039.h" +#include "effect/effect_039_entry.h" + +/** @brief Stride between the prim and frame banks carved out of the TIM. */ +#define EFFECT_BANK_SIZE 0x6000 + +/** + * @brief Start the effect's script and hand back its task pool. + * + * @param animSet Animation set the effect plays. + * @return The pool the root entity lives in. + */ +void *func_801A0000(EffectAnimSet *animSet) { + u8 *bank0; + EffectEntity *entity; + u8 *bank1; + u8 *frames; + + D_801D9744 = 0; + D_801D9748 = 0; + func_800B2A00(&D_801DA304, &D_801DA234, 0x64, 2); + entity = effectSpawnTask(&D_801DA304, func_801A9D2C, 0x64, NULL); + entity->animSet = animSet; + entity->unk02C = animSet->anims[entity->unk02A].unk000; + entity->unk02D = + entity->animSet->anims[entity->unk02A].parts[entity->unk02B].unk000; + entity->pc = 0; + entity->unk05A = animSet->anims->unk010; + entity->unk058 = animSet->anims->unk011; + entity->unk02F = entity->unk05A - 1; + if (entity->unk02F < entity->unk058) { + entity->unk02F = entity->unk058; + } + if (!(animSet->flags & EFFECT_ANIMSET_FLAG_LOADED)) { + func_800C3BE0(&D_801B01EC); + func_800BB084(&D_801B0924); + } + D_801D9754 = &D_801B0924; + bank0 = &D_801B0924; + D_801DA21C = bank0; + bank1 = bank0 + EFFECT_BANK_SIZE; + D_801DA224 = bank0 + EFFECT_BANK_SIZE; + D_801D9754 = bank0 + EFFECT_BANK_SIZE; + frames = bank1; + D_801DA220 = frames; + frames += EFFECT_BANK_SIZE; + D_801D9754 = frames; + D_801DA228 = frames; + func_800B2A00(&D_801DA474, &D_801DA314, 0x58, 4); + func_800B2A00(&D_801DA544, &D_801DA484, 0x3C, 3); + func_800B2A00(&g_effectChildPool, &D_801D9A14, 0x2A4, 3); + func_800B2A00(&D_801D99E4, &D_801D9764, 0x40, 0xA); + return &D_801DA304; +} diff --git a/src/effect/lib/emitteralloc.c b/src/effect/lib/emitteralloc.c index 0b30f13b..8de49bbf 100644 --- a/src/effect/lib/emitteralloc.c +++ b/src/effect/lib/emitteralloc.c @@ -14,7 +14,8 @@ /** * @brief Allocate an emitter from its pool and put it on the draw list. * - * The search starts where the last one left off and gives up after one lap. + * The search starts where the last one left off, and tries one slot more + * than the ring holds, so the slot it started on is examined last. * * @return The emitter, or NULL when the pool is full. */ @@ -23,7 +24,7 @@ EffectEmitter *effectEmitterAlloc(void *owner, s16 source, s16 index) { s32 i = g_effectEmitterCursor; s32 n; - for (n = 0; n < 0x5A; n++) { + for (n = 0; n < EFFECT_EMITTER_COUNT + 1; n++) { if (g_effectEmitterBank[i].inUse == 0) { EffectEmitter *emitter = &g_effectEmitterBank[i]; diff --git a/src/effect/lib/particlealloc.c b/src/effect/lib/particlealloc.c index c9e8fc58..67ccc459 100644 --- a/src/effect/lib/particlealloc.c +++ b/src/effect/lib/particlealloc.c @@ -13,7 +13,8 @@ /** * @brief Allocate a particle from its pool and put it on the draw list. * - * The search starts where the last one left off and gives up after one lap. + * The search starts where the last one left off, and tries one slot more + * than the ring holds, so the slot it started on is examined last. * * @return The particle, or NULL when the pool is full. */ @@ -22,7 +23,7 @@ EffectParticle *effectParticleAlloc(EffectEmitter *owner, u8 source) { s32 i = g_effectParticleCursor; s32 n; - for (n = 0; n < 0x8C; n++) { + for (n = 0; n < EFFECT_PARTICLE_COUNT + 1; n++) { if (g_effectParticleBank[i].inUse == 0) { EffectParticle *particle = &g_effectParticleBank[i]; From 54474c33edc9340447ebe45ff92acf5145c3eca5 Mon Sep 17 00:00:00 2001 From: rengstrom Date: Wed, 9 Sep 2026 20:24:02 +0000 Subject: [PATCH 4/5] Decompile the effect_036 overlay and build three twins from their sources effect_050, effect_051 and effect_056 are byte-identical to effect_001, effect_025 and effect_039, so each yaml entry names the twin's own source files at the twin's offsets. They need only a symbol file of their own, and effect_056 a parameter header. No new C. effect_036 (Confuse) links the same nineteen library units as effect_039 in the same order, four bytes along. 99 of its 121 functions come from src/effect/lib, and 16 of the remaining 21 are bodies already written for effect_001, effect_025 and effect_028 -- five of them the same handler that consumes an opcode and does nothing else. lib/bankclear is 84 bytes here against effect_039's 88 because Confuse's particle bank fits a 16-bit immediate where Drain's needs lui and ori. Both ring sizes fall out of those two immediates: 0x1D emitters and 0x31 particles. func_800C2BD0 had no declaration and one parameter, but its only caller passes two, and its sibling func_800C2B88 has the same shape with two. An unused parameter emits no code, so the definition takes the second one and types the first as the slot it is handed; the pointer the flags hang off is named on BattleEffectSlot rather than reached at 0x74. --- Makefile | 2 +- config/ff8.yaml | 100 +++- config/symbols.effect_036.txt | 113 ++++ config/symbols.effect_050.txt | 49 ++ config/symbols.effect_051.txt | 72 +++ config/symbols.effect_056.txt | 114 ++++ include/battle.h | 6 +- include/battle/bc_object13.h | 3 + include/effect/effect_036.h | 86 +++ include/effect/effect_036_entry.h | 19 + .../effect/params/effect_036/effect_params.h | 13 + .../effect/params/effect_056/effect_params.h | 13 + src/battle/bc_object13.c | 30 +- src/effect/effect_036.c | 496 ++++++++++-------- src/effect/effect_036_entry.c | 62 +++ src/effect/effect_050.c | 169 ------ src/effect/effect_051.c | 294 ----------- src/effect/effect_056.c | 263 ---------- 18 files changed, 936 insertions(+), 968 deletions(-) create mode 100644 config/symbols.effect_036.txt create mode 100644 config/symbols.effect_050.txt create mode 100644 config/symbols.effect_051.txt create mode 100644 config/symbols.effect_056.txt create mode 100644 include/effect/effect_036.h create mode 100644 include/effect/effect_036_entry.h create mode 100644 include/effect/params/effect_036/effect_params.h create mode 100644 include/effect/params/effect_056/effect_params.h create mode 100644 src/effect/effect_036_entry.c delete mode 100644 src/effect/effect_050.c delete mode 100644 src/effect/effect_051.c delete mode 100644 src/effect/effect_056.c diff --git a/Makefile b/Makefile index 10f5d97c..2206756c 100644 --- a/Makefile +++ b/Makefile @@ -140,7 +140,7 @@ CODE_OVERLAYS := field_init intro field \ tripletriad battle_render battle world ALL_EFFECT_OVERLAYS := $(filter effect_%,$(SPLAT_BINARIES)) -EFFECTS ?= effect_001 effect_025 effect_028 effect_052 effect_039 +EFFECTS ?= effect_001 effect_025 effect_028 effect_052 effect_039 effect_056 effect_050 effect_051 effect_036 EFFECT_OVERLAYS := $(if $(filter all,$(EFFECTS)),$(ALL_EFFECT_OVERLAYS),$(EFFECTS)) OVERLAYS := $(MENU_OVERLAYS) $(CODE_OVERLAYS) $(EFFECT_OVERLAYS) ALL_OVERLAYS := $(MENU_OVERLAYS) $(CODE_OVERLAYS) $(ALL_EFFECT_OVERLAYS) diff --git a/config/ff8.yaml b/config/ff8.yaml index 59980b5d..d87ccc74 100644 --- a/config/ff8.yaml +++ b/config/ff8.yaml @@ -1256,16 +1256,41 @@ binaries: options: target_path: original/effect/effect_036.bin src_path: src/effect + section_order: [.text, .rodata, .data, .bss] segments: - name: effect_036 type: code start: 0x0 vram: 0x801A0000 subsegments: - - [0x0, c, effect_036] - - [0x9D6C, .rodata, effect_036] - - [0x9D80, bin, effect_036] + - [0x0, c, effect_036_entry] + - [0x20C, c, lib/common] + - [0x97C, c, lib/rotz] + - [0xB08, c, lib/heading] + - [0xB38, c, lib/entity] + - [0x16A8, c, lib/tint] + - [0x1984, c, lib/vector] + - [0x20F0, c, lib/emit] + - [0x3F24, c, lib/packet] + - [0x412C, c, lib/particlestep] + - [0x5420, c, lib/particlealloc] + - [0x553C, c, lib/draw] + - [0x6198, c, lib/emitteralloc] + - [0x62B8, c, lib/spawn] + - [0x806C, c, lib/list] + - [0x8688, c, lib/trail] + - [0x87FC, c, lib/strands] + - [0x8CE8, c, lib/tables] + - [0x8FFC, c, lib/bankclear] + - [0x9050, c, lib/drawscript] + - [0x94B4, c, effect_036] + - [0x9D6C, .rodata, lib/particlestep] + - [0x9D80, pad] + - [0x9D84, .rodata, lib/list] + - [0x9DB0, .rodata, effect_036] + - [0x9DF8, bin, effect_036] - [0x422F0] + - name: effect_037 sha1: b612bceb1b012825e0742387b0c698f409303e42 options: @@ -1492,14 +1517,24 @@ binaries: options: target_path: original/effect/effect_050.bin src_path: src/effect + section_order: [.text, .rodata, .data, .bss] segments: - name: effect_050 type: code start: 0x0 vram: 0x801A0000 subsegments: - - [0x0, c, effect_050] - - [0x4614, .rodata, effect_050] + # Potion+ is byte for byte effect_001, so it links effect_001's sources. + - [0x0, c, effect_001_entry] + - [0x1F0, c, lib/common] + - [0x960, c, lib/aim] + - [0xAD8, c, lib/entity] + - [0x1648, c, lib/sprite] + - [0x16E4, c, lib/step] + - [0x172C, c, effect_001_anim] + - [0x181C, c, lib/render] + - [0x2E48, c, effect_001] + - [0x4614, .rodata, effect_001] - [0x4678, bin, effect_050] - [0x258E0] - name: effect_051 @@ -1507,14 +1542,34 @@ binaries: options: target_path: original/effect/effect_051.bin src_path: src/effect + section_order: [.text, .rodata, .data, .bss] segments: - name: effect_051 type: code start: 0x0 vram: 0x801A0000 subsegments: - - [0x0, c, effect_051] - - [0x8304, .rodata, effect_051] + # Hi-Potion+ is byte for byte effect_025, so it links effect_025's sources. + - [0x0, c, effect_025_entry] + - [0x14C, c, lib/common] + - [0x8BC, c, lib/aim] + - [0xA34, c, lib/heading] + - [0xA64, c, lib/scatter] + - [0xB6C, c, lib/render] + - [0x2198, c, lib/entity] + - [0x2D08, c, lib/emit_mode] + - [0x4BFC, c, effect_025_scroll] + - [0x4F44, c, lib/sprite] + - [0x4FE0, c, effect_025_anim] + - [0x5204, c, lib/step] + - [0x524C, c, effect_025_motes] + - [0x5CEC, c, lib/fill] + - [0x5D10, c, lib/rot] + - [0x5F14, c, lib/pose] + - [0x6910, c, lib/interpolate] + - [0x6A00, c, effect_025] + - [0x8304, .rodata, effect_025_motes] + - [0x8344, .rodata, effect_025] - [0x83D0, bin, effect_051] - [0x33EA4] - name: effect_052 @@ -1608,15 +1663,40 @@ binaries: options: target_path: original/effect/effect_056.bin src_path: src/effect + section_order: [.text, .rodata, .data, .bss] segments: - name: effect_056 type: code start: 0x0 vram: 0x801A0000 subsegments: - - [0x0, c, effect_056] - - [0x9F34, .rodata, effect_056] - - [0x9F48, bin, effect_056] + # Absorb is byte for byte effect_039 (Drain), so it links Drain's sources. + - [0x0, c, effect_039_entry] + - [0x208, c, lib/common] + - [0x978, c, lib/rotz] + - [0xB04, c, lib/heading] + - [0xB34, c, lib/entity] + - [0x16A4, c, lib/tint] + - [0x1980, c, lib/vector] + - [0x20EC, c, lib/emit] + - [0x3F20, c, lib/packet] + - [0x4128, c, lib/particlestep] + - [0x541C, c, lib/particlealloc] + - [0x5538, c, lib/draw] + - [0x6194, c, lib/emitteralloc] + - [0x62B4, c, lib/spawn] + - [0x8068, c, lib/list] + - [0x8684, c, lib/trail] + - [0x87F8, c, lib/strands] + - [0x8CE4, c, lib/tables] + - [0x8FF8, c, lib/bankclear] + - [0x9050, c, lib/drawscript] + - [0x94B4, c, effect_039] + - [0x9F34, .rodata, lib/particlestep] + - [0x9F48, pad] + - [0x9F4C, .rodata, lib/list] + - [0x9F78, .rodata, effect_039] + - [0x9FD8, bin, effect_056] - [0x39744] - name: effect_057 sha1: 1ae05f01dd5c2a348e1f11bfad13b9419ee00177 diff --git a/config/symbols.effect_036.txt b/config/symbols.effect_036.txt new file mode 100644 index 00000000..1d9bf5c2 --- /dev/null +++ b/config/symbols.effect_036.txt @@ -0,0 +1,113 @@ +effectTextInit = 0x801A020C; // type:func +effectTextHex = 0x801A035C; // type:func +effectTextNewline = 0x801A0408; // type:func +effectNop = 0x801A0428; // type:func +effectDrawQuad128 = 0x801A0430; // type:func +effectDrawQuad256 = 0x801A052C; // type:func +effectMatrixIdentity = 0x801A0628; // type:func +effectMatrixRotX = 0x801A0660; // type:func +effectMatrixRotY = 0x801A07F0; // type:func +effectMatrixRotZ = 0x801A097C; // type:func +effectMatrixHeading = 0x801A0B08; // type:func +effectReleaseWait = 0x801A0B38; // type:func +effectSpawnTask = 0x801A0B60; // type:func +effectCacheSlotAnchors = 0x801A0CEC; // type:func +effectSlotAnchor0 = 0x801A0E20; // type:func +effectSlotAnchor1 = 0x801A0E50; // type:func +effectSlotAnchorMid = 0x801A0E80; // type:func +effectCacheAnimSlotAnchors = 0x801A0EB0; // type:func +effectAnimSlotAnchor0 = 0x801A0FEC; // type:func +effectAnimSlotAnchor1 = 0x801A101C; // type:func +effectAnimSlotAnchorMid = 0x801A104C; // type:func +effectUpdateModelBounds = 0x801A107C; // type:func +effectGetModelBounds = 0x801A12C8; // type:func +effectModelRadius = 0x801A1318; // type:func +effectModelHalfHeight = 0x801A13BC; // type:func +effectModelHalfWidth = 0x801A13EC; // type:func +effectModelHeight = 0x801A1444; // type:func +effectModelTop = 0x801A1468; // type:func +effectModelBottom = 0x801A14B0; // type:func +effectModelRandomY = 0x801A14F8; // type:func +effectModelCentreY = 0x801A15B0; // type:func +effectModelCentre = 0x801A1604; // type:func +effectZeroWords = 0x801A1670; // type:func +effectTintPlay = 0x801A16A8; // type:func +effectRandBetween = 0x801A1984; // type:func +effectRandProduct = 0x801A1A08; // type:func +effectRandVector = 0x801A1AAC; // type:func +effectMatrixFromAngles = 0x801A1B24; // type:func +effectJitterAngle = 0x801A1BF0; // type:func +effectJitterVector = 0x801A1C84; // type:func +effectJitterAngleS = 0x801A1CFC; // type:func +effectJitterSVector = 0x801A1D8C; // type:func +effectCopyVector = 0x801A1E04; // type:func +effectFadeValue = 0x801A1E34; // type:func +effectFadeVector = 0x801A1E90; // type:func +effectBlendPointSets = 0x801A1F5C; // type:func +effectEmitTris = 0x801A20F0; // type:func +effectEmitQuads = 0x801A23BC; // type:func +effectEmitTexTris = 0x801A26E0; // type:func +effectEmitTexQuads = 0x801A2A68; // type:func +effectEmitGouraudTris = 0x801A2E4C; // type:func +effectEmitGouraudQuads = 0x801A3154; // type:func +effectEmitGouraudTexTris = 0x801A34DC; // type:func +effectEmitGouraudTexQuads = 0x801A3898; // type:func +effectEmitStream = 0x801A3CE0; // type:func +effectBuildMeshPacket = 0x801A3F24; // type:func +effectParticleLateStep = 0x801A412C; // type:func +effectParticleAdvance = 0x801A41E4; // type:func +effectParticleAgeHold = 0x801A49EC; // type:func +effectParticlePose = 0x801A4AE0; // type:func +effectParticleAlloc = 0x801A5420; // type:func +effectStepRunKind = 0x801A553C; // type:func +effectStepFire = 0x801A5574; // type:func +effectParticleStep = 0x801A5620; // type:func +effectEmitterCountStep = 0x801A570C; // type:func +effectSpriteEmit = 0x801A5724; // type:func +effectSpritePacket = 0x801A5D50; // type:func +effectParticleDrawPacket = 0x801A5FB8; // type:func +effectDrawParticles = 0x801A6078; // type:func +effectEmitterAlloc = 0x801A6198; // type:func +effectEmitterAge = 0x801A62B8; // type:func +effectEmitterSpawn = 0x801A6320; // type:func +effectEmitterSpawnShare = 0x801A6DBC; // type:func +effectEmitterStep = 0x801A6EBC; // type:func +effectEmitterOnStrand = 0x801A6F5C; // type:func +effectEmitterOnTrail = 0x801A71E4; // type:func +effectEmitterOnOwner = 0x801A73EC; // type:func +effectEmitterSlide = 0x801A75FC; // type:func +effectListAppend = 0x801A806C; // type:func +effectListRemove = 0x801A80A8; // type:func +effectListClear = 0x801A80E8; // type:func +effectListRun = 0x801A8100; // type:func +effectEmitterSetup = 0x801A8188; // type:func +effectStepFireSlots = 0x801A83BC; // type:func +effectEmittersOnCue = 0x801A8470; // type:func +effectTrailPush = 0x801A85AC; // type:func +effectTrailAim = 0x801A8688; // type:func +effectStrandsSeed = 0x801A87FC; // type:func +effectStrandsPush = 0x801A8908; // type:func +effectStrandsAim = 0x801A8A20; // type:func +effectPoseTablesRelocate = 0x801A8CE8; // type:func +effectStartChildScript = 0x801A8F8C; // type:func +effectBanksClear = 0x801A8FFC; // type:func +effectDrawScriptStart = 0x801A9050; // type:func +effectDrawScriptRun = 0x801A92F8; // type:func +effectDrawListSpan = 0x801A9420; // type:func +g_effectStackBase = 0x801E22F8; +g_effectStackTop = 0x801E22FC; +g_effectEmitterBank = 0x801E25A0; +g_effectParticleBank = 0x801E25A4; +g_effectDrawList = 0x801E25A8; +g_effectEmitterCursor = 0x801E25AC; +g_effectParticleCursor = 0x801E25AE; +g_effectParticleTotal = 0x801E25B0; +g_effectLiveTotal = 0x801E25B2; +g_effectChildPool = 0x801E2DB0; +g_effectPrimCursor = 0x801E2DC0; +g_effectHexGlyphs = 0x801E3100; +g_effectTextX = 0x801E3114; +g_effectTextY = 0x801E3118; +g_effectTextColour = 0x801E311C; +g_effectBankUnk90 = 0x801E25B4; +g_effectBankUnk92 = 0x801E25B6; diff --git a/config/symbols.effect_050.txt b/config/symbols.effect_050.txt new file mode 100644 index 00000000..43ce60a6 --- /dev/null +++ b/config/symbols.effect_050.txt @@ -0,0 +1,49 @@ +effectTextInit = 0x801A01F0; // type:func +effectTextHex = 0x801A0340; // type:func +effectTextNewline = 0x801A03EC; // type:func +effectNop = 0x801A040C; // type:func +effectDrawQuad128 = 0x801A0414; // type:func +effectDrawQuad256 = 0x801A0510; // type:func +effectMatrixIdentity = 0x801A060C; // type:func +effectMatrixRotX = 0x801A0644; // type:func +effectMatrixRotY = 0x801A07D4; // type:func +effectMatrixAim = 0x801A0960; // type:func +effectMatrixLookAt = 0x801A0A6C; // type:func +effectReleaseWait = 0x801A0AD8; // type:func +effectSpawnTask = 0x801A0B00; // type:func +effectCacheSlotAnchors = 0x801A0C8C; // type:func +effectSlotAnchor0 = 0x801A0DC0; // type:func +effectSlotAnchor1 = 0x801A0DF0; // type:func +effectSlotAnchorMid = 0x801A0E20; // type:func +effectCacheAnimSlotAnchors = 0x801A0E50; // type:func +effectAnimSlotAnchor0 = 0x801A0F8C; // type:func +effectAnimSlotAnchor1 = 0x801A0FBC; // type:func +effectAnimSlotAnchorMid = 0x801A0FEC; // type:func +effectUpdateModelBounds = 0x801A101C; // type:func +effectGetModelBounds = 0x801A1268; // type:func +effectModelRadius = 0x801A12B8; // type:func +effectModelHalfHeight = 0x801A135C; // type:func +effectModelHalfWidth = 0x801A138C; // type:func +effectModelHeight = 0x801A13E4; // type:func +effectModelTop = 0x801A1408; // type:func +effectModelBottom = 0x801A1450; // type:func +effectModelRandomY = 0x801A1498; // type:func +effectModelCentreY = 0x801A1550; // type:func +effectModelCentre = 0x801A15A4; // type:func +effectZeroWords = 0x801A1610; // type:func +effectDrawSprite = 0x801A1648; // type:func +effectStepCounter = 0x801A16E4; // type:func +effectRenderSetPose = 0x801A181C; // type:func +effectRenderPoseJoints = 0x801A1960; // type:func +effectRebasePointers = 0x801A1A0C; // type:func +effectRenderFaceCamera = 0x801A1A4C; // type:func +effectRenderReset = 0x801A1D38; // type:func +effectRenderSetTexture = 0x801A1DF4; // type:func +effectRenderMesh = 0x801A1EBC; // type:func +effectRenderModel = 0x801A2D0C; // type:func +g_effectPrimCursor = 0x801C58F4; +g_effectHexGlyphs = 0x801D5D00; +g_effectTextX = 0x801D5D14; +g_effectTextY = 0x801D5D18; +g_effectTextColour = 0x801D5D1C; +g_effectJointOffsets = 0x801D5D20; diff --git a/config/symbols.effect_051.txt b/config/symbols.effect_051.txt new file mode 100644 index 00000000..8decca0e --- /dev/null +++ b/config/symbols.effect_051.txt @@ -0,0 +1,72 @@ +effectTextInit = 0x801A014C; // type:func +effectTextHex = 0x801A029C; // type:func +effectTextNewline = 0x801A0348; // type:func +effectNop = 0x801A0368; // type:func +effectDrawQuad128 = 0x801A0370; // type:func +effectDrawQuad256 = 0x801A046C; // type:func +effectMatrixIdentity = 0x801A0568; // type:func +effectMatrixRotX = 0x801A05A0; // type:func +effectMatrixRotY = 0x801A0730; // type:func +effectMatrixAim = 0x801A08BC; // type:func +effectMatrixLookAt = 0x801A09C8; // type:func +effectMatrixHeading = 0x801A0A34; // type:func +effectScatter = 0x801A0A64; // type:func +effectRenderSetPose = 0x801A0B6C; // type:func +effectRenderPoseJoints = 0x801A0CB0; // type:func +effectRebasePointers = 0x801A0D5C; // type:func +effectRenderFaceCamera = 0x801A0D9C; // type:func +effectRenderReset = 0x801A1088; // type:func +effectRenderSetTexture = 0x801A1144; // type:func +effectRenderMesh = 0x801A120C; // type:func +effectRenderModel = 0x801A205C; // type:func +effectReleaseWait = 0x801A2198; // type:func +effectSpawnTask = 0x801A21C0; // type:func +effectCacheSlotAnchors = 0x801A234C; // type:func +effectSlotAnchor0 = 0x801A2480; // type:func +effectSlotAnchor1 = 0x801A24B0; // type:func +effectSlotAnchorMid = 0x801A24E0; // type:func +effectCacheAnimSlotAnchors = 0x801A2510; // type:func +effectAnimSlotAnchor0 = 0x801A264C; // type:func +effectAnimSlotAnchor1 = 0x801A267C; // type:func +effectAnimSlotAnchorMid = 0x801A26AC; // type:func +effectUpdateModelBounds = 0x801A26DC; // type:func +effectGetModelBounds = 0x801A2928; // type:func +effectModelRadius = 0x801A2978; // type:func +effectModelHalfHeight = 0x801A2A1C; // type:func +effectModelHalfWidth = 0x801A2A4C; // type:func +effectModelHeight = 0x801A2AA4; // type:func +effectModelTop = 0x801A2AC8; // type:func +effectModelBottom = 0x801A2B10; // type:func +effectModelRandomY = 0x801A2B58; // type:func +effectModelCentreY = 0x801A2C10; // type:func +effectModelCentre = 0x801A2C64; // type:func +effectZeroWords = 0x801A2CD0; // type:func +effectEmitTris = 0x801A2D08; // type:func +effectEmitQuads = 0x801A2FE8; // type:func +effectEmitTexTris = 0x801A3320; // type:func +effectEmitTexQuads = 0x801A36B4; // type:func +effectEmitGouraudTris = 0x801A3AAC; // type:func +effectEmitGouraudQuads = 0x801A3DD4; // type:func +effectEmitGouraudTexTris = 0x801A4174; // type:func +effectEmitGouraudTexQuads = 0x801A4548; // type:func +effectEmitMesh = 0x801A49A8; // type:func +effectDrawSprite = 0x801A4F44; // type:func +effectStepCounter = 0x801A5204; // type:func +effectFillWords = 0x801A5CEC; // type:func +effectMatrixSetRotX = 0x801A5D10; // type:func +effectMatrixSetRotY = 0x801A5D8C; // type:func +effectMatrixSetRotZ = 0x801A5E08; // type:func +effectMatrixSetRotZXY = 0x801A5E84; // type:func +effectPoseInit = 0x801A5F14; // type:func +effectPoseFindShorts = 0x801A6094; // type:func +effectPoseFindWords = 0x801A60FC; // type:func +effectPoseStepChannel = 0x801A6164; // type:func +effectPoseWalk = 0x801A6354; // type:func +effectInterpolateFrames = 0x801A6910; // type:func +g_effectPrimCursor = 0x801D3EB8; +g_effectHexGlyphs = 0x801ED404; +g_effectTextX = 0x801ED418; +g_effectTextY = 0x801ED41C; +g_effectTextColour = 0x801ED420; +g_effectJointOffsets = 0x801ED424; +g_effectDrawMode = 0x801EEA0C; diff --git a/config/symbols.effect_056.txt b/config/symbols.effect_056.txt new file mode 100644 index 00000000..9a2f0f7d --- /dev/null +++ b/config/symbols.effect_056.txt @@ -0,0 +1,114 @@ +func_801A0000 = 0x801A0000; // type:func +effectTextInit = 0x801A0208; // type:func +effectTextHex = 0x801A0358; // type:func +effectTextNewline = 0x801A0404; // type:func +effectNop = 0x801A0424; // type:func +effectDrawQuad128 = 0x801A042C; // type:func +effectDrawQuad256 = 0x801A0528; // type:func +effectMatrixIdentity = 0x801A0624; // type:func +effectMatrixRotX = 0x801A065C; // type:func +effectMatrixRotY = 0x801A07EC; // type:func +effectMatrixRotZ = 0x801A0978; // type:func +effectMatrixHeading = 0x801A0B04; // type:func +effectReleaseWait = 0x801A0B34; // type:func +effectSpawnTask = 0x801A0B5C; // type:func +effectCacheSlotAnchors = 0x801A0CE8; // type:func +effectSlotAnchor0 = 0x801A0E1C; // type:func +effectSlotAnchor1 = 0x801A0E4C; // type:func +effectSlotAnchorMid = 0x801A0E7C; // type:func +effectCacheAnimSlotAnchors = 0x801A0EAC; // type:func +effectAnimSlotAnchor0 = 0x801A0FE8; // type:func +effectAnimSlotAnchor1 = 0x801A1018; // type:func +effectAnimSlotAnchorMid = 0x801A1048; // type:func +effectUpdateModelBounds = 0x801A1078; // type:func +effectGetModelBounds = 0x801A12C4; // type:func +effectModelRadius = 0x801A1314; // type:func +effectModelHalfHeight = 0x801A13B8; // type:func +effectModelHalfWidth = 0x801A13E8; // type:func +effectModelHeight = 0x801A1440; // type:func +effectModelTop = 0x801A1464; // type:func +effectModelBottom = 0x801A14AC; // type:func +effectModelRandomY = 0x801A14F4; // type:func +effectModelCentreY = 0x801A15AC; // type:func +effectModelCentre = 0x801A1600; // type:func +effectZeroWords = 0x801A166C; // type:func +effectTintPlay = 0x801A16A4; // type:func +effectRandBetween = 0x801A1980; // type:func +effectRandProduct = 0x801A1A04; // type:func +effectRandVector = 0x801A1AA8; // type:func +effectMatrixFromAngles = 0x801A1B20; // type:func +effectJitterAngle = 0x801A1BEC; // type:func +effectJitterVector = 0x801A1C80; // type:func +effectJitterAngleS = 0x801A1CF8; // type:func +effectJitterSVector = 0x801A1D88; // type:func +effectCopyVector = 0x801A1E00; // type:func +effectFadeValue = 0x801A1E30; // type:func +effectFadeVector = 0x801A1E8C; // type:func +effectBlendPointSets = 0x801A1F58; // type:func +effectEmitTris = 0x801A20EC; // type:func +effectEmitQuads = 0x801A23B8; // type:func +effectEmitTexTris = 0x801A26DC; // type:func +effectEmitTexQuads = 0x801A2A64; // type:func +effectEmitGouraudTris = 0x801A2E48; // type:func +effectEmitGouraudQuads = 0x801A3150; // type:func +effectEmitGouraudTexTris = 0x801A34D8; // type:func +effectEmitGouraudTexQuads = 0x801A3894; // type:func +effectEmitStream = 0x801A3CDC; // type:func +effectBuildMeshPacket = 0x801A3F20; // type:func +effectParticleLateStep = 0x801A4128; // type:func +effectParticleAdvance = 0x801A41E0; // type:func +effectParticleAgeHold = 0x801A49E8; // type:func +effectParticlePose = 0x801A4ADC; // type:func +effectParticleAlloc = 0x801A541C; // type:func +effectStepRunKind = 0x801A5538; // type:func +effectStepFire = 0x801A5570; // type:func +effectParticleStep = 0x801A561C; // type:func +effectEmitterCountStep = 0x801A5708; // type:func +effectSpriteEmit = 0x801A5720; // type:func +effectSpritePacket = 0x801A5D4C; // type:func +effectParticleDrawPacket = 0x801A5FB4; // type:func +effectDrawParticles = 0x801A6074; // type:func +effectEmitterAlloc = 0x801A6194; // type:func +effectEmitterAge = 0x801A62B4; // type:func +effectEmitterSpawn = 0x801A631C; // type:func +effectEmitterSpawnShare = 0x801A6DB8; // type:func +effectEmitterStep = 0x801A6EB8; // type:func +effectEmitterOnStrand = 0x801A6F58; // type:func +effectEmitterOnTrail = 0x801A71E0; // type:func +effectEmitterOnOwner = 0x801A73E8; // type:func +effectEmitterSlide = 0x801A75F8; // type:func +effectListAppend = 0x801A8068; // type:func +effectListRemove = 0x801A80A4; // type:func +effectListClear = 0x801A80E4; // type:func +effectListRun = 0x801A80FC; // type:func +effectEmitterSetup = 0x801A8184; // type:func +effectStepFireSlots = 0x801A83B8; // type:func +effectEmittersOnCue = 0x801A846C; // type:func +effectTrailPush = 0x801A85A8; // type:func +effectTrailAim = 0x801A8684; // type:func +effectStrandsSeed = 0x801A87F8; // type:func +effectStrandsPush = 0x801A8904; // type:func +effectStrandsAim = 0x801A8A1C; // type:func +effectPoseTablesRelocate = 0x801A8CE4; // type:func +effectStartChildScript = 0x801A8F88; // type:func +effectBanksClear = 0x801A8FF8; // type:func +effectDrawScriptStart = 0x801A9050; // type:func +effectDrawScriptRun = 0x801A92F8; // type:func +effectDrawListSpan = 0x801A9420; // type:func +g_effectStackBase = 0x801D974C; +g_effectStackTop = 0x801D9750; +g_effectEmitterBank = 0x801D99F4; +g_effectParticleBank = 0x801D99F8; +g_effectDrawList = 0x801D99FC; +g_effectEmitterCursor = 0x801D9A00; +g_effectParticleCursor = 0x801D9A02; +g_effectParticleTotal = 0x801D9A04; +g_effectLiveTotal = 0x801D9A06; +g_effectBankUnk90 = 0x801D9A08; +g_effectBankUnk92 = 0x801D9A0A; +g_effectChildPool = 0x801DA204; +g_effectPrimCursor = 0x801DA214; +g_effectHexGlyphs = 0x801DA554; +g_effectTextX = 0x801DA568; +g_effectTextY = 0x801DA56C; +g_effectTextColour = 0x801DA570; diff --git a/include/battle.h b/include/battle.h index 220e15b3..f4837c0c 100644 --- a/include/battle.h +++ b/include/battle.h @@ -1346,7 +1346,9 @@ typedef struct BattleEffectSlot { /* 0x60 */ u8 unk060[0x64 - 0x60]; /* 0x64 */ struct EffectMesh *mesh; /* 0x68 */ u8 pad068[0x6C - 0x68]; - /* 0x6C */ u8 unk06C[0x78 - 0x6C]; + /* 0x6C */ u8 unk06C[0x74 - 0x6C]; + /* 0x74 */ u8 *unk074; /**< The battle entity behind the slot; + its @c 0x2C halfword carries the flags. */ /* 0x78 */ struct EffectAttachment *unk078; /* 0x7C */ u32 unk07C; /**< Bit @c n set: mesh part @c n is drawn. */ /* 0x80 */ u8 pad080[0x9C - 0x80]; @@ -1408,6 +1410,8 @@ extern s32 D_800EEC5C; /** @brief Angle every sprite prim is rolled by unless it opts out. */ extern s16 D_800F02A0; +extern s16 D_800F02C2; + /** @brief The world matrix for this frame; effect matrices compose onto it. */ extern MATRIX D_800F02C8; diff --git a/include/battle/bc_object13.h b/include/battle/bc_object13.h index c88beb97..4cce9833 100644 --- a/include/battle/bc_object13.h +++ b/include/battle/bc_object13.h @@ -14,4 +14,7 @@ void func_800C3BE0(u8 *base); /** @brief Queue the AKAO sequence at @p sequence for playback. */ void func_800C4764(u8 *sequence, s32 arg1, s32 arg2); +/** @brief Reset @p slot when its entity's flags call for it. */ +s32 func_800C2BD0(struct BattleEffectSlot *slot, s32 arg1); + #endif /* BATTLE_BC_OBJECT13_H */ diff --git a/include/effect/effect_036.h b/include/effect/effect_036.h new file mode 100644 index 00000000..cdc03d5f --- /dev/null +++ b/include/effect/effect_036.h @@ -0,0 +1,86 @@ +#ifndef EFFECT_EFFECT_036_H +#define EFFECT_EFFECT_036_H + +#include "effect.h" +#include "effect/lib/particle.h" +#include "effect/lib/tint.h" + +/** + * @file + * @brief Confuse: the overlay's own storage. + */ + +/** @brief Cursor the record banks are carved off, moving up as they are taken. */ +extern u8 *D_801E2300; + +/** + * @brief Value the script feeds to @c D_800F02C2, one entry per frame. + * + * Ends with @ref EFFECT_TABLE_END rather than carrying a length. + */ +extern s16 D_801A9DF8[]; + +/** @brief Sound cue the dispatcher fires on its first frame. */ +extern u8 D_801A9E10[]; + +/** @brief Argument the frame-20 child is started with. */ +extern EffectTintStep D_801A9E04[]; + +/** @brief Pose script the model-taking handler runs. */ +extern EffectPoseTables D_801B2DE0; + +/** @brief Task pools the script's children run in, and their storage. */ +extern s32 D_801E2EB0; +extern s32 D_801E3020; +extern s32 D_801E30F0; +extern s32 D_801E2590; +extern s32 D_801E2DE0; +extern s32 D_801E2EC0; +extern s32 D_801E3030; +extern s32 D_801E25C0; +extern s32 D_801E2310; + +/** @brief Cleared when the effect starts. */ +extern s32 D_801E22F0; +extern s32 D_801E22F4; + +/** + * @name Overlay blob + * + * The data carried in the overlay image behind the code. + * @{ + */ + +/** @brief Table of two offsets battle.bin resolves when the effect starts. */ +extern u8 D_801B89C8; + +/** + * @brief TIM uploaded to VRAM when the effect starts. + * + * Once it is in VRAM the image memory is reused: the prim and frame banks the + * renderer double-buffers through start at this address. + */ +extern u8 D_801B96D0; +/** @} */ + +/** + * @name Prim buffers + * + * Two of each, so the frame being built and the frame being drawn never share. + * @{ + */ +extern void *D_801E2DC8; +extern void *D_801E2DCC; +extern void *D_801E2DD0; +extern void *D_801E2DD4; +/** @} */ + +/** @brief Cursor the effect's second prim buffer is written through. */ +extern void *D_801E2DC4; + +/** + * @brief Run one frame of the effect: its opcode, then every task pool it owns. + */ +s32 func_801A9B64(EffectEntity *entity); + +#endif /* EFFECT_EFFECT_036_H */ diff --git a/include/effect/effect_036_entry.h b/include/effect/effect_036_entry.h new file mode 100644 index 00000000..6784999b --- /dev/null +++ b/include/effect/effect_036_entry.h @@ -0,0 +1,19 @@ +#ifndef EFFECT_EFFECT_036_ENTRY_H +#define EFFECT_EFFECT_036_ENTRY_H + +#include "effect.h" + +/** + * @file effect_036_entry.h + * @brief Confuse: the overlay entry point. + */ + +/** + * @brief Start the effect's script and hand back its task pool. + * + * @param animSet Animation set the effect plays. + * @return The pool the root entity lives in. + */ +void *func_801A0000(EffectAnimSet *animSet); + +#endif /* EFFECT_EFFECT_036_ENTRY_H */ diff --git a/include/effect/params/effect_036/effect_params.h b/include/effect/params/effect_036/effect_params.h new file mode 100644 index 00000000..3b7dfc7d --- /dev/null +++ b/include/effect/params/effect_036/effect_params.h @@ -0,0 +1,13 @@ +#ifndef EFFECT_PARAMS_H +#define EFFECT_PARAMS_H + +/** + * @file effect_params.h + * @brief Confuse: the ring sizes its particle engine is built with. + */ + +/** @brief Highest index each ring reaches before it wraps. */ +#define EFFECT_EMITTER_COUNT 0x1D +#define EFFECT_PARTICLE_COUNT 0x31 + +#endif /* EFFECT_PARAMS_H */ diff --git a/include/effect/params/effect_056/effect_params.h b/include/effect/params/effect_056/effect_params.h new file mode 100644 index 00000000..13642149 --- /dev/null +++ b/include/effect/params/effect_056/effect_params.h @@ -0,0 +1,13 @@ +#ifndef EFFECT_PARAMS_H +#define EFFECT_PARAMS_H + +/** + * @file effect_params.h + * @brief Absorb: the ring sizes its particle engine is built with. + */ + +/** @brief Highest index each ring reaches before it wraps. */ +#define EFFECT_EMITTER_COUNT 0x27 +#define EFFECT_PARTICLE_COUNT 0x8B + +#endif /* EFFECT_PARAMS_H */ diff --git a/src/battle/bc_object13.c b/src/battle/bc_object13.c index 91d51266..f618ba4b 100644 --- a/src/battle/bc_object13.c +++ b/src/battle/bc_object13.c @@ -1,7 +1,16 @@ #include "common.h" +#include "battle.h" #include "battle/bc_object8.h" #include "battle/bc_object13.h" +/** + * @name Flags in the halfword at @c 0x2C of a slot's battle entity. + * @{ + */ +#define BATTLE_ENTITY_FLAG_UNK40 0x40 +#define BATTLE_ENTITY_FLAG_UNK100 0x100 +/** @} */ + extern u8 D_800F1A90[]; extern u8 D_800F1A94[]; @@ -47,7 +56,7 @@ s32 func_800C3418(s32); void func_800C2B88(s32 a0, s32 a1) { u8 *entity = *(u8 **)(a0 + 0x74); a1 &= ~0x1000; - if (*(u16 *)(entity + 0x2C) & 0x40) { + if (*(u16 *)(entity + 0x2C) & BATTLE_ENTITY_FLAG_UNK40) { func_800C2AB0(a0); } else { entity[3] = a1; @@ -55,19 +64,16 @@ void func_800C2B88(s32 a0, s32 a1) { } /** - * @brief Check entity status flags and reset if certain bits set. + * @brief Reset @p slot when its entity's flags call for it. * - * Reads halfword at entity->0x74->0x2C, tests bits 0x140. - * If any of those bits are set, calls func_800C2AB0 and returns 0. - * Otherwise returns -1. - * - * @param a0 Entity pointer. - * @return 0 if flags triggered reset, -1 otherwise. + * @param slot Entity whose flags are checked. + * @param arg1 Ignored; the one call site passes 4. + * @return 0 if the slot was reset, -1 if its flags did not ask for one. */ -s32 func_800C2BD0(s32 a0) { - u16 flags = *(u16 *)(*(s32 *)(a0 + 0x74) + 0x2C); - if ((flags & 0x140) != 0) { - func_800C2AB0(a0); +s32 func_800C2BD0(BattleEffectSlot *slot, s32 arg1) { + u16 flags = *(u16 *)(slot->unk074 + 0x2C); + if ((flags & (BATTLE_ENTITY_FLAG_UNK40 | BATTLE_ENTITY_FLAG_UNK100)) != 0) { + func_800C2AB0((s32)slot); return 0; } return -1; diff --git a/src/effect/effect_036.c b/src/effect/effect_036.c index 2013d5ae..eb0e8b0d 100644 --- a/src/effect/effect_036.c +++ b/src/effect/effect_036.c @@ -3,250 +3,310 @@ * @brief Confuse */ #include "common.h" - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0000); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A020C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A035C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0408); - -void func_801A0428(void) { +#include "game.h" +#include "effect.h" +#include "psxsdk/libgpu.h" +#include "effect/effect_036.h" +#include "effect/lib/particle.h" +#include "effect/lib/entity.h" +#include "effect/lib/tables.h" +#include "effect/lib/drawscript.h" +#include "effect/lib/bankclear.h" +#include "effect/lib/common.h" +#include "effect/lib/tint.h" +#include "battle.h" +#include "battle/bc_object13.h" +#include "btl_entity.h" +#include "effect_params.h" + +/** @brief Where in the scratchpad the effect keeps its view matrix. */ +#define EFFECT_SCRATCHPAD ((MATRIX *)0x1F8002E0) + +/** @brief @ref EffectEntity::unk05C -- the frame counter's low bit picks a bank. */ +#define EFFECT_FRAME_ODD 0x1 + +/** @brief Sentinel ending @ref D_801A9DF8: the script stops on this entry. */ +#define EFFECT_TABLE_END 0x7F + +static void func_801A94B4(EffectEntity *entity); +static void func_801A9508(EffectEntity *entity); +static s32 func_801A9510(EffectEntity *entity); +static s32 func_801A9810(EffectEntity *entity); +static void func_801A99B4(EffectEntity *entity); +static void func_801A95A8(EffectEntity *entity); +static void func_801A9604(EffectEntity *entity); +static void func_801A964C(EffectEntity *entity); +static s32 func_801A9654(EffectEntity *entity); +static void func_801A96F4(EffectEntity *entity); +static void func_801A974C(EffectEntity *entity); +static void func_801A9780(EffectEntity *entity); +static void func_801A9808(EffectEntity *entity); +static void func_801A998C(EffectEntity *entity); +static void func_801A99A0(EffectEntity *entity); +static void func_801A9A24(EffectEntity *entity); +static void func_801A9A7C(EffectEntity *entity); +static void func_801A9ADC(EffectEntity *entity); +static void func_801A9AF0(EffectEntity *entity); +static void func_801A9B18(EffectEntity *entity); +static void func_801A9B2C(EffectEntity *entity); +static void func_801A9B40(EffectEntity *entity); +static void func_801A9B5C(EffectEntity *entity); + +/** @brief Opcode handler: play this frame's table entry, or stop at the end. */ +static void func_801A94B4(EffectEntity *entity) { + if (D_801A9DF8[entity->unk024] == EFFECT_TABLE_END) { + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } else { + D_800F02C2 = D_801A9DF8[entity->unk024]; + } } -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0430); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A052C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0628); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0660); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A07F0); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A097C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0B08); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0B38); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0B60); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0CEC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0E20); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0E50); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0E80); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0EB0); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A0FEC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A101C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A104C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A107C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A12C8); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1318); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A13BC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A13EC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1444); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1468); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A14B0); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A14F8); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A15B0); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1604); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1670); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A16A8); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1984); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1A08); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1AAC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1B24); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1BF0); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1C84); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1CFC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1D8C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1E04); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1E34); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1E90); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A1F5C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A20F0); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A23BC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A26E0); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A2A68); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A2E4C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A3154); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A34DC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A3898); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A3CE0); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A3F24); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A412C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A41E4); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A49EC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A4AE0); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A5420); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A553C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A5574); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A5620); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A570C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A5724); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A5D50); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A5FB8); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A6078); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A6198); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A62B8); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A6320); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A6DBC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A6EBC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A6F5C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A71E4); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A73EC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A75FC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A806C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A80A8); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A80E8); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A8100); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A8188); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A83BC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A8470); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A85AC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A8688); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A87FC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A8908); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A8A20); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A8CE8); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A8F8C); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A8FFC); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9050); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A92F8); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9420); - -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A94B4); +/** @brief Opcode handler: no-op. */ +static void func_801A9508(EffectEntity *entity) { +} -void func_801A9508(void) { +/** + * @brief Script dispatcher for the table player. + * + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ +static s32 func_801A9510(EffectEntity *entity) { + EffectHandler handlers[2] = { func_801A94B4, func_801A9508 }; + + handlers[entity->pc](entity); + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait != 0) { + return 0; + } + effectReleaseWait(entity); + return 2; + } + return 0; } -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9510); +/** @brief Opcode handler: draw and retire once the frame count is reached. */ +static void func_801A95A8(EffectEntity *entity) { + EffectDrawScript *script = (EffectDrawScript *)entity; -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A95A8); + if (entity->unk024 >= script->stopFrame) { + /* Called with no argument: the entity is already in $a0 and stays there. */ + ((void (*)())effectDrawScriptStart)(); + effectDrawScriptRun(script); + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9604); +/** @brief Opcode handler: hold still until the draw script finishes. */ +static void func_801A9604(EffectEntity *entity) { + if (effectDrawScriptRun((EffectDrawScript *)entity) != 0) { + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } +} -void func_801A964C(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A964C(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9654); +/** + * @brief Script dispatcher: run this frame's step, draw, and retire the entity. + * + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ +static s32 func_801A9654(EffectEntity *entity) { + EffectHandler handlers[3] = { func_801A95A8, func_801A9604, func_801A964C }; + + handlers[entity->pc](entity); + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait != 0) { + return 0; + } + effectReleaseWait(entity); + return 2; + } + return 0; +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A96F4); +/** @brief Opcode handler: start the pose script on the taken model. */ +static void func_801A96F4(EffectEntity *entity) { + effectStartChildScript(entity, func_801A9654, &D_801B2DE0, 0, 0x2D, 0); + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A974C); +/** @brief Opcode handler: release the model once the count reaches 30. */ +static void func_801A974C(EffectEntity *entity) { + if (entity->unk024 == 30) { + entity->unk010->unk063 = 0; + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9780); +/** @brief Opcode handler: hand the current part to battle, then stop. */ +static void func_801A9780(EffectEntity *entity) { + if (entity->unk024 >= 30) { + func_800BFE1C(&entity->animSet->anims[entity->unk02A].parts[entity->unk02B]); + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } +} -void func_801A9808(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A9808(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9810); +/** + * @brief Script dispatcher: pose the model, then run this frame's opcode. + * + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ +static s32 func_801A9810(EffectEntity *entity) { + EffectHandler handlers[4] = { func_801A96F4, func_801A974C, func_801A9780, + func_801A9808 }; + + effectCacheSlotAnchors(entity); + effectUpdateModelBounds(entity); + handlers[entity->pc](entity); + if (entity->unk024 == 0) { + func_800C4764(D_801A9E10, 0, 0x80); + } + if (entity->unk024 == 20) { + effectSpawnTask(&D_801E2590, func_801A9510, 0x40, entity); + } + if (entity->unk024 == 20) { + EffectTintScript *child = effectSpawnTask(&D_801E30F0, effectTintPlay, + sizeof(EffectTintScript), entity); + child->steps = D_801A9E04; + } + if (entity->unk024 == 18) { + func_800C2BD0(&D_800EF2D0[entity->unk02D], 4); + } + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait != 0) { + return 0; + } + effectReleaseWait(entity); + return 2; + } + return 0; +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A998C); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A998C(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A99A0); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A99A0(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A99B4); +/** @brief Opcode handler: carve both record banks. */ +static void func_801A99B4(EffectEntity *entity) { + if (entity->wait == 0) { + /* Both banks are carved out of the same byte arena behind the TIM. */ + g_effectEmitterBank = (EffectEmitter *)D_801E2300; + D_801E2300 += EFFECT_EMITTER_BANK_BYTES; + g_effectParticleBank = (EffectParticle *)D_801E2300; + D_801E2300 += EFFECT_PARTICLE_BANK_BYTES; + effectBanksClear(); + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9A24); +/** @brief Opcode handler: start a task running @ref func_801A9810. */ +static void func_801A9A24(EffectEntity *entity) { + entity->unk063 = 1; + effectSpawnTask(&D_801E3020, func_801A9810, 0x58, entity); + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9A7C); +/** @brief Opcode handler: repeat the preceding opcode until the count runs out. */ +static void func_801A9A7C(EffectEntity *entity) { + if (entity->unk063 != 0) { + return; + } + if (entity->unk02A < entity->unk058) { + entity->unk02A++; + entity->unk02E++; + entity->pc--; + } else { + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9ADC); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9ADC(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9AF0); +/** @brief Opcode handler: stall here until @c unk05E reaches zero. */ +static void func_801A9AF0(EffectEntity *entity) { + if (entity->unk05E == 0) { + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9B18); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9B18(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9B2C); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9B2C(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9B40); +/** @brief Opcode handler: raise @ref EFFECT_FLAG_STOP and consume the opcode. */ +static void func_801A9B40(EffectEntity *entity) { + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; +} -void func_801A9B5C(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A9B5C(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_036/nonmatchings/effect_036", func_801A9B64); +s32 func_801A9B64(EffectEntity *entity) { + EffectHandler handlers[11] = { + func_801A998C, func_801A99A0, func_801A99B4, func_801A9A24, func_801A9A7C, + func_801A9ADC, func_801A9AF0, func_801A9B18, func_801A9B2C, func_801A9B40, + func_801A9B5C + }; + MATRIX *view = EFFECT_SCRATCHPAD; + + *view = D_800F02C8; + g_effectStackTop = (u8 *)view; + g_effectStackBase = view; + if (entity->unk05C & EFFECT_FRAME_ODD) { + g_effectPrimCursor = D_801E2DC8; + D_801E2DC4 = D_801E2DD0; + } else { + g_effectPrimCursor = D_801E2DCC; + D_801E2DC4 = D_801E2DD4; + } + effectCacheAnimSlotAnchors(entity); + handlers[entity->pc](entity); + g_effectParticleTotal = 0; + entity->unk05E = 0; + g_effectLiveTotal = 0; + entity->unk05E += func_800B2B68(&D_801E3020); + entity->unk05E += func_800B2B68(&D_801E30F0); + entity->unk05E += func_800B2B68(&g_effectChildPool); + entity->unk05E += func_800B2B68(&D_801E2590); + entity->unk05C++; + entity->unk024++; + if (entity->flags & EFFECT_FLAG_STOP) { + if (entity->wait == 0) { + effectReleaseWait(entity); + return 2; + } + } + return 0; +} diff --git a/src/effect/effect_036_entry.c b/src/effect/effect_036_entry.c new file mode 100644 index 00000000..b45b390a --- /dev/null +++ b/src/effect/effect_036_entry.c @@ -0,0 +1,62 @@ +/** + * @file effect_036_entry.c + * @brief Confuse: the overlay entry point. + */ +#include "common.h" +#include "effect.h" +#include "effect/lib/entity.h" +#include "effect/lib/tables.h" +#include "effect/effect_036.h" +#include "effect/effect_036_entry.h" + +/** @brief Stride between the prim and frame banks carved out of the TIM. */ +#define EFFECT_BANK_SIZE 0xE000 + +/** + * @brief Start the effect's script and hand back its task pool. + * + * @param animSet Animation set the effect plays. + * @return The pool the root entity lives in. + */ +void *func_801A0000(EffectAnimSet *animSet) { + u8 *bank0; + EffectEntity *entity; + u8 *bank1; + u8 *frames; + + D_801E22F0 = 0; + D_801E22F4 = 0; + func_800B2A00(&D_801E2EB0, &D_801E2DE0, 0x64, 2); + entity = effectSpawnTask(&D_801E2EB0, func_801A9B64, 0x64, NULL); + entity->animSet = animSet; + entity->unk02C = animSet->anims[entity->unk02A].unk000; + entity->unk02D = + entity->animSet->anims[entity->unk02A].parts[entity->unk02B].unk000; + entity->pc = 0; + entity->unk05A = animSet->anims->unk010; + entity->unk058 = animSet->anims->unk011; + entity->unk02F = entity->unk05A - 1; + if (entity->unk02F < entity->unk058) { + entity->unk02F = entity->unk058; + } + if (!(animSet->flags & EFFECT_ANIMSET_FLAG_LOADED)) { + func_800C3BE0(&D_801B89C8); + func_800BB084(&D_801B96D0); + } + D_801E2300 = &D_801B96D0; + bank0 = &D_801B96D0; + D_801E2DC8 = bank0; + bank1 = bank0 + EFFECT_BANK_SIZE; + D_801E2DD0 = bank0 + EFFECT_BANK_SIZE; + D_801E2300 = bank0 + EFFECT_BANK_SIZE; + frames = bank1; + D_801E2DCC = frames; + frames += EFFECT_BANK_SIZE; + D_801E2300 = frames; + D_801E2DD4 = frames; + func_800B2A00(&D_801E3020, &D_801E2EC0, 0x58, 4); + func_800B2A00(&D_801E30F0, &D_801E3030, 0x3C, 3); + func_800B2A00(&g_effectChildPool, &D_801E25C0, 0x2A4, 3); + func_800B2A00(&D_801E2590, &D_801E2310, 0x40, 0xA); + return &D_801E2EB0; +} diff --git a/src/effect/effect_050.c b/src/effect/effect_050.c deleted file mode 100644 index 229d61fa..00000000 --- a/src/effect/effect_050.c +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @file effect_050.c - * @brief Potion/Potion+ - */ -#include "common.h" - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0000); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A01F0); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0340); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A03EC); - -void func_801A040C(void) { -} - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0414); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0510); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A060C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0644); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A07D4); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0960); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0A6C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0AD8); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0B00); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0C8C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0DC0); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0DF0); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0E20); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0E50); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0F8C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0FBC); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A0FEC); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A101C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1268); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A12B8); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A135C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A138C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A13E4); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1408); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1450); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1498); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1550); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A15A4); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1610); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1648); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A16E4); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A172C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A181C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1960); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1A0C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1A4C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1D38); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1DF4); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A1EBC); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A2D0C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A2E48); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A351C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A3640); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A3840); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A38A0); - -void func_801A391C(void) { -} - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A3924); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A39CC); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A3A74); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A3AE8); - -void func_801A3B64(void) { -} - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A3B6C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A3C14); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A3D94); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A3DCC); - -void func_801A3E5C(void) { -} - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A3E64); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A40D4); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A4124); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A4138); - -void func_801A41C0(void) { -} - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A41C8); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A42A4); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A42B8); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A42CC); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A42F4); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A434C); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A43AC); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A43C0); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A43E8); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A43FC); - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A4410); - -void func_801A442C(void) { -} - -INCLUDE_ASM("asm/ovl/effect_050/nonmatchings/effect_050", func_801A4434); diff --git a/src/effect/effect_051.c b/src/effect/effect_051.c deleted file mode 100644 index 9b0d65bd..00000000 --- a/src/effect/effect_051.c +++ /dev/null @@ -1,294 +0,0 @@ -/** - * @file effect_051.c - * @brief Hi-Potion/Hi-Potion+ - */ -#include "common.h" - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A0000); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A014C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A029C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A0348); - -void func_801A0368(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A0370); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A046C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A0568); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A05A0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A0730); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A08BC); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A09C8); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A0A34); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A0A64); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A0B6C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A0CB0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A0D5C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A0D9C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A1088); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A1144); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A120C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A205C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2198); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A21C0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A234C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2480); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A24B0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A24E0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2510); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A264C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A267C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A26AC); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A26DC); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2928); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2978); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2A1C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2A4C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2AA4); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2AC8); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2B10); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2B58); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2C10); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2C64); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2CD0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2D08); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A2FE8); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A3320); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A36B4); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A3AAC); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A3DD4); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A4174); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A4548); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A49A8); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A4BFC); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A4D9C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A4F44); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A4FE0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A50D4); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5204); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A524C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A527C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A52D8); - -void func_801A5334(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A533C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5404); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A548C); - -void func_801A54D4(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A54DC); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A55C0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5620); - -void func_801A56A8(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A56B0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5778); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A581C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5884); - -void func_801A58CC(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A58D4); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5AE8); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5BD4); - -void func_801A5C1C(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5C24); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5CEC); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5D10); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5D8C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5E08); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5E84); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A5F14); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A6094); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A60FC); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A6164); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A6354); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A6910); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A6A00); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A6D68); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A6DB0); - -void func_801A6E9C(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A6EA4); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A6F7C); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A6FD4); - -void func_801A70C8(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A70D0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7170); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A71B8); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7214); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7240); - -void func_801A729C(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A72A4); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7354); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7390); - -void func_801A74F8(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7500); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A75A0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7614); - -void func_801A7728(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7730); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A77D0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7844); - -void func_801A7940(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7948); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A79E8); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7B1C); - -void func_801A7BA0(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7BA8); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7D18); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7DDC); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7E58); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7EB0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7F08); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7F68); - -void func_801A7FE0(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A7FE8); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A80DC); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A80F0); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A8148); - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A8198); - -void func_801A81C8(void) { -} - -INCLUDE_ASM("asm/ovl/effect_051/nonmatchings/effect_051", func_801A81D0); diff --git a/src/effect/effect_056.c b/src/effect/effect_056.c deleted file mode 100644 index ad32d0f6..00000000 --- a/src/effect/effect_056.c +++ /dev/null @@ -1,263 +0,0 @@ -/** - * @file effect_056.c - * @brief Absorb - */ -#include "common.h" - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0000); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0208); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0358); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0404); - -void func_801A0424(void) { -} - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A042C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0528); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0624); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A065C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A07EC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0978); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0B04); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0B34); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0B5C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0CE8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0E1C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0E4C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0E7C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0EAC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A0FE8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1018); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1048); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1078); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A12C4); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1314); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A13B8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A13E8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1440); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1464); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A14AC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A14F4); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A15AC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1600); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A166C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A16A4); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1980); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1A04); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1AA8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1B20); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1BEC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1C80); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1CF8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1D88); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1E00); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1E30); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1E8C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A1F58); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A20EC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A23B8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A26DC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A2A64); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A2E48); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A3150); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A34D8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A3894); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A3CDC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A3F20); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A4128); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A41E0); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A49E8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A4ADC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A541C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A5538); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A5570); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A561C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A5708); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A5720); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A5D4C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A5FB4); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A6074); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A6194); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A62B4); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A631C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A6DB8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A6EB8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A6F58); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A71E0); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A73E8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A75F8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A8068); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A80A4); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A80E4); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A80FC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A8184); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A83B8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A846C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A85A8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A8684); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A87F8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A8904); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A8A1C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A8CE4); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A8F88); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A8FF8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9050); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A92F8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9420); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A94B4); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9500); - -void func_801A9568(void) { -} - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9570); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9610); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9628); - -void func_801A9684(void) { -} - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A968C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A972C); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9788); - -void func_801A97D0(void) { -} - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A97D8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9878); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A98D0); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9904); - -void func_801A998C(void) { -} - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9994); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9ADC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9AF0); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9B04); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9B94); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9BEC); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9C50); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9CB8); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9CE0); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9CF4); - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9D08); - -void func_801A9D24(void) { -} - -INCLUDE_ASM("asm/ovl/effect_056/nonmatchings/effect_056", func_801A9D2C); From 1c686e023e620bf5ad5aeeb864c02a311fb90064 Mon Sep 17 00:00:00 2001 From: rengstrom Date: Wed, 9 Sep 2026 20:25:00 +0000 Subject: [PATCH 5/5] Document the effect_036 script runner at its definition --- src/effect/effect_036.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/effect/effect_036.c b/src/effect/effect_036.c index eb0e8b0d..a887e5b1 100644 --- a/src/effect/effect_036.c +++ b/src/effect/effect_036.c @@ -273,6 +273,13 @@ static void func_801A9B40(EffectEntity *entity) { static void func_801A9B5C(EffectEntity *entity) { } +/** + * @brief Run one frame of the effect: its opcode, then every task pool it owns. + * + * @param entity The script's root entity. + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ s32 func_801A9B64(EffectEntity *entity) { EffectHandler handlers[11] = { func_801A998C, func_801A99A0, func_801A99B4, func_801A9A24, func_801A9A7C,