ExecuteOWModeScript walks each map's <Map>_MapScripts table of
`dbw OWMODE_<MODE>, <handler>` entries -- tcg2's variable-length
generalization of tcg1's fixed 8-slot MapScripts table. Like tcg1, the
handlers are named per map+slot.
tools/name_mapscripts.py generates <Map>_<OWMODEAction> names mechanically
(16 OWMODE modes -> CamelCase actions) for every Func_* handler that is
map-specific and collision-free, then applies them. 554 handlers across
116 map tables named in one pass (e.g. GrCastleEntrance_LoadNPCs,
FightingFortMaze22_StepEvent, IshiharasHouse_MusicPreload). Func_2c4db was
a duplicate in-table entry, named manually (LightningClub_MusicPreload).
This clears ~48% of the remaining Func_* placeholders.
make compare: poketcg2.gbc OK (symbol-only, byte-identical).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8 subagents analyzed ~15 functions in parallel; verified and applied:
OW/engine: LoadOWObjectStates, SetOWObjectSpriteAnimMovement,
LoadOWMapTilemapNoDimensions, LoadFirstSpriteAnimFrame
Duel/UI: PlayDuelistIntroScene, LoadNPCDuelConfiguration,
PrintTextNoDelay_ZeroAttributes
Key discovery: ExecuteOWModeScript dispatches a per-map <Map>_MapScripts
table of `dbw OWMODE_*, handler` entries, so each map's lifecycle handlers
are nameable as <Map>_<OWMODEAction>. Did two full map tables:
RockClubEntrance_{MusicPreload,MusicPostload,StepEvent,WarpFadeInPreload}
RockClub_{MusicPreload,StepEvent,LoadNPCs}
Deferred Func_235e (low-confidence text-LRU helper).
make compare: poketcg2.gbc OK (symbol-only, byte-identical).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fanned the analysis out to 7 subagents (each read the body + checked tcg1,
returned a structured name proposal); verified and applied centrally:
Func_1059f -> BackupOverworldStateToWRAM3
Func_105de -> RestoreOverworldStateFromWRAM3
Func_10ea7 -> PushOWObjectsAndExtraByteToBank3
Func_10ed3 -> PullOWObjectsAndExtraByteFromBank3
Func_10d40 -> InitOverworldObjectState
Func_10f32 -> SaveOWObjectStates
Func_12c0b7 -> LoadOWMapTilemap
Func_12c1c1 -> DecompressPermissionMap (tcg1 name match)
Func_10b9c -> ReloadSpriteAnimTilesets
Func_1dfb9 -> ClearDuelAnimationState
Func_189d -> CheckAndDisplayDefenderTransparency (the deferred one,
resolved via a deep dive into wEffectFunctionsFeedback)
make compare: poketcg2.gbc OK (symbol-only, byte-identical).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Func_17fb -> HandleAfterDamageEffects (tcg1 name; the AFTER_DAMAGE effect ->
status conditions -> last-turn damage -> knockouts cascade run
by PlayAttackAnimation_DealAttackDamage)
Func_83b3 -> DrawCurrentPlayAreaPrizeCards (player/opp prize-card draw for
TurnDuelistTakePrizes; tcg1 Func_82b6)
Deferred Func_189d (tcg2-specific wEffectFunctionsFeedback) and Func_2c4b
(ambiguous text helper) rather than guess.
make compare: poketcg2.gbc OK (symbol-only, byte-identical).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Next duel/engine batch (8), from the dynamic graph + static callees:
Func_1c735 -> FadeBGPalsToTarget (FadeColorToTarget over wTargetBGPalettes)
Func_1c767 -> FadeOBPalsToTarget
Func_1c799 -> UpdatePaletteFadeToWhiteOrBlack
Func_1c7b6 -> UpdatePaletteFadeToTarget (FadePalettes dispatches to these two)
Func_1e088 -> UpdateScreenAnimations (active screen-anim fn or anim queue)
Func_6c12 -> LoadDuelScreenBGPalettes (Pals_6f0d8 -> BG pals 2-4)
Func_6c15 -> LoadDuelBGPalettesFromHL (shared copy core)
Func_6c1d -> LoadCardPictureBGPalettes (Pals_6f0f0; the card-pic palettes)
The 6c12/6c1d pair resolves the TODO left during the duel-gfx work.
make compare: poketcg2.gbc OK (symbol-only, byte-identical).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Static analysis can't see indirect dispatch (jump tables, `jp hl`), which
reaches most of the ~974 unreferenced Func_*. Add a runtime call graph:
- SameBoy (tools/sameboy_trace) patched to accumulate a DEDUPLICATED set of
(caller -> callee) edges for every taken CALL/RST/`jp hl`, gated by
SAMEBOY_CALLGRAPH=<file>. The output is bounded by distinct edges, not a
growing per-call log; dumped on clean exit / SIGTERM. (Patch lives in the
separate sameboy checkout's SDL/main.c; binary installed in tools/.)
- tools/callgraph.py --dyn <dump>: resolves bank:pc edges to func->func via
poketcg2.sym and flags dynamic-only callers/callees (<-* / ->*) -- the
indirect edges the static graph misses.
Validated: a short boot/title run already surfaces real indirect dispatch,
e.g. FadePalettes -> Func_1c799/Func_1c7b6 (bank-specific fade handlers).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 1 pilot on bank 04's xref-referenced cluster. Named the two
per-frame "frame functions" and their Set/Unset stack wrappers, using
tcg2's existing FrameFunc_* / Set..FrameFunc / Unset..FrameFunc
convention and confirming each by callers + named callees:
Func_3a39 -> FrameFunc_Overworld (UpdateOWScroll + sprite anims + FadePalettes)
Func_1109f -> SetOverworldFrameFunc (pushes it; OverworldLoop / CreditsCmd_InitOW)
Func_110a8 -> UnsetOverworldFrameFunc (pops it; CreditsCmd_DeinitOW ...)
Func_3a81 -> FrameFunc_AnimationQueue (gated on wActiveScreenAnim)
Func_110b9 -> SetAnimationQueueFrameFunc (ResetAnimationQueue)
Func_110c2 -> UnsetAnimationQueueFrameFunc (FinishQueuedAnimations)
make compare: poketcg2.gbc OK (symbol-only, byte-identical).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stand up the infrastructure for naming the 1,209 Func_* placeholders:
- tools/match_tcg1.py: fingerprints function bodies (opcode stream with
16-bit address operands masked) and proposes byte-identical tcg1 names.
- tools/callgraph.py: caller/callee graph; surfaces named callees that
describe a Func_, and lists a bank's Func_* by reference count.
- FUNC_LABELS.md: ledger + methodology + the measured reality.
Key finding that reshapes the plan: tcg1 byte-porting only resolves ~10
functions (the byte-identical engine code is already named in tcg2; the
unnamed Func_* are mostly tcg2-specific sequel code). Static xref is the
real lever (~225 funcs self-describe via named callees); the other ~974
are fallthrough/indirect/dead and need per-function analysis + tracing.
First validated rename via the loop: Func_8f10 ->
InitBoosterPacksAndDeckCounterSaveData (tcg1 exact match, adapted to
tcg2's SRAM symbols).
make compare: poketcg2.gbc OK (byte-identical).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>