Files
BT411/context/reconstruction-method.md
T
Joe DiPrimaandClaude Opus 5 c791fae0f8 KB: new topic test-harness.md -- the bench machinery + the verification doctrine
User mandate (2026-08-02): "do tests like this from now on" -- after the #110
grind bench, where the field composition (peer fire destroying an arm over the
wire) replaced the constructed proxy that had let #86 be called fixed while
players kept hitting it.

The topic carries two halves on purpose:

DOCTRINE -- what counts as VERIFIED:
  1. reproduce the REPORTED scenario, not a convenient adjacent one
  2. scalpel hooks (BT_SELF_DAMAGE_ZONE / BT_KILL_SUBSYS / BT_FORCE_*) locate
     defects; they support a "fixed" claim only with proven path-identity to
     the field composition -- and the field composition still gets run
  3. MP symptom -> two-node proof (master-side correctness says nothing about
     what a peer sees)
  4. visual symptom -> pixel proof (gotcha 23)
  5. coverage claims need the axis enumerated and measured (all gates, all
     chassis), because per-chassis behaviour lives in authored data
  6. an unexplained extra effect in a passing run means the run has not passed

MACHINERY -- the bench_common.sh contract (summarized, file = source of truth),
single-node and two-node skeletons (relay, ports, affinity, fire cadence,
GOTO_STOP standoff), process hygiene (stale-node taskkill first, never
double-background, teardown kill order, stale-exe tells), and log-reading rules
(capped diagnostics are not evidence of absence; alarm lines are not trends;
name the actor at every refusal; field logs have no gates set -- spawn-time
summaries ungated, per-frame traces gated).

Routed: Quick Lookup row, CLAUDE.md reasoning step 4, build-and-run parity
section, reconstruction-method Key Relationships.  checkctx CLEAN.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 09:17:01 -05:00

4.0 KiB

id, title, status, source_sections, related_topics, key_terms
id title status source_sections related_topics key_terms
reconstruction-method Reconstruction Method — the loop, the no-stand-ins rule, decomp technique established PROGRESS_LOG.md §10b, §5a (decompilation), §10c
reconstruction-gotchas
decomp-reference
source-completeness
decomp
oracle
bridge
BTL4OPT
WinTesla

Reconstruction Method

How the missing BT game logic is rebuilt from the binary. The governing rule: no stand-ins. Full detail: docs/PROGRESS_LOG.md §10b; the systemic bug classes are reconstruction-gotchas.

The loop (per feature)

  1. Read the RAW decomp reference/decomp/all/part_*.c for the relevant FUN_xxxx.
  2. Map FUN_/DAT_/this+0xNN to engine symbols using: the BT headers + the WinTesla MUNGA source + game/reconstructed/CLASSMAP.md + RP's parallel code (VTV≈mech, WEAPSYS≈weapons).
  3. Write the real reconstruction into game/reconstructed/*.cpp.
  4. Build; run env-gated; read content\<stem>_YYYYMMDD.log (grep [anim]/[drive]/[target]/[fire]/[damage] markers).
  5. cdb on any crash. static_assert-lock the layout against the binary's offsets. [T2]

RULE: no stand-ins

The full game logic IS in the pseudocode (the binary ran the game); a "gap" is a reconstruction stub not yet filled, not a hole in the original. Never write stand-in/placeholder logic for an apparent gap — read the decomp. (User: "there are no gaps, just work to be done.") Bring-up scaffolding (the BT_AUTOFIRE/BT_AUTODRIVE/BT_GOTO env harness; historically explosion-for-beam and a player-gated drive, since replaced by the real reconstructions) is clearly MARKED and meant to be REPLACED by the real reconstructed system, never to substitute for reading the decomp. [T2]

Decompilation stack (established)

  • Ghidra 12.1.2 + JDK21 are an EXTERNAL install (tools/ holds only python utilities); the headless scripts live in reference/ghidra_scripts/ (ExportBTSource.java, DecompVSS.java, ExportAll.java). ExportBTSource.java run headless on BTL4OPT.EXE → decompiled C in reference/decomp/ (bt_<src>.cpp.c assert-anchored files; bulk pseudocode in reference/decomp/all/part_*.c). The pass is assert-anchored (few funcs/file — anchored on the asserts that carry source paths). [T2]
  • For a FUN_ the assert-anchored exporter skipped: tools/disas2.py <VA> [len] (capstone disassembly of BTL4OPT.EXE — recovers x87 math Ghidra drops, folds known calls + float constants). Or DecompVSS.java (headless address-list decompiler). [T2]
  • Resolving a .data fn-pointer (a PTR_LAB_xxxx callback/vtable slot the decomp didn't export): PE-parse the DWORD at its VA, then capstone-disassemble the target. Used for the gait callbacks (@0x4a6d8c), the valve handler (@0x4ae464), gauge widget slots. [T2]
  • .data float constants are the biggest "couldn't recover" bucket (tuning values); read them as the x87 80-bit float10 the decomp uses, not 32-bit float (scratchpad/rdtbyte.py). [T2]

Effort model (honest)

~0.5-1.5 hr/module → ~30-50 agent-hours + human review for ~40 modules, with a long tail (modules with no surviving .HPP fragment, or split across decomp windows, cost more). Process upgrades: per-class function lists (not address clusters), complete vtable rows, recover .data constants. [T3]

Workflows (for scale)

For exhaustive multi-function decomp analysis, fan out a read-only Workflow (understanding phase — one agent per function/class produces an offset map + findings, + an adversarial verify), THEN implement hands-on so each change is visible + consistent. This is the §10c pattern; used for the ground-model decode (10 agents), the alarm-unification (8), the gauge-widget decode (6). [T2]

Key Relationships