Gitea #48 ROOT-CAUSED + FIXED: MFD "stray blocks / misplaced lamps" = uninitialized translation-table entries leaking pixels into other displays' bit-planes
The conviction was empirical, not theoretical: a new write-site trap
(BT_PLANE_AUDIT) in the seven L4VB16 drawing primitives logs any draw whose
color carries bits outside its port's plane mask -- the exact cross-display
corruption condition (Replace ORs an unmasked color; Or/Xor ignore the mask
entirely; And clears foreign planes). A quiet solo session produced 15-30
leaks per minute:
[plane] PORT 'sec' pixmap draw at(0,0) idx 217 entry=0xffffff00 mask=0x3f
[plane] LEAK DrawPixelMap8[table] at(639,0) color=0xffffff00 mask=0x3f leak=0xff00
THE DEFECT: L4GraphicsPort::translationTable[256] is never initialized in the
ctor, and BuildSecondaryTranslation fills only the entries its BitWrangler
reaches -- 2^numberOfBits: 64 for the sec plane (mask 0x3F), 4 for the overlay
(0xC0). Entries above that stay heap garbage. Every draw resolves color
through this table, and the PIXMAP path indexes it with raw pixel values
0..255: the 480x640 radar background carries pixel index 217, whose garbage
entry's high bits (0xFF00 = ALL EIGHT MFD planes) were stamped into the shared
640x480 buffer -- invisible on the culprit page (the in-plane bits happened
dark) and visible as bright fragments at the same coordinates on every OTHER
display. That is the operator's screenshot exactly: the same-position blips
on Mfd1+Mfd2 and the Heat-display block.
FIX (engine, both layers):
* zero translationTable in the L4GraphicsPort ctor (plane-neutral default);
* BuildSecondaryTranslation now cycles the in-plane pattern across entries
[2^bits..255] -- high-index art degrades to its (index mod 2^bits) colour
IN-PLANE and can never leak. The 1995 binary ships the SAME 64-entry fill
and survived on 6-bit art discipline; garbage is not a preservable
behaviour, so the cycle-fill is a guarded PORT deviation (documented).
A/B PROOF: same probe, 60s -- 0 leaks after the fix (15-30/min before).
sim3 3-pod regression: zero crashes.
SECOND real defect found + fixed en route: sessions configure the CAMERA seat
first ("cameraInit" -- which includes the MISSION-REVIEW context:
configure(0, sec, 0, 0x00FF, native, rgb, mrpal.pcc), a DirectColor context
whose translation tables legitimately hold full RGB565 values spanning all 16
plane bits), and the viewpoint swap to the mech re-configured WITHOUT tearing
that tree down (btl4app's s_gaugeTreeBuilt latch treats the mech build as the
first). The orphaned review gauges kept executing through stale DirectColor
ports. BTL4GaugeRenderer::ConfigureForModel now overrides (ConfigureForModel
made virtual in L4GREND.h) and tears the prior entity-bound tree down before
every rebuild -- safe on first build, and the review screen rebuilds the same
way when the seat returns to the camera.
Also logged (open-questions): the review-screen PlayerStatus panels read the
compiled player at RAW BINARY OFFSETS (+0x1FC vehicle / +0x1C8 score /
+0x1C4 alive-dead box) -- the databinding trap, dormant until the review
screen runs; bridge before enabling the review.
Ruled out along the way (with evidence): the pilot-list label/erase geometry
(erase box 128x32 covers the 64x16 name rasters), the radar name labels
(view-level ClipImage clips them), PlayerStatus in-game execution ([ps] probe:
never runs in-game), and the PNAME bitmap dimensions (egg generator emits
64x16 exactly).
Why it "started with the comms feature" (#43): that wave registered the new
gauge classes with the config interpreter, letting more of the authored page
furniture parse and draw than before -- the leaking high-index pixmaps rode in
with it. [T3 correlation detail; the leak + fix are T2 live-verified.]
Diagnostics kept (env-gated): BT_PLANE_AUDIT (the leak trap, now a permanent
regression tripwire), BT_PS_LOG, the port-level pixmap identity trap.
KB: gauges-hud.md (#48 section), decomp-reference.md (BT_PLANE_AUDIT),
open-questions.md (PlayerStatus databinding entry). checkctx CLEAN.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
6f5a264835
commit
6bb03aed0b
@@ -419,6 +419,7 @@ default-ON (`'0'` disables).
|
||||
| `BT_GAUGE_SKIP_LOG` | `[gskip] <primitive>` per unregistered gauge widget the parse skips |
|
||||
| `BT_VALVE_LOG` | condenser valve flow distribution |
|
||||
| `BT_BAYTEST=<frame>` | #46 rig: send message 1 (crit-induced cook-off arm) to the first AmmoBin at the given sim frame — the 10 s fuse then runs live (`scratchpad/baytest.py` / `baypurge.py`) |
|
||||
| `BT_PLANE_AUDIT` | #48 forensics: log every gauge draw whose color carries bits outside its port's plane mask (the cross-display leak trap; `[plane] LEAK/PORT` lines) |
|
||||
| `BT_LOOP_AUDIT` | `[loop-audit]` per-sound `sample-flag × source-render-type -> AL_LOOPING` (Gitea #51; rig `scratchpad/loopaudit.py`) |
|
||||
| `BT_LOOP_LEGACY=1` | restore the OLD always-loop rule (`AL_LOOPING = sample != ForceStatic`) for a field A/B — see the loop-flag note in [[wintesla-port]] |
|
||||
| `BT_AUDIO_DUMP` | once-a-second `[playing]` dump of every playing AL source + gain/pitch/**loop** — catches a stuck looping source red-handed |
|
||||
|
||||
@@ -639,3 +639,44 @@ BITMAPS from the egg, not text — format, renderers, and the operator-console g
|
||||
- Full history: `docs/GAUGE_COMPOSITE.md`; reticle recovery: `phases/phase-02-dpl2d-reticle.md`.
|
||||
- Uses: [[attribute-pointer]] + [[reconstruction-gotchas]]; reads [[subsystems]] state.
|
||||
- Renders on: [[pod-hardware]] MFD surfaces.
|
||||
|
||||
## #48 MFD ARTIFACTS -- ROOT-CAUSED + FIXED (2026-07-25) [T2 live-convicted]
|
||||
The night-3 "stray blocks + misaligned lamps" on Heat/Mfd/sec: **uninitialized
|
||||
translation-table entries leaking pixels into other displays' bit-planes.**
|
||||
`L4GraphicsPort::translationTable[256]` was never ctor-initialized, and
|
||||
`BuildSecondaryTranslation` fills only the entries its BitWrangler reaches --
|
||||
**2^numberOfBits: 64 for the sec plane (mask 0x3F), 4 for the overlay (0xC0)**
|
||||
-- so entries above that stayed heap garbage. Every draw resolves color
|
||||
through this table, and the pixmap path indexes it with RAW PIXEL VALUES
|
||||
(0..255): the 480x640 radar background carries pixel index 217 -> its garbage
|
||||
entry's high bits (e.g. 0xFF00 = ALL EIGHT MFD planes) were written into the
|
||||
shared 640x480 buffer at that position -- invisible on the culprit page (the
|
||||
in-plane low bits happened dark), visible as bright fragments at the same
|
||||
coordinates on EVERY OTHER display. Convicted empirically with the new
|
||||
**`BT_PLANE_AUDIT`** write-site trap (L4VB16 primitives: a draw whose color
|
||||
carries bits outside its port's plane mask logs primitive/port/position/mask;
|
||||
Or/Xor ignore the mask entirely and And clears foreign planes -- all audited):
|
||||
15-30 leaks/minute in a quiet solo session, `PORT 'sec' ... idx 217
|
||||
entry=0xffffff00 mask=0x3f`, at exactly the artifact positions in the
|
||||
operator's screenshot. FIX: zero the table in the ctor + cycle the in-plane
|
||||
pattern across entries [2^bits..255] (high-index art degrades to its
|
||||
index-mod-2^bits colour IN-PLANE, can never leak). The 1995 binary ships the
|
||||
SAME 64-entry fill and relied on 6-bit art discipline -- garbage is not a
|
||||
preservable behaviour, so the cycle-fill is a guarded PORT deviation.
|
||||
Post-fix: **0 leaks over 60s** on the same probe; sim3 3-pod regression clean.
|
||||
SECOND real defect fixed en route: sessions configure the CAMERA seat first
|
||||
(`cameraInit` -- which builds the MISSION-REVIEW context: `configure(0, sec,
|
||||
0, 0x00FF, native, rgb, mrpal.pcc)`, a DirectColor context whose table holds
|
||||
full RGB565 values), and the swap to the mech re-configured WITHOUT tearing
|
||||
that tree down (the btl4app latch treated the mech build as "first") -- the
|
||||
orphaned review gauges kept executing through stale DirectColor ports.
|
||||
`BTL4GaugeRenderer::ConfigureForModel` now tears down before every rebuild
|
||||
(`ConfigureForModel` made virtual in L4GREND.h). Note the review-screen
|
||||
`PlayerStatus` gauges also read the compiled player at RAW BINARY OFFSETS
|
||||
(+0x1FC vehicle / +0x1C8 score / +0x1C4 alive-dead -- the databinding trap,
|
||||
dormant until review runs); logged in [[open-questions]].
|
||||
Why "it started with the comms feature": the #43 wave registered the new gauge
|
||||
classes (PlayerStatus/pilotList/...) with the config interpreter, which let
|
||||
more of the authored page furniture parse + draw than before -- the leaking
|
||||
high-index pixmaps rode in with that. [T3 for this correlation detail; the
|
||||
leak itself and its fix are T2 live-verified.]
|
||||
|
||||
@@ -247,6 +247,13 @@ register. ⚠ The audit also flags the damage-economy item as SELF-CONTRADICTOR
|
||||
lamps for the aux/eng bezel buttons (LAMP.cpp/L4LAMP.cpp are T0-compiled; the glass panels
|
||||
+ pod RIO both consume `RIO::SetLamp`, so the flash lands on-screen AND on the pod).
|
||||
Decode the type-31 stream format first — it names which conditions flash which lamps.
|
||||
- **PlayerStatus (the mission-review panels) reads the compiled player at RAW BINARY OFFSETS
|
||||
(2026-07-25, found via #48) [T1 code-read].** btl4gau3.cpp `PlayerStatus::Execute`:
|
||||
`player+0x1FC` (vehicle), `+0x1C8` (score, drawn as a numeric), `+0x1C4` (alive/dead -- a
|
||||
state flip draws a 160x240 filled box) -- all 1995 offsets, garbage on our compiled layout
|
||||
(the databinding trap). DORMANT in-game (the review context no longer survives the viewpoint
|
||||
swap -- the #48 teardown fix) but LIVE the moment the mission-review screen actually runs at
|
||||
round end. Bridge all three through btplayer.cpp accessors before enabling the review screen.
|
||||
- **Factory capability-roster loops 2-4 are STILL DEAD (task #57 discovery).** mech.cpp's
|
||||
post-roster loops add to `heatableSubsystems`(0x51155c)/`weaponRoster`(0x511830)/
|
||||
`damageableSubsystems`(0x50e4fc) through the local `SubProxy` stub whose `IsDerivedFrom`
|
||||
|
||||
Reference in New Issue
Block a user