Skip to content

Decompile Enemy/bosseel#128

Open
KakarottoCake wants to merge 34 commits into
doldecomp:mainfrom
KakarottoCake:decomp-bosseel
Open

Decompile Enemy/bosseel#128
KakarottoCake wants to merge 34 commits into
doldecomp:mainfrom
KakarottoCake:decomp-bosseel

Conversation

@KakarottoCake

Copy link
Copy Markdown
Contributor

Summary

  • decompile Enemy/bosseel.cpp end-to-end, including the tears/oil-ball subsystem, manager parameters, teeth, eyes, vortex, heart coins, collision actors, Boss Eel initialization, the main perform loop, and the complete battle nerve graph
  • preserve reverse retail definition order required by this TU's -inline deferred build
  • use semantic fields and existing engine APIs for sound, particles, matrices, collision, animation, and state handling
  • account for all 27 mario.MAP UNUSED entries; reconstruct the recoverable inline helpers and mark dead-stripped bodies with focused human-review TODOs and retail sizes

Matching

  • mario/Enemy/bosseel: 79.24% fuzzy match
  • matched code: 15.89%
  • matched data: 2.34%
  • TBossEel::perform: 76.81%

Several nerves and support routines are above 90%, with many weak functions and small routines fully matching.

Validation

  • native Python 3.12 Ninja build passes
  • ninja changes_all passes
  • no unintended regressions reported
  • git diff --check passes

The existing warnings in JGadget/std-list.hpp and MoveBG/MapObjGeneral.hpp are unchanged.

Human review

The remaining TODOs are primarily dead-stripped UNUSED routines whose original bodies do not survive in linked assembly. Each is explicitly labeled with its retail MAP size so it can be reviewed or completed separately.

@decomp-dev

decomp-dev Bot commented Jul 22, 2026

Copy link
Copy Markdown

Report for GMSJ01 (a4e0950 - 794f6a7)

📈 Matched code: 35.09% (+0.25%, +9068 bytes)
📈 Matched data: 47.30% (+0.09%, +548 bytes)

✅ 95 new matches
Unit Item Bytes Before After
mario/Enemy/bosseel __sinit_bosseel_cpp +764 0.00% 100.00%
mario/Enemy/bosseel .bss +384 0.00% 100.00%
mario/Enemy/bosseel TBossEel::shedTears(float(*)[4]) +360 0.00% 100.00%
mario/Enemy/bosseel TBEelTearsManager::perform(unsigned long, JDrama::TGraphics*) +252 0.00% 100.00%
mario/Enemy/bosseel TNerveBEelTearsGenerate::execute(TSpineBase<TLiveActor>*) const +248 0.00% 100.00%
mario/Enemy/bosseel TBEelTears::reset() +236 0.00% 100.00%
mario/Enemy/bosseel TBossEel::TBossEel(const char*) +232 0.00% 100.00%
mario/Enemy/bosseel TBossEelHeartCoin::generate(JGeometry::TVec3<float>&) +204 0.00% 100.00%
mario/Enemy/bosseel TBossEelBodyCollision::~TBossEelBodyCollision() +156 0.00% 100.00%
mario/Enemy/bosseel TBossEelAwaCollision::~TBossEelAwaCollision() +156 0.00% 100.00%
mario/Enemy/bosseel TBossEelBarrierCollision::~TBossEelBarrierCollision() +156 0.00% 100.00%
mario/Enemy/bosseel TBossEelTearsRecoverCollision::~TBossEelTearsRecoverCollision() +156 0.00% 100.00%
mario/Enemy/bosseel .sbss +144 0.00% 100.00%
mario/Enemy/bosseel TBEelTearsDrop::~TBEelTearsDrop() +132 0.00% 100.00%
mario/Enemy/bosseel TOilBall::~TOilBall() +132 0.00% 100.00%
mario/Enemy/bosseel TBossEelTooth::~TBossEelTooth() +132 0.00% 100.00%
mario/Enemy/bosseel TBossEelVortex::~TBossEelVortex() +132 0.00% 100.00%
mario/Enemy/bosseel TBossEelEye::~TBossEelEye() +132 0.00% 100.00%
mario/Enemy/bosseel TBossEelHeartCoin::~TBossEelHeartCoin() +132 0.00% 100.00%
mario/Enemy/bosseel TBossEelCollision::~TBossEelCollision() +132 0.00% 100.00%
mario/Enemy/bosseel TBEelTears::setMActorAndKeeper() +128 0.00% 100.00%
mario/Enemy/bosseel TBEelTearsManager::createEnemyInstance() +120 0.00% 100.00%
mario/Enemy/bosseel TBossEel::~TBossEel() +108 0.00% 100.00%
mario/Enemy/bosseel TBEelTearsManager::load(JSUMemoryInputStream&) +108 0.00% 100.00%
mario/Enemy/bosseel TBEelTearsManager::~TBEelTearsManager() +100 0.00% 100.00%
mario/Enemy/bosseel TBossEelManager::~TBossEelManager() +100 0.00% 100.00%
mario/Enemy/bosseel TNerveBEelTearsGenerate::theNerve() +100 0.00% 100.00%
mario/Enemy/bosseel TNerveBEelTearsMoveUp::theNerve() +100 0.00% 100.00%
mario/Enemy/bosseel TNerveBEelTearsWaterHit::theNerve() +100 0.00% 100.00%
mario/Enemy/bosseel TNerveBEelTearsMarioRecover::theNerve() +100 0.00% 100.00%

...and 65 more new matches

📈 54 improvements in unmatched items
Unit Item Bytes Before After
mario/Enemy/bosseel .data +2877 0.00% 93.17%
mario/Enemy/bosseel .rodata +2776 0.00% 91.81%
mario/Enemy/bosseel TBossEel::perform(unsigned long, JDrama::TGraphics*) +2461 0.00% 78.79%
mario/Enemy/bosseel TBossEel::init(TLiveManager*) +2297 0.00% 81.59%
mario/Enemy/bosseel TBossEelSaveParams::TBossEelSaveParams() +1649 0.00% 99.83%
mario/Enemy/bosseel TNerveBossEelEat::execute(TSpineBase<TLiveActor>*) const +1475 0.00% 92.48%
mario/Enemy/bosseel TNerveBossEelOutWait::execute(TSpineBase<TLiveActor>*) const +1429 0.00% 97.90%
mario/Enemy/bosseel TBossEelTooth::perform(unsigned long, JDrama::TGraphics*) +1369 0.00% 88.26%
mario/Enemy/bosseel TNerveBossEelMouthOpenWait::execute(TSpineBase<TLiveActor>*) const +1200 0.00% 93.25%
mario/Enemy/bosseel TNerveBossEelDie::execute(TSpineBase<TLiveActor>*) const +1018 0.00% 87.79%
mario/Enemy/bosseel TNerveBossEelSecondSpin::execute(TSpineBase<TLiveActor>*) const +941 0.00% 95.25%
mario/Enemy/bosseel ExecBackNerve_Sub(TSpineBase<TLiveActor>*, float) +939 0.00% 99.94%
mario/Enemy/bosseel TBossEel::collideToMario() +928 0.00% 95.10%
mario/Enemy/bosseel TBEelTearsSaveLoadParams::TBEelTearsSaveLoadParams(const char*) +917 0.00% 98.02%
mario/Enemy/bosseel TBEelTears::moveObject() +877 0.00% 90.65%
mario/Enemy/bosseel TNerveBossEelFirstSpin::execute(TSpineBase<TLiveActor>*) const +858 0.00% 99.85%
mario/Enemy/bosseel TBossEelTooth::receiveMessage(THitActor*, unsigned long) +844 0.00% 99.12%
mario/Enemy/bosseel TNerveBossEelAppear::execute(TSpineBase<TLiveActor>*) const +833 0.00% 98.29%
mario/Enemy/bosseel TBossEelVortex::perform(unsigned long, JDrama::TGraphics*) +810 0.00% 95.55%
mario/Enemy/bosseel TOilBall::moveObject() +785 0.00% 89.63%
mario/Enemy/bosseel TNerveBEelTearsWaterHit::execute(TSpineBase<TLiveActor>*) const +715 0.00% 99.94%
mario/Enemy/bosseel TBossEelManager::loadAfter() +675 0.00% 99.92%
mario/Enemy/bosseel TBossEel::updateTearsCnt() +659 0.00% 99.97%
mario/Enemy/bosseel TBEelTears::init(TLiveManager*) +650 0.00% 81.74%
mario/Enemy/bosseel TBossEelEye::perform(unsigned long, JDrama::TGraphics*) +625 0.00% 90.94%
mario/Enemy/bosseel TNerveBEelTearsSplit::execute(TSpineBase<TLiveActor>*) const +599 0.00% 99.93%
mario/Enemy/bosseel TBEelTearsManager::splitTears(JGeometry::TVec3<float>&) +576 0.00% 90.62%
mario/Enemy/bosseel TBossEelHeartCoin::perform(unsigned long, JDrama::TGraphics*) +549 0.00% 90.37%
mario/Enemy/bosseel TBEelTearsDrop::TBEelTearsDrop(TBEelTears*, int, SDLModelData*, const char*) +537 0.00% 96.73%
mario/Enemy/bosseel TBossEelCollision::behaveToMario() +520 0.00% 94.34%

...and 24 more improvements in unmatched items

KakarottoCake and others added 12 commits July 22, 2026 19:40
…t refinements

__sinit registers the JAL sound lists (MSBgm/MSSetSound(Grp)/JALSeMod*),
which come from MSSetSound.hpp - it was missing from the includes so
__sinit was 9.7%. Adding it before MSoundBGM.hpp (same as MapObjSample.cpp)
reproduces the exact registration order: 9.7% -> 100%.

Also refine the TBEelTears/TOilBall moveObject push handling and
TNerveBEelTearsMarioRecover.

Unit 91.9% -> 93.4%.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…init

The target float-copies mPosition into mInitialPosition (lfs/stfs); operator=
was compiling to an integer lwz/stw copy. 76.3% -> 78.1% on init.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The target constructs the Mario target vec with y=10 then overwrites y=15;
that redundant write was missing (mine built it with y=15 directly).
93.1% -> 99.6%.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The target inlines mMActor->getModel() (mMActor->unk4) and caches it, but
getModel() is out-of-line so it emitted a bl each time. Using mMActor->getModel()
directly (cached in a local for the skin-deform block) matches the inline
fetch. 76.3% -> 80.5%.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Same as init: getModel() is out-of-line; the target inlines mMActor->getModel().
76.9% -> 78.8%.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The map marks ExecBackNerve_Sub as local, but it was declared in the header
(extern) and emitted global. Drop the header declaration and make the
definition static. Verified with tools/validate-symbol-order.py.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
KakarottoCake and others added 3 commits July 23, 2026 16:07
getFrameCtrl(0)->getEnd() returns an int; the target doubles it as an
integer (slwi) before the float divide, not getEnd() * 2.0f. 97.3% -> 99.9%.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Same as ExecBackNerve_Sub: getEnd() * 2 (integer slwi) not * 2.0f. 95.7% -> 98.3%.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
mPosition (0x70, on TSharedParts) is copied with a batched float load/store,
not the integer operator=. Spelling it set(position.x, position.y,
position.z) evaluates all three loads before the stores. 92.8% -> 100%.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@KakarottoCake

Copy link
Copy Markdown
Contributor Author

Marking ready for review. The whole TU is implemented end-to-end (every function and symbol from the map present, reverse definition order preserved for the -inline deferred build).

State: ~94%, 91/142 functions at 100% (22 more at ≥99%, 11 at 95–99%).

Recent structural passes:

  • __sinit 9.7% → 100% — was missing the MSSetSound.hpp rogue include that instantiates the JAL sound-list statics (same pair MapObjSample.cpp uses).
  • getModel() inliningTLiveActor::getModel() is out-of-line, so bare getModel() emitted a bl; the target inlines mMActor->getModel(). Applied across init/perform.
  • integer frame-count doublinggetFrameCtrl(0)->getEnd() * 2 (int slwi), not * 2.0f (ExecBackNerve_Sub, TNerveBossEelAppear).
  • batched vec copyTBossEelHeartCoin::generate: mPosition (0x70, on TSharedParts) wants set(p.x, p.y, p.z) (batched float), not integer operator= → 100%.
  • linkageExecBackNerve_Sub is local in the map; dropped the header decl and made it static (validated with the symbol-order tool).

Known-remaining residuals, all verified as the human-tier category (instruction streams and logic match): stack-frame size, register allocation, and the -inline deferred theNerve() inline-depth. There's also a function-order reshuffle the symbol-order validator flags (correctness/CI, doesn't affect fuzzy %) that's best done as a focused reorder pass.

🤖 Posted by Claude Code

The symbol-order validator flagged this UNUSED helper as the sole non-weak
symbol out of order: it sat after the whole nerve block, but the map emits it
between theNerve(FirstSpin) and execute(WaitAppear). Since -inline deferred
emits in reverse of source order, moving its definition to just after the
WaitAppear nerve (before FirstSpin) reproduces the map order.

validate-symbol-order.py now passes (non-weak order + linkage + presence).
No fuzzy change (ordering doesn't affect per-function matching).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@KakarottoCake

Copy link
Copy Markdown
Contributor Author

Ran the new symbol-order validator (the CI check from the symbol-order-validation branch) against this TU and fixed what it flagged:

  • Linkage: ExecBackNerve_Sub is local in the map but was declared in the header (extern) and emitted global — dropped the header decl, made it static.
  • Order: the sole non-weak symbol out of place was ExecSpinNerve_Sub. The map emits it between theNerve(FirstSpin) and execute(WaitAppear); it sat after the whole nerve block. Since MoveBG/Enemy build -inline deferred (emission = reverse of source order), moving its definition to just after the WaitAppear nerve reproduces the map order.

validate-symbol-order.py now returns PASS (presence + linkage + non-weak order all OK). Remaining items are non-failing warnings only: compiler-controlled weak-symbol order, and the UNUSED-inline exact sizes (best-effort per the tool).

No fuzzy change from either fix — ordering/linkage don't affect per-function matching; the TU stays at ~94% (91/142 at 100%).

🤖 Posted by Claude Code

Fixes the lint CI check (variable-declaration alignment and multi-line
continuation indentation). Whitespace only; no codegen change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant