diff --git a/Makefile b/Makefile index 2206756c..961fc794 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 effect_056 effect_050 effect_051 effect_036 +EFFECTS ?= effect_001 effect_025 effect_028 effect_052 effect_039 effect_056 effect_050 effect_051 effect_036 effect_027 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 d87ccc74..9b44dcdb 100644 --- a/config/ff8.yaml +++ b/config/ff8.yaml @@ -62,8 +62,7 @@ binaries: - [0x130, .rodata, bc_object2] - [0xA84, .rodata, bc_object3] - [0xECC, .rodata, bc_object4] - - [0xF48, pad] - - [0xF4C, .rodata, bc_object5] + - [0xF78, .rodata, bc_object5] - [0xF90, .rodata, bc_object6] - [0x14C0, .rodata, bc_object7] - [0x14E8, .rodata, bc_object8] @@ -83,7 +82,7 @@ binaries: - [0x3AC4, c, bc_object2] - [0x98E0, c, bc_object3] - [0xE184, c, bc_object4] - - [0x10B7C, c, bc_object5] + - [0x1268C, c, bc_object5] - [0x134A8, c, bc_object6] - [0x17358, c, bc_object7] - [0x19624, c, bc_object8] @@ -1097,16 +1096,40 @@ binaries: options: target_path: original/effect/effect_027.bin src_path: src/effect + section_order: [.text, .rodata, .data, .bss] segments: - name: effect_027 type: code start: 0x0 vram: 0x801A0000 subsegments: - - [0x0, c, effect_027] - - [0x9BB8, .rodata, effect_027] - - [0x9BCC, bin, effect_027] + - [0x0, c, effect_027_entry] + - [0x1EC, c, lib/common] + - [0x95C, c, lib/rotz] + - [0xAE8, c, lib/heading] + - [0xB18, c, lib/entity] + - [0x1688, c, lib/vector] + - [0x1DF4, c, lib/emit] + - [0x3C28, c, lib/packet] + - [0x3E30, c, lib/particlestep] + - [0x5124, c, lib/particlealloc] + - [0x5240, c, lib/draw] + - [0x5E9C, c, lib/emitteralloc] + - [0x5FBC, c, lib/spawn] + - [0x7D70, c, lib/list] + - [0x838C, c, lib/trail] + - [0x8500, c, lib/strands] + - [0x89EC, c, lib/tables] + - [0x8D00, c, lib/bankclear] + - [0x8D58, c, lib/drawscript] + - [0x91BC, c, effect_027] + - [0x9BB8, .rodata, lib/particlestep] + - [0x9BCC, pad] + - [0x9BD0, .rodata, lib/list] + - [0x9BFC, .rodata, effect_027] + - [0x9C5C, bin, effect_027] - [0x3AAF8] + - name: effect_028 sha1: eb8243db98aedc14e57e62c7b42d639c8171f9c5 options: diff --git a/config/symbols.battle.txt b/config/symbols.battle.txt index 194c6d2a..b98a7014 100644 --- a/config/symbols.battle.txt +++ b/config/symbols.battle.txt @@ -241,43 +241,27 @@ func_800AA980 = 0x800AA980; // type:func func_800AAB50 = 0x800AAB50; // type:func func_800AABEC = 0x800AABEC; // type:func func_800AACD0 = 0x800AACD0; // type:func -func_800AAD5C = 0x800AAD5C; // type:func func_800AAE10 = 0x800AAE10; // type:func func_800AAE98 = 0x800AAE98; // type:func func_800AAF48 = 0x800AAF48; // type:func func_800AAF70 = 0x800AAF70; // type:func func_800AAFB8 = 0x800AAFB8; // type:func func_800AB008 = 0x800AB008; // type:func -func_800AB02C = 0x800AB02C; // type:func func_800AB054 = 0x800AB054; // type:func -func_800AB07C = 0x800AB07C; // type:func func_800AB0C0 = 0x800AB0C0; // type:func func_800AB11C = 0x800AB11C; // type:func func_800AB1AC = 0x800AB1AC; // type:func func_800AB208 = 0x800AB208; // type:func func_800AB28C = 0x800AB28C; // type:func -func_800AB300 = 0x800AB300; // type:func -func_800AB36C = 0x800AB36C; // type:func func_800AB3FC = 0x800AB3FC; // type:func func_800AB488 = 0x800AB488; // type:func func_800AB4A8 = 0x800AB4A8; // type:func func_800AB570 = 0x800AB570; // type:func func_800AB668 = 0x800AB668; // type:func func_800AB6F4 = 0x800AB6F4; // type:func -func_800AB744 = 0x800AB744; // type:func func_800AB844 = 0x800AB844; // type:func func_800AB914 = 0x800AB914; // type:func func_800AB9B4 = 0x800AB9B4; // type:func -func_800ABA3C = 0x800ABA3C; // type:func -func_800ABCA4 = 0x800ABCA4; // type:func -func_800AC034 = 0x800AC034; // type:func -func_800AC094 = 0x800AC094; // type:func -func_800AC190 = 0x800AC190; // type:func -func_800AC2E4 = 0x800AC2E4; // type:func -func_800AC348 = 0x800AC348; // type:func -func_800AC368 = 0x800AC368; // type:func -func_800AC400 = 0x800AC400; // type:func -func_800AC4E4 = 0x800AC4E4; // type:func func_800ACF84 = 0x800ACF84; // type:func func_800AD4A4 = 0x800AD4A4; // type:func func_800AD50C = 0x800AD50C; // type:func diff --git a/config/symbols.effect_027.txt b/config/symbols.effect_027.txt new file mode 100644 index 00000000..840d55c9 --- /dev/null +++ b/config/symbols.effect_027.txt @@ -0,0 +1,112 @@ +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 +effectRandBetween = 0x801A1688; // type:func +effectRandProduct = 0x801A170C; // type:func +effectRandVector = 0x801A17B0; // type:func +effectMatrixFromAngles = 0x801A1828; // type:func +effectJitterAngle = 0x801A18F4; // type:func +effectJitterVector = 0x801A1988; // type:func +effectJitterAngleS = 0x801A1A00; // type:func +effectJitterSVector = 0x801A1A90; // type:func +effectCopyVector = 0x801A1B08; // type:func +effectFadeValue = 0x801A1B38; // type:func +effectFadeVector = 0x801A1B94; // type:func +effectBlendPointSets = 0x801A1C60; // type:func +effectEmitTris = 0x801A1DF4; // type:func +effectEmitQuads = 0x801A20C0; // type:func +effectEmitTexTris = 0x801A23E4; // type:func +effectEmitTexQuads = 0x801A276C; // type:func +effectEmitGouraudTris = 0x801A2B50; // type:func +effectEmitGouraudQuads = 0x801A2E58; // type:func +effectEmitGouraudTexTris = 0x801A31E0; // type:func +effectEmitGouraudTexQuads = 0x801A359C; // type:func +effectEmitStream = 0x801A39E4; // type:func +effectBuildMeshPacket = 0x801A3C28; // type:func +effectParticleLateStep = 0x801A3E30; // type:func +effectParticleAdvance = 0x801A3EE8; // type:func +effectParticleAgeHold = 0x801A46F0; // type:func +effectParticlePose = 0x801A47E4; // type:func +effectParticleAlloc = 0x801A5124; // type:func +effectStepRunKind = 0x801A5240; // type:func +effectStepFire = 0x801A5278; // type:func +effectParticleStep = 0x801A5324; // type:func +effectEmitterCountStep = 0x801A5410; // type:func +effectSpriteEmit = 0x801A5428; // type:func +effectSpritePacket = 0x801A5A54; // type:func +effectParticleDrawPacket = 0x801A5CBC; // type:func +effectDrawParticles = 0x801A5D7C; // type:func +effectEmitterAlloc = 0x801A5E9C; // type:func +effectEmitterAge = 0x801A5FBC; // type:func +effectEmitterSpawn = 0x801A6024; // type:func +effectEmitterSpawnShare = 0x801A6AC0; // type:func +effectEmitterStep = 0x801A6BC0; // type:func +effectEmitterOnStrand = 0x801A6C60; // type:func +effectEmitterOnTrail = 0x801A6EE8; // type:func +effectEmitterOnOwner = 0x801A70F0; // type:func +effectEmitterSlide = 0x801A7300; // type:func +effectListAppend = 0x801A7D70; // type:func +effectListRemove = 0x801A7DAC; // type:func +effectListClear = 0x801A7DEC; // type:func +effectListRun = 0x801A7E04; // type:func +effectEmitterSetup = 0x801A7E8C; // type:func +effectStepFireSlots = 0x801A80C0; // type:func +effectEmittersOnCue = 0x801A8174; // type:func +effectTrailPush = 0x801A82B0; // type:func +effectTrailAim = 0x801A838C; // type:func +effectStrandsSeed = 0x801A8500; // type:func +effectStrandsPush = 0x801A860C; // type:func +effectStrandsAim = 0x801A8724; // type:func +effectPoseTablesRelocate = 0x801A89EC; // type:func +effectStartChildScript = 0x801A8C90; // type:func +effectBanksClear = 0x801A8D00; // type:func +effectDrawScriptStart = 0x801A8D58; // type:func +effectDrawScriptRun = 0x801A9000; // type:func +effectDrawListSpan = 0x801A9128; // type:func +g_effectStackBase = 0x801D35BC; +g_effectStackTop = 0x801D35C0; +g_effectEmitterBank = 0x801D3864; +g_effectParticleBank = 0x801D3868; +g_effectDrawList = 0x801D386C; +g_effectEmitterCursor = 0x801D3870; +g_effectParticleCursor = 0x801D3872; +g_effectParticleTotal = 0x801D3874; +g_effectLiveTotal = 0x801D3876; +g_effectBankUnk90 = 0x801D3878; +g_effectBankUnk92 = 0x801D387A; +g_effectChildPool = 0x801D4074; +g_effectPrimCursor = 0x801D4084; +g_effectHexGlyphs = 0x801D42F4; +g_effectTextX = 0x801D4308; +g_effectTextY = 0x801D430C; +g_effectTextColour = 0x801D4310; diff --git a/include/battle.h b/include/battle.h index f4837c0c..3159a370 100644 --- a/include/battle.h +++ b/include/battle.h @@ -351,7 +351,7 @@ typedef struct { u8 unkC8[3]; u8 linkedIdx; u8 unkCC; - u8 unkCD; /* 0xCD: stat byte used in case-0 damage formula (squared). */ + u8 unkCD[1]; /* 0xCD: stat byte used in case-0 damage formula (squared). */ u8 unkCE; u8 unkCF; /* 0xCF: stat byte averaged with arg2 in func_8009DEF0 mode-7. */ } BattleEntity; /* 208 bytes */ @@ -494,8 +494,8 @@ typedef struct { /* 0x1292 */ s16 unk1292; /* 0x1294 */ s16 unk1294; /* 0x1296 */ s16 unk1296; - /* 0x1298 */ u8 pad1298[0x12B8 - 0x1298]; - /* 0x12B8 */ u16 array12B8[7]; + /* 0x1298 */ s32 unk1298[8]; + /* 0x12B8 */ u16 unk12B8[7]; /* 0x12C6 */ u8 pad12C7[0x12CC - 0x12C6]; /* 0x12CC */ Struct_12CC array12CC[1]; /* used in func_8009D594 */ /* 0x12CF */ u8 pad12CF[0x12D8 - 0x12CF]; @@ -523,7 +523,9 @@ typedef struct { /* 0x12F7 */ u8 unk12F7; /* 0x12F8 */ u8 unk12F8; /* 0x12F9 */ u8 unk12F9; - /* 0x12FA */ u8 pad12FA[3]; + /* 0x12FA */ u8 pad12FA; + /* 0x12FB */ u8 unk12FB; // used as index for entities (max 7) + /* 0x12FC */ u8 unk12FC; // used as index for unkD54,unkD14 (max 8) /* 0x12FD */ u8 unk12FD; /* 0x12FE */ u8 unk12FE; /* 0x12FF */ u8 unk12FF; @@ -697,6 +699,14 @@ typedef struct { u8 unk3; } BattleUnkSlot; +typedef struct{ + u8 unk0; + u8 unk1; + u8 unk2; + u8 unk3; + u8 unk4; +} BattleTestSlot; + /** @brief Battle character render data (g_battleChars, stride 0x1D0 = 464 bytes). */ typedef struct { /* 0x000 */ u8 pad0[0x008 - 0x000]; @@ -708,7 +718,8 @@ typedef struct { /* 0x01C */ u8 unk1C; /* 0x01D */ u8 unk1D; /* 0x01E */ BattleCmdSlot cmdSlots[4]; - /* 0x02E */ u8 pad2E[0x082 - 0x02E]; + /* 0x02E */ u8 pad2E[4]; + /* 0x032 */ BattleTestSlot testSlots[16]; /* 0x082 */ BattleMagicSlot magicSlots[32]; /* 0x122 */ BattleItemSlot itemSlots[16]; /* 0x172 */ s16 unk172; /**< Mirrored HP cap (set with hpRegenCap when battle HP is reduced). */ @@ -717,7 +728,7 @@ typedef struct { /* 0x17C */ s32 xpToNext; /**< XP needed to reach next level. */ /* 0x180 */ u32 unk180; /* 0x184 */ u32 unk184; - /* 0x188 */ s32 unk188; /**< Status/ability mask checked for bit 0x60000. */ + /* 0x188 */ u32 unk188; /**< Status/ability mask checked for bit 0x60000. */ /* 0x18C */ s32 abilityFlags; /* 0x190 */ s32 statusFlags; /* 0x194 */ u16 elemResistances[8];/**< Element resistance values (8 × s16). */ @@ -739,7 +750,7 @@ typedef struct { /** @brief GF battle entry (12 bytes, used for GF HP in battle). */ typedef struct { - u8 pad0[8]; + u8 unk0[8]; u16 maxHp; /* max HP cap (used to restore hp on revive) */ s16 hp; /* current HP */ } BattleGfEntry; @@ -754,17 +765,27 @@ typedef struct { u8 pad5[7]; } BattleLevelEntry; +typedef struct{ + u8 unk0; + u8 unk1; +} splitStruct; + /** @brief Complete battle character/GF state block. */ typedef struct { /* 0x000 */ BattleCharData chars[3]; /* 3 party members × 0x1D0 */ - /* 0x570 */ u8 pad570[0x610 - 0x570]; + /* 0x570 */ u8 pad570[4]; + /* 0x574 */ u16 unk574[3]; + /* 0x57A */ u16 unk57A[3]; + /* 0x580 */ u16 unk580[16]; + /* 0x5A0 */ u16 unk5A0[16]; + /* 0x5C0 */ u16 unk5C0[16]; + /* 0x5E0 */ splitStruct unk5E0[24]; /* 0x610 */ BattleGfEntry gfEntries[1]; /* hp sub-array (stride 12, 16 entries) */ /* 0x61C */ u8 pad61C[0x620 - 0x61C]; /* 0x620 */ BattleLevelEntry levelEntries[16]; /* 16 × 12 bytes */ } BattleCharState;/* 0x6E0 */ - /** * @brief Battle/scene context struct pointed to by D_800D244C. * @@ -916,7 +937,9 @@ typedef struct { */ typedef struct { u16 lookupId; /**< u16 passed to resolveKernelPtr. */ - u8 pad2[6]; + u8 unk2; + u8 unk3; + u8 pad4[4]; } BattleSceneRow8; /* 8 bytes */ typedef struct { @@ -949,12 +972,12 @@ typedef struct { typedef struct { u16 unk0; - u8 unk1; u8 unk2; u8 unk3; u8 unk4; u8 unk5; u8 unk6; + u8 unk7; u8 unk8; u8 unk9; u16 unkA; @@ -991,7 +1014,7 @@ typedef struct { u8 unk2; u8 unk3; u8 unk4; - u8 pad5; + u8 unk5; u8 unk6; u8 unk7; u8 unk8; @@ -1071,8 +1094,13 @@ typedef struct { /* 0x00D8 */ u8 pad00D8[0x00DC - 0x00D8]; /* 0x00DC */ s32 unk4C0CArg; /**< resolveKernelPtr arg paired with unk4C0C[]. */ /* 0x00E0 */ u8 pad00E0[0x00E8 - 0x00E0]; - /* 0x00E8 */ structE8 unkE8[36]; - /* 0x0208 */ u8 pad0208[0x0220 - 0x0208]; + /* 0x00E8 */ structE8 unkE8[7]; + /* 0x0120 */ u8 pad00F0[0x0139 - 0x0120]; + /* 0x0139 */ u8 unk0139; + /* 0x013A */ u8 unk013A; + /* 0x013B */ u8 pad013B[0x015A - 0x013B]; + /* 0x015A */ u8 unk015A; + /* 0x015B */ u8 pad015B[0x0220 - 0x015B]; /* 0x0220 */ BattleSpellRow spells[1]; /**< 60-byte stride (size unknown, index past). */ /* 0x025C */ u8 pad025C[0x0F78 - 0x025C]; /* 0x0F78 */ BattleSceneRow rows132[1]; /**< 132-byte stride (size unknown, index past). */ @@ -1098,8 +1126,7 @@ typedef struct { /* 0x3F63 */ u8 pad3F63[0x4020 - 0x3F63]; /* 0x4020 */ Struct_4020 array4020[1]; /* 0x4030 */ u8 pad4034[0x4484 - 0x4030]; - /* 0x4484 */ Struct_446C array4484[1]; - /* 0x449C */ u8 pad449C[0x44FC - 0x449C]; + /* 0x4484 */ Struct_446C array4484[5]; /* 0x44FC */ Struct_4020 array44FC[1]; /* 0x450C */ u8 pad4510[0x45F8 - 0x450C]; /* 0x45F8 */ Struct_45F8 array45F8[1]; /**< stride 8 */ @@ -1225,6 +1252,7 @@ extern s16 D_8005F11C; extern u8 D_80077E58; extern u8 D_80077E92; extern u8 D_80077E59; +extern u8 D_8007809A; extern u8 D_800786D9; extern u8 D_80078DF8; extern BattleSceneData D_80078E00; @@ -1242,9 +1270,10 @@ extern u8 D_800E3CC5; extern u8 D_800E3CC6; extern u8 D_800E3CBC[]; extern u8 D_800E3CE8; +extern u8 D_800E3CEC[]; extern BattleSystem D_800ED148; extern BattleCmdBuf D_800EE4C0; -extern BattleAnimTable D_800EE9E8; +extern BattleAnimTable D_800EE9E8; // (D_800EE9B3 = D_800EE9E8-3) extern u8 D_800EEBA8[]; extern u8 D_800EEBB0; extern u8 D_800EEBB8; @@ -1260,6 +1289,9 @@ extern u16 D_800EEBC2; extern s32 D_800EEBC4; extern u8 D_800EEBC8; extern u8 D_800EEBD0; +extern s32 D_800EEBD8; +extern s32 D_800EEBDC; +extern u8 D_800EEBE0[7]; /* ---------------------------------------------------------------- * * Battle-overlay function prototypes (battle internals). @@ -1306,7 +1338,6 @@ void func_800D0608(void); /* bc_object17: overlay VSync handler (RENDER_OVERLAY) void func_8002A2C4(u8 *, s32); s32 func_80037ADC(void); -u16 func_800A97FC(s32 arg0); /* ---------------------------------------------------------------- * * Records the effect overlays share with battle.bin diff --git a/include/battle/bc_object1.h b/include/battle/bc_object1.h index d20409b0..99227e01 100644 --- a/include/battle/bc_object1.h +++ b/include/battle/bc_object1.h @@ -142,4 +142,4 @@ void func_8009B924(s32, s32, s32); u16 func_8009BA5C(s32, u16); -#endif \ No newline at end of file +#endif /* BC_OBJECT1_H */ \ No newline at end of file diff --git a/include/battle/bc_object2.h b/include/battle/bc_object2.h index 86b3a181..956af422 100644 --- a/include/battle/bc_object2.h +++ b/include/battle/bc_object2.h @@ -1,8 +1,6 @@ #ifndef BC_OBJECT2_H #define BC_OBJECT2_H -#include "game.h" - #define BATTLE_ENTITY_FLAG_BIT_0 (1 << 0) /* 0x00000000 */ #define BATTLE_ENTITY_FLAG_BIT_10 (1 << 10) /* 0x00000400 */ @@ -195,4 +193,4 @@ void func_800A184C(s32 idx, u16 attr, s32 flags); void func_800A1888(s32 arg0); -#endif \ No newline at end of file +#endif /* BC_OBJECT2_H */ \ No newline at end of file diff --git a/include/battle/bc_object3.h b/include/battle/bc_object3.h index fe8b091c..f2e47ef2 100644 --- a/include/battle/bc_object3.h +++ b/include/battle/bc_object3.h @@ -170,4 +170,4 @@ void func_800A5C48(InternalStruct*); void func_800A5F24(s32, s32, s32, s32, u16); -#endif \ No newline at end of file +#endif /* BC_OBJECT3_H */ \ No newline at end of file diff --git a/include/battle/bc_object4.h b/include/battle/bc_object4.h index d32823c8..a643c742 100644 --- a/include/battle/bc_object4.h +++ b/include/battle/bc_object4.h @@ -1,5 +1,6 @@ -#ifndef BATTLE_BC_OBJECT4_H -#define BATTLE_BC_OBJECT4_H +#ifndef BC_OBJECT4_H +#define BC_OBJECT4_H + void func_800A6184(s32, s32, s32, u16); @@ -147,4 +148,90 @@ void func_800A8A48(BattleCharData*, s32, u8, s32); s32 func_800A8AFC(s32); -#endif /* BATTLE_BC_OBJECT4_H */ \ No newline at end of file +s32 func_800A8B7C(s32); + +void func_800A8CA4(s32, s32); + +void func_800A8D7C(s32, s32); + +void func_800A8E90(BattleCharData*, s32); + +s32 func_800A8EFC(BattleCharData*); + +void func_800A8F98(BattleCharData*, s32, s32); + +s32 func_800A8FDC(BattleCharData*); + +s32 func_800A9064(BattleCharData*); + +// func_800A9084 + +s32 func_800A9240(s32); + +s32 func_800A9284(BattleCharData*); + +s32 func_800A9370(s32); + +void func_800A9490(void); + +void func_800A94E0(void); + +s32 func_800A9568(s32); + +void func_800A95A0(s32, s32); + +void func_800A960C(s32); + +s32 func_800A972C(s32); + +u8* func_800A9784(u16, s32); + +s32 func_800A97A4(s32); + +void func_800A97D4(void); + +s32 func_800A97FC(s32); + +u16 func_800A980C(void); + +u16 func_800A9888(void); + +u16 func_800A9904(s32); + +void func_800A9938(void); + +void func_800A9970(s32); + +void func_800A99E8(s32); + +void func_800A9A6C(s32); + +void func_800A9AC0(s32, s32); + +void func_800A9C68(s32, s32); + +void func_800A9E08(s32, s32); + +void func_800A9F98(void); + +void func_800A9FDC(void); + +u16 func_800AA034(s32, s32, s32, s32); + +s32 func_800AA368(s32); + +u16 func_800AA44C(s32); + +s32 func_800AA4E0(void); + +s32 func_800AA4E8(void); + +s32 func_800AA4F0(void); + +s32 func_800AA4F8(s32); + +s32 func_800AA530(s32); + +// func_800AA57C + +#endif /* BC_OBJECT4_H */ \ No newline at end of file diff --git a/include/battle/bc_object5.h b/include/battle/bc_object5.h index c2b826e0..1b1b2adb 100644 --- a/include/battle/bc_object5.h +++ b/include/battle/bc_object5.h @@ -1,25 +1,69 @@ -/** - * @file bc_object5.h - * @brief Public symbols owned by bc_object5 — battle command/state queries. - * - * @note Two of this unit's public functions are deliberately absent. - * @c func_800A97FC is still declared in @c battle.h, where bc_object3 - * and bc_object8 pick it up; moving it here means giving those two - * units their own headers first. @c func_800A9784 is defined here - * taking a @c u16 offset but called from bc_object6 through an - * @c (s32, s32) view -- an inconsistent-ABI pair, so that prototype - * stays file-local to bc_object6 where the narrower parameter cannot - * change its call-site codegen. - */ #ifndef BC_OBJECT5_H #define BC_OBJECT5_H -#include "common.h" -extern void func_800A97D4(void); +s32 func_800AA68C(s32, u32, u32); -/** @brief State queries polled by the battle flow controller (bc_object6). */ -extern s32 func_800A980C(void); -extern s32 func_800A9888(void); +s32 func_800AA71C(s32, s32); -#endif /* BC_OBJECT5_H */ +s32 func_800AA768(s32, s32); + +s32 func_800AA7B4(s32, s32); + +s32 func_800AA840(s32, s32); + +s32 func_800AA88C(s32, s32); + +s32 func_800AA930(s32); + +s32 func_800AA980(s32, s32); + +s32 func_800AA9C8(s32, s32); + +s32 func_800AAA10(s32); + +s32 func_800AAA50(s32, s32, s32); + +s32 func_800AAA9C(s32, u32, BattleEntityData*); + +s32 func_800AAB50(s32, u32, BattleEntityData*); + +s32 func_800AABEC(s32, s32, s32, s32, s32); + +s32 func_800AACD0(s32, s32, s32, s32); + +s32 func_800AAE10(s32, s32, s32); + +s32 func_800AAE98(s32); + +void func_800AAF48(s32); + +void func_800AAF70(s32, s16); + +void func_800AAFB8(s32); + +void func_800AB008(s32); + +void func_800AB054(s32); + +void func_800AB0C0(s32, u16); + +void func_800AB11C(s16); + +void func_800AB1AC(s32); + +void func_800AB208(u16); + +s32 func_800AB24C(void); + +void func_800AB28C(void); + +void func_800AB3C4(void); + +void func_800AB3E0(void); + +void func_800AB3FC(s32, s32, s32); + +void func_800AB488(s32, s32); + +#endif /* BC_OBJECT5_H */ \ No newline at end of file diff --git a/include/effect/effect_027.h b/include/effect/effect_027.h new file mode 100644 index 00000000..6f851c78 --- /dev/null +++ b/include/effect/effect_027.h @@ -0,0 +1,68 @@ +#ifndef EFFECT_EFFECT_027_H +#define EFFECT_EFFECT_027_H + +#include "effect.h" +#include "effect/lib/particle.h" + +/** + * @file + * @brief Full-Life: the overlay's own storage. + */ + +/** @brief Cursor the record banks are carved off, moving up as they are taken. */ +extern u8 *D_801D35C4; + +/** @brief Sound cue the script fires on its first frame. */ +extern u8 D_801A9C5C[]; + +/** @brief Pose script the model-taking handler runs. */ +extern EffectPoseTables D_801D4314; + +/** @brief Task pools the script's children run in, and their storage. */ +extern s32 D_801D4174; +extern s32 D_801D42E4; +extern s32 D_801D3854; +extern s32 D_801D40A4; +extern s32 D_801D4184; +extern s32 D_801D3884; +extern s32 D_801D35D4; + +/** @brief Cleared when the effect starts. */ +extern s32 D_801D35B4; +extern s32 D_801D35B8; + +/** + * @name Prim buffers + * + * Two of each, so the frame being built and the frame being drawn never share. + * @{ + */ +extern void *D_801D408C; +extern void *D_801D4090; +extern void *D_801D4094; +extern void *D_801D4098; +/** @} */ + +/** @brief Cursor the effect's second prim buffer is written through. */ +extern void *D_801D4088; + +/** + * @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_801A9D3C; + +/** @brief TIM uploaded to VRAM when the effect starts. */ +extern u8 D_801AA794; +/** @} */ + +/** + * @brief Run one frame of the effect: its opcode, then every task pool it owns. + */ +s32 func_801A99C8(EffectEntity *entity); + +#endif /* EFFECT_EFFECT_027_H */ diff --git a/include/effect/effect_027_entry.h b/include/effect/effect_027_entry.h new file mode 100644 index 00000000..0b48a4d4 --- /dev/null +++ b/include/effect/effect_027_entry.h @@ -0,0 +1,19 @@ +#ifndef EFFECT_EFFECT_027_ENTRY_H +#define EFFECT_EFFECT_027_ENTRY_H + +#include "effect.h" + +/** + * @file effect_027_entry.h + * @brief Full-Life: 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_027_ENTRY_H */ diff --git a/include/effect/params/effect_027/effect_params.h b/include/effect/params/effect_027/effect_params.h new file mode 100644 index 00000000..42463bb7 --- /dev/null +++ b/include/effect/params/effect_027/effect_params.h @@ -0,0 +1,13 @@ +#ifndef EFFECT_PARAMS_H +#define EFFECT_PARAMS_H + +/** + * @file effect_params.h + * @brief Full-Life: the ring sizes its particle engine is built with. + */ + +/** @brief Highest index each ring reaches before it wraps. */ +#define EFFECT_EMITTER_COUNT 0x31 +#define EFFECT_PARTICLE_COUNT 0x8B + +#endif /* EFFECT_PARAMS_H */ diff --git a/src/battle/bc_object1.c b/src/battle/bc_object1.c index 614cd9a9..1516f7fb 100644 --- a/src/battle/bc_object1.c +++ b/src/battle/bc_object1.c @@ -915,8 +915,7 @@ void func_8009B0F8(s32 a0) { * @param entry Caller-supplied context pointer / value. * @return Pointer to the command buffer, or NULL if the queue is full. */ - - // some functions want arg1 to be s32, probably forgot to include the prototype + SoundCmd* func_8009B134(s32 arg0, s32 arg1, void* unused) { return func_800B8564(arg0, arg1); } diff --git a/src/battle/bc_object2.c b/src/battle/bc_object2.c index 25833bb6..ba752c78 100644 --- a/src/battle/bc_object2.c +++ b/src/battle/bc_object2.c @@ -8,6 +8,7 @@ #include "common.h" #include "battle.h" #include "gamestate.h" +#include "game.h" #include "battle/bc_object2.h" #include "battle/bc_object6.h" #include "battle/bc_object7.h" @@ -336,8 +337,8 @@ s32 func_8009C300(s32 arg0, s32 arg1) { u8 func_8009C390(s32 arg0, s32 arg1, s32 arg2) { s32 temp_s3; - s32 var_s0; - s32 var_s1; + s32 i; + s32 mask; s32 var_s2; s32 var_s5; s32 sp20; @@ -349,7 +350,7 @@ u8 func_8009C390(s32 arg0, s32 arg1, s32 arg2) { sp20 = entities[arg1].flags; if (arg2 == 0) { - var_s5 = entities[arg0].unkCD; + var_s5 = entities[arg0].unkCD[0]; temp_s3 = func_8009C300(arg1, 0); } @@ -358,18 +359,22 @@ u8 func_8009C390(s32 arg0, s32 arg1, s32 arg2) { temp_s3 = func_8009C300(arg1, 1); } - var_s1 = 1; - for (var_s0 = 0; var_s0 < 7; var_s0++, var_s1 *= 2) { - if (D_800EEBC2 & var_s1) { - var_s2 += func_8009C104(arg0, arg1, var_s0, var_s1, 0, var_s5, temp_s3, D_800EEBBA); + mask = 1; + for (i = 0; i < 7; i++) { + if (D_800EEBC2 & mask) { + var_s2 += func_8009C104(arg0, arg1, i, mask, 0, var_s5, temp_s3, D_800EEBBA); } + + mask <<= 1; } - var_s1 = 1; - for (var_s0 = 8; var_s0 < 40; var_s0++, var_s1 *= 2) { - if (D_800EEBC4 & var_s1) { - var_s2 += func_8009C104(arg0, arg1, var_s0, var_s1, 1, var_s5, temp_s3, D_800EEBBA); + mask = 1; + for (i = 8; i < 40; i++) { + if (D_800EEBC4 & mask) { + var_s2 += func_8009C104(arg0, arg1, i, mask, 1, var_s5, temp_s3, D_800EEBBA); } + + mask <<= 1; } func_8009BF70(sp20, &D_800ED148.entities[arg1].flags); @@ -662,24 +667,7 @@ s32 func_8009CF18(void) { return func_8009B7BC(33) + 239; } -/** - * @brief Compute damage for a battle action based on type and route to dispatcher. - * - * - case 0/19: scale formula using attacker @c unkCD (squared), defense, - * power, and the @c func_8009CF18 modifier. Case 19 forces - * @c defense to 0 first. - * - case 1: if target's @c controlFlags bit 0x10000 is set, mark - * @c D_800EE4C0[6] (bit 2) and report 0; else scale @c unk28. - * - case 3: multiply attacker's @c unk2C by 5. - * - case 16: active party member's kill count (selected via the party - * slot at @c targetIdx) times power. If @c targetIdx >= 3, - * the damage is forced to 0. - * - * @param attackerIdx Battle entity index of the attacker (case 0/3 path). - * @param targetIdx Battle entity index of the target (case 1) or party slot (case 16). - * @param power Damage multiplier. - * @param type Action type, indexes the case dispatch. - */ + s32 func_8009CF38(s32 attackerIdx, s32 targetIdx, s32 power, u32 type) { s32 defense; s32 dmg; @@ -693,7 +681,7 @@ s32 func_8009CF38(s32 attackerIdx, s32 targetIdx, s32 power, u32 type) { defense = 0; case 0: mod = func_8009CF18(); - stat = D_800ED148.entities[attackerIdx].unkCD; + stat = D_800ED148.entities[attackerIdx].unkCD[0]; sq = stat * stat / 16 + stat; dmg = sq * (265 - defense) / 256 * power / 16 * mod / 256; break; @@ -779,9 +767,9 @@ s32 func_8009D228(s32 arg0, s32 arg1, s32 arg2) { result1 = func_8009C300(arg1, 0); result2 = func_8009CF18(); - var_v1 = D_800ED148.entities[arg0].unkCD * D_800ED148.entities[arg0].unkCD; + var_v1 = D_800ED148.entities[arg0].unkCD[0] * D_800ED148.entities[arg0].unkCD[0]; - var2 = ((var_v1 / 16) + D_800ED148.entities[arg0].unkCD) * (265 - result1); + var2 = ((var_v1 / 16) + D_800ED148.entities[arg0].unkCD[0]) * (265 - result1); var1 = (var2 / 256) * arg2; @@ -1022,7 +1010,7 @@ void func_8009DD2C(s32 arg0, s32 arg1, u16 sp10, s32 arg3) { s32 i; BattleEntity* entities; BattleEntity* entity; - s32 var_s0; + s32 mask; s32 var_s2; @@ -1031,22 +1019,22 @@ void func_8009DD2C(s32 arg0, s32 arg1, u16 sp10, s32 arg3) { func_8009B878(arg0, &sp10, &D_800EEBC4, 0); var_s2 = 0; - var_s0 = 1; + mask = 1; for(i = 0; i < 7; i++) { - if ((sp10 & var_s0) && (entities[arg0].status & var_s0)) { + if ((sp10 & mask) && (entities[arg0].status & mask)) { var_s2 = 1; } - var_s0 *= 2; + mask <<= 1; } - var_s0 = 1; + mask = 1; for(i = 8; i < 40; i++) { - if ((arg3 & var_s0) && (D_800ED148.entities[arg0].flags & var_s0) && (func_800B0668(arg0, var_s0) == 0)) { + if ((arg3 & mask) && (D_800ED148.entities[arg0].flags & mask) && (func_800B0668(arg0, mask) == 0)) { var_s2 = 1; } - var_s0 *= 2; + mask <<= 1; } @@ -2105,17 +2093,8 @@ void func_8009FE14(s32 arg0) { break; case 7: - case 23: - case 24: - case 25: - case 26: - case 27: - case 29: - case 30: - case 31: - case 32: - case 33: - case 34: + case 23 ... 27: + case 29 ... 34: case 38: D_800EEBB9 = D_80078E00.array4020[D_800EE4C0.statusCode].unk8; D_800EEBBA = D_80078E00.array4020[D_800EE4C0.statusCode].unk9; @@ -2437,10 +2416,10 @@ void func_800A09D0(s32 arg0) { break; case 29: - func_8009FCF4(D_80078E00.array4020[D_800EE4C0.statusCode].unk5); - var_s3 = D_80078E00.array4020[D_800EE4C0.statusCode].unk4; - D_800EE4C0.unk4 = D_80078E00.array4020[D_800EE4C0.statusCode].unk2; - var_a0 = D_80078E00.array4020[D_800EE4C0.statusCode].unk3; + func_8009FCF4(D_80078E00.array4020[D_800EE4C0.statusCode].unk6); + var_s3 = D_80078E00.array4020[D_800EE4C0.statusCode].unk5; + D_800EE4C0.unk4 = D_80078E00.array4020[D_800EE4C0.statusCode].unk3; + var_a0 = D_80078E00.array4020[D_800EE4C0.statusCode].unk4; D_800EE4C0.unkC = func_8009F930(var_a0, temp_s4, arg0, var_s3); break; @@ -2512,10 +2491,10 @@ void func_800A09D0(s32 arg0) { break; case 15: - func_8009FCF4(D_80078E00.array44FC[D_800EE4C0.statusCode].unk5); + func_8009FCF4(D_80078E00.array44FC[D_800EE4C0.statusCode].unk6); var_s3 = D_80078E00.array45F8[func_8009FDE0(temp_s4, D_800EE4C0.statusCode)].unk6; - D_800EE4C0.unk4 = D_80078E00.array44FC[D_800EE4C0.statusCode].unk1; - var_a0 = D_80078E00.array44FC[D_800EE4C0.statusCode].unk2; + D_800EE4C0.unk4 = D_80078E00.array44FC[D_800EE4C0.statusCode].unk2; + var_a0 = D_80078E00.array44FC[D_800EE4C0.statusCode].unk3; D_800EE4C0.unkC = func_8009F930(var_a0, temp_s4, arg0, var_s3); break; @@ -2529,20 +2508,12 @@ void func_800A09D0(s32 arg0) { break; case 7: - case 23: - case 24: - case 25: - case 26: - case 27: - case 30: - case 31: - case 32: - case 33: - case 34: - func_8009FCF4(D_80078E00.array4020[D_800EE4C0.statusCode].unk5); - var_s3 = D_80078E00.array4020[D_800EE4C0.statusCode].unk4; - D_800EE4C0.unk4 = D_80078E00.array4020[D_800EE4C0.statusCode].unk2; - var_a0 = D_80078E00.array4020[D_800EE4C0.statusCode].unk3; + case 23 ... 27: + case 30 ... 34: + func_8009FCF4(D_80078E00.array4020[D_800EE4C0.statusCode].unk6); + var_s3 = D_80078E00.array4020[D_800EE4C0.statusCode].unk5; + D_800EE4C0.unk4 = D_80078E00.array4020[D_800EE4C0.statusCode].unk3; + var_a0 = D_80078E00.array4020[D_800EE4C0.statusCode].unk4; D_800EE4C0.unkC = func_8009F930(var_a0, temp_s4, arg0, var_s3); break; diff --git a/src/battle/bc_object3.c b/src/battle/bc_object3.c index 3907cad5..df47e1a2 100644 --- a/src/battle/bc_object3.c +++ b/src/battle/bc_object3.c @@ -1,6 +1,7 @@ #include "common.h" #include "gamestate.h" #include "battle.h" +#include "game.h" #include "battle/bc_object2.h" #include "battle/bc_object3.h" #include "battle/bc_object7.h" @@ -225,18 +226,24 @@ s32 func_800A20AC(s32 arg0) { s32 result; temp_a0 = &g_battleChars.chars[arg0]; - result = 0; - for (mask = 1, i = 0; i < 8; i++, mask *= 2) { + + mask = 1; + for (i = 0; i < 8; i++) { if (temp_a0->displayStatus & mask) { result += D_80078E00.unk4CDC[i]; } + + mask <<= 1; } - for (mask = 1, i = 0; i < 24; i++, mask *= 2) { + mask = 1; + for (i = 0; i < 24; i++) { if (temp_a0->unk188 & mask) { result += D_80078E00.unk4CE4[i]; } + + mask <<= 1; } return result; @@ -647,7 +654,7 @@ u16 func_800A2E48(BattleEntityData* arg0, s32 index) { return arg0->unk150[entity[index+1].slot8.byteView.unkA + result]; } -s32 func_800A2EB8(s32 arg0, s32 arg1) { +s32 func_800A2EB8(s32 arg0, s32 flags) { s32 var_a0; s32 mask; s32 i; @@ -658,12 +665,13 @@ s32 func_800A2EB8(s32 arg0, s32 arg1) { } do { - for (i = 0, mask = 1; i < var_a0; i++) { - mask *= 2; + mask = 1; + for (i = 0; i < var_a0; i++) { + mask <<= 1; } var_a0--; - } while (!(mask & arg1)); + } while (!(mask & flags)); return var_a0 + 1; } @@ -851,7 +859,7 @@ s32 func_800A30F8(s32 arg0, u8 arg1, u16 arg2, u8 arg3, u8 arg4, u16 arg5, u8 ar else { arg2 = D_80078E00.unkE8[arg1].unk0; - var_s3 = D_80078E00.array4020[arg2].unk6; + var_s3 = D_80078E00.array4020[arg2].unk7; sp2E = D_80078E00.array4020[arg2].unk0; break; } @@ -1135,18 +1143,15 @@ s32 func_800A30F8(s32 arg0, u8 arg1, u16 arg2, u8 arg3, u8 arg4, u16 arg5, u8 ar var_s2 = getGfSummonData(arg3); break; - case 17: - case 18: - case 20: - case 21: - case 22: + case 17 ... 18: + case 20 ... 22: var_s3 = D_80078E00.array4484[arg2].unk8; sp2E = D_80078E00.array4484[arg2].unk0; var_s2 = getJuncCategoryName(arg2); break; case 15: - var_s3 = D_80078E00.array44FC[arg2].unk6; + var_s3 = D_80078E00.array44FC[arg2].unk7; sp2E = D_80078E00.array44FC[arg2].unk0; var_s2 = getJuncEffectName(arg2); break; @@ -1261,7 +1266,7 @@ s32 func_800A30F8(s32 arg0, u8 arg1, u16 arg2, u8 arg3, u8 arg4, u16 arg5, u8 ar if (!(D_800ED148.entities[sp2A].status & 4)) { if (func_8009EF64(sp2A) != 0) { arg2 = D_80078E00.unkE8[arg1].unk0; - var_s3 = D_80078E00.array4020[arg2].unk6; + var_s3 = D_80078E00.array4020[arg2].unk7; sp2E = D_80078E00.array4020[arg2].unk0; break; } @@ -1270,18 +1275,10 @@ s32 func_800A30F8(s32 arg0, u8 arg1, u16 arg2, u8 arg3, u8 arg4, u16 arg5, u8 ar func_800A42DC(112, &arg1, &arg6, &sp2E, &arg2); break; - case 23: - case 24: - case 25: - case 26: - case 27: - case 30: - case 31: - case 32: - case 33: - case 34: + case 23 ... 27: + case 30 ... 34: arg2 = D_80078E00.unkE8[arg1].unk0; - var_s3 = D_80078E00.array4020[arg2].unk6; + var_s3 = D_80078E00.array4020[arg2].unk7; sp2E = D_80078E00.array4020[arg2].unk0; var_s2 = getAbilityEntryName(arg1); break; @@ -1500,7 +1497,7 @@ s32 func_800A4798(u32 arg0, s32 arg1) { // arg0 is always 0-6 u16 mask = 1 << arg0; for (i = 0; i < arg1; i++) { - if (mask & D_800ED148.array12B8[i]) { + if (mask & D_800ED148.unk12B8[i]) { count++; } } @@ -1671,7 +1668,7 @@ void func_800A4B88(u16 arg0, s32 arg1) { var_a1 = func_800A4E08(var_a1, var_s0); } - D_800ED148.array12B8[i] = func_800A4A74(arg1, var_a1); + D_800ED148.unk12B8[i] = func_800A4A74(arg1, var_a1); } D_800ED148.unk130A = var_s0; @@ -1691,7 +1688,7 @@ void func_800A4C84(u16 arg0) { func_800A4B88(arg0, D_800EE4C0.unkB); for (i = 0; i < D_800EE4C0.unkB; i++) { - temp_s1 = func_800A4FC4(D_800ED148.array12B8[i], sp10); + temp_s1 = func_800A4FC4(D_800ED148.unk12B8[i], sp10); var_s5 += temp_s1; if (temp_s1 != 0) { @@ -2276,12 +2273,7 @@ void func_800A5C48(InternalStruct* arg0) { case 11: case 14: case 15: - case 17: - case 18: - case 19: - case 20: - case 21: - case 22: + case 17 ... 22: D_800E3CE8 = func_8009B2A4(D_800ED148.unkD64[1], &D_800ED148.unk1100[1], 11); var_s3 = 1; func_800A5AF4(p->unk2); diff --git a/src/battle/bc_object4.c b/src/battle/bc_object4.c index 1aa6d1c5..882ace5c 100644 --- a/src/battle/bc_object4.c +++ b/src/battle/bc_object4.c @@ -3,11 +3,9 @@ #include "gf.h" #include "gamestate.h" #include "battle/bc_object4.h" - extern void func_800E1850(void); - void func_800A6184(s32 arg0, s32 arg1, s32 arg2, u16 arg3) { func_800A5A7C(arg0, arg1, arg2, 0, arg3, 0, &D_800ED148.unk1244[arg0].unk0); } @@ -314,9 +312,6 @@ void func_800A69BC(void) { case 4: func_8009AF3C(getMenuString(0x2F), (D_80077E59 * 8) + 8, 3, 128, 86); break; - - default: - return; } } @@ -600,6 +595,7 @@ s32 func_800A703C(s32 a0) { if (a0 < limit) { return a0; } + return limit; } @@ -1071,13 +1067,7 @@ INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object4", func_800A7D8C); u8 func_800A7EE0(BattleEntityData* arg0, s32 arg1) { switch (arg1) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: + case 0 ... 6: return arg0->unk168[arg1]; case 8: @@ -1133,8 +1123,8 @@ void func_800A7FD0(s32 arg0, s32 arg1, s32 arg2) { temp_s3 = *D_800ED148.entities[arg0].entityData; - D_800EE9E8.subEntries[arg0 - 3].unk10 = 0; temp_s1 = (BattleEntityData*)&D_800ED148.entities[arg0].entityData; + D_800EE9E8.subEntries[arg0 - 3].unk10 = 0; temp_s1->unkBC = func_800A7154(arg1); temp_s1->unk7C = 17; if (temp_s3->immunityFlags & 0x10) { @@ -1438,4 +1428,841 @@ s32 func_800A8AFC(s32 arg0) { func_800A8A48(ptr, 2, 0, 0); return 2; -} \ No newline at end of file +} + +#include "battle/bc_object7.h" + +s32 func_800A8B7C(s32 arg0) { + BattleCharData* temp_s0; + + temp_s0 = &g_battleChars.chars[arg0]; + func_800A8A48(temp_s0, 2, 0, 1); + + switch (temp_s0->unk188 & 0x60000) { + case 0: + return 0; + + case 0x60000: + func_800A8A48(temp_s0, 0, 0x23, 1); + func_800A8A48(temp_s0, 1, 0x24, 1); + func_800A8A48(temp_s0, 2, 0x25, 1); + return 3; + + case 0x20000: + func_800A8A48(temp_s0, 0, 0x23, 1); + func_800A8A48(temp_s0, 1, 0x24, 1); + return 2; + + case 0x40000: + func_800A8A48(temp_s0, 0, 0x23, 1); + func_800A8A48(temp_s0, 1, 0x25, 1); + return 2; + } +} + +void func_800A8CA4(s32 characterId, s32 targetId) { + BattleAnimSubEntry* var_s0; + s32 i; + + if (D_800ED148.entities[targetId].controlFlags & 1) { + for (i = 0; i < 4; i++) { + var_s0 = &D_800EE9E8.subEntries[targetId - 3]; + if (var_s0->array0[i].unk0 < 64) { + if (hasJunctionedAbility(characterId, var_s0->array0[i].unk0) != 0) { + var_s0->array0[i].unk1 |= 4; + } + + else { + var_s0->array0[i].unk1 &= 0xFB; + } + } + } + } +} + +void func_800A8D7C(s32 arg0, s32 arg1) { + BattleCharData* temp_s0; + + temp_s0 = &g_battleChars.chars[arg0]; + temp_s0->pad0[0] = 10; + temp_s0->pad0[1] = D_80078E00.unk0139; + temp_s0->pad0[2] = D_80078E00.unk013A; + temp_s0->pad0[3] = 0; + if (arg1 < 64) { + temp_s0->pad0[4] = 9; + temp_s0->pad0[5] = D_80078E00.spells[arg1].unk5; + temp_s0->pad0[6] = D_80078E00.spells[arg1].magicId; + temp_s0->pad0[7] = 0; + + if (D_80078E00.spells[arg1].unk7 & 0x80) { + temp_s0->pad0[7] = 1; + + if (D_80078E00.spells[arg1].unk7 & 0x80) { + temp_s0->pad0[3] |= 1; + } + } + + if (func_800A89B8(arg0, arg1) != 0) { + temp_s0->pad0[3] |= 2; + } + } + + else { + temp_s0->pad0[4] = 9; + temp_s0->pad0[5] = 0; + temp_s0->pad0[6] = 0; + temp_s0->pad0[7] = 2; + } +} + +void func_800A8E90(BattleCharData* arg0, s32 arg1) { + arg0->testSlots[0].unk0 = arg1; + arg0->testSlots[0].unk2 = D_80078E00.array4484[arg1].unk5; + arg0->testSlots[0].unk3 = D_80078E00.array4484[arg1].unk6; + arg0->testSlots[0].unk4 = 0; + arg0->testSlots[0].unk1 = 1; + + if (D_80078E00.array4484[arg1].unk7 & 0x80) { + arg0->testSlots[0].unk4 |= 1; + } +} + +s32 func_800A8EFC(BattleCharData* arg0) { + s32 bit; + s32 i; + s32 val; + + val = 0; + bit = 1; + + for (i = 0; i < 16; i++) { + if (g_gameState.mainData.limitBreaks.quistisLimits & bit) { + arg0->testSlots[val].unk0 = i; + arg0->testSlots[val].unk2 = D_80078E00.array44FC[i].unk4; + arg0->testSlots[val].unk3 = D_80078E00.array44FC[i].unk5; + arg0->testSlots[val].unk4 = 0; + arg0->testSlots[val].unk1 = 1; + arg0->testSlots[val].unk4 &= 0xEF; + + if (D_80078E00.array44FC[i].unk6 & 0x80) { + arg0->testSlots[val].unk4 |= 1; + } + + val++; + } + + bit <<= 1; + } + + return val; +} + +void func_800A8F98(BattleCharData* arg0, s32 arg1, s32 arg2) { + arg0->testSlots[arg2].unk0 = arg1; + arg0->testSlots[arg2].unk2 = D_80078E00.rows8[arg1].unk2; + arg0->testSlots[arg2].unk3 = D_80078E00.rows8[arg1].unk3; + arg0->testSlots[arg2].unk4 = 0; + arg0->testSlots[arg2].unk1 = 1; +} + +s32 func_800A8FDC(BattleCharData* arg0) { + s32 current; + s32 val = 0; + + if (!(g_gameState.mainData.partyLockFlag & 0x10)) { + val++; + func_800A8F98(arg0, 0, 0); + } + + current = val; + if (g_gameState.mainData.partyLockFlag & 0x20) { + val++; + func_800A8F98(arg0, 1, current); + } + + return val; +} + +s32 func_800A9064(BattleCharData* arg0) { + arg0->testSlots[0].unk0 = 65; + arg0->testSlots[1].unk0 = 67; + arg0->testSlots[2].unk0 = 66; + + return 3; +} + +INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object4", func_800A9084); + +s32 func_800A9240(s32 arg0) { + s32 i; + + for (i = 0; i < 198; i++) { + if (g_gameState.mainData.itemSlots[i].id == arg0) { + return g_gameState.mainData.itemSlots[i].count; + } + } + + return 0; +} + +s32 func_800A9284(BattleCharData* arg0) { + s32 i; + u16 mask; + s32 val; + s32 temp_a0; + s32 var_s1; + + val = 0; + mask = 1; + var_s1 = 101; + + for (i = 0; i < 8; i++) { + temp_a0 = func_800A9240(var_s1); + if ((g_gameState.mainData.limitBreaks.irvineLimits & mask) || (temp_a0 != 0)) { + arg0->testSlots[val].unk0 = var_s1; + arg0->testSlots[val].unk2 = 0x80; + arg0->testSlots[val].unk3 = D_80078E00.unk015A; + arg0->testSlots[val].unk4 = 0; + arg0->testSlots[val].unk1 = temp_a0; + arg0->testSlots[val].unk4 &= 0xEF; + + if (temp_a0 == 0) { + arg0->testSlots[val].unk4 |= 2; + } + + val++; + } + + var_s1++; + mask <<= 1; + } + + return val; +} + +s32 func_800A9370(s32 arg0) { + BattleCharData* temp_a0; + s32 i; + + temp_a0 = &g_battleChars.chars[arg0]; + + for (i = 0; i < 16; i++) { + temp_a0->testSlots[i].unk4 = 0; + temp_a0->testSlots[i].unk1 = 0; + temp_a0->testSlots[i].unk3 = 0; + temp_a0->testSlots[i].unk2 = 0; + temp_a0->testSlots[i].unk0 = 0; + temp_a0->testSlots[i].unk4 |= 0x10; + } + + switch (temp_a0->characterId) { + case 0: + case 1: + return 0; + + case 2: + return func_800A9284(temp_a0); + + case 3: + return func_800A8EFC(temp_a0); + + case 4: + return func_800A8FDC(temp_a0); + + case 5: + return func_800A9064(temp_a0); + + case 6: + func_800A8E90(temp_a0, 0); + return 1; + + case 7: + func_800A8E90(temp_a0, 1); + return 1; + + case 8: + func_800A8E90(temp_a0, 2); + return 1; + + case 9: + func_800A8E90(temp_a0, 3); + return 1; + + case 10: + func_800A8E90(temp_a0, 4); + return 1; + } +} + +void func_800A9490(void) { + s32 i; + + for (i = 0; i < 3; i++) { + g_battleChars.unk57A[i] = 0; + g_battleChars.unk574[i] = 0; + } + + for (i = 0; i < 16; i++) { + g_battleChars.unk5A0[i] = 0; + g_battleChars.unk580[i] = 0; + } +} + +void func_800A94E0(void) { + s32 i; + + func_800A9490(); + + for (i = 0; i < 16; i++) { + g_battleChars.unk5C0[i] = 0; + } + + for (i = 0; i < 24; i++) { + g_battleChars.unk5E0[i].unk1 = 0; + g_battleChars.unk5E0[i].unk0 = 0; + } + + + + for (i = 0; i < 8; i++) { + g_battleChars.gfEntries[0].unk0[i] = 255; + } +} + +s32 func_800A9568(s32 arg0) { + s32 i; + + for (i = 0; i < 32; i++) { + if (D_800EE9E8.animSlots[i].id == arg0) { + return 1; + } + } + + return 0; +} + +void func_800A95A0(s32 arg0, s32 arg1) { + func_800B0754(arg0, 4, arg1, func_800A97FC(arg0)); + func_800AF4BC(arg1, 1); + + if (func_800AE390(arg1) == 0) { + func_800AE3D4(arg1); + } +} + +void func_800A960C(s32 arg0) { + s32 result; + + if (D_800ED148.entities[arg0].status & 0x200) { + result = D_800ED148.entities[arg0].unk2C - D_800ED148.entities[arg0].unk28; + if (result <= 200) { + return; + } + + if (result > 1000) { + if (func_800A9568(3) != 0) { + func_800A95A0(arg0, 3); + } + + else if (func_800A9568(1) != 0) { + func_800A95A0(arg0, 1); + } + + else if (func_800A9568(2) != 0) { + func_800A95A0(arg0, 2); + } + + else if (func_800A9568(4) != 0) { + func_800A95A0(arg0, 4); + } + + else if (func_800A9568(5) != 0) { + func_800A95A0(arg0, 5); + } + + else if (func_800A9568(9) != 0) { + func_800A95A0(arg0, 9); + } + } + + else { + if (func_800A9568(1) != 0) { + func_800A95A0(arg0, 1); + } + } + } +} + + +s32 func_800A972C(s32 arg0) { + return func_800B0F9C(D_80078E00.entriesA0[arg0].unk7) | func_800B0F7C(D_80078E00.entriesA0[arg0].unk7); +} + +u8* func_800A9784(u16 arg0, s32 arg1) { + if (arg0 == 65535) { + return D_800E3CEC; + } + + return arg0 + arg1; // weird +} + +s32 func_800A97A4(s32 arg0) { + return func_8009B15C() % arg0; +} + +void func_800A97D4(void) { + s32 i; + + for (i = 0; i < 8; i++) { + D_800ED148.unk1298[i] = 0; + } +} + +s32 func_800A97FC(s32 arg0) { + return (u16)(1 << arg0); // functions in this folder break with u16 return prototype +} + +u16 func_800A980C(void) { + s32 idx; + + if (func_800AE730() == 255) { + return 0; + } + + do { + idx = func_800A97A4(3); + } while (D_800ED148.entities[idx].status & 1); + + return (1 << idx); +} + +u16 func_800A9888(void) { + s32 idx; + + if (func_800AE788() == 255) { + return 8; + } + + do { + idx = func_800A97A4(4) + 3; + } while (D_800ED148.entities[idx].status & 1); + + return (1 << idx); +} + +u16 func_800A9904(s32 arg0) { + return (1 << D_800ED148.entities[arg0].unk98); +} + +void func_800A9938(void) { + s32 i; + + for (i = 0; i < 7; i++) { + D_800EEBE0[i] = ~D_800EEBE0[i] & 1; + } +} + +void func_800A9970(s32 arg0) { + s32 i; + + for (i = 0; i < 7; i++) { + if (D_800ED148.entities[i].controlFlags & 0x100) { + D_800EEBE0[i] = 1; + } + + else { + D_800EEBE0[i] = 0; + } + } + + if (arg0 == 200) { + func_800A9938(); + } +} + +void func_800A99E8(s32 arg0) { + s32 i; + + for (i = 0; i < 7; i++) { + if (arg0 < 16) { + if ((D_800ED148.entities[i].status >> arg0) & 1) { + D_800EEBE0[i] = 1; + } + + else { + D_800EEBE0[i] = 0; + } + } + + else { + s32 result = 1 << (arg0 - 16); + if (D_800ED148.entities[i].flags & result) { + D_800EEBE0[i] = 1; + } + + else { + D_800EEBE0[i] = 0; + } + } + } +} + +void func_800A9A6C(s32 arg0) { + switch (arg0) { + case 200: + D_800EEBD8 = 0; + D_800EEBDC = 3; + break; + + case 201: + D_800EEBD8 = 3; + D_800EEBDC = 7; + break; + + default: + D_800EEBD8 = 0; + D_800EEBDC = 7; + break; + } +} + +void func_800A9AC0(s32 arg0, s32 arg1) { + s32 i; + s32 val; + s32 idx; + + func_800A9A6C(arg1); + + if (arg0 < 213) { + val = 0; + idx = arg0 - 0xCD; + for (i = D_800EEBD8; i < D_800EEBDC; i++) { + if (!(D_800ED148.entities[i].status & 1)) { + u8* cd = D_800ED148.entities[i].unkCD; + if (val < cd[idx]) { + val = cd[idx]; + } + } + } + } + + else { + val = 255; + idx = arg0 - 0xD5; + for (i = D_800EEBD8; i < D_800EEBDC; i++) { + if (!(D_800ED148.entities[i].status & 1)) { + u8* cd = D_800ED148.entities[i].unkCD; + if (cd[idx] < val){ + val = cd[idx]; + } + } + } + } + + for (i = 0; i < 7; i++) { + u8* cd = D_800ED148.entities[i].unkCD; + if (val == cd[idx]) { + D_800EEBE0[i] = 1; + } + + else { + D_800EEBE0[i] = 0; + } + } +} + +void func_800A9C68(s32 arg0, s32 arg1) { + s32 i; + u16 val; + s32 idx; + + func_800A9A6C(arg1); + + if (arg0 < 229) { + val = 0; + idx = arg0 - 221; + for (i = D_800EEBD8; i < D_800EEBDC; i++) { + if (!(D_800ED148.entities[i].status & 1)) { + if (val < D_800ED148.entities[i].unk54[idx]) { + val = D_800ED148.entities[i].unk54[idx]; + } + } + } + } + + else { + val = 65535; + idx = arg0 - 229; + for (i = D_800EEBD8; i < D_800EEBDC; i++) { + if (!(D_800ED148.entities[i].status & 1)) { + if (D_800ED148.entities[i].unk54[idx] < val) { + val = D_800ED148.entities[i].unk54[idx]; + } + } + } + } + + + for (i = 0; i < 7; i++) { + if (val == D_800ED148.entities[i].unk54[idx]) { + D_800EEBE0[i] = 1; + } + + else { + D_800EEBE0[i] = 0; + } + } +} + +void func_800A9E08(s32 arg0, s32 arg1) { + s32 i; + s32 val; + + func_800A9A6C(arg1); + + if (arg0 == 203) { + val = 0; + for (i = D_800EEBD8; i < D_800EEBDC; i++) { + if (!(D_800ED148.entities[i].status & 1)) { + if (val < D_800ED148.entities[i].unk28) { + val = D_800ED148.entities[i].unk28; + } + } + } + } + + else { + val = 0x7FFFFFFF; + for (i = D_800EEBD8; i < D_800EEBDC; i++) { + if (!(D_800ED148.entities[i].status & 1)) { + if ((D_800ED148.entities[i].unk28 < val) && (D_800ED148.entities[i].unk28 != 0)) { + val = D_800ED148.entities[i].unk28; + } + } + } + } + + for (i = 0; i < 7; i++) { + if (val == D_800ED148.entities[i].unk28) { + D_800EEBE0[i]= 1; + } + + else { + D_800EEBE0[i] = 0; + } + } +} + +void func_800A9F98(void) { + s32 i; + + for (i = 0; i < 7; i++) { + if (!(D_800ED148.entities[i].controlFlags & 1)) { + D_800EEBE0[i] = 0; + } + } +} + +void func_800A9FDC(void) { + s32 i; + + for (i = 0; i < 7; i++) { + if (!(D_800ED148.entities[i].controlFlags & 1) || (D_800ED148.entities[i].status & 1)) { + D_800EEBE0[i] = 0; + } + } +} + +u16 func_800AA034(s32 arg0, s32 arg1, s32 arg2, s32 arg3) { + s32 i; + s32 result; + s32 var_s0; + + var_s0 = 0; + + switch (arg3) { + case 200: case 201: + func_800A9970(arg3); + break; + + case 0: + var_s0 = 1; + /* fallthrough */ + case 1 ... 9: + case 16 ... 42: + case 46 ... 47: + func_800A99E8(arg3); + break; + + case 205 ... 220: + func_800A9AC0(arg3, arg1); + break; + + case 221 ... 236: + func_800A9C68(arg3, arg1); + break; + + case 203 ... 204: + func_800A9E08(arg3, arg1); + break; + + default: + break; + } + + if (arg2 == 3) { + func_800A9938(); + } + + if (var_s0 == 0) { + func_800A9FDC(); + } + + else { + func_800A9F98(); + } + + if (arg0 == 0) { + switch (arg1) { + case 200: + do { + i = func_800A97A4(3); + } while (D_800EEBE0[i] == 0); + result = func_800A97FC(i); + break; + + case 201: + do { + i = func_800A97A4(4) + 3; + } while (D_800EEBE0[i] == 0); + result = func_800A97FC(i); + break; + + default: + do { + i = func_800A97A4(7); + } while ((D_800EEBE0[i] == 0) || D_800ED148.entities[i].linkedIdx != arg1); + result = func_800A97FC(i); + break; + } + } + + else { + result = 32768; + switch (arg1) { + case 200: + for (i = 0; i < 3; i++) { + if (D_800EEBE0[i] != 0) { + result |= func_800A97FC(i); + } + } + break; + + case 201: + for (i = 3; i < 7; i++) { + if (D_800EEBE0[i] != 0) { + result |= func_800A97FC(i); + } + } + break; + + default: + for (i = 0; i < 7; i++) { + if ((D_800ED148.entities[i].linkedIdx == arg1) && (D_800EEBE0[i] != 0)) { + result |= func_800A97FC(i); + } + } + break; + } + } + + return result; +} + +s32 func_800AA368(s32 arg0) { + s32 i; + s32 val; + + val = 0; + switch(arg0) { + case 200: + for (i = 0; i < 3; i++) { + if (!(D_800ED148.entities[i].status & 1)) { + val++; + } + } + break; + + case 201: + for (i = 3; i < 7; i++) { + if (!(D_800ED148.entities[i].status & 1)) { + val++; + } + } + break; + + default: + for (i = 0; i < 7; i++) { + if ((D_800ED148.entities[i].linkedIdx == arg0) && !(D_800ED148.entities[i].status & 1)) { + val++; + } + } + break; + } + + return val; +} + +u16 func_800AA44C(s32 arg0) { + s32 bit; + + if (func_800AA368(201) == 1) { + bit = arg0; + } + + else { + do { + bit = func_800A97A4(4) + 3; + } while (bit == arg0 || (D_800ED148.entities[bit].status & 1)); + } + + return (1 << bit); +} + +s32 func_800AA4E0(void) { + return 32775; +} + +s32 func_800AA4E8(void) { + return 33016; +} + +s32 func_800AA4F0(void) { + return 33023; +} + +s32 func_800AA4F8(s32 arg0) { + s32 i; + + for (i = 0; i < 7; i++) { + if (D_800ED148.entities[i].linkedIdx == arg0) { + return i; + } + } + + return 255; +} + +s32 func_800AA530(s32 arg0) { + s32 i; + + for (i = 0; i < 7; i++) { + if (!(D_800ED148.entities[i].status & 1) && ((D_800ED148.entities[i].linkedIdx == arg0))) { + return i; + } + } + + return 255; +} + +INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object4", func_800AA57C); \ No newline at end of file diff --git a/src/battle/bc_object5.c b/src/battle/bc_object5.c index b153c562..46fddc0b 100644 --- a/src/battle/bc_object5.c +++ b/src/battle/bc_object5.c @@ -2,595 +2,337 @@ #include "battle.h" #include "gamestate.h" #include "battle/bc_object5.h" -#include "battle/bc_object6.h" -#include "battle/bc_object7.h" -extern u8 D_800E3CEC[]; -void func_800AB054(void); -void func_800AB1AC(void); -s32 func_800B0398(s32); -void func_800A59AC(s32, s32, s32); -s32 func_800A97A4(s32); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A8B7C); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A8CA4); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A8D7C); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A8E90); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A8EFC); - -/** - * @brief Initialize entity ability fields from the ability table. - * - * Writes a1 as the ability ID at offset 0x32 of the entity entry - * (computed as a0 + a2*5). Looks up ability data in D_80078E00 - * (offset 0x4A60, stride 8) and copies two bytes to offsets 0x34-0x35. - * Clears offset 0x36 and sets offset 0x33 to 1. - * - * @param a0 Base entity pointer (as integer). - * @param a1 Ability ID. - * @param a2 Slot index (multiplied by 5 for stride). - */ -void func_800A8F98(s32 a0, s32 a1, s32 a2) { - s32 entry = a0 + a2 * 5; - s32 tbl = (s32)&D_80078E00; - s32 lookup = a1 * 8; - s32 b; - *(u8 *)(entry + 0x32) = a1; - *(u8 *)(entry + 0x34) = *(u8 *)(tbl + lookup + 0x4A60); - b = *(u8 *)(tbl + lookup + 0x4A61); - *(u8 *)(entry + 0x36) = 0; - *(u8 *)(entry + 0x33) = 1; - *(u8 *)(entry + 0x35) = b; -} - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A8FDC); +s32 func_800AA68C(s32 arg0, u32 arg1, u32 arg2) { + switch (arg1) { + case 0: + if (arg0 == arg2) { + return 1; + } + break; + + case 1: + if (arg0 < arg2) { + return 1; + } + break; + + case 2: + if (arg2 < arg0) { + return 1; + } + break; + + case 3: + if (arg0 != arg2) { + return 1; + } + break; + + case 4: + if (arg2 >= arg0) { + return 1; + } + break; + + case 5: + if (arg0 >= arg2) { + return 1; + } + break; + } -/** - * @brief Initialize three type bytes in an entity structure. - * - * @param a0 Pointer to entity data. - * @return Always 3. - */ -s32 func_800A9064(u8 *a0) { - a0[0x32] = 0x41; - a0[0x37] = 0x43; - a0[0x3C] = 0x42; - return 3; + return 0; } -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A9084); - -/** - * @brief Search g_gameState+0xB44 table for entry matching a given byte. - * - * Iterates up to 198 entries (stride 2) in g_gameState at offset 0xB44. - * If byte[0] matches a0, returns byte[1]. Returns 0 if not found. - * - * @param a0 Value to search for. - * @return Unsigned byte at offset 1 of matching entry, or 0 if not found. - */ -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A9240); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A9284); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A9370); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A9490); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A94E0); - -/** - * @brief Search D_800EE9E8 table for a matching byte value. - * - * Iterates up to 32 entries (stride 5) in D_800EE9E8, comparing - * the first byte of each entry to a0. - * - * @param a0 Value to search for. - * @return 1 if found, 0 if not found. - * - * @code - * s32 func_800A9568(s32 a0) { - * s32 i = 0; - * u8 *ptr = D_800EE9E8; - * do { - * if (*ptr == a0) return 1; - * i++; - * ptr += 5; - * } while (i < 32); - * return 0; - * } - * @endcode - */ -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A9568); - -/** - * @brief Set up entity action with sound and visual effects. - * - * Calls func_800A97FC to get a value, then triggers entity action - * via func_800B0754, sets animation via func_800AF4BC, and - * conditionally calls func_800AE3D4 based on func_800AE390 result. - * - * @param a0 Entity index passed to func_800A97FC and func_800B0754. - * @param a1 Mode parameter for func_800B0754 and subsequent calls. - */ -void func_800A95A0(s32 a0, s32 a1) { - s32 val = func_800A97FC(a0); - func_800B0754(a0, 4, a1, (u16)val); - func_800AF4BC(a1, 1); - if (func_800AE390(a1) == 0) { - func_800AE3D4(a1); +s32 func_800AA71C(s32 arg0, s32 arg1) { + if (arg0 == 0) { + return func_800AA4F8(arg1) != 255; + } + + if (arg0 == 3) { + return func_800AA4F8(arg1) == 255; } } -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A960C); - -/** - * @brief Compute paired lookup results from entity table and return combined. - * - * Computes D_80078E00 + a0 * 20 as the base address, loads the byte at - * offset 0x3EE7, calls func_800B0F9C and func_800B0F7C with it, and - * returns the bitwise OR of both results masked to 16 bits. - * - * @param a0 Entity index (stride 20 in D_80078E00). - * @return Combined result from both lookups, masked to u16. - */ -s32 func_800A972C(s32 arg0) { - return func_800B0F9C(D_80078E00.entriesA0[arg0].unk7) | func_800B0F7C(D_80078E00.entriesA0[arg0].unk7); -} +s32 func_800AA768(s32 arg0, s32 arg1) { + if (arg0 == 0) { + return func_800AA530(arg1) != 255; + } -/** - * @brief Resolve a 16-bit offset to an address. - * - * If the offset is 0xFFFF (sentinel), returns D_800E3CEC. - * Otherwise returns offset + base. - * - * @param offset 16-bit offset value (0xFFFF = invalid). - * @param base Base address to add offset to. - * @return Resolved address. - */ -s32 func_800A9784(u16 offset, s32 base) { - if ((offset & 0xFFFF) == 0xFFFF) { - return (s32)D_800E3CEC; + if (arg0 == 3) { + return func_800AA530(arg1) == 255; } - return offset + base; } -/** - * @brief Return a random number modulo @p a0. - * - * @param a0 Divisor (also the modulo bound). - * @return Remainder of @c func_8009B15C() / @p a0. - */ -s32 func_800A97A4(s32 a0) { - return func_8009B15C() % a0; +s32 func_800AA7B4(s32 unused, s32 arg1) { + s32 i; + + for (i = 0; i < 3; i++) { + if ((D_800ED148.entities[i].controlFlags & 1) && !(D_800ED148.entities[i].status & 1)) { + if (arg1 == 202) { + if (!(D_800ED148.entities[i].controlFlags & 0x100)) { + return i; + } + } + + else { + if ((D_800ED148.entities[i].controlFlags & 0x100)) { + return i; + } + } + } + } + + return 255; } -/** - * @brief Clear 8 entity word fields in the battle entity table. - * - * Zeros 8 consecutive words at offset 0x12B4 down to 0x1298 - * relative to D_800ED148. - */ -void func_800A97D4(void) { - s32 i = 7; - s32 base = (s32)&D_800ED148; - base += 0x1C; -top: - *(s32 *)(base + 0x1298) = 0; - i--; - base -= 4; - if (i >= 0) goto top; -} +s32 func_800AA840(s32 arg0, s32 arg1) { + if (arg0 == 0) { + return func_800AA7B4(arg1, arg1) != 255; + } -/** - * @brief Compute a single-bit mask at the given position. - * - * @param bitPos Bit position (0-15). - * @return 16-bit mask with bit at bitPos set. - */ -u16 func_800A97FC(s32 arg0) { - return 1 << arg0; + if (arg0 == 3) { + return func_800AA7B4(arg1, arg1) == 255; + } } -/** - * @brief Find a random available entity (among first 3) and return its bitmask. - * - * Calls func_800AE730 to get entity count. If 0xFF, returns 0. - * Otherwise loops calling func_800A97A4(3) to pick random indices, - * checking entity[0x90] bit 0 (busy flag). Returns (1 << idx) & 0xFFFF - * when an available entity is found. - * - * @return Bitmask of selected entity, or 0 if none available. - */ -s32 func_800A980C(void) { - s32 idx; - u8 *table; - if (func_800AE730() == 0xFF) { +s32 func_800AA88C(s32 arg0, s32 arg1) { + if (arg0 == 0) { + if ((D_800ED148.entities[arg1].controlFlags & 1) && !(D_800ED148.entities[arg1].status & 1)) { + return 1; + } + return 0; } - table = (u8 *)&D_800ED148; - do { - idx = func_800A97A4(3); - } while (*(u16 *)(table + idx * 0xD0 + 0x90) & 1); - return (1 << idx) & 0xFFFF; -} - -/** - * @brief Find a random available entity (among 4, offset by 3) and return its bitmask. - * - * Calls func_800AE788 to get entity count. If 0xFF, returns 8. - * Otherwise loops calling func_800A97A4(4), adds 3 to the index, - * checks entity[0x90] bit 0 (busy flag). Returns (1 << (idx+3)) & 0xFFFF - * when an available entity is found. - * - * @return Bitmask of selected entity, or 8 if none available. - */ -s32 func_800A9888(void) { - s32 idx; - u8 *table; - if (func_800AE788() == 0xFF) { - return 8; - } - table = (u8 *)&D_800ED148; - do { - idx = func_800A97A4(4) + 3; - } while (*(u16 *)(table + idx * 0xD0 + 0x90) & 1); - return (1 << idx) & 0xFFFF; -} + + if (arg0 == 3) { + if ((D_800ED148.entities[arg1].controlFlags & 1) && !(D_800ED148.entities[arg1].status & 1)) { + return 0; + } -/** - * @brief Compute a bitmask from an entity's byte at offset 0x98. - * - * @param a0 Entity index (stride 0xD0). - * @return 16-bit mask with one bit set at the position given by entity[0x98]. - */ -u16 func_800A9904(s32 a0) { - u8 *base = (u8 *)&D_800ED148; - u8 *entity; - asm(""); - entity = base + a0 * 0xD0; - return (1 << entity[0x98]) & 0xFFFF; + return 1; + } } -extern u8 D_800EEBE0[]; +s32 func_800AA930(s32 arg0) { + drawSlot* var_v1; + s32 i; -/** - * @brief Toggle the least significant bit of 7 bytes in D_800EEBE0. - */ -void func_800A9938(void) { - s32 i = 0; - u8 *base = D_800EEBE0; - do { - u8 *p = (u8 *)(i + (s32)base); - *p = (~*p) & 1; - i++; - } while (i < 7); -} - -/** - * @brief Populate entity alive flags array from status bits. - * - * Iterates over 7 entities at stride 0xD0 from D_800ED148. For each, - * checks bit 8 (0x100) of the flags word at offset 0x8C. Writes 1 to - * D_800EEBE0[i] if the bit is set, 0 otherwise. If a0 equals 0xC8, - * calls func_800A9938 to toggle the result bits. - * - * @param a0 Trigger value — if 0xC8, post-processes the flags. - */ -void func_800A9970(s32 a0) { - s32 i = 0; - s32 one = 1; - u8 *output = D_800EEBE0; - u8 *entity = (u8 *)&D_800ED148; - do { - if (*(s32 *)(entity + 0x8C) & 0x100) { - *output = one; - } else { - *output = 0; + + var_v1 = D_800EE9E8.subEntries[arg0 - 3].array0; + for (i = 0; i < 4; i++) { + if (var_v1[i].unk0 > 63) { + return 1; } - output++; - i++; - entity += 0xD0; - } while (i < 7); - if (a0 == 0xC8) { - func_800A9938(); } + + return 0; } -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A99E8); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A9A6C); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A9AC0); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A9C68); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800A9E08); - -/** - * @brief Clear D_800EEBE0 entries for inactive entities. - * - * Loops over 7 entities at D_800ED148 (stride 0xD0). If bit 0 of the - * word at offset 0x8C is not set, clears D_800EEBE0[i] to zero. - */ -void func_800A9F98(void) { - s32 i = 0; - s32 arr = (s32)D_800EEBE0; - s32 ptr = (s32)&D_800ED148; - do { - if (!(*(s32 *)(ptr + 0x8C) & 1)) { - *(u8 *)(i + arr) = 0; - } - i++; - ptr += 0xD0; - } while (i < 7); -} +s32 func_800AA980(s32 arg0, s32 arg1) { + if (arg0 == 0) { + return func_800AA930(arg1); + } -/** - * @brief Clear D_800EEBE0 entries for inactive or dead entities. - * - * Iterates 7 entities (stride 0xD0 in D_800ED148). Clears - * D_800EEBE0[i] to zero unless the entity is both active and alive. - */ -void func_800A9FDC(void) { - s32 i = 0; - s32 arr = (s32)D_800EEBE0; - s32 ptr = (s32)&D_800ED148; -top: - if (!(*(s32 *)(ptr + 0x8C) & 1) || (*(u16 *)(ptr + 0x90) & 1)) { - *(u8 *)(i + arr) = 0; - } - i++; - ptr += 0xD0; - if (i < 7) goto top; + if (arg0 == 3) { + return (~func_800AA930(arg1)) & 1; + } } -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AA034); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AA368); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AA44C); +s32 func_800AA9C8(s32 arg0, s32 arg1) { + if (arg0 == 0) { + return (D_8007809A >> arg1) & 1; + } -/** @brief Return constant 0x8007. */ -s32 func_800AA4E0(void) { - return 0x8007; + if (arg0 == 3) { + return ((D_8007809A >> arg1) & 1) ^ 1; + } } -/** @brief Return constant 0x80F8. */ -s32 func_800AA4E8(void) { - return 0x80F8; -} +s32 func_800AAA10(s32 arg0) { + if (arg0 == 0) { + return g_gameState.mainData.countdownTimer == 0; + } -/** @brief Return constant 0x80FF. */ -s32 func_800AA4F0(void) { - return 0x80FF; + if (arg0 == 3) { + return g_gameState.mainData.countdownTimer != 0; + } } -/** - * @brief Search entity table for a matching byte at offset 0xCB. - * - * @param a0 Value to search for. - * @return Entity index (0-6) if found, or 0xFF if not found. - */ -s32 func_800AA4F8(s32 a0) { - s32 i = 0; - u8 *entity = (u8 *)&D_800ED148; - do { - if (entity[0xCB] == a0) { - return i; +s32 func_800AAA50(s32 arg0, s32 arg1, s32 bit) { + if (arg1 == 0) { + s32 mask = (1 << bit); + if (arg0 & mask) { + return 1; } - i++; - entity += 0xD0; - } while (i < 7); - return 0xFF; -} + } -/** - * @brief Search entity table for active entity linked to index a0. - * - * @param a0 Link index to search for. - * @return Entity index if found, 0xFF otherwise. - */ -s32 func_800AA530(s32 a0) { - s32 i = 0; - s32 base = (s32)&D_800ED148; - s32 ptr = base; - s32 result; -top: - if (!(*(u16 *)(ptr + 0x90) & 1)) { - result = i; - if (*(u8 *)(ptr + 0xCB) == a0) { - return result; + if (arg1 == 3) { + s32 mask = (1 << bit); + if (!(arg0 & mask)) { + return 1; } } - i++; - ptr += 0xD0; - if (i < 7) goto top; - return 0xFF; -} -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AA57C); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AA68C); - -/** - * @brief Conditionally search entity table and check for 0xFF result. - * - * If a0 is 0, returns whether func_800AA4F8(a1) is not 0xFF. - * If a0 is 3, returns whether func_800AA4F8(a1) is 0xFF. - * - * @param a0 Mode selector (0 = found check, 3 = not-found check). - * @param a1 Search value passed to func_800AA4F8. - * @return Boolean result based on mode. - */ -s32 func_800AA71C(s32 a0, s32 a1) { - if (a0 == 0) { - return func_800AA4F8(a1) != 0xFF; - } - if (a0 == 3) { - return func_800AA4F8(a1) == 0xFF; - } + return 0; } -/** - * @brief Conditionally search via func_800AA530 and check for 0xFF result. - * - * If a0 is 0, returns whether func_800AA530(a1) is not 0xFF. - * If a0 is 3, returns whether func_800AA530(a1) is 0xFF. - * - * @param a0 Mode selector (0 = found check, 3 = not-found check). - * @param a1 Search value passed to func_800AA530. - * @return Boolean result based on mode. - */ -s32 func_800AA768(s32 a0, s32 a1) { - if (a0 == 0) { - return func_800AA530(a1) != 0xFF; +s32 func_800AAA9C(s32 arg0, u32 arg1, BattleEntityData* arg2) { + if (arg1 < 16) { + if (arg0 == 0 && ((arg2->unk80 >> arg1) & 1)) { + return 1; + } + + if (arg0 == 3 && !((arg2->unk80 >> arg1) & 1)) { + return 1; + } } - if (a0 == 3) { - return func_800AA530(a1) == 0xFF; + + else if (arg0 == 0 && (arg2->unk8 & (1 << (arg1 - 16)))) { + return 1; + } + + else if (arg0 == 3 && !(arg2->unk8 & (1 << (arg1 - 16)))) { + return 1; } + + + return 0; } -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AA7B4); +s32 func_800AAB50(s32 arg0, u32 arg1, BattleEntityData* arg2) { + switch (arg1) { + case 1 ... 9: + return func_800AA68C(arg2->unk18, arg0, (arg2->unk1C / 10) * arg1); + + case 10: + return func_800AA68C(arg2->unk18, arg0, arg2->unk1C >> 2); -/** - * @brief Conditionally search via func_800AA7B4 and check for 0xFF result. - * - * If a0 is 0, returns whether func_800AA7B4(a1) is not 0xFF. - * If a0 is 3, returns whether func_800AA7B4(a1) is 0xFF. - * - * @param a0 Mode selector (0 = found check, 3 = not-found check). - * @param a1 Search value passed to func_800AA7B4. - * @return Boolean result based on mode. - */ -s32 func_800AA840(s32 a0, s32 a1) { - if (a0 == 0) { - return func_800AA7B4(a1) != 0xFF; - } - if (a0 == 3) { - return func_800AA7B4(a1) == 0xFF; + default: + return func_800AA68C(arg2->unk18, arg0, arg1); } } -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AA88C); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AA930); - -/** - * @brief Conditionally call func_800AA930 and optionally invert the result. - * - * If a0 is 0, calls func_800AA930 with a1 and returns its result. - * If a0 is 3, calls func_800AA930 with a1 and returns the inverted - * lowest bit of the result. - * - * @param a0 Mode selector (0 = normal, 3 = inverted). - * @param a1 Parameter passed to func_800AA930. - * @return Result of func_800AA930, possibly with bit 0 inverted. - */ -s32 func_800AA980(s32 a0, s32 a1) { - if (a0 == 0) { - return func_800AA930(a1); +s32 func_800AABEC(s32 arg0, s32 arg1, s32 arg2, s32 arg3, s32 arg4) { + if (arg4 != 0 && arg1 == 0) { + if (D_800ED148.entities[arg3].controlFlags & 1) { + BattleEntityData* var_a2 = (BattleEntityData*)&D_800ED148.entities[arg3].entityData; + arg2 += func_800AAA9C(arg0, arg1, var_a2); + } + + return arg2; } - if (a0 == 3) { - s32 result = func_800AA930(a1); - return (~result) & 1; + + else if (D_800ED148.entities[arg3].controlFlags & 1) { + if (!(D_800ED148.entities[arg3].status & 1)) { + BattleEntityData* var_a2 = (BattleEntityData*)&D_800ED148.entities[arg3].entityData; + if (arg4 == 0) { + arg2 += func_800AAB50(arg0, arg1, var_a2); + } + + else { + arg2 += func_800AAA9C(arg0, arg1, var_a2); + } + } } + + return arg2; } -/** - * @brief Test a specific bit in D_8007809A, optionally inverting. - * - * If a0 is 0, returns bit a1 of D_8007809A. - * If a0 is 3, returns the inverse of bit a1 of D_8007809A. - * Otherwise returns 0 (falls through without setting return value). - * - * @param a0 Mode selector (0 = normal, 3 = inverted). - * @param a1 Bit position to test. - * @return Bit value (0 or 1). - */ -s32 func_800AA9C8(s32 a0, s32 a1) { - if (a0 == 0) { - return (D_8007809A >> a1) & 1; +s32 func_800AACD0(s32 arg0, s32 arg1, s32 arg2, s32 arg3) { + s32 result; + s32 var_s2; + s32 i; + + var_s2 = 0; + if (arg3 == 0) { + var_s2 = arg1; } - if (a0 == 3) { - return ((D_8007809A >> a1) & 1) ^ 1; + + result = 0; + switch(arg0) { + case 200: + for (i = 0; i < 3; i++) { + result = func_800AABEC(var_s2, arg2, result, i, arg3); + } + break; + + case 201: + for (i = 3; i < 7; i++) { + result = func_800AABEC(var_s2, arg2, result, i, arg3); + } + break; + + default: + for (i = 0; i < 7; i++) { + if (D_800ED148.entities[i].linkedIdx == arg0) { + result = func_800AABEC(var_s2, arg2, result, i, arg3); + } + } + break; } -} - -/** - * @brief Test countdownTimer, optionally inverted. - * - * If a0 == 0, returns 1 when countdownTimer is zero (no battle active). - * If a0 == 3, returns 1 when countdownTimer is nonzero (battle active). - * Other values fall through with no explicit return. - * - * @param a0 Query mode (0 = test no-battle, 3 = test in-battle). - * @return 1 or 0 based on the flag value. - */ -s32 func_800AAA10(s32 a0) { - if (a0 == 0) { - volatile GameState *gs = &g_gameState; - return gs->mainData.countdownTimer == 0; + + if (arg3 == 0) { + return result != 0; } - if (a0 == 3) { - volatile GameState *gs = &g_gameState; - return gs->mainData.countdownTimer != 0; + + if (result == 0) { + return arg1 != 0; } + + return arg1 == 0; } -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AAA50); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AAA9C); +s32 func_800AAE10(s32 arg0, s32 arg1, s32 arg2) { + if (D_800ED148.entities[arg2].controlFlags & 1) { + if ((D_800ED148.entities[arg2].status & 1)) { + return arg1; + } + + arg1 += func_800AAA9C(0, arg0, &D_800ED148.entities[arg2].entityData); + } + -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AAB50); + return arg1; +} -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AABEC); +s32 func_800AAE98(s32 arg0) { + s32 check1; + s32 check2; + s32 i; -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AACD0); + check1 = 0; + check2 = 0; -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AAD5C); + for (i = 0; i < 3; i++) { + if ((D_800ED148.entities[i].controlFlags & 1) && !(D_800ED148.entities[i].status & 1)) { + check2++; + } + } + + for (i = 0; i < 3; i++) { + check1 = func_800AAE10(arg0, check1, i); -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AAE10); + } + + return check1 == check2; +} -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AAE98); +void func_800AAF48(s32 arg0) { + BattleEntityData* temp_v0; -/** - * @brief Allocate structure via func_800AA57C and copy field +0x1C to +0x18. - * - * @param a0 Second parameter to func_800AA57C (first is 0xC8). - */ -void func_800AAF48(s32 a0) { - u8 *result = func_800AA57C(0xC8, a0); - *(s32 *)(result + 0x18) = *(s32 *)(result + 0x1C); + temp_v0 = func_800AA57C(200, arg0); + temp_v0->unk18 = temp_v0->unk1C; } -/** - * @brief Allocate entry and add signed offset to its field at 0x18. - * - * Calls func_800AA57C with 0xC8 and a0, then sign-extends a1 to 16 bits - * and adds it to the word at offset 0x18 of the returned entry. - * - * @param a0 Second parameter to func_800AA57C. - * @param a1 Signed 16-bit offset to add. - */ -void func_800AAF70(s32 a0, s32 a1) { - u8 *result = func_800AA57C(0xC8, a0); - *(s32 *)(result + 0x18) += (s16)a1; +void func_800AAF70(s32 arg0, s16 arg1) { + BattleEntityData* temp_v0; + + temp_v0 = func_800AA57C(200, arg0); + temp_v0->unk18 += arg1; } -/** - * @brief Look up entity entry by index, call animation init, set active flag. - * - * Computes D_800EE28C + a0 * 16 to get the entry, calls func_8009AF3C - * with entry[4], duration 0x1E, mode 3, size 0x80, and zero flag. - * Then sets entry[0xF] to 1. - * - * @param a0 Entity index (stride 16). - */ void func_800AAFB8(s32 arg0) { TaskEntry* data; @@ -599,24 +341,24 @@ void func_800AAFB8(s32 arg0) { data->done = 1; } -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AB008); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AB02C); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AB054); +void func_800AB008(s32 arg0) { + s32 idx; + + TaskEntry* task = &D_800ED148.taskData[func_8009B3D0(&func_800AAFB8)]; + task->unk4 = func_800B0398(arg0); +} -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AB07C); +void func_800AB054(s32 arg0) { + TaskEntry* td = &D_800ED148.taskData[arg0]; + + if (td->timer == 0) { + func_8009AF3C(td->unk4, 0x1E, 3, 0xF0, 0); + td->done = 1; + } + + td->timer--; +} -/** - * @brief Allocate entry via func_8009B3D0 and store battle data. - * - * Allocates an entry using func_800AB054 as callback, computes the - * entry address from D_800EE28C + index * 16, stores the result of - * func_800B0398(a0) at offset 4, and a1 as halfword at offset 8. - * - * @param a0 Parameter passed to func_800B0398. - * @param a1 Halfword value stored at entry offset 8. - */ void func_800AB0C0(s32 arg0, u16 arg1) { TaskEntry* currentEntry; @@ -625,89 +367,89 @@ void func_800AB0C0(s32 arg0, u16 arg1) { currentEntry->timer = arg1; } -/** - * @brief Clear control flags and reset animation state for a battle entity. - * - * Clears CTRL_FLAG_40, CTRL_FLAG_80, and CTRL_FLAG_02 from the entity's - * controlFlags field, then calls func_800AE6C0 and func_800A59AC to - * reset animation state. - * - * @param idx Entity index (stride 0xD0 in D_800ED148). - */ -void func_800AB11C(s16 idx) { - BattleEntity *base = (BattleEntity *)&D_800ED148; - volatile s32 *flags = &base[idx].controlFlags; - *flags &= ~CTRL_FLAG_40; - *flags &= ~CTRL_FLAG_80; - *flags &= ~CTRL_FLAG_02; +void func_800AB11C(s16 arg0) { + D_800ED148.entities[arg0].controlFlags &= ~0x40; + D_800ED148.entities[arg0].controlFlags &= ~0x80; + D_800ED148.entities[arg0].controlFlags &= ~2; + func_800AE6C0(); - func_800A59AC(idx, 0, 0); + func_800A59AC(arg0, 0, 0); } -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AB1AC); +void func_800AB1AC(s32 arg0) { + TaskEntry* temp_a0; + + temp_a0 = &D_800ED148.taskData[arg0]; + if (temp_a0->timer == 0) { + D_800ED148.unk5C2 = 1; + D_800ED148.unk12FD = 0; + temp_a0->done = 1; + return; + } + + + D_800ED148.unk5C2 = 0; + D_800ED148.unk12FD = 1; + temp_a0->timer--; +} -/** - * @brief Allocate entry via func_8009B3D0 and store value at offset 8. - * - * Calls func_8009B3D0 with func_800AB1AC as callback, shifts result - * left by 4 (multiply by 16), adds D_800EE28C as base, then stores a0 - * as halfword at offset 8 of the computed entry. - * - * @param a0 Value to store as halfword. - */ void func_800AB208(u16 arg0) { TaskEntry* currentEntry = &D_800ED148.taskData[func_8009B3D0(func_800AB1AC)]; currentEntry->timer = arg0; } -/** - * @brief Find the first active entity (bit 0 set at offset 0x8C). - * - * Scans entities 3-6 in the D_800ED148 array (offset 0x270, stride 0xD0). - * Returns the index of the first entity whose word at offset 0x8C has bit 0 set. - * Returns 0xFF if no active entity is found. - * - * @return Entity index (3-6), or 0xFF if none active. - */ s32 func_800AB24C(void) { - s32 i = 3; - s32 base = (s32)&D_800ED148; - s32 entry = base + 0x270; - do { - if (!(*(s32 *)(entry + 0x8C) & 1)) { + s32 i; + + for(i = 3; i < 7; i++) { + if (!(D_800ED148.entities[i].controlFlags & 1)) { return i; } - i++; - entry += 0xD0; - } while (i < 7); - return 0xFF; + } + + return 255; } -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AB28C); +void func_800AB28C(void) { + u8 entityIdx; + u8 idx; -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AB300); + idx = D_800ED148.unk12FC; + entityIdx = D_800ED148.unk12FB; + func_800A7FD0(entityIdx, D_800ED148.unkD54[idx], D_800ED148.unkD14[idx]); + func_800A8430(entityIdx); + -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object5", func_800AB36C); + + if (func_8009A514(D_800ED148.unkCE0, 7 - idx) != 0) { + D_800ED148.entities[entityIdx].controlFlags |= 2; + } + + if (func_8009A514(D_800ED148.unkCE2, 7 - idx) != 0) { + D_800ED148.entities[entityIdx].controlFlags |= 0x40; + } + + if (func_8009A514(D_800ED148.unkCE1, 7 - idx) != 0) { + D_800ED148.entities[entityIdx].controlFlags |= 0x80; + } + + func_800A890C(entityIdx); + func_800A8794(); + func_800D8A94(); + func_8009A528(entityIdx, idx); +} -/** - * @brief Set battle flag 0x5C2 and clear status bytes 0x12F9 and 0x12FD. - */ void func_800AB3C4(void) { - u8 *base = (u8 *)&D_800ED148; - base[0x5C2] = 1; - base[0x12F9] = 0; - base[0x12FD] = 0; + D_800ED148.unk5C2 = 1; + D_800ED148.unk12F9 = 0; + D_800ED148.unk12FD = 0; } -/** - * @brief Clear battle flag 0x5C2 and set status bytes 0x12F9 and 0x12FD. - */ void func_800AB3E0(void) { - u8 *base = (u8 *)&D_800ED148; - base[0x5C2] = 0; - base[0x12F9] = 1; - base[0x12FD] = 1; + D_800ED148.unk5C2 = 0; + D_800ED148.unk12F9 = 1; + D_800ED148.unk12FD = 1; } /** @@ -735,12 +477,6 @@ void func_800AB3FC(s32 a0, s32 a1, s32 a2) { func_8009AF3C(result, a2, 3, 0xF0, 0); } -/** - * @brief Call func_800AB3FC with a fixed duration of 0x1E. - * - * @param a0 First parameter passed through. - * @param a1 Second parameter passed through. - */ -void func_800AB488(s32 a0, s32 a1) { - func_800AB3FC(a0, a1, 0x1E); -} +void func_800AB488(s32 arg0, s32 arg1) { + func_800AB3FC(arg0, arg1, 30); +} \ No newline at end of file diff --git a/src/battle/bc_object6.c b/src/battle/bc_object6.c index ecea248d..d71d35e9 100644 --- a/src/battle/bc_object6.c +++ b/src/battle/bc_object6.c @@ -1,7 +1,6 @@ #include "common.h" #include "battle.h" #include "gamestate.h" -#include "battle/bc_object5.h" #include "battle/bc_object6.h" #include "battle/bc_object1.h" extern u8 D_800EE441[]; @@ -17,8 +16,6 @@ INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AB668); INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AB6F4); -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AB744); - INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AB844); INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AB914); @@ -37,26 +34,6 @@ s16 func_800AB998(u8 *ptr) { INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AB9B4); -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800ABA3C); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800ABCA4); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AC034); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AC094); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AC190); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AC2E4); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AC348); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AC368); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AC400); - -INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object6", func_800AC4E4); - /** * @brief Check if an entity is available (no blocking status flags). * diff --git a/src/battle/bc_object8.c b/src/battle/bc_object8.c index 68a89073..a5378920 100644 --- a/src/battle/bc_object8.c +++ b/src/battle/bc_object8.c @@ -18,7 +18,6 @@ extern u8 D_800EEEC0[]; extern u8 g_gameState[]; void func_800B3164(void); void func_800B2F3C(void); -extern u8 D_8007809A[]; extern u8 D_800EE45C[]; extern u8 D_800EEDD8[]; extern u8 D_800EEDE8[]; @@ -35,6 +34,8 @@ s32 func_800AA4E0(void); extern u8 D_800EEED0[]; extern u8 D_800EEED4[]; +u16 func_800A97FC(s32 arg0); + INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object8", func_800B1624); INCLUDE_ASM("asm/ovl/battle/nonmatchings/bc_object8", func_800B16C0); @@ -138,23 +139,19 @@ s32 func_800B1A78(void) { return 1; } -/** - * @brief Check battle conditions and trigger entity action sequence. - * - * Checks bit 1 of D_8007809A. If set, calls func_800B1A78 to validate. - * If valid, calls func_8009B79C(0x20, 0xFF) to test entity availability. - * If available, clears D_800EE45C and calls func_800B1A48 to start action. - */ void func_800B1ACC(void) { - if (!(*(u8 *)D_8007809A & 2)) { + if (!(D_8007809A & 2)) { return; } + if (func_800B1A78() == 0) { return; } - if (func_8009B79C(0x20, 0xFF) == 0) { + + if (func_8009B79C(32, 255) == 0) { return; } + D_800ED148.unk1314 = 0; func_800B1A48(); } @@ -271,20 +268,12 @@ void func_800B2038(void) { } } -/** - * @brief Check battle mode flag and conditionally trigger entity processing. - * - * Checks bit 3 of D_8007809A. If set, calls func_8009B79C(8, 0xFF) to test - * entity availability. If available, calls func_800B1B68 and returns. - * Otherwise (bit not set or entity unavailable), clears D_800EE465. - */ void func_800B2084(void) { - if (*(u8 *)D_8007809A & 8) { - if (func_8009B79C(8, 0xFF) != 0) { - func_800B1B68(); - return; - } + if (D_8007809A & 8 && func_8009B79C(8, 255) != 0) { + func_800B1B68(); + return; } + D_800ED148.unk131D = 0; } @@ -308,34 +297,30 @@ s32 func_800B20D8(void) { return 1; } -/** - * @brief Check if conditions are met to initiate an auto-battle action. - * - * Checks a chain of conditions: whether func_800AE788 returns the sentinel - * 0xFF, whether func_800B20D8 indicates busy, bit 2 of D_8007809A flags, - * whether g_battleConfig matches 0x13D, and whether entity slot 0x40 is - * available via func_8009B79C. If all pass, sets D_800EE45C to 1 and - * calls func_800B1A48 to start the action. - * - * @return 1 if action was initiated, 0 otherwise. - */ s32 func_800B2128(void) { - if (func_800AE788() == 0xFF) { + if (func_800AE788() == 255) { return 0; } + if (func_800B20D8() != 0) { return 0; } - if (*(u8 *)D_8007809A & 4) { - if (*(u16 *)&g_battleConfig != 0x13D) { - if (func_8009B79C(0x40, 0xFF) != 0) { - D_800ED148.unk1314 = 1; - func_800B1A48(); - return 1; - } - } + + if (!(D_8007809A & 4)) { + return 0; } - return 0; + + if (g_battleConfig.battleSceneId == 0x13D) { + return 0; + } + + if (func_8009B79C(64, 255) == 0) { + return 0; + } + + D_800ED148.unk1314 = 1; + func_800B1A48(); + return 1; } /** diff --git a/src/effect/effect_025.c b/src/effect/effect_025.c index f707faa9..8ff0a161 100644 --- a/src/effect/effect_025.c +++ b/src/effect/effect_025.c @@ -279,7 +279,7 @@ static void func_801A71B8(EffectEntity *entity) { entity->pos.vx = 0x600; entity->pc++; } - for (i = 3; i >= 0; i--) { + for (i = 0; i < 4; i++) { tint->level = entity->pos.vx; tint++; } @@ -304,7 +304,7 @@ static void func_801A7240(EffectEntity *entity) { entity->flags |= EFFECT_FLAG_STOP; entity->pc++; } - for (i = 3; i >= 0; i--) { + for (i = 0; i < 4; i++) { tint->level = entity->pos.vx; tint++; } diff --git a/src/effect/effect_027.c b/src/effect/effect_027.c index 4b60d2b6..d4ecf6c1 100644 --- a/src/effect/effect_027.c +++ b/src/effect/effect_027.c @@ -3,259 +3,383 @@ * @brief Full-Life */ #include "common.h" - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0000); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A01EC); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A033C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A03E8); - -void func_801A0408(void) { +#include "game.h" +#include "effect.h" +#include "psxsdk/libgte.h" +#include "effect/effect_027.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 "battle.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 Ceiling the tint ramp clamps to, four @ref EFFECT_TINT_STEP steps up. */ +#define EFFECT_TINT_MAX 0x400 + +/** @brief How far the tint ramp moves per frame. */ +#define EFFECT_TINT_STEP 0x100 + +static void func_801A91BC(EffectEntity *entity); +static void func_801A9208(EffectEntity *entity); +static void func_801A9270(EffectEntity *entity); +static s32 func_801A9278(EffectEntity *entity); +static void func_801A9318(EffectEntity *entity); +static void func_801A9330(EffectEntity *entity); +static void func_801A938C(EffectEntity *entity); +static s32 func_801A9394(EffectEntity *entity); +static void func_801A9434(EffectEntity *entity); +static void func_801A9490(EffectEntity *entity); +static void func_801A94D8(EffectEntity *entity); +static s32 func_801A94E0(EffectEntity *entity); +static void func_801A9580(EffectEntity *entity); +static void func_801A95D8(EffectEntity *entity); +static void func_801A960C(EffectEntity *entity); +static void func_801A9694(EffectEntity *entity); +static s32 func_801A969C(EffectEntity *entity); +static void func_801A9778(EffectEntity *entity); +static void func_801A978C(EffectEntity *entity); +static void func_801A97A0(EffectEntity *entity); +static void func_801A9830(EffectEntity *entity); +static void func_801A9888(EffectEntity *entity); +static void func_801A98EC(EffectEntity *entity); +static void func_801A9954(EffectEntity *entity); +static void func_801A997C(EffectEntity *entity); +static void func_801A9990(EffectEntity *entity); +static void func_801A99A4(EffectEntity *entity); +static void func_801A99C0(EffectEntity *entity); + +/** @brief Opcode handler: clear the screen tint. */ +static void func_801A91BC(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_027/nonmatchings/effect_027", func_801A0410); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A050C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0608); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0640); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A07D0); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A095C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0AE8); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0B18); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0B40); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0CCC); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0E00); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0E30); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0E60); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0E90); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0FCC); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A0FFC); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A102C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A105C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A12A8); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A12F8); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A139C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A13CC); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1424); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1448); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1490); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A14D8); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1590); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A15E4); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1650); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1688); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A170C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A17B0); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1828); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A18F4); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1988); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1A00); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1A90); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1B08); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1B38); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1B94); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1C60); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A1DF4); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A20C0); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A23E4); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A276C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A2B50); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A2E58); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A31E0); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A359C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A39E4); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A3C28); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A3E30); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A3EE8); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A46F0); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A47E4); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A5124); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A5240); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A5278); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A5324); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A5410); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A5428); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A5A54); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A5CBC); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A5D7C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A5E9C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A5FBC); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A6024); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A6AC0); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A6BC0); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A6C60); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A6EE8); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A70F0); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A7300); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A7D70); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A7DAC); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A7DEC); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A7E04); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A7E8C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A80C0); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A8174); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A82B0); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A838C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A8500); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A860C); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A8724); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A89EC); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A8C90); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A8D00); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A8D58); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A9000); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A9128); - -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A91BC); +/** @brief Opcode handler: ramp the screen tint up to the maximum, then stop. */ +static void func_801A9208(EffectEntity *entity) { + BattleTint *tint = D_800EF738; + s32 i; + + entity->pos.vx += EFFECT_TINT_STEP; + if (entity->pos.vx >= EFFECT_TINT_MAX) { + entity->pos.vx = EFFECT_TINT_MAX; + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } + for (i = 0; i < 4; i++) { + tint->level = entity->pos.vx; + tint++; + } +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A9208); +/** @brief Opcode handler: no-op. */ +static void func_801A9270(EffectEntity *entity) { +} -void func_801A9270(void) { +/** + * @brief Script dispatcher for the tint fade-in. + * + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ +static s32 func_801A9278(EffectEntity *entity) { + EffectHandler handlers[3] = { func_801A91BC, func_801A9208, func_801A9270 }; + + 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_027/nonmatchings/effect_027", func_801A9278); +/** @brief Opcode handler: hold the screen tint at the maximum. */ +static void func_801A9318(EffectEntity *entity) { + entity->pos.vx = EFFECT_TINT_MAX; + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A9318); +/** @brief Opcode handler: ramp the screen tint back to zero, then stop. */ +static void func_801A9330(EffectEntity *entity) { + BattleTint *tint = D_800EF738; + s32 i; + + entity->pos.vx -= EFFECT_TINT_STEP; + if (entity->pos.vx <= 0) { + entity->pos.vx = 0; + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } + for (i = 0; i < 4; i++) { + tint->level = entity->pos.vx; + tint++; + } +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A9330); +/** @brief Opcode handler: no-op. */ +static void func_801A938C(EffectEntity *entity) { +} -void func_801A938C(void) { +/** + * @brief Script dispatcher for the tint fade-out. + * + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ +static s32 func_801A9394(EffectEntity *entity) { + EffectHandler handlers[3] = { func_801A9318, func_801A9330, func_801A938C }; + + 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_027/nonmatchings/effect_027", func_801A9394); +/** @brief Opcode handler: draw and retire once the frame count is reached. */ +static void func_801A9434(EffectEntity *entity) { + EffectDrawScript *script = (EffectDrawScript *)entity; -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A9434); + 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_027/nonmatchings/effect_027", func_801A9490); +/** @brief Opcode handler: hold still until the draw script finishes. */ +static void func_801A9490(EffectEntity *entity) { + if (effectDrawScriptRun((EffectDrawScript *)entity) != 0) { + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; + } +} -void func_801A94D8(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A94D8(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A94E0); +/** + * @brief Script dispatcher for the draw script. + * + * @return 2 once the script has stopped and its children have drained, 0 while + * it is still running. + */ +static s32 func_801A94E0(EffectEntity *entity) { + EffectHandler handlers[3] = { func_801A9434, func_801A9490, func_801A94D8 }; + + 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_027/nonmatchings/effect_027", func_801A9580); +/** @brief Opcode handler: start the pose script on the taken model. */ +static void func_801A9580(EffectEntity *entity) { + effectStartChildScript(entity, func_801A94E0, &D_801D4314, 0, 0x2D, 0); + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A95D8); +/** @brief Opcode handler: release the model once the count reaches 30. */ +static void func_801A95D8(EffectEntity *entity) { + if (entity->unk024 == 30) { + entity->unk010->unk063 = 0; + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A960C); +/** @brief Opcode handler: hand the current part to battle, then stop. */ +static void func_801A960C(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_801A9694(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A9694(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A969C); +/** @brief Run one frame of this effect's script and report whether it ended. */ +static s32 func_801A969C(EffectEntity *entity) { + EffectHandler handlers[4] = { func_801A9580, func_801A95D8, func_801A960C, + func_801A9694 }; + + effectCacheSlotAnchors(entity); + effectUpdateModelBounds(entity); + handlers[entity->pc](entity); + if (entity->unk024 == 0) { + func_800C4764(D_801A9C5C, 0, 0x80); + } + 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_027/nonmatchings/effect_027", func_801A9778); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9778(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A978C); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A978C(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A97A0); +/** @brief Opcode handler: carve both record banks and start the draw script. */ +static void func_801A97A0(EffectEntity *entity) { + if (entity->wait == 0) { + /* Both banks are carved out of the same byte arena behind the TIM. */ + g_effectEmitterBank = (EffectEmitter *)D_801D35C4; + D_801D35C4 += EFFECT_EMITTER_BANK_BYTES; + g_effectParticleBank = (EffectParticle *)D_801D35C4; + D_801D35C4 += EFFECT_PARTICLE_BANK_BYTES; + effectBanksClear(); + effectSpawnTask(&D_801D3854, func_801A9278, 0x40, entity); + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A9830); +/** @brief Opcode handler: start a task running @ref func_801A969C. */ +static void func_801A9830(EffectEntity *entity) { + entity->unk063 = 1; + effectSpawnTask(&D_801D42E4, func_801A969C, 0x58, entity); + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A9888); +/** @brief Opcode handler: repeat the step until the loop counter runs out. */ +static void func_801A9888(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_027/nonmatchings/effect_027", func_801A98EC); +/** @brief Opcode handler: spawn the tint fade-out once the wait runs out. */ +static void func_801A98EC(EffectEntity *entity) { + /* The byte trio at unk060 is this script's countdown, one halfword wide. */ + if (--*(s16 *)entity->unk060 <= 0) { + effectSpawnTask(&D_801D3854, func_801A9394, 0x40, entity); + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A9954); +/** @brief Opcode handler: stall here until @c unk05E reaches zero. */ +static void func_801A9954(EffectEntity *entity) { + if (entity->unk05E == 0) { + entity->pc++; + } +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A997C); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A997C(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A9990); +/** @brief Opcode handler: consume the opcode and do nothing else. */ +static void func_801A9990(EffectEntity *entity) { + entity->pc++; +} -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A99A4); +/** @brief Opcode handler: raise @ref EFFECT_FLAG_STOP and consume the opcode. */ +static void func_801A99A4(EffectEntity *entity) { + entity->flags |= EFFECT_FLAG_STOP; + entity->pc++; +} -void func_801A99C0(void) { +/** @brief Opcode handler: no-op. */ +static void func_801A99C0(EffectEntity *entity) { } -INCLUDE_ASM("asm/ovl/effect_027/nonmatchings/effect_027", func_801A99C8); +/** + * @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_801A99C8(EffectEntity *entity) { + EffectHandler handlers[11] = { + func_801A9778, func_801A978C, func_801A97A0, func_801A9830, func_801A9888, + func_801A98EC, func_801A9954, func_801A997C, func_801A9990, func_801A99A4, + func_801A99C0 + }; + MATRIX *view = EFFECT_SCRATCHPAD; + + *view = D_800F02C8; + g_effectStackTop = (u8 *)view; + g_effectStackBase = view; + if (entity->unk05C & EFFECT_FRAME_ODD) { + g_effectPrimCursor = D_801D408C; + D_801D4088 = D_801D4094; + } else { + g_effectPrimCursor = D_801D4090; + D_801D4088 = D_801D4098; + } + effectCacheAnimSlotAnchors(entity); + handlers[entity->pc](entity); + g_effectParticleTotal = 0; + entity->unk05E = 0; + g_effectLiveTotal = 0; + entity->unk05E += func_800B2B68(&D_801D42E4); + entity->unk05E += func_800B2B68(&g_effectChildPool); + entity->unk05E += func_800B2B68(&D_801D3854); + 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_027_entry.c b/src/effect/effect_027_entry.c new file mode 100644 index 00000000..727e07ff --- /dev/null +++ b/src/effect/effect_027_entry.c @@ -0,0 +1,61 @@ +/** + * @file effect_027_entry.c + * @brief Full-Life: the overlay entry point. + */ +#include "common.h" +#include "effect.h" +#include "effect/lib/entity.h" +#include "effect/lib/tables.h" +#include "effect/effect_027.h" +#include "effect/effect_027_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_801D35B4 = 0; + D_801D35B8 = 0; + func_800B2A00(&D_801D4174, &D_801D40A4, 0x64, 2); + entity = effectSpawnTask(&D_801D4174, func_801A99C8, 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_801A9D3C); + func_800BB084(&D_801AA794); + } + D_801D35C4 = &D_801AA794; + bank0 = &D_801AA794; + D_801D408C = bank0; + bank1 = bank0 + EFFECT_BANK_SIZE; + D_801D4094 = bank0 + EFFECT_BANK_SIZE; + D_801D35C4 = bank0 + EFFECT_BANK_SIZE; + frames = bank1; + D_801D4090 = frames; + frames += EFFECT_BANK_SIZE; + D_801D35C4 = frames; + D_801D4098 = frames; + func_800B2A00(&D_801D42E4, &D_801D4184, 0x58, 4); + func_800B2A00(&g_effectChildPool, &D_801D3884, 0x2A4, 3); + func_800B2A00(&D_801D3854, &D_801D35D4, 0x40, 0xA); + return &D_801D4174; +} diff --git a/src/effect/effect_028.c b/src/effect/effect_028.c index 929f8133..5dcc75ce 100644 --- a/src/effect/effect_028.c +++ b/src/effect/effect_028.c @@ -86,7 +86,7 @@ static void func_801A9500(EffectEntity *entity) { entity->flags |= EFFECT_FLAG_STOP; entity->pc++; } - for (i = 3; i >= 0; i--) { + for (i = 0; i < 4; i++) { tint->level = entity->pos.vx; tint++; } @@ -134,7 +134,7 @@ static void func_801A9628(EffectEntity *entity) { entity->flags |= EFFECT_FLAG_STOP; entity->pc++; } - for (i = 3; i >= 0; i--) { + for (i = 0; i < 4; i++) { tint->level = entity->pos.vx; tint++; } diff --git a/src/effect/effect_039.c b/src/effect/effect_039.c index c7af5bf2..264e07a0 100644 --- a/src/effect/effect_039.c +++ b/src/effect/effect_039.c @@ -80,7 +80,7 @@ static void func_801A9500(EffectEntity *entity) { entity->flags |= EFFECT_FLAG_STOP; entity->pc++; } - for (i = 3; i >= 0; i--) { + for (i = 0; i < 4; i++) { tint->level = entity->pos.vx; tint++; } @@ -128,7 +128,7 @@ static void func_801A9628(EffectEntity *entity) { entity->flags |= EFFECT_FLAG_STOP; entity->pc++; } - for (i = 3; i >= 0; i--) { + for (i = 0; i < 4; i++) { tint->level = entity->pos.vx; tint++; } diff --git a/src/effect/lib/fill.c b/src/effect/lib/fill.c index 284c5e71..38557ed8 100644 --- a/src/effect/lib/fill.c +++ b/src/effect/lib/fill.c @@ -6,7 +6,13 @@ #include "effect.h" #include "effect/lib/fill.h" -/** @brief Fill @p count words at @p dst with @p value. */ +/** + * @brief Fill @p count words at @p dst with @p value. + * + * The index is never read, which makes it look like a loop that should count + * up. It is not: the ascending form generates different code, so counting down + * to @c -1 is load-bearing. + */ void effectFillWords(s32 *dst, s32 value, s32 count) { s32 i; diff --git a/src/effect/lib/rot.c b/src/effect/lib/rot.c index 2efe4010..2d475252 100644 --- a/src/effect/lib/rot.c +++ b/src/effect/lib/rot.c @@ -1,6 +1,10 @@ /** * @file rot.c * @brief Rotation matrices built from an angle. + * + * The three builders clear the matrix through a countdown whose index is never + * read, which makes it look like a loop that should count up. It is not: the + * ascending form generates different code, so the countdown is load-bearing. */ #include "common.h" #include "effect.h" diff --git a/src/menu/menusts/menusts.c b/src/menu/menusts/menusts.c index 27e5d3db..1808b04a 100644 --- a/src/menu/menusts/menusts.c +++ b/src/menu/menusts/menusts.c @@ -6,7 +6,7 @@ #include "gamestate.h" #include "btl_color.h" #include "btl_entity.h" -#include "battle/bc_object2.h" +#include "game.h" /* menumain is called at a fixed overlay address, so its prototype stays * file-local here (overlay-conflict rule, as in the other sub-overlays). */