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>
41 lines
1.1 KiB
Python
41 lines
1.1 KiB
Python
import sys
|
|
from PIL import Image
|
|
|
|
BOX = (8, 52, 648, 531) # the DOSBox client area = the gauge framebuffer
|
|
SHIPPED = "shipped.png"
|
|
|
|
|
|
def load(p):
|
|
return Image.open(p).convert("RGB").crop(BOX)
|
|
|
|
|
|
def magenta(p):
|
|
return p[0] > 150 and p[2] > 150 and p[1] < 140
|
|
|
|
|
|
def score(path):
|
|
a, b = load(SHIPPED), load(path)
|
|
if a.size != b.size:
|
|
return "%-10s SIZE MISMATCH %s vs %s" % (path, a.size, b.size)
|
|
pa, pb = a.load(), b.load()
|
|
w, h = a.size
|
|
same = lit_ship = lit_both = mag = 0
|
|
for y in range(h):
|
|
for x in range(w):
|
|
s, o = pa[x, y], pb[x, y]
|
|
if s == o:
|
|
same += 1
|
|
if sum(s) > 60:
|
|
lit_ship += 1
|
|
if sum(o) > 60:
|
|
lit_both += 1
|
|
if 0 <= x < 200 and 0 <= y < 60 and magenta(o):
|
|
mag += 1
|
|
n = w * h
|
|
return "%-10s identical %5.1f%% coverage %3d%% title-band magenta %4d" % (
|
|
path, 100.0 * same / n, round(100.0 * lit_both / max(lit_ship, 1)), mag)
|
|
|
|
|
|
for p in sys.argv[1:]:
|
|
print(score(p))
|