Skip to content

daBakubaku_c: the last intermediate base, named and given a layout - #1408

Merged
andrewboudreau merged 2 commits into
mainfrom
cpp/bakubaku
Aug 12, 2026
Merged

daBakubaku_c: the last intermediate base, named and given a layout#1408
andrewboudreau merged 2 commits into
mainfrom
cpp/bakubaku

Conversation

@andrewboudreau

Copy link
Copy Markdown
Collaborator

daBakubaku_c is the last of the three intermediate bases the RTTI puts under
dEnemyBase_c — except it has no children, so it is only "intermediate" by where
it sits in the graph. The decomp had no name for it at all: every one of its eight
functions was still func_ov032_*, and it had no header. It gets both here.

With this, all three bases are done — #1402 (dCapEnemy_c = CapEnemy), #1403 and
#1406 (daOts_c and its three children), and this one.

Two witnesses, agreeing offset for offset

func_ov032_0211244c is the factory: ActorBase::operator new(0x438), then
_ZN5EnemyC2Ev, then one vtable store — one, not two, which is what says nothing
derives from this class — then five members. func_ov032_021111a0 destroys the same
five backwards and chains to _ZN5EnemyD2Ev; func_ov032_021111f0 does that and then
Memory::Deallocate, so it is the deleting destructor.

0x110 MovingCylinderClsnWithPos   0x40 -> 0x150
0x150 MovingCylinderClsnWithPos   0x40 -> 0x190
0x190 WithMeshClsn               0x1bc -> 0x34c
0x34c ModelAnim                   0x64 -> 0x3b0
0x3b0 4 bytes of padding                -> 0x3b4   <-- real, and both witnesses agree
0x3b4 ShadowModel                 0x28 -> 0x3dc

Size 0x438, the factory's own literal. The 0x5c above 0x3dc stays padding: none of
the eight functions reaches it through anything but a raw offset, so there is nothing
to name it from.

Named from the vtable, all 31 slots checked

Eight overrides, and every one is renamed from its placeholder:

slot was is
0 func_ov032_021122dc _ZN12daBakubaku_c13InitResourcesEv
3 func_ov032_02112124 _ZN12daBakubaku_c16CleanupResourcesEv
6 func_ov032_021121b4 _ZN12daBakubaku_c8BehaviorEv
9 func_ov032_02112164 _ZN12daBakubaku_c6RenderEv
12 func_ov032_02112160 _ZN12daBakubaku_c16OnPendingDestroyEv
16 func_ov032_021111a0 _ZN12daBakubaku_cD1Ev
17 func_ov032_021111f0 _ZN12daBakubaku_cD0Ev
29 func_ov032_02112444 _ZN12daBakubaku_c16OnAimedAtWithEggEv

The destructor and four of the overrides become real C++ methods. Two are renamed
only, and the PR says which and why rather than pretending otherwise.

The vtable at ov032 0x02113824 gets the name _ZTV12daBakubaku_c; the word before it
is 0x021137e4, _ZTI12daBakubaku_c. Worth noting: ov027 has _ZTV10SlidingIce at
that same address
— ov027 and ov032 overlap, so an address alone does not identify a
symbol here.

Two spellings that turned out to be load-bearing

Render's temporary. The original wrote int b = (flag != 0); if (b) .... Folded
into if ((mFlags & 0x40000) != 0) the function came out 0x44 against the ROM's 0x50 —
the temporary is what makes the compiler materialise the test as a 0/1 value
(movne #1 / moveq #0 / cmp) before branching. Restored, with a comment saying not to
fold it.

Behavior's pointer-to-member. That file builds a typedef void (Klass::*PMF)()
on an incomplete class, and a PMF's representation depends on that incompleteness.
Giving Klass a real definition is a codegen change, not a cleanup, so this one is
renamed and left alone — the same shape that currently blocks UnchainedChomp.

Render also reached its model through a six-slot stand-in whose last member was
Target(int). That shape was doing real work: it made the call a virtual dispatch
through slot 5, and slot 5 of ModelAnim is Render(const Vector3 *). The real
declaration reproduces it exactly — ldr r2,[r2,#0x14]; blx r2.

Split into two commits, from the start

First commit is git mv only, second is the content. A commit that moves and rewrites
a file drops below git's 50% rename threshold and credit for the old path is reported
lost. Done this way it reads 8 renamed with credit intact.

Verified

gate result
rombuild -j16 106/106 exact, 10,816 source-built, 0 mismatching
byte matches all 8 functions reproduce, plus the factory re-verified after its vtable was renamed
check_header_offsets 0 mismatched, spans 0x438, the factory's own literal
eligible.py bracket 10,818; vs current main the diff is exactly the 8 renames, one for one
check_references OK — 239 unresolved vs baseline 239
prepush_attribution 8 renamed with credit intact, 0 changed, 0 lost
langmode ratchet PASS
check_data_definitions 11,027 objects, none define a ROM data symbol
check_duplicate_sources 11,282 stems, none doubled
port_refcheck 393 references, all resolve
layout_check clean

Counts are unchanged: a migration and eight renames, not a new match.

Not claimed

The factory keeps the name func_ov032_0211244c. Its siblings are spelt
<DecompName>_Spawn, and this class has no decomp name — inventing one to fit the
convention would be a guess, and the production name does not fit it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XxDmkQ47fWa3GB6mj8xEQe

andrewboudreau and others added 2 commits August 11, 2026 20:14
Moves only, so git records R100 and contributor credit follows; the content
lands in the next commit. See the note in tools/prepush_attribution.py -- a
commit that both moves and rewrites a file drops below git's rename threshold
and the old path is reported as lost credit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XxDmkQ47fWa3GB6mj8xEQe
@tangos-validator

tangos-validator Bot commented Aug 12, 2026

Copy link
Copy Markdown

✅ PR validation — Passed

Committed merge introduces no reconstruction or attribution regression.

Full merge validation

Check Result
Committed test merge yes
Matched functions 11,178 / 11,347 (98.5%, +0)
Matched code bytes 2,078,800 / 2,211,124 (94.0%, +0)
Tracked source enrollment 10,788 functions, 1,938,604 bytes (87.68%, +0)
Perfect source moves 0 R100
Contributor credit 0 added, 0 changed, 0 lost
Relocation check 9 checked; 9 VERIFIED
Port reference check 393 checked; 0 stale
Module fidelity 106/106 exact; 100.000000% compared bytes
Code linked from verified source 10,816 functions, 1,945,492 bytes (87.99%)
Per-file link-check detail

All 9 changed file(s) compile to the ROM byte-for-byte with correct relocation targets.

File Symbol Result Slots checked
src/_ZN12daBakubaku_c13InitResourcesEv.c _ZN12daBakubaku_c13InitResourcesEv ✅ verified 1
src/_ZN12daBakubaku_c16CleanupResourcesEv.cpp _ZN12daBakubaku_c16CleanupResourcesEv ✅ verified 1
src/_ZN12daBakubaku_c16OnAimedAtWithEggEv.cpp _ZN12daBakubaku_c16OnAimedAtWithEggEv ✅ verified 1
src/_ZN12daBakubaku_c16OnPendingDestroyEv.cpp _ZN12daBakubaku_c16OnPendingDestroyEv ✅ verified 1
src/_ZN12daBakubaku_c6RenderEv.cpp _ZN12daBakubaku_c6RenderEv ✅ verified 1
src/_ZN12daBakubaku_c8BehaviorEv.cpp _ZN12daBakubaku_c8BehaviorEv ✅ verified 1
src/_ZN12daBakubaku_cD0Ev.c _ZN12daBakubaku_cD0Ev ✅ verified 1
src/_ZN12daBakubaku_cD1Ev.cpp _ZN12daBakubaku_cD1Ev ✅ verified 1
src/func_ov032_0211244c.c func_ov032_0211244c ✅ verified 1

The private worker commits a test merge, builds the stock ROM profile, compares every executable module, measures matched and source-built code, checks contributor lineage, and verifies affected relocations. The mod profile is opt-in and is not part of this merge gate.

@andrewboudreau
andrewboudreau merged commit 1859d7e into main Aug 12, 2026
3 checks passed
@andrewboudreau
andrewboudreau deleted the cpp/bakubaku branch August 12, 2026 02:00
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