Skip to content

battle: decompile the hit and particle effects - #268

Merged
Xeeynamo merged 2 commits into
Xeeynamo:mainfrom
eduardovra:battle-effect-ticks
Oct 7, 2026
Merged

Xeeynamo merged 2 commits into
Xeeynamo:mainfrom
eduardovra:battle-effect-ticks

Conversation

@eduardovra

Copy link
Copy Markdown
Contributor

Continuing from #261, this decompiles the battle functions that spawn and animate small visual effects, like hit flashes, sparkles and trails.

It also names the matrix helpers they share and the world view matrix behind them. Two existing names didn't match what the functions do, so I renamed them. That's why most of the magic overlays are touched.

@eduardovra
eduardovra marked this pull request as ready for review October 6, 2026 02:11

@Xeeynamo Xeeynamo left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few changes required

extern u16 D_80163B80;
extern void (*D_80163B84[60])(void);
extern DR_MODE* D_80163C74; // TODO might be a generic u_long*, not DR_MODE*
extern void* D_80163C74;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This to me looks like the Gpu* type from main.h which encompass the various polygon types.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type is returned by several functions (func_800D29D4, func_800D4D90, BattleEffectSpriteAdd) and each seems to return a different pointer (DR_MODE, POLY_FT4, 0x24-byte model packets...), so I think we can already tell it's not DR_MODE. I also tried Gpu but it didn't match (battle.exe and choco0.exe break). So I thought leaving it void* for now, at least until we know more.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair. Let's not have this PR blocked then, but we need not to forget this detail.

Comment thread src/battle/battle2.c
otz = RotAverage4(&D_800F1914, &D_800F191C, &D_800F1924, &D_800F192C, (long*)&quad->x0, (long*)&quad->x1,
(long*)&quad->x2, (long*)&quad->x3, &p, &flag);
if (otz > 0) {
quad->tag = 0x09000000;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tricky low-level optimization.

Suggested change
quad->tag = 0x09000000;
#ifdef PLATFORM_PSYZ
setlen(quad, 9);
#else
quad->tag = 0x09000000;
#endif

this is required, because PsyZ splits a tag into addr and len.

Comment thread src/battle/battle2.c
*(u32*)&quad->r0 = 0x2E202020;
}
quad->clut = 0x78C7;
quad->tpage = 0x3A;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please decode this as a getTPage?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It didn't match with the current getTPage, because it calls GetGraphType(). I tried the version from before #147 and that one matches, but it breaks field and world, which need the current one. So I'm not sure what to do here.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into it. I forgot about GetGraphType, but it still doesn't sound right. I'll look into the macro shortly.

Comment thread src/battle/battle2.c Outdated
Comment on lines +2875 to +2877
frame = slot->frame + 1;
slot->frame = frame;
if ((s16)frame == 16) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
frame = slot->frame + 1;
slot->frame = frame;
if ((s16)frame == 16) {
if (++slot->frame == 16) {

doesn't this match? it would also allow you to remove the local var frame

Comment thread src/battle/battle2.c Outdated
u8 anim;

p = (BattleKeyframeParticleSlot*)&D_801621F0[D_801590D4];
desc = (SpriteRenderDesc*)0x1F800000;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
desc = (SpriteRenderDesc*)0x1F800000;
desc = (SpriteRenderDesc*)getScratchAddr(0);

Comment thread src/battle/battle2.c Outdated
m = &D_800F10B8;
desc->frames = D_800F0B14[anim];
} else {
m = (MATRIX*)0x1F80000C;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
m = (MATRIX*)0x1F80000C;
m = (MATRIX*)getScratchAddr(3);

this will likely crash on 64-bit builds, but let's keep it this way for now.

Use getScratchAddr for the scratchpad pointers, setlen under
PLATFORM_PSYZ since psyz splits the tag into addr and len, and drop
the temporary in BattleHitFlashGrowTick. Move the getScratchAddr
fallback for psyz into game.h so battle and world share it.
@Xeeynamo
Xeeynamo merged commit f4ec968 into Xeeynamo:main Oct 7, 2026
1 check passed
@eduardovra
eduardovra deleted the battle-effect-ticks branch October 7, 2026 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants