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>
7.8 KiB
I have completed the adversarial verification against the raw decomp, the CFG, the sibling templates, and the data-binding source files. Every load-bearing claim in the spec was checked. Here is the corrected verdict.
ADVERSARIAL VERIFY — MessageBoard reconstruction spec
Bottom line: the spec is substantially CORRECT and ready-to-implement. All addresses, sizeof, ctor offset writes, the base class, the methodDescription row set, the Make/dtor conventions, and the DEFERRED-data verdict are verified against the binary. The spec's three header corrections are all genuinely correct, and its correction of the task hint (source is BTPlayer status queue, not SubsystemMessageManager 0xBD3) is verified. I found one wrong citation, one fidelity deviation to flag, and two small notes. No blocking errors.
What I verified as CORRECT (accept as-is)
- Identity / addresses (all confirmed
part_014.c): Make@004cb678:3825, ctor@004cb704:3849, dtor@004cb788:3872, TestInstance@004cb7e4:3892→FUN_004448ac, no-op slot@004cb7f4:3903, BecameActive@004cb7fc:3913, SetSource@004cb818:3925, Execute@004cb82c:3936, vtablePTR_FUN_0051bddc(:3858/:3876). Base =GraphicGauge(FUN_00444818), ends at 0x90. - sizeof 0xA4 == Make alloc
FUN_00402298(0xa4)(:3832). ✓ - ctor offset writes (
:3859-3864):[0x25]=stripImage(0x94),[0x26]=color(0x98),[0x24]=trackedMech(0x90)=0;SetOrigin(x,y)vialocalViewvtbl+0x10. ✓ - The three header fixes are all correct:
enabled→Entity *trackedMech: 0x90 is a pointer dereferenced at+0x190(iVar1 = *(*(param_1+0x90)+400),:3950) and written only bySetSource(:3928). It is not a bool. ✓- previousMessageId / previousNameId are SWAPPED in the current header. Binary proof: BecameActive writes
0x9c=-1, 0xa0=-2(:3916-3917); Execute compares messageId vs 0xa0 (:3960) and nameEntity(iVar5) vs 0x9c (:3983). ⇒0x9c=previousNameId(-1),0xa0=previousMessageId(-2)— exactly the spec's relabel, and it matches the prose atbtl4gau3.cpp:784. ✓
- methodDescription rows match the CFG call
messageBoard(E, ModeAlwaysActive, btsmsgs.pcx, 0)atL4GAUGE.CFG:4913-4917under theoffset=(113,607)at:4912→ 4 rowstypeRate/typeModeMask/typeString/typeColor; position threaded from theoffsetdirective; entity param ignored (binary Make never touchesparam_4,:3825-3843). This is exactly the PilotList template (btl4gau3.cpp:218-239), except MessageBoard does useposition(SetOrigin). ✓ - Make presence-check + return is byte-faithful and matches the codebase template
VertTwoPartBar::Make(btl4gaug.cpp:1099-1107:Get(string); if NULL return False; Release; return True).content/GAUGE/BTSMSGS.PCXexists → returns True in practice. ✓ - dtor correctly omits the base-dtor call (
FUN_00444870is compiler epilogue glue,:3880) — avoids the double-dtor bug.FUN_004700acis the string-dup helper used across widgets; freeing viadelete[]/FUN_004022e8is consistent. ✓ - Data-binding blocker — CONFIRMED on both legs:
- SetSource (
FUN_004cb818) has ZERO callers anywhere inreference/decomp/all/(grep returns only its own definition) →trackedMechstays NULL. ✓ StatusMessagePool = 0— the NULL stub is real (btstubs.cpp:62), and the only writer ofBTPlayer+0x1dcis gatedif (sender_owner && StatusMessagePool)(btplayer.cpp:508) → no messages ever created. ✓- Task-hint correction is right:
SubsystemMessageManager(messmgr.cpp) is reconstructed but is the per-mech damage/explosion hub (ConsolidateAndSendDamage/weaponExplosions), not a{msgId,nameEntity}source; MessageBoard never references it.mech+0x190=owningPlayer confirmed (btplayer.cpp:68,MECH_OWNING_PLAYER);DAT_004efc94==application (App+0xc8 name cache,btplayer.cpp:53). ✓
- SetSource (
- Systemic checks: leaf
GraphicGauge(not a container) that overrides both Execute and a non-inactivating BecameActive → Container-Execute/Fail rule satisfied. No shadow/alias/phantom fields (all new slots 0x90–0xA3, ends exactly at 0xA4). Rawmech+0x190/player+0x1dc/+0x1e0/App+0xc8 reads kept out of the widget TU via theBTResolveMessageBoardbridge (databinding trap avoided). Every-mech crash risk: none (early return on NULL)./FORCEstub for the bridge required. ✓
CORRECTIONS (the list of what I changed)
-
[Citation fix — §2, §5, §6]
StatusMessagePool's NULL definition isbtstubs.cpp:62(MemoryBlock *StatusMessagePool = 0;), notbtplayer.cpp:135/508. Those btplayer lines are theexterndecl and the guard site; the actual stub lives inbtstubs.cpp. The conclusion (feed is dead) is unchanged — only name the correct file so the follow-up (wiring the pool) edits the right place. -
[Fidelity deviation — §4.8, must be flagged, not fixed] The Execute name-cell path is a STRUCTURAL simplification, not byte-faithful. The binary stores the previous name ENTITY POINTER at 0x9c and, when the sender changes to "none", looks up that previous entity's name bitmap via its
+0x1e0key and erases it withDrawBitMap(vtbl+0x54,:3992-3996). The spec collapses 0x9c to a booleannameState(0/1) and drops the erase-previous path. While DEFERRED this is functionally identical (nameEntity always 0, previousNameId init −1 → first Execute takes theiVar5==0 && prev==-1clear branch,:3986-3990, matching the binary), so it is safe for the landing. But it changespreviousNameId's semantics from pointer→int, so when the status feed goes live the entity-pointer tracking + erase branch must be restored for correct name repainting. Keep the spec's body for the deferred landing; add a code comment marking this as the restore point. (The spec does acknowledge the deviation; I am raising it to an explicit action item because it silently redefines a member.) -
[Minor note — §1/§4.5] The no-op vtable slot
@004cb7f4("ShowInstance"): the binary override is a barereturn. The spec omits it and inherits (per the PilotList/PlayerStatus precedent). This is only byte-faithful if theGraphicGaugebase slot is itself trivial for this call site; if strict fidelity is wanted, add an empty override. Low risk (leaf widget, slot rarely hit) — accept the omission but note it. -
[No change, confirmation] Make's
boolreturn on a missing bitmap is binary-faithful and template-matched; becauseBTSMSGS.PCXis present it returns True, so registration/parse is unaffected. No action.
Everything else in the spec — the layout table + static_assert locks, ctor/dtor/BecameActive/TestInstance/SetSource/Make bodies, the BTResolveMessageBoard bridge + returns-False stub in btplayer.cpp, the methodDescription literal, and the registration line inserted before &BTL4ChainToPrevious in btl4grnd.cpp (after GeneratorCluster) plus adding static MethodDescription methodDescription; to the class — is verified and should be implemented as written.
FINAL CONFIDENCE: HIGH
- Layout/methods/registration/sizeof/offsets: HIGH — fully recovered and cross-checked against
part_014.c:3823-4013and thePilotList/VertTwoPartBartemplates. - DEFERRED/empty verdict: HIGH — both blockers independently confirmed in-source (
btstubs.cpp:62NULL pool; SetSource zero callers). - Only residual UNKNOWN (non-blocking, for the alive path, not the landing): the exact
Player__StatusMessagerecord layout (+0xcmessageId,+0x10nameEntity) and the App+0xc8 name-bitmap cache shape needed insideBTResolveMessageBoardonceStatusMessagePoolis wired — decodeFUN_0042e580(AddStatusMessage) + the message-record ctorFUN_0042d990to expose them as compiled accessors. The default landing (safe no-op) does not touch these.