The "gimp" family had two conflicting donor readings -- limp vs jump-jet --
flagged in 5.3.94 rather than guessed at. The binary settles it: LIMP. The
mode test in every gimp function is mech+0x40 in {3,4}, the same values the
damage model documents as "limp gait graphic (left 3 / right 4)"; there is no
jump-jet control anywhere in the pod cockpit; and the donor's port routing
("graphicAlarm 3/4") was the same field under a different name. Its
"run-jump clip" mech3 annotations were the misreading that started the murk.
RECONSTRUCTED, completing all 12 of mech2's census functions:
GimpLegClipFinished @004a7970 GimpBodyClipFinished @004a6344
AdvanceLegAnimationGimp @004a71f4 AdvanceBodyAnimationGimp @004a5bf8
+ the limp branch atop both normal *ClipFinished
+ the limp pick in Simulate (replaces the normal advancers while limping)
HOW A LIMP WORKS, now from the bytes rather than description:
It replaces ONE stride. Limping left, the right stride (6) hands off to
the left limp figure (0x16 -> the self-cycling 0x18) while the other leg
keeps its normal clips. The asymmetry IS the limp.
Both machines CLAMP THEIR DEMAND while in a cycle -- the leg machine
writes the mapper's own speedDemand cell down to the damaged side's cap
(new MechControlsMapper::SetSpeedDemand, matching the binary's direct
mapper+0x128 write), the body machine clamps bodyTargetSpeed, both floor
at zero. A limping mech cannot command more than its figure carries, nor
reverse out of a forward cycle.
The limp advancers keep states 0x16-0x1b LIVE -- the normal advancers
treat those as the reset group, which is exactly why the limp flavours
must be selected while limping or the figure is neutralized mid-cycle.
No death latch, no wind-down: the movement modes are exclusive.
ALSO EXPLAINED IN PASSING: Ghidra's 3760-byte FUN_004a6344 -- the census's
largest function -- is really THREE functions. The two normal ClipFinished
callbacks (@004a6928/@004a6d8c) are reached only via data pointers, so the
decompiler folded them into the gimp-body machine's extent.
All movement-mode reads route through Mech::MovementMode() (mech+0x40 == the
simulation state), which honours a BT_FORCE_LIMP=3|4 dev hook so the gait
could be verified before the damage model's limp hook exists.
VERIFIED, two runs on the rig:
NO-REGRESSION: the normal mission's speed sequence is BIT-IDENTICAL to
5.3.95 (7.31972, 26.6726, 22.1601, ...). The branch costs nothing.
FORCED LEFT LIMP (new pod_render_limp.conf): the mapper still demands
26.9; the hull lurches at 10-23. And on the wire the healthy walk's tight
pose-count pairs (650/649 ... 434/421) BREAK to a 3x asymmetry -- the
drag-leg joint at 18 poses against its partner's 55. The limp is visible
in the data exactly the way it will be visible on screen.
STILL OPEN in this family: the damage hook (leg zone >= 0.5 -> mode 3/4, a
MECHDMG increment -- nothing sets the mode in real play yet), and
IntegrateMotion's remaining pieces.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
source410 — literal reconstruction of the missing BT 4.10 game source
Everything in this directory is RECONSTRUCTED, not recovered. The authentic surviving
source lives in CODE/ and is never mixed with this tree. The goal here is an
archival-grade recreation of the d:\tesla_bt\ translation units that exist only inside
BTL4OPT.EXE (the shipped 4.10 binary), written in the 1995 VWE house style against the
1995 MUNGA/MUNGA_L4 engine headers that DID survive.
Ground rules
- Never copy a reconstructed file into
CODE/— the assembled buildable tree (originals + reconstructions) is produced by a script into a build directory, so provenance stays unambiguous file-by-file. - Every
.CPPhere has a.NOTES.mdsidecar carrying the evidence: the binary address map, decomp references, which sibling sources supplied each idiom, and every judgment call with its tier ([T1] decomp-proven … [T4] style guess). The.CPPitself stays clean 1995 style — no modern annotations inside. - Assert line numbers are constraints. The binary's
Fail()sites record the original file+line (BTL4APP.CPP:400etc.); reconstructed files are shaped so those calls land on their recorded lines. A file that can't meet its line constraints yet says so in the sidecar. - Layout mirrors the original tree:
BT/(bt.lib, 36 TUs) andBT_L4/(btl4.lib, 13 TUs + BTL4.CPP), matching the survivingBT.MAK/BTL4.MAK.
What drives the work
- The per-TU manifest:
C:\VWE\BT411\reference\BT410_SOURCE_MANIFEST.md(tooltools/manifest410.py; method logphases/phase-03-bt410-source-manifest.md). - The decomp:
C:\VWE\BT411\reference\decomp\all\part_*.c(+section_dump.txtstrings). - The port's semantic reconstructions:
C:\VWE\BT411\game\reconstructed\(WinTesla-hosted; each literal file here re-hosts one back onto the 1995 engine APIs). - Style/idiom exemplars: surviving
CODE/BT/*.CPP,CODE/RP/RP_L4/*.CPP,CODE/RP/MUNGA*/**(the 1995 engine source itself).
Status (2026-07-19)
Compile verification is LIVE: ./compile410.sh --sweep (BC4.52 + the authentic OPT.MAK
flags; the period compiler is the reviewer). backdate.py mechanizes WinTesla→1995 header
back-dating (donors: C:\VWE\BT412\engine\MUNGA\*.h).
| item | state |
|---|---|
| THE WHOLE TREE COMPILES (2026-07-19) | ✅ 11/11: all 10 surviving originals + the BTL4APP.CPP pilot build clean under BC4.52 + authentic OPT flags (./compile410.sh --sweep) |
| BT/BTCNSL.HPP + BT/BTSCNRL.HPP | ✅ reconstructed — console wire IDs recovered from the binary (Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1]; TeamScore=12 [T4 GUESS — verify]); see BTCNSL.NOTES.md |
| BT_L4/BTL4APP.CPP (pilot reconstruction) | ✅ compiles (18.5KB obj); 12/12 functions, Fail() at recorded line 400 |
| Staged header family (13: mech/mechsub/heat/powersub/mechweap/emitter/mechmppr/btplayer/projtile/missile + btl4mppr/btl4vid) | ✅ [T3] interface-proven by every surviving consumer; layouts parked in reserved[] blocks — see STAGED-HEADERS.NOTES.md + MECH-LAYOUT.md |
| MUNGA backfills (VDATA, ROTATION, VECTOR2D, AUDREND, APP, LAMP, GAUGREND, GAUGE) | ✅ compile-proven (BACKFILLS.NOTES.md) |
Next work package — the mech-family, REVISED (round-3 finding, 2026-07-19): the plan to "reconstruct mech.hpp first" was the wrong order. A full read of the port's mech.hpp shows it is a hybrid (1995 skeleton + Recon proxies + port-only members + relocated fields), and substantial regions of the binary's 0x854-byte Mech object remain UNMAPPED — the port declares "the remaining members up to sizeof==0x854" in its mech2-4 slices. A literal MECH.HPP that precedes those TU reconstructions would be fiction. Corrected order:
- MECH.HPP is the CAPSTONE, grown incrementally with each mech-family TU
reconstruction (mech.cpp → mech2-4 → subsystem TUs), starting as an interface +
known-ordered members with explicit
reserved[]filler for unmapped regions (sidecar-tracked), tightened as each TU pins its slice. - The dependent headers (
mechsub,mechmppr,btl4mppr,emitter+mechweap,btplayer,projtile,missile) ship WITH their TUs against the staged MECH.HPP. - The blocked originals (BTTOOL, GAUSS, PPC, BTREG) and the BTL4APP pilot compile green as those land — BTREG last (it includes the whole game-header world). Offset oracles for every stage: BT411 CLASSMAP.md, decomp-reference.md §3, and the port headers' static_assert-locked members.
Toolchain — IN HAND (2026-07-19)
Borland C++ 4.52, archived at ../../BORLAND/BC45/, chosen by byte-match: the fleet's own
CODE/RP/CW32.LIB is identical to 4.52's (and not 4.5's). BCC32/TLINK32/TLIB/MAKE run natively
on Win11. The shipped BTL4OPT.EXE recipe is CODE/BT/OPT.MAK (plain bcc32,
-DLBE4;DEBUG_LEVEL=0;DEBUG_STREAM=cout, -5 -a4 -ff -k- -V -Jg -x- -RT- + the full -O set,
PCH btopt.csm; link -Tpe -ax with c0x32.obj + dpmi32.lib + cw32.lib = Borland PowerPack
DPMI32, not Phar Lap TNT). Compile verification of reconstructed TUs is therefore possible
file-by-file; the current blocker for full closure is the 1995 engine header gap (vdata.hpp
first — only the drifted WinTesla VDATA.h survives, in BT412/engine). Include order for
builds: CODE/BT/* over CODE/RP/*, -DNO_PRECOMPILED_HEADERS until the mech-family headers
are reconstructed. Remaining gap: TASM32 (JOYSTICK.ASM only).
Link campaign (build410, 2026-07-19)
source410/build410.sh assembles BTL4OPT.EXE: merged-engine mass compile (152/152 green
— the ENTIRE surviving engine compiles), BT TUs (11/11), tlib libs (munga 1.25MB / mungal4
with the prebuilt-1995 objs / bt / btl4), then the authentic tlink32 link rooted by a probe
main (build scaffold). First true link run: 52 unresolved externals
(UNRESOLVED-LEDGER.txt) = the measured remaining gap. Kill-lists: l4gauge.cpp back-date
(14 widget statics), the missing-engine-body back-date wave (~24: rotation, player, team,
l4app, explode, dropzone, terrain, cultural, subsystm-statics, netclient...), the prebuilt
RANDOM.obj fold, and the staged game-TU statics blocks (MECH.CPP et al. — each TU file opens
with its binary-evidenced Derivation/SharedData statics and grows into the full body).
Link-lib arbitration: SOS = SOSDBXC+SOSMBXC (the 32-bit Borland-flat variants; SOSMW*=16-bit),
WATTCP excluded (it belongs to the 16-bit NetNub TSR — the game talks to it via shared
memory), filestrm = the RP-era pair (BT-tree pair is post-4.10 drift; override layer).