Files
BT412/scratchpad/wf_5_PrepEngr_verify.md
T
arcattackandClaude Opus 4.8 4a4ec6855c gauge-complete P4e: SectorDisplay reconstructed + registered -> radar SECTOR X/Z read-out LIVE
The "sectorDisplay" cockpit primitive (Secondary overlay, the radar SECTOR X/Z
coordinate read-out) was PROSE-ONLY in btl4gau3 (placeholder Make, no ctor/
methodDescription/registration) -> the config line was parse-SKIPPED and never built.

Reconstructed byte-verified from the disassembly (ctor @4c9e10, Execute @4ca07c,
methodDescription PE-parse): SectorDisplay : GraphicGauge, sizeof 0xC4. Its Execute
reads the linked mech's world position and shows two 100-unit sector numerics:
  numericA = Round(-localOrigin.z * 0.01) + 500
  numericB = Round( localOrigin.x * 0.01) + 500
(rounding = round-to-nearest == FUN_004dcd94, corrected from the reviewer's wrong
"truncate" claim; 0.01 const PE-verified; -Z/+X axis + fchs confirmed from asm).
Overridden slots: LinkToEntity(9) caches the subject, BecameActive(3, non-inactivating),
Execute(16) -> satisfies the container-Execute rule. Layout overflow-locked
(static_assert sizeof<=0xC4). Make/ctor/dtor mirror the registered PilotList sibling;
the config image name is copied (nameCopy) since Execute reads it per-frame.
Registered in BTL4MethodDescription[].

VERIFIED LIVE (BT_SECTOR_LOG): Make port=1 pos=(125,579) image=helv15.pcc gridCached=1;
Execute -Z=960.4 X=361.6 -> sectorA=510 sectorB=504 (Round(9.6)+500=510, Round(3.6)+500=504
-- authentic 100-unit sectors from live mech position). Gauge composite renders full,
no crash. The skip list is now exactly the two remaining widgets (prepEngr x12, messageBoard).

Also: a permanent BT_GAUGE_SKIP_LOG diagnostic (GAUGREND.cpp, gated) that logs each
unregistered gauge primitive the dev-parse skips -- the tool that pinned this down
(earlier "not built" runs were killed before the lazy gauge-renderer init).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 21:25:48 -05:00

47 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
I have now verified every load-bearing claim against the raw decomp, the vtable data, the BackgroundBitmap twin, and the established reconstruction templates. Here is my adversarial-verification verdict.
---
# VERIFY VERDICT: PrepEngrScreen spec — **CONFIRMED CORRECT** (with 3 minor strengthenings)
The colleague's spec is **sound and ready-to-implement**. Its three headline corrections to the existing stub are all independently verified. I found no incorrect claim; the changes below are hardening, not fixes.
## Core claims — all VERIFIED against the raw
**(a) Base class / sizeof / ctor offsets — CORRECT**
- Base = `GraphicGaugeBackground`, **confirmed**: PrepEngr's ctor `FUN_004c7bf0` calls base ctor `FUN_004440d4` (part_014.c:1213), and `FUN_004440d4` is the ctor called by `BackgroundBitmap` and its siblings (part_009.c:1633/1695/1758/1838/1956) — the L4GAUGE `GraphicGaugeBackground` leaves. 5-arg base ctor `(mode, renderer, owner, port, id)` matches `GraphicGaugeBackground(ModeMask, GaugeRenderer*, unsigned, int, const char*)` (GAUGE.h:117). The stub's `public Gauge` is **wrong** → change to `GraphicGaugeBackground`.
- sizeof **0x90** = `FUN_00402298(0x90)` (part_014.c:1189). ✓
- ctor field writes: `param_1[0x1b]=param_7`(screen)@0x6C, `param_1[0x1c]=param_6`(mech)@0x70 (part_014.c:1215-1216). **Stub has these two swapped** (btl4gau2.hpp:318-319) → spec's fix is correct.
- ctor param order `(mode, renderer, owner, port, mech, screen, img0..6, id)` matches the Make→ctor call (part_014.c:1191). ✓
**(b) methodDescription rows — CORRECT.** CFG `prepEngr(...)` (L4GAUGE.CFG:4595) has exactly 9 args: `ModeMFD1Eng1, 1, helv42.pcc, escnd.pcc, edmg.pcc, bteslev.pcc, bteunjm.pcc, espeed.pcc, btesrnge.pcc``typeModeMask, typeInteger, 7×typeString`. Global-DAT spacing confirms the parameterList mapping: `sizeof(ParameterDescription)=0x44` (4 + `maxStringLength`=0x40, GAUGREND.h:242-262), and `DAT_0051936c`(screen)=`parameterList[1].data`, `DAT_005193b0`(img0)=`parameterList[2].data.string`, stride 0x44 — exactly the reconstruction's read `p[i].data.{integer,string,modeMask}`. ✓
**(c) Container-Execute rule — CORRECTLY N/A.** `Execute` first appears on `Gauge` (GAUGE.h:366, vtable slot ~14); a `GraphicGaugeBackground` vtable has only 13 slots and no `Execute`. **The overridden slot is BecameActive, not Execute** — proved three ways:
1. PrepEngr vtable (vtables.tsv row `0051a040`, ptr `0051a06c`) = `[4c7d14(dtor), 4173b8, 417938, 4c7e48, 444004…]`**byte-identical shape** to BackgroundBitmap (`004fb918`, ptr `471d7c`) = `[471d7c(dtor), 4173b8, 417938, 471dec, 444004…]`.
2. `BackgroundBitmap` is *explicitly* a `GraphicGaugeBackground` (L4GAUGE.cpp:2443) whose **only non-dtor override is `BecameActive()`** (L4GAUGE.cpp:2511) → its single override slot (3) = BecameActive → PrepEngr's slot 3 (`4c7e48`) = BecameActive.
3. Slots 1/2 are Node virtuals: `FUN_004173b8` = `return 0` = `Node::ReceiveNodeCommand` (node.h:10 inline `{return 0;}`); `FUN_00417938` = `ReleaseLinkHandler` — so slot 3 is the *first GaugeBase virtual* = `BecameActive` (GAUGE.h:52).
`FUN_004c7e48` is a paint-on-activation (walk roster → draw labels into `localView`), semantically a BecameActive, not a per-frame Execute. No container/child-chain exists (ctor builds none; dtor `FUN_004c7d14` only frees 7 images + implicit localView/base dtor) → the abort-on-unoverridden-Execute hazard does not apply. ✓
**(d) shadow/alias/phantom / databinding — CORRECTLY handled.** No shadow/alias/phantom fields. Roster read uses the databinding-safe `Entity::GetSubsystemCount()/GetSubsystem(i)` (ENTITY.h:167-177, reads the reconstructed `subsystemArray/subsystemCount`) + `BTGetSubsystemAuxScreen` — the exact `VehicleSubSystems::Make` pattern (btl4gau2.cpp:1621-1636). NumericDisplay/DrawPortBackground operate on the object's own `localView`/`warehouse`. The two raw-offset reads (`hs+0x1D4`, `sub+0x224`) are correctly guarded fail-soft and flagged (§6).
**(e) every-mech / abort / NULL — no crash risk.** `mech` null-checked; `GetSubsystem(i)` bounded by `i<count` (its internal `Verify(index<subsystemCount)` can't trip); `ResolveLink("HeatSink")` null-guarded before the `+0x1D4` read; the `0x50f4bc` filter + auxScreen check gate every deref. Not an every-mech path (gauge is bound to the viewpoint mech). ✓
## Bonus confirmations (spec was even more right than it claimed)
- **NumericDisplay usage is EXACT, not just "structural."** L4GAUGE.h:22-63 defines `class NumericDisplay` with `NumericDisplay(L4Warehouse*, int x, int y, const char* font, int digits, NumericFormat, int bg, int fg)` and `void Draw(GraphicsView*, Scalar)`. The spec's `NumericDisplay num(warehouse,0xe9,0x176,font,2,unsignedFormat,0,0xff); num.Draw(&localView,(Scalar)screenNumber)` maps **1:1** to the raw `FUN_004700bc(…,0xe9,0x176,font,2,0,0,0xff)` + `FUN_00470430(…)` + dtor `FUN_0047018c` (part_014.c:1310-1313). `Draw` (not `DrawAt`) is the correct method name.
- **`DrawPortBackground(GraphicsView*, L4Warehouse*, int x, int y, const char*)`** = `FUN_004c2ec4` (btl4gau2.cpp:923) — signature matches the spec's calls; the raw's `(x,y,view,warehouse,name)` arg order is correctly reordered by the existing helper.
## Changes I made (3, all hardening)
1. **Make allocation — switch to plain `new PrepEngrScreen(...)`** (drop `operator new(0x90)`+placement-new). The reconstructed `GraphicsView localView` is not byte-exact to the 1995 `0x24..0x6B` window, so `sizeof(PrepEngrScreen)` may exceed 0x90 — a fixed `operator new(0x90)` would then heap-overflow. `new PrepEngrScreen(...)` allocates the true size and matches `BackgroundBitmap::Make` (L4GAUGE.cpp:2379); no external code reads this object at raw offsets, so the binary alloc size is not load-bearing. Keep `static_assert(sizeof(PrepEngrScreen) <= 0x90)` only as a compile-time canary. Optionally add `Register_Object(g);` after construction for parity with BackgroundBitmap (debug leak-tracking only).
2. **§6 #4 UPGRADED from "unknown" to CONFIRMED FAITHFUL.** `BTGetSubsystemAuxScreen` (powersub.cpp:1333) applies `BTIsPoweredSubsystem` = `FUN_0041a1a4(…,0x50f4bc)` — the *exact* filter the raw uses (part_014.c:1308) — and returns `auxScreenNumber` via the real `PoweredSubsystem` type (+0x104 = binary `sub+0x1DC`). So folding the filter + `auxScreen==screenNumber` gate into the bridge is byte-faithful; the qualifying-subsystem set is identical.
3. **Acknowledge the dropped erase in the label block.** The raw does 3 unresolved `localView` vtbl calls (`+0x18/+0x24/+0x48`, args not recovered by Ghidra) *before* the `sub+0x224` label draw (part_014.c:1323-1325) — a cell-erase/setup. The spec drops them and substitutes `SetColor(0xff)` + `DrawPortBackground(label64)`. Cosmetic only; add to the §6 best-effort list next to #1.
## Residual UNKNOWNS (unchanged from spec, all cosmetic, none block registration)
- `sub+0x224` drawn-label ≠ `auxScreenLabel` (`sub+0x1E4`, what the bridge returns) — the label bitmap name may differ; needs a subsystem-ctor field-map pass (`disas2.py`). Guarded/flagged.
- `resolvedHeatSink+0x1D4` (1-digit sink index) is past byte-exact `HeatSink` (0x1D0) → resolved link must be a larger subclass; guarded raw read, best-effort.
- `DrawStatusCells` C-NULL branch `vtbl+0x4c(99,10)` — unresolved GraphicsView slot; plain fill substituted.
## FINAL CONFIDENCE: **HIGH**
Identity, base class, the BecameActive slot, layout, ctor/dtor/Make/BecameActive bodies, the 9-param methodDescription, and the `BTL4MethodDescription[]` registration line are all verified against `part_014.c`, `vtables.tsv`, `L4GAUGE.cpp/h`, `GAUGE.h`, `ENTITY.h`, and `powersub.cpp`. Registering `&PrepEngrScreen::methodDescription` (btl4grnd.cpp, before `&BTL4ChainToPrevious`) + the corrected header (`public GraphicGaugeBackground`, `void BecameActive()`, `screenNumber@0x6C`/`mech@0x70`) + the bodies as written (with change #1) will build and stop the 12 `prepEngr(...)` lines from parse-skipping. The only behavioral caveats are the two flagged cosmetic label reads.