re: mining the base-solver index -- a false-positive mode named, and the AI-table reader found

277 rows over 190 distinct functions (a function can read several blocks).
name_block_bases.py extended with a confidence split.

The tool's false-positive mode, measured and named: 107 of 277 rows solve to a
base on a 64K boundary -- a bare "addis rX, r0, 0xHHHH" with no addi, so any
scatter of displacements votes for it.  82 are 0x820B0000: about 60
near-identical functions in 0x8281xxxx-0x8284xxxx all "naming" the same rou_e0NN
list.  The 170 rows with a non-zero low half are the trustworthy set.  A round
base is not automatically wrong -- sub_822215D0 sits on 0x820A0000 and resolves
205/206 -- so read the ratio, not the base.

The index re-derives every loader we already knew (unit 217, stage settings 129,
PlayerParams 90, hangar 81, squadron orders, missile guidance, shell movement,
substructures, six camera/fog readers) -- that is the control.

The find: sub_8233C368 reads the AI behaviour table.  r28, base 0x8208583C, 20
names -- Enumerate_AIs, FiringLength, GuardLength, AutoGuardLength, CounterLength,
MusterLength.  stage-mission-tables.md owns those field names on the data side,
but Enumerate_AIs appears in no document and no reader was known; the corpus
carries the AI tail of Maneuver as NEEDS-HUMAN/runtime.  It is statically
reachable after all.  The same base also serves sub_82338EE0 (97 names, Weapon
TargetType SpecialWeaponType ReticleType IsCharging ...) -- the weapon datasheet
loader, also not previously named.

Five unowned blocks surfaced and NOT opened: PGHUD_*/PGREMAIN_NUM HUD part names
(205/206), STAGE_RESULT/stage_num_shoot_down_aircrafts/EX_OVERVIEW,
g_mWorldViewProjection/NormalMap/GlossinessMap engine material slots,
Boss16Collision* (cross-links the S16 Guardian object), and roh_n001_menu1_cam_pos
menu camera tags.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
This commit is contained in:
Claude (auto)
2026-08-27 21:41:03 +00:00
parent ae37e15d7d
commit 17b4a791eb
4 changed files with 114 additions and 0 deletions

View File

@@ -84,6 +84,21 @@ def main():
for name, reg, B, tot, n in rows:
print(" %-18s %-5s 0x%08X %d / %d" % (name, reg, B, tot, n))
# Confidence. A base whose low half is 0x0000 is a bare `addis` with no
# `addi` of its own -- any scatter of displacements votes for it, so those
# rows are the tool's false-positive mode and must be read with the
# resolution ratio, not on their own.
round_rows = [r for r in rows if (r[2] & 0xFFFF) == 0]
solved_rows = [r for r in rows if (r[2] & 0xFFFF) != 0]
print("\n## Confidence split")
print(" bases with a non-zero low half (a real `addis`+`addi` pair): %d" % len(solved_rows))
print(" bases on a 64K boundary (LOW CONFIDENCE, see below) : %d" % len(round_rows))
rb = collections.Counter(r[2] for r in round_rows)
for B, c in sorted(rb.items(), key=lambda kv: (-kv[1], kv[0])):
print(" 0x%08X x%d rows" % (B, c))
print(" ⚠ the 0x820B0000 cluster is ~60 near-identical functions in"
" 0x8281xxxx-0x8284xxxx that all name the same `rou_e0NN` list.")
print("\n## The schema each one names, in code order")
for name, reg, B, tot, n in rows:
seen, names = set(), []