Files
TeslaRel410/restoration/source410
CydandClaude Fable 5 f0f0e3d70e BT410 5.3.88: hinges flush as MATRICES -- the axis was never on the wire, and a DCS remembers how it was last set
The mech rendered with a live root and frozen limbs.  Cause, and it is not in
the renderer:

  L4VIDRND.CPP:1028 sets SINGLE_AXIS_HINGE True, so HingeRenderable pushes a
  joint with dpl_SetDCSXAxis / YAxis / ZAxis -- three separate libDPL entry
  points, each handed only (sine, cosine).  The AXIS is carried by WHICH
  FUNCTION WAS CALLED, and libDPL never puts it on the wire.

Confirmed against a live capture rather than argued: every articulation
record in joints_check.fifodump is 12 bytes, [handle][sin][cos], 26133 of
them, no axis field anywhere.  And the renderer cannot recover it from
context either -- that capture contains ZERO action-0x22 name records, so a
DCS handle cannot be matched back to a .SKL node.  vrboard was parsing those
records correctly and dropping them on purpose, with a comment saying so.

THE FIX is the archive's own alternative.  The #else half of that same #if
(L4VIDRND.CPP:1153) builds a Quaternion from the Hinge and assigns it over
the DCS matrix -- the axis ends up IN the matrix, and it flushes as a
12-float pose the renderer already applies.  That is precisely what
BallJointRenderable::Execute does unconditionally, with no #if at all, which
is why ball joints were never affected.  So this is the branch the original
authors wrote and did not take, applied to hinges so they behave like the
ball joints beside them.

A DCS REMEMBERS HOW IT WAS LAST SET -- the part that cost a build.

The first attempt subclassed HingeRenderable and overrode only Execute.  It
compiled, ran, and did not work: the wire still carried 12-byte records.  What
it DID change was their contents -- the pair went from (sin, cos) to
(0.9990, 0.0000), which is m00 and m01 of the matrix being written.  That is
the whole diagnosis in one number.  The base ctor calls dpl_SetDCS?Axis before
the subclass gets control, which puts the DCS in single-axis mode, and the
flush then serialises two floats out of it no matter what goes in through
dpl_GetDCSMatrix.

So the axis setter must never touch this DCS.  BTL4HingeRenderable therefore
derives from ChildOffsetRenderable, whose ctor builds the offset DCS and calls
no axis setter -- making it the exact hinge analogue of BallJointRenderable:
same base, holds its own attribute pointer plus a previous-value copy, writes
a full matrix in Execute.  CODE/ untouched; Component::Execute is virtual
(CMPNNT.HPP:40) so the override dispatches normally, and shadowing 1900 lines
of L4VIDRND.CPP to flip one #define was not needed.

VERIFIED on the rig, torso-sweep conf, clean run:

    before   26133 records, ALL 2-float, 1 handle, renderer applied NOTHING
    after     7626 records, ALL 12-float, ZERO 2-float messages remaining,
              22 handles emitted, renderer applied all 22 (anim_abs)

  and the swept joint moves: handle 0x684, m00 across 1532 distinct values
  from 0.1582 to 1.0000 -- cos of a 0..80 degree sweep, which is exactly what
  BT_FORCE_TORSO drives.

LEG GAIT: NOT FIXED, and the earlier note claiming this would fix it was
wrong.  The transport was necessary but not sufficient.  On a walking run
(new pod_render_joints.conf = the arena mission with BT_JOINTS) all 22 joints
flush as matrices and the renderer applies them, but only handle 0x672 -- the
vehicle ROOT -- animates.  The limbs emit their initial pose and never change.

  Because nothing drives them.  Joint::SetHinge / SetRotation exist, and the
  ONLY caller anywhere in the reconstruction is TorsoSimulation
  (BT/TORSO.CPP:382, horizontalJointNode->SetRotation).  That is why the
  torso is the one thing that moves.  MAD.SKL declares JointCount=25 --
  jointhip, jointlthigh, jointrthigh, jointtorso, jointshakey, jointeye and
  the rest -- and the gait that should walk them is simply not reconstructed
  yet.  Separate piece of work, now unblocked rather than done.

HARNESS CAVEAT: pose_probe frames on "the last-articulated root" in
anim_abs.  With 21 joint DCSs now landing there, that heuristic picks a joint
instead of the vehicle root and frames empty arena.  The change invalidated
the assumption; the render is not evidence either way until it takes the root
handle explicitly.  The counts above are the evidence.

FAULTS SEEN: two crashes during this work, both cr2=7000FA64 at host 66D9 --
the known parked load-window fault, address unmoved across a relink (which is
the standing test for "not ours").  They died at DIFFERENT points ([mer] 217
and [mer] 116), where a defect in new construction code would die
consistently.  Third and fourth runs clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 09:25:12 -05:00
..

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

  1. 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.
  2. Every .CPP here has a .NOTES.md sidecar 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 .CPP itself stays clean 1995 style — no modern annotations inside.
  3. Assert line numbers are constraints. The binary's Fail() sites record the original file+line (BTL4APP.CPP:400 etc.); 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.
  4. Layout mirrors the original tree: BT/ (bt.lib, 36 TUs) and BT_L4/ (btl4.lib, 13 TUs + BTL4.CPP), matching the surviving BT.MAK/BTL4.MAK.

What drives the work

  • The per-TU manifest: C:\VWE\BT411\reference\BT410_SOURCE_MANIFEST.md (tool tools/manifest410.py; method log phases/phase-03-bt410-source-manifest.md).
  • The decomp: C:\VWE\BT411\reference\decomp\all\part_*.c (+ section_dump.txt strings).
  • 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:

  1. 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.
  2. The dependent headers (mechsub, mechmppr, btl4mppr, emitter+mechweap, btplayer, projtile, missile) ship WITH their TUs against the staged MECH.HPP.
  3. 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).

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).