Playtester DOS-binary comparison: our radar showed blank SECTOR:/SCALE: values.
Root cause [T1]: the secondary CRT's low byte is authored as TWO ports
(L4GAUGE.CFG:4395-4396) -- sec (0x3F, btspal) + overlay (0xC0, btopal,
TransparentZero) carrying the btsec1ov graticule, the SCALE numeral
(RadarRange) and the SECTOR numerals (sectorDisplay). Both numeral writers
are reconstructed and RUN -- their pixels were in the shared buffer's 0xC0
bits all along -- but every desktop expand indexed the LUT with pixel & 0x3F,
stripping them. The arcade DAC indexed the FULL low byte.
Key mechanism: clut0 ALREADY holds the DAC's combined 256-entry table --
BuildSecondaryPalette (AllChannels, sec) fills all 256 indices and the
overlay's TransparentZero pass overwrites groups 0x40/0x80/0xC0 -- so the
composite is exactly a mask change, no blending code:
- BTSecCompositeMask(): sec->GetBitMask() | overlay's (NULL-guarded, same
display), used by BTDrawGaugeSurfaces + BTDrawCockpitPanels (surround),
SVGA16::Update case 0 (pod parity), and the glass BlitSurface palette
expand.
- GlassWindowToken: the palette-expanded radar window's dirty token now
includes the overlay port -- the SECTOR numerals tick on that plane, and
a pixel-only 0x3F token would never repaint them.
The overlay's ColorMapper re-stomp over combined indexes is authentic (the
shipped machine ran the identical palette code) and is left alone.
Verified live (glass panels): SECTOR: 497.503 ticking with movement,
SCALE: 1000 at spawn (radarRange init 250*2^2 -- the DOS reference's 4000 is
max zoom, not a delta), and the btsec1ov graticule rules now draw. KB:
GAUGE_COMPOSITE row 28 + polish list updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>