From 5a465c2321f89ad9b24dd6362f62dde940d22b45 Mon Sep 17 00:00:00 2001 From: Cyd Date: Thu, 30 Jul 2026 08:03:00 -0500 Subject: [PATCH] BT410 5.3.85: the six-bit hazard surveyed -- draw site named, 94 art files inventoried, a 1996 config typo found Follow-up survey to 5.3.84, written into L4GREND.NOTES.md rather than left as conversation. THE DRAW SITE, NAMED. This closes a question that had been open across several sessions ("which of the three DrawBitMapOpaque sites draws sentinel-bearing sec art"). Answer: none of them. It is a DrawPixelMap8 -- BTL4GAU2.CPP:1524, the bgPixelMap widget, MoveToAbsolute(0,0) then a full-image OPAQUE blit. BT_VIS_LOG places it at port=0, the six-bit head. Every pixel of the colour head's background therefore goes through the 64-entry translation table, sentinels included. ALSO PROVEN: no drawing operation contains the damage. The opaque inner loop's Replace case is *dest = (Word)((*dest & bitmask) | color); which clears THIS port's bits and then ORs the whole table entry back -- including garbage in other ports' bit positions. Replace leaks exactly like Or does. ART INVENTORY. Swept all 428 PCX/PCC under GAUGE (which is all the art there is -- nothing lives outside it). 94 carry pixels > 63: index 231 in 53 files (sparse, 4-7%, the 172x217 avatar CRIT/HEAT silhouettes), 255 in 27 (the *HT heat backgrounds), 226/228/229 as 1-2px specks in QJAK*, and 254 in 2. BTSEC1.PCX is the only one whose out-of-range region is a SOLID RECTANGLE and the only one proven to reach the screen -- 676px at (199,526)-(250,538), rotation 270 mapping screen = (src_y, 479 - src_x), landing exactly on the measured mask. WHAT IS STILL OPEN, recorded as open rather than smoothed over: The 354px cluster. Of the provoke control's 1030 lit pixels, 676 are the bar; the remaining 33x32 cluster at (67,3)-(99,34) is NOT file-borne -- no gauge file has a count near 354. So it is generated at runtime. The obvious suspect CreateMutantPixelmap8 is ruled out: it is an inert stub returning NULL, so recoloredMech never blits here. Unattributed; the fix covers it regardless. A possible second exposure, in-mission. L4GAUGE.CFG carries 1345 colour-mapper entries (656 cmCrit, 662 cmHeat, 27 cmArmor), BT_VIS_LOG puts ALL of them on port 0, and their mode is ModeSecondaryCritical. They name adpal/adpal2/heatpal, three of which the sweep flags -- ADPAL and ADPAL2 are 2x5 and ENTIRELY index 99. Whether that matters turns on whether a mapper blits those pixels or merely reads their VGA palette, which nobody has checked. Written down as a hypothesis with that caveat attached, NOT as a finding. If the pixels are used as indices it would dwarf the bar and would fire in-mission, which is where the operator sees the artifact. The boot cockpit lighting only 1030 pixels says the avatar/mapper art is not drawn on THAT screen. It says nothing about a live mission. A SHIPPED DATA BUG, found in passing and deliberately NOT fixed: L4GAUGE.CFG:2513-2514 name adpa12.pcc -- digit one for lowercase L. The file does not exist; adpal2.pcc does. Two of 1345 lines, so the GAUSS and AFC25 ammo-bin criticals have been loading a missing palette since 1996. It is the original's bug and the shipped binary lives with it; the archive is sacred, so we live with it too. Noted so the next person who sees a warning about adpa12.pcc does not go hunting for a reconstruction defect. Co-Authored-By: Claude Fable 5 --- .../source410/MUNGA_L4/L4GREND.NOTES.md | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 restoration/source410/MUNGA_L4/L4GREND.NOTES.md diff --git a/restoration/source410/MUNGA_L4/L4GREND.NOTES.md b/restoration/source410/MUNGA_L4/L4GREND.NOTES.md new file mode 100644 index 00000000..2e159476 --- /dev/null +++ b/restoration/source410/MUNGA_L4/L4GREND.NOTES.md @@ -0,0 +1,118 @@ +# L4GREND.CPP — reconstruction shadow notes + +The shadow exists for ONE reason: to construct a `BTL4GraphicsPort` instead of +an `L4GraphicsPort`, so the colour head's uninitialised translation-table tail +gets zeroed. Everything else in the file is the archive's, verbatim. + +The mechanism, the proof, and the honest verification status live in the file's +own header comment. This sidecar carries the survey work that did not belong in +a source comment. + +## The hazard, in one line + +The colour head is **six bits** (`sec`, mask `0x003F`, `L4GAUGE.CFG`), so +`BuildSecondaryTranslation` (`L4VB16.CPP:5419`) fills only `1< 63` reads +uninitialised memory, and `DrawPixelMap8` ORs the result into the shared +plane-packed framebuffer **unmasked**. + +Worth noting that even `Replace` leaks. The opaque inner loop is + +```c +color = (Word) translation_table[source_data]; +case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); +``` + +`& bitmask` clears *this* port's bits, then `| color` ORs the whole table entry +back — including whatever garbage sits in other ports' bit positions. There is +no drawing operation that contains the damage. + +## The draw site — answers a long-open question + +`restoration/source410/BT_L4/BTL4GAU2.CPP:1524`, the `bgPixelMap` widget: + +```c +localView.MoveToAbsolute(0, 0); +localView.DrawPixelMap8(True, 0, bg, 0, 0, // opaque, full image + bg->Data.Size.x - 1, bg->Data.Size.y - 1); +``` + +`BT_VIS_LOG` places it at `[w] bgPixelMap port=0 at 0,0` — port 0 is `sec`. +Full-image, opaque, on the six-bit head: every pixel of the background goes +through the table, sentinels included. Of the three `DrawBitMapOpaque` sites +that were under suspicion, none is the culprit; this `DrawPixelMap8` is. + +## Art inventory — 94 of 428 gauge files carry out-of-range pixels + +Swept every `.PCX`/`.PCC` under `ALPHA_1/REL410/BT/GAUGE` (all the art there is +— nothing lives outside that directory). Distinct out-of-range values: + +| index | files | shape | reading | +|---|---|---|---| +| 231 | 53 | sparse, ~4–7%, in a mech-silhouette region of 172×217 `*CRIT`/`*HEAT` art | avatar damage/heat art | +| 255 | 27 | sparse, ~5–7%, `*HT` art (252×200, 229×199, 303×200) | heat backgrounds | +| 254 | 2 | **solid 52×13 rect** in `BTSEC1.PCX` | the confirmed offender | +| 226/228/229 | 8/8/7 | 1–2px specks in `QJAK*.PCC` | paint spatter, harmless | +| 99 | 2 | `ADPAL.PCC`, `ADPAL2.PCC` — 2×5, **100%** at 99 | palette swatches, see below | +| 100 | 1 | `HEATPAL.PCC` — 3×3, one pixel | ditto | +| 120, 127 | 1 each | | | + +`BTSEC1.PCX` — "BT SEC-ondary", the colour head's own background — is the only +one whose out-of-range region is a **solid rectangle**, and the only one proven +to reach the screen: 676 pixels of index 254 at source (199,526)-(250,538), +which the port's **rotation 270** maps to screen (526,228)-(538,279) via +`screen = (src_y, 479 - src_x)`. The provoke mask measured exactly that box. + +## What is NOT yet resolved + +**The 354px cluster.** The provoke control lights 1030 pixels on the boot +cockpit: 676 for the bar, and a 33×32 cluster at screen (67,3)-(99,34) that is +*not* file-borne — no gauge file has an out-of-range count anywhere near 354, +and all art lives in that one directory. It is therefore generated at runtime. +The obvious suspect, `CreateMutantPixelmap8` (`BTL4GAU3.CPP:1067`), is ruled +out: it is an inert stub returning NULL, so `recoloredMech` never blits in our +build. Unattributed. The fix covers it either way, since it zeroes the whole +tail regardless of who indexes it. + +**The colour mappers may be a second exposure, in-mission.** `L4GAUGE.CFG` +carries **1345** colour-mapper entries — 656 `cmCrit`, 662 `cmHeat`, 27 +`cmArmor` — and `BT_VIS_LOG` puts all of them on **port 0**, the six-bit head, +at 50,0. Their mode is literally `ModeSecondaryCritical`. They name +`adpal.pcc`, `adpal2.pcc`, `heatpal.pcc`, `heatpal2.pcc`, three of which the +sweep flags as out-of-range (`ADPAL`/`ADPAL2` are 2×5 and **entirely** index +99; `HEATPAL` has one pixel at 100). + +Whether that matters depends on something not yet established: these are tiny +swatch files, and a colour mapper plausibly reads their **VGA palette** rather +than blitting their pixels. Do not repeat this as a finding until someone has +read the mapper's implementation. It is recorded because if the pixels *are* +used as colour indices, every one of 1345 mappers writes an out-of-range index +on the six-bit head — which would dwarf the 676px bar and would fire +in-mission, matching where the operator sees the artifact. + +That the boot cockpit lights only 1030 pixels says the avatar/mapper art is not +being drawn on that screen. It does not say anything about a live mission. + +## A shipped data bug, found in passing — do NOT fix + +``` +L4GAUGE.CFG:2513: cmCrit(I,ModeSecondaryCritical,56,adpal.pcc,adpa12.pcc,AmmoBinGAUSS); +L4GAUGE.CFG:2514: cmCrit(J,ModeSecondaryCritical,57,adpal.pcc,adpa12.pcc,AmmoBinAFC25); +``` + +`adpa12.pcc` — digit one for lowercase L — does not exist. `adpal2.pcc` does. +Two of 1345 lines, so the GAUSS and AFC25 ammo-bin criticals have been loading +a missing palette since 1996. This is the original's bug, present in the +shipped config; the archive is sacred and the shipped binary lives with it, so +we live with it too. Noted only so the next person who sees a warning about +`adpa12.pcc` does not go hunting for a reconstruction defect. + +## Method note + +Zero is the right fix precisely because it is invisible — and that is what made +it unverifiable. The `BT_TRANS_PROVOKE` positive control (fill the tail with +`0xFF00` instead) is what turned "I cannot see a difference" into "1030 pixels, +here they are, here is the shape". See `emulator/render-bridge/gauge-ab/README.md` +for the rig, `oormask.py` for the mask, and the caution about within-boot vs +across-boot noise floors that nearly cost this fix.