diff --git a/context/reconstruction-gotchas.md b/context/reconstruction-gotchas.md index 3755196..316631a 100644 --- a/context/reconstruction-gotchas.md +++ b/context/reconstruction-gotchas.md @@ -795,3 +795,37 @@ grep its helper types for `return 0` bodies FIRST; (b) a bring-up shim must either Fail() loudly or log its own emptiness, never silently iterate nothing; (c) before shimming an engine-side structure, check whether the engine already has it -- the offsets in the decomp comment ARE the lookup key. + +## 27. Drawing where the design says DON'T: under-surface buttons, shared planes, and inherited D3D state (#118, 2026-08-03) + +Three MFD-corruption incidents in one evening, all mine, all the same class: +adding a DRAW to a compositor whose layout invariants I had not read. + +1. **The eject-wipe gauge** (BitMapInverseWipeScalar) drew into a weapon's ENG + graphics port -- but the Eng1-3 planes SHARE composite dest cells with the + weapon pages (`ckSlotOf` in L4VB16), so its mis-geometry scribbled striped + garbage OVER the weapon MFDs whenever an eject cycle redrew it (= at + overheat-jam onset, which the operator correctly correlated with "when the + coolant warning starts"). +2. **The "flash overlay"** re-drew flashing buttons' full faces ON TOP of the + surfaces. But the side buttons are BIG rects deliberately tucked UNDER the + displays -- the protruding edge IS the lamp (the pod's backlit keys sat + beside the CRT; there is no in-display face). A full-face redraw is wrong + BY DESIGN: it covers gauge imagery with button faces. +3. **The same overlay, drawn after `DrawDevSurface`, inherited its bound + texture** -- an un-reset `CkFill` renders a TEXTURED quad sampling the + gauge atlas: green diagonal-striped rectangles. (With the state reset the + bug became honest: solid flashing faces covering the MFD -- which is how + the operator's "the panel buttons took over the MFD" report finally + identified the author.) + +Rules: (a) before ADDING a draw to an existing render pass, read the pass's +layering comments -- "UNDER the surfaces", "masks the part inside", "shares +its sibling's dest cell" are INVARIANTS, not descriptions; (b) any D3D draw +inserted after another subsystem's draws must re-assert its own texture/color +state (CkColorState-equivalent) -- the previous draw's bindings are live; +(c) when a visual corruption tracks an EVENT ("starts with the coolant +warning"), list what STARTS DRAWING at that event -- alarm-driven redraws, +state-change repaints -- before suspecting the event's logic; (d) the +operator's screenshot is worth ten theories: the red-faces capture identified +in one frame what three log-side hypotheses missed.