emulator/render-bridge/first-3d-frame.png: the arena from the pod -- sky,
horizon, ground, the arena structures along the skyline -- at ~31fps on the
VelociRender bridge.
The whole chain now works in our build: MakeVideoRenderer ->
BTL4VideoRenderer over DPLRenderer -> board boot -> Renderer::LoadMission ->
DPLReadEnvironment for the art paths -> 40/40 arena objects loaded -> mission
launch -> per-frame submission over the wire.
The mistake worth remembering: the run was never stalled after
InitializePlayerLink. I called that from a 150-second sample and it was just
too short. CheckLoadMessageHandler reposts every second and will not advance
until the min-priority event queue drains, and with the video renderer in the
mission that takes minutes. A BT_LAUNCH_LOG trace showed the queue draining
and then both RunMissionMessageHandler calls, the plasma display, and the
first sensor tick -- matching the shipped binary line for line. The renderer
deliberately holds a blank screen until RunningMission (L4VIDEO.CPP:5100), so
'black' was the app still loading, not a rendering bug.
Zero unbuildable entities, zero geometry failures. The frame is static only
because the mech is parked with no input, and the camera in the bridge title
is the bridge's own viewer, not the game's eyepoint.
Also banked the launch-gate trace (BT_LAUNCH_LOG) behind an env var.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PlayerStatus (dirty-gated, blits an 8-bit pixmap -- but the widget map for a
DIRTY run contains no playerStatus at all; it belongs to cameraInit and never
exists in a mech cockpit) and heat-driven redraw (a BT_FORCE_FIRE run came
back clean). Seven hypotheses killed by measurement so far.
It is a heisenbug: dirty on ~3 runs in 25, and every run since instrumenting
has been clean. The pattern tracks STARTUP LOG VOLUME -- the three dirty
runs all had the lighter conf, and a chatty trace slows init enough to
suppress it. The blit trace is therefore narrowed to fire only for pixmaps
landing on a non-palette port, which is near-silent when nothing is wrong.
That narrowed trace caught real traffic: 17x17 PixelMap8 blits onto
Mfd1/2/3 -- 8-bit pixmaps on single-bit planes. They render correctly, so
the library thresholds them; not the culprit but the right bug class.
Also banked a hunting recipe, because two detector traps cost runs: Eng1 == 0
means the cockpit is not up (not dirty), and an early capture during mission
start caught a full 3-D cockpit frame with the gauges at pod positions
(Eng1 62927) that did not recur over the next minute. BTDPL.INI is in the
mount and DPLRenderer is linked, so the dPL path may emit a frame during
launch even with L4VIDEO=OFF -- first evidence the 3-D path produces
anything, and explicitly NOT a claim that btl4vid works.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The gauge framebuffer is PLANE-PACKED: L4GAUGE.CFG gives each port a bit
mask, not a rectangle, so all six heads share the same x/y and are separated
only by bit -- the packing the VDB splits into the pod's physical screens.
Comparing RGB was therefore measuring nothing useful; the "magenta artifact"
just meant the wrong heads were lit at that pixel.
New instruments (emulator/render-bridge/gauge-ab/, with a README):
planes.py per-head scoreboard -- shipped vs ours, missing vs extra, per
port mask, recovering the 16-bit word from DOSBox's RGB565
BT_VIS_LOG a complete cockpit widget map from the single dispatch every
gauge widget is built through (MethodDescription::Execute),
printing name + port + authored position
ab.sh stages the fresh build over BTL4REC.EXE and kills any running
DOSBox before launching -- see below
The fix: the Comm page's pilot roster is the POD roster (the viewpoint mech's
ControlsMapper pilot array, mapper attributes 15/16), not the mission's
player list. It is zero in a solo mission, so the shipped page draws empty;
ours resolved the local player and painted its icon in colour 0xff. The gate
belongs in the row source, not PilotList::Execute -- Execute's empty branch
still has to run, because erasing is what the shipped page draws.
head shipped ours missing extra (was)
Eng1 17981 17981 0 0 (0 / 1030)
Eng2 17981 17981 0 0
Eng3 17981 17981 0 0
Comm 15656 13557 2099 0 (2099 / 1253)
Heat 21374 20913 566 105 (566 / 990)
Title-band magenta 404 -> 0. The 2099 Comm pixels we are missing were
missing before the gate, so it is a strict improvement.
Method note, which cost more than the bug: the rig's confs run BTL4REC.EXE
out of the mount while the build writes build410/btl4opt.exe, and nothing
connected the two. Three measurements ran an hour-old binary, so a change
that "did nothing" three times had never been tested -- and the correct first
hypothesis was discarded on that evidence. ab.sh now re-stages every launch.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Six TUs born in one wave (4-agent re-hosting workflow from the BT411 donors
+ inline integration): BTL4GAUG (16 widget primitives + 5 connections, the
TU anchor @004c3f6c), BTL4GAU2 (13 composite panel clusters), BTL4GAU3
(PilotList/PlayerStatus/SectorDisplay/MessageBoard/mapping group), BTL4RDR
(the MapDisplay radar vs the authentic surviving header), BTL4GRND (the
real renderer: L4LampManager + L4Warehouse + BuildConfigurationFile with
the 19-entry BT registry chained onto the engine table). btl4.lib grows
7 -> 11 members; all 50 game TUs compile; link clean.
VERIFIED LIVE: with L4GAUGE=640x480x16 the interpreter parses the full
authentic L4GAUGE.CFG, Bhk1Init runs, ColorMapperArmor binds the live
mech's damage zones by name (cross-chassis names take the authentic inert
path), and the complete mutual missile fight runs with the cockpit stack
updating from real combat -- 16/16 rounds, 138 zone hits, zero faults.
Gauges-off regressions untouched.
Engine bring-up deviation (documented): ParseAttribute normalizes
unpublished attribute names to a shared writable zero cell -- the 1995
GaugeConnectionDirectOf ctor hard-derefs its source (first boot crashed
there); widgets on unpublished names draw static zeros and light up
automatically as the attribute waves publish the 1995 CFG spellings the
bindings already carry.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Missile entity family is reconstructed: Projectile : Mover gets a real
make-path ctor; Missile hosts the Seeker + MissleThruster roster (the
AUTHENTIC surviving SEEKER.HPP / MISTHRST.HPP interfaces -- the 1995
misspelling included) and flies the binary's guided integrator (@004bef78):
age/lifetime, seeker re-lead with the decoded loft constants
(200/50/300/0.1), thruster burn, steering (gain 4.0, deadband 1e-4), and
the proximity fuse delivering the cluster damage ONCE with the launcher as
inflictor. Live-verified end-to-end: LAUNCH -> flight telemetry (thruster
visibly accelerating) -> DETONATE on the target ~0.9s out.
OPEN: the first ~Missile off the death row completes, then the frame
page-faults with EIP in the heap -- the first entity/subsystem teardown the
reconstructed sim has ever run. The spawn path is therefore OPT-IN
(BT_MISSILE_FLIGHT=1); default SRM delivery stays the 5.3.18a instant-hit
cluster (verified 1:1, zero exceptions). Forensics + engine truths
(SearchList crashes on non-directory ids; MakeMessages need FAMILY resource
ids; explosionModelFile is a model-list INDEX) in MISSILE.NOTES.md.
Also fixed on the way: the Subsystem NAME ctor left damageZone
UNINITIALIZED (latent garbage for every name-built subsystem).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
First of the 3 missing Mech embedded-helper classes. AlarmIndicator is the
multi-level status indicator the Mech carries four of (master/heat/stability/
status). Reconstructed as a StateIndicator subclass: the shipped ctor
(@0041b9ec) is byte-for-byte the surviving StateIndicator(unsigned) ctor
(stateCount=oldState=currentState=count; 3 watcher sockets NULL) with a distinct
vtable, so a derived class reproduces it exactly and adds the level API
(SetLevel/GetLevel/GetLevelCount -> SetState/GetState/stateCount). Header-only
(StateIndicator's methods are in SIMULATE.CPP, already in munga.lib).
Compile-verified standalone under BC4.52 with the authentic build flags.
Evidence + placement in ALARM.NOTES.md.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The reconstructed tree now produces a runnable binary with the authentic
1995 toolchain (BC4.52 / tlink32 / DPMI32):
- BTL4.CPP main TU reconstructed from the 4.11 Ghidra decomp (FUN_0040109c)
+ the 4.10 binary's own string pool + surviving RPL4TOOL.CPP house style;
probe_main.cpp scaffold retired (BTL4.NOTES.md documents every decoded call)
- L4NET.CPP staged: L4NetworkManager ctor/dtor + 10 vtable-pulled virtuals
(standalone-benign ones no-op, network ones Fail loudly) + NetNub client
globals (Net_Common_Ptr=NULL routes L4File to its plain-DOS path)
- build410.sh: libs now built in the AUTHENTIC makefile member order
(MUNGA.MAK / mungal4.mak / BT.MAK / BTL4.MAK). Order is load-bearing:
tlink emits static-init records in module pull order, and alphabetical
order booted into a null-vptr crash (IcomManager::ClassDerivations
constructing before parent NetworkClient::ClassDerivations). Also fixed
stage_link to the proven 32-bit lib set (SOSDBXC+SOSMBXC, no WATTCPLG)
- BOXTREE.HPP MemoryBlock unify, BTL4GRND notify stubs, remaining engine
backfills (audio/gauge/resource/stream TUs) that closed the deep ledger
Smoke test (DOSBox-X + 32RTM, copy of the pod BT tree, our exe swapped in):
BattleTech v4.10
BTL4Application::BTL4Application
l4net.cpp(22): L4NetworkManager -- l4net.cpp not yet reconstructed
Static init, main, -egg parse, BTL4.RES load (version 1.0.6 check passes),
ApplicationManager and the BTL4Application ctor chain all execute real
reconstructed code; boot halts at the first staged Fail() as designed.
Next brick: the real l4net.cpp body.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The tlink32 campaign after the checkpoint: eleven engine bodies back-dated
from BT412 (rotation player team explode dropzone terrain cultural receiver
subsystm app l4gauge - the Application core included), the WinTesla-ectomy
handled by backdate.py's new unwrap rules (accessor-fn statics -> 1995 static
objects, decl rewrites, pointer->reference Derivation ctor, 2007 windowed-
gauge/console-marshal/idle-pump excisions), staged statics TUs opened for the
game classes (MECH/BTPLAYER/BTDIRECT/PROJTILE/MISSILE/BTL4MPPR .CPP + L4APP/
NETWORK engine statics).
State: every compiled symbol short of the shallow graph RESOLVED (the 52- and
17-symbol ledgers burned to zero); with 32stub.exe in place the linker reaches
full vtable closure and emits the deep ledger (~210 symbols, UNRESOLVED-
LEDGER.txt): remaining engine bodies (objstrm cstr gauge/gaugrend graphics
pixelmap palette resfile ray scnrole explosion-table), the DOS driver extern
layer (_SVGA*/_PCSerial*/_PCSPAK*/joystick/netnub/sosMIDI), the full L4App
body, and the real game-TU frontier (Mech::Make et al.). Recipe proven for
every category.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>