Commit Graph
19 Commits
Author SHA1 Message Date
CydandClaude Fable 5 50341b4a66 BT410 5.3.41: the plane-write hunt -- two more hypotheses dead, defect bounded
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>
2026-07-27 22:43:13 -05:00
CydandClaude Fable 5 90daf5e9b7 BT410: bank the plane-write hypothesis ledger and the instrument to use next
Four hypotheses tried and killed by measurement, recorded so the next session
does not repeat them: misrouted eng port (traced -- resolves correctly),
OneOfSeveral's DrawPixelMap8 branch (only OneOfSeveralPixInt uses it, and all
four instances are on the 6-bit colour port where it is correct), an 8-bit
value overflowing a 6-bit field (the bits are far too high), and a displaced
copy from elsewhere in the buffer (the rows appear nowhere else).

Observed structure: constant low byte, varying high byte -- one field written
correctly while another is garbage.

The next move is an instrument, not a fifth hypothesis: trace at the VIEW
layer and log every draw whose absolute position lands in the artifact rect,
with port, colour and call site.  The rect is tiny so the log is short.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 13:42:26 -05:00
CydandClaude Fable 5 c8350408fc BT410 5.3.40: correction -- the 'exact' heads are exact only on lucky runs
Same binary (md5 identical), different run: Eng1/Eng2/Comm read
17981/17981/15656 on some runs and 19011/19011/16909 on others.  The shipped
binary is STABLE across three runs, so this is ours.  Eleven consecutive
clean runs is what let it hide, and the dirty numbers are exactly the
pre-gate numbers from 5.3.32 -- the same artifact recurring.

Read off the raw words rather than inferred: in the artifact rect the shipped
binary writes ONE masked plane bit per pixel (0x4000 = Heat, 0x002D = sec),
while we write arbitrary 16-bit words (0x8BD6 / 0x8AD6 / 0x8AC0) that light
sec+overlay+Mfd1+Eng1+Eng2+Comm at once.  Raw values going into a
plane-packed buffer -- which is why one bad draw appears as extra pixels on
six heads and as 483 MISSING on Heat at the same time.

Intermittent because these widgets are change-driven: on runs where the
coolant value never moves after the first paint, the bad draw never happens.

The six fixes of 5.3.33-39 stand (each moved specific attributable pixels).
What must be restated is the claim that four heads are exact -- true only
when this defect does not fire.  The rig now needs a run-variance check
before any per-head number is believed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 13:39:11 -05:00
CydandClaude Fable 5 b6426388de BT410: correct what the sec head is -- the colour radar, not the 3-D scene
I had it recorded as 'the 3-D scene head, this is btl4vid'.  It is not.  Port
0 carries map / headingPointer / digitalClock / numericSpeed / messageBoard /
the armour colour-mappers / the four GeneratorClusters, and its plate shows
the radar scope, the SPEED / HEADING / MISSION TIME dials and the ARMOR
DAMAGE diagram -- the pod's colour screen, the one the VDB splits out
alongside the five mono MFDs.

So sec is ordinary gauge work and is now the largest single head delta.
btl4vid is a separate deliverable this rig cannot measure at all: the 3-D
main view never enters the gauge framebuffer -- it goes down the dPL path to
the render board, and these confs run L4VIDEO=OFF, so it is not even being
produced.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 13:17:09 -05:00
CydandClaude Fable 5 540c41e497 BT410: correct the leak-gauge note -- both of my guesses about it were wrong
The CFG parameter order is fine (Make already maps third/frames by name,
with a comment saying so), and we do not paint nothing: cropping the plane
shows both binaries draw the hatch, ours about three columns narrower.  So
it is a level/frame-width detail, and most likely the same root as the
coolant numerals -- our coolant value differing by a step.  Folded the two
into one thread and pointed it at the value rather than the widget.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 13:00:06 -05:00
CydandClaude Fable 5 ce199103a9 BT410: session landing -- the cockpit at 98.9% identical, four heads exact
Final per-head state, the binding audit (31 CFG bindings resolve, zero NULL),
and the open list in priority order: btl4vid for the sec head, then the
leak-gauge hatch (with the CFG parameter-order question that probably
explains it), the coolant numerals, and the MFD remainders.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 12:58:33 -05:00
CydandClaude Fable 5 377aec92b0 BT410: the MFD wave landing report (5.3.33-38)
Where the cockpit stands per head, the five defects the rig found and the
order they fell, and the measurement lesson: a large overlapping error makes
a small one measure as already-optimal, which is exactly what I recorded for
the title banner before the strip art was fixed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 12:48:34 -05:00
CydandClaude Fable 5 883315a647 BT410 5.3.32b: the weapon-panel work list, measured
With the engineering heads exact, the entire remaining cockpit difference is
the three MFD quadrant heads -- the SubsystemCluster panels, which the widget
map shows are built by vehicleSubSystems rather than by the CFG, so they are
our code end to end.

Banked with evidence: the ammo weapon's disc+rays are absent while both
energy weapons draw theirs; the ammo digits render as empty cells at exactly
the right position; the mech silhouette is misplaced low-left; the state box
reads OFF where shipped shows a digit.

Also settled by experiment that the title banner is NOT misplaced: 0xb3 is
the measured optimum (0xb6 and 0xb0 both score worse), and the equal
missing/extra counts are overlap fringes, not an offset.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 12:14:48 -05:00
CydandClaude Fable 5 740ef2b0a7 BT410 Phase 5.3.32: the per-head A/B -- three engineering heads now exact
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>
2026-07-27 12:04:43 -05:00
CydandClaude Fable 5 c6cafadb28 BT410 Phase 5.3.31: traced the stray blocks -- PilotList, not PlayerStatus
Three rounds of source inspection produced three wrong suspects; one
instrumented run settled it:

    [pl] PilotList slot=0 at (180,225)      <- the only drawer
    (no [ps] lines at all)

So the magenta blocks over the top-left title are PilotList's slot-0 entry
(the local pilot's name art + mech icon) on the Comm port -- content that
SHOULD draw; what is wrong is the entry's coordinate convention inside that
port.  The port geometry itself is proven right: the Comm background
(btcomm.pcx, the KILLS/DEATHS columns) lands pixel-identical in both exes.

Second, separate finding: PlayerStatus never draws at all.  The cfg builds
8 of them (sec port, 4x2, players 1..8) but our roster resolve is 0-based
against 1-based cfg player numbers, so every panel stays unbound and its
Execute returns early.  Fixing that will add a whole scoreboard page, so it
belongs in an A/B session against the shipped reference rather than a blind
edit -- both leads are written up in GAUGE-BLOCK.NOTES.md.

Also recorded: the capture rig's occlusion failure mode (CopyFromScreen
grabs whatever is in front -- one run scored 77%/47% purely because an
editor covered half the window) and the PrintWindow fix for unattended runs.

Verified build, zero faults; last valid A/B measurement stands at 94.7%
identical / 92% coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 10:45:20 -05:00
CydandClaude Fable 5 10e1a70055 BT410 Phase 5.3.30: the pilot name resolves -- and the magenta boxes diagnosed
The name art was never missing.  The egg carries it as notation pages of hex
rows ([BitMap::Small::Aeolus]); the engine BitMap has a ctor that reads
exactly that format; and the AUTHENTIC Mission ctor already loads them into
smallNameBitmapChain (MISSION.CPP:525 -- implemented, called, working).  The
break was ours: btl4gau3's LookupPlayerNameBitmap was a bring-up stub
returning NULL.  It now uses the authentic API (GetCurrentMission()->
GetSmallNameBitmap(playerBitmapIndex)) and resolves live -- traced index=1
to a real BitMap, with the fallback-box branch provably never firing.
Coverage 91% -> 92%.

DIAGNOSIS CORRECTED for the stray magenta blocks over the top-left title:
they are NOT a missing-name placeholder.  They are the REAL name bitmap
drawn at the wrong slot coordinates -- PilotList lays its 8 roster slots
out from the PE-recovered DAT_0051af88 (x,y,mode) table, and ours puts them
top-left instead of the shipped exe's centre row.  Recovering that table is
the next cockpit thread; the egg-hex -> live-BitMap pipeline is verified end
to end, so what remains there is layout, not art or lookup.

(A duplicate loader written before finding the authentic one was removed --
CODE/RP/MUNGA/MISSION.CPP already does this job.)

Gauge fight 11/11, smoke and novice clean, zero faults.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 09:47:19 -05:00
CydandClaude Fable 5 42ff5c3856 BT410 Phase 5.3.29: the panel titles -- 94.8% identical to the shipped cockpit
Reading the art settled where the titles live: qsensors/qmyomers/qermlas/
qppc/qstrk6.pcc are 299x26 TITLE BANNERS, while the qblh0..7.pcc strings
the cfg hands vehicleSubSystems are 77x120 MECH ICONS (already lit by the
5.3.28 placement fix).  So the authored auxScreenLabel IS the panel title
-- it just belongs on the MFD panel, not only the ENG page.

SubsystemCluster now builds a titleBanner child from the cached label.
Placement was MEASURED against the shipped framebuffer through the A/B rig
(BackgroundBitmap places by left/BOTTOM): a bring-up BT_TITLE_DY knob, then
a green-pixel correlation over the title band, then baked at x+0x09,
y+0xb3 from the panel origin.  "SENSOR CLUSTER", "MYOMERS", "TYPE II 65
TONS" and both "ERMED LASER RANGE 500M" banners now render where the
shipped binary puts them.

Score progression vs the shipped cockpit on identical GAUGE content:
  5.3.26 birth            90.1% identical / 82% coverage
  5.3.28 authored screens 93.2% / 85%
  5.3.29 titles tuned     94.8% / 91%

Also: grab.ps1 now focuses the target window before capturing -- the
screen-copy grabbed whatever was in front, which cost two junk captures
(a white frame and an unrelated 3-D app window).

Gauge fight 11/11 rounds and smoke both clean, zero faults.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 23:09:15 -05:00
CydandClaude Fable 5 24ea06574c BT410 Phase 5.3.28: the visual A/B pass -- 93% pixel-identical to the shipped cockpit
Ran the reconstructed exe and the shipped ALPHA_1 binary against the SAME
GAUGE content, same mount, gauges on, and diffed the 640x480x16
framebuffers.  OUR EXE DRAWS THE COCKPIT: 90.1% pixel-identical on the
first run, and every difference traced to a single root cause.

The authored aux-screen block (screen number / background placement /
label) lives in the subsystem resource -- which is freed with the Mech
ctor's stream buffer (the 5.3.24 use-after-free landmine).  Both this tree
and the BT411 port had stubbed it, which is why BT411's displays show the
same artifacting.  PoweredSubsystem now caches the block at ctor time with
accessors, and btl4gau2 uses the AUTHORED screen instead of a roster-order
stand-in and builds the placement strip art.  Panels snapped onto their
authored screens -- weapon dials now land on the same panels as the
shipped exe, mech icons appear on the sensor/myomer panels, generator
letters correct -- taking the match to 93.2% identical / 85% coverage.

Remaining differences are donor-inherited stubs: the panel title art (now
proven to come from the q-strip statusImage path, not auxScreenLabel --
the label blit is wired and guarded regardless), the pilot name bitmap,
and some lamp frames.

The A/B rig is banked at emulator/render-bridge/gauge-ab/ (both confs +
the window-grab script) so the comparison is repeatable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 22:29:01 -05:00
CydandClaude Fable 5 d67f8d5eda BT410 Phase 5.3.27: the attribute wave -- 48/50 cockpit bindings go LIVE
The gauges now read the real simulation: heat/power/sensor/mech attribute
tables published under the 1995 L4GAUGE.CFG spellings the widgets already
bind by name.  Temperatures, coolant mass/capacity/leak rate, condenser
valve settings, generator voltages and numbers, radar percent, and the
mech's radar/speed rows all resolve to live members.

THE NUMBERING IS PINNED: the chain publishes 2..0x0E so
PoweredSubsystem::NextAttributeID lands on the authentic 0x0F -- the
surviving SENSOR.HPP numbers RadarPercent off it and MechWeapon's
binary-pinned table starts at 0x12, so its pads shrank 16 -> 3
(0x0F..0x11) exactly as the 5.3.x header comment predicted.  Sensor's
authentic enum finally has its table defined; MechWeapon/Sensor rechain to
PoweredSubsystem and Reservoir/AggregateHeatSink to HeatSink so the whole
family is visible where the cfg expects it.

Verified with BT_GAUGE_ATTR_LOG: 48 OK / 2 NULL (was 33/17, and 0/50 at
the block's birth).  The two remaining have no member to bind --
HeatSink/AmbientTemperature (a sim constant) and Searchlight/LightOn (a
memberless subclass) -- and fall to the documented zero cell.  Gauge
fight (15/15 rounds, 127 zone hits), smoke and novice all clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 20:09:08 -05:00
CydandClaude Fable 5 64e208f121 BT410 Phase 5.3.26: THE COCKPIT GAUGE BLOCK -- the first rendered milestone
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>
2026-07-24 19:02:04 -05:00
CydandClaude Fable 5 f11cc0247e BT410: gauge worksheet donor path fixed (exact-byte repair, forward slashes)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 17:41:28 -05:00
CydandClaude Fable 5 b02ce77f06 BT410: byte-level fix for the gauge worksheet donor path (CR/BS escapes)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 17:40:26 -05:00
CydandClaude Fable 5 7bfbece12d BT410: fix a mangled donor path in the gauge worksheet header
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 17:39:36 -05:00
CydandClaude Fable 5 2e0c8a0681 BT410: the gauge-block worksheet -- per-class re-hosting dossiers banked
Three-dossier workflow output (65KB, verbatim): every class across the six
missing gauge TUs audited -- engine base, the L4GAUGE.CFG keyword + the
attribute each widget binds (and which reconstructed subsystem publishes
it), the port-shim -> 1995-native mapping, BC++4.52 hazards, and the
binary @ADDR anchors.  This is the implementing session's hot-start
worksheet for the first rendered milestone (see RENDER-ROADMAP.NOTES.md).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 17:39:16 -05:00