NameFilter is the Mech's mechNameFilter (@0x36c), a small fixed debounce record the ctor initialises. Reconstructed from FUN_00435a7c: a 10-word (0x28) struct, Initialize() sets [2]=1 / [8]=[9]=-1 / rest 0 exactly. Header-only. Field semantics unresolved (only caller is Initialize; reader is the unbuilt HUD) -- names best-effort, but size + init values are binary-exact, which is all the Mech layout + ctor need. All 3 missing embedded helper classes now reconstructed + compile-verified under BC4.52 (AlarmIndicator, SequenceController struct+Init, NameFilter). MECH-LAYOUT.md step 1 marked done. Next: MechSubsystem base + the subsystem roster, then finalize MECH.HPP (probe sizeof==0x854), then the ctor + segment-table walk. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
128 lines
8.1 KiB
Markdown
128 lines
8.1 KiB
Markdown
# MECH.HPP staging worksheet (opened 2026-07-19)
|
||
|
||
The working ledger for growing the literal MECH.HPP alongside the mech-family TU
|
||
reconstructions. **The period compiler is the layout authority**: `../layout_probe.cpp`
|
||
compiled+run under BC4.52 with the authentic OPT.MAK flags (`-a4` alignment) measures the
|
||
1995 base-class sizes from the SURVIVING engine headers.
|
||
|
||
## Probe results (2026-07-19) — methodology VALIDATED 3/3
|
||
|
||
| class | sizeof | validation |
|
||
|---|---|---|
|
||
| Simulation | 0x0D0 | |
|
||
| Entity | 0x1C4 | (⇒ Entity-own fields span 0x0D0–0x1C4: playerLink@0x190 ✓, subsystem roster @0x124/0x128 ✓) |
|
||
| Mover | 0x300 | (⇒ Mover-own 0x1C4–0x300: localOrigin@0x260 ✓) |
|
||
| **JointedMover** | **0x328** | **⇒ Mech's own region = 0x328–0x854 (0x52C bytes)** |
|
||
| Mission | 0x0E4 | BTMission's experienceLevel @+0xE4 = first BT member ✓ |
|
||
| BTMission | 0x0FC | **== the binary's `new(0xfc)`** (BTL4Mission alloc) ✓ |
|
||
| ModeManager / BTL4ModeManager | 0x00C | **== the binary's `new(0xc)`** ✓ |
|
||
| BTRegistry | 0x010 | **== the binary's `new(0x10)`** ✓ |
|
||
|
||
Three independent allocation-size matches against the shipped binary ⇒ headers + compiler +
|
||
flags reproduce 1995 layout exactly. Any future header where the probe disagrees with a
|
||
binary alloc size is WRONG and must be fixed before use.
|
||
|
||
## Consequences for MECH.HPP staging
|
||
|
||
- Every binary offset **< 0x328 is a BASE-CLASS field**, not a Mech member. The port's
|
||
mech.hpp declares several pose members in that range (orientation@0xD0, bodyRotation@0x100,
|
||
turretBase@0x1C4, headPitch@0x1CC, torsoTwist@0x1DC, legAngle@0x1F4, hipAngle@0x200,
|
||
torsoAim*@0x298/0x2C8, netOrientation@0x2D4) — in the 1995 header these belong to
|
||
Simulation/Entity/Mover/JointedMover (or their equivalents) and must be RE-ATTRIBUTED by
|
||
checking the surviving engine headers' member lists at those offsets (probe with offsetof
|
||
where members are public).
|
||
- Mech-own members with binary offsets ≥ 0x328 (from the port/CLASSMAP, to be laid out with
|
||
`reserved[]` filler between mapped runs): reduceButton@0x340, forwardCycleRate@0x344,
|
||
legCycleSpeed@0x348, reverseStrideLength@0x34C, gimpStrideLength@0x350, mechName@0x360,
|
||
masterAlarm@0x39C(+legStateAlarm), legAnimationState@0x3B0, unstablePercentage@0x3F0,
|
||
airborne@0x3F4, radar block @0x3F8–0x40C, rearFiring@0x410, missionReview@0x414,
|
||
messageManager@0x434, torsoCache@0x438, lastInflictingID@0x43C, damageLookupTable@0x444,
|
||
weaponCount@0x448, collisionTemporaryState@0x44C, heatAlarm@0x450–0x464, throttleState@0x4A4,
|
||
fallDirection@0x4A8, fallScalar@0x4B4(+collisionSpeed), templateBottomLift@0x4B8,
|
||
stabilityAlarm@0x4C4–0x4D8, standing/duckedTemplateMaxY@0x518/0x51C (≡heatLevel/Capacity —
|
||
CONFLICT, resolve), gyroSubsystem@0x528, gait caps @0x52C–0x548, look angles @0x564–0x570,
|
||
turn rates @0x574/0x578, jump flags @0x580–0x588, motionEventName@0x598, motionEventArmed@0x5A4,
|
||
time scales @0x5A8–0x5B0, hudSubsystem@0x5B4, cycle rates @0x5B8–0x5C0, gyroRumbleTimer@0x5C4,
|
||
footStepRootJoint@0x5C8, animationClips@0x5CC(+namedClip alias @0x5E0, crash clips
|
||
@0x5D4–0x5DC), gimpBaseClip@0x64C, deathAnimationLatched@0x650, leg/bodyResetLatch@0x654/0x658,
|
||
legAnimation@0x65C, controllableSubsystems@0x65C(CONFLICT — one is a chain @0x65C, resolve),
|
||
bodyTargetSpeed@0x6B4, bodyCycleSpeed@0x6B8, bodyAnimation@0x6BC(≡watchedSubsystems CONFLICT),
|
||
statusAlarm/bodyStateAlarm@0x714, bodyAnimationState@0x728, deadband block @0x768–0x770,
|
||
creationTime@0x778, poseSyncLatch@0x77C, heatLevelSnapshot@0x780, unstable tuning @0x784–0x798,
|
||
reverseSpeedMax2@0x7A0, heatableSubsystems@0x7AC, weaponRoster@0x7BC, damageableSubsystems@0x7CC,
|
||
sensorSubsystem@0x7DC, telemetryFilter@0x7E0, linearSpeed@0x81C, resource names @0x844–0x84C,
|
||
deathHandler@0x850, end 0x854.
|
||
- The flagged CONFLICTs are port-side double-attributions to untangle against the decomp
|
||
before the first staged MECH.HPP is written.
|
||
- Real 1995 types to substitute for the port proxies: ReconChain→`ChainOf<Subsystem*>`? /
|
||
AlarmIndicator→the engine alarm type / ReconSeq→the SequenceController analog / BTVal→per
|
||
case — settle each against the surviving engine headers + sizes via the probe.
|
||
|
||
## Next actions
|
||
1. Extend layout_probe.cpp with offsetof checks on public base members to re-attribute the
|
||
sub-0x328 pose fields to their true base classes.
|
||
2. Untangle the three offset CONFLICTs above (decomp reads).
|
||
3. Write the first staged MECH.HPP (interface + mapped runs + reserved[] filler) and
|
||
compile-verify sizeof(Mech)==0x854 with the probe.
|
||
|
||
---
|
||
|
||
## ADDENDUM 2026-07-19 (later) — spawn factory reached the Mech ctor; proxy layer resolved
|
||
|
||
The boot ladder now runs the full spawn factory (CreatePlayerVehicle -> Mech::MakeMessage ->
|
||
MakeAndLinkViewpointEntity -> registry -> Mech::Make -> `new Mech` -> JointedMover base
|
||
streams the model) and halts at the Mech ctor. So the ctor is the live frontier and this
|
||
worksheet is the active blocker.
|
||
|
||
### Proxy layer resolved (BT411 mechrecon.hpp -> real 1995 types)
|
||
|
||
Settles the open item in the "Real 1995 types" bullet above:
|
||
|
||
| BT411 alias | real type | in 4.10 archive? |
|
||
|---|---|---|
|
||
| ReconAlarm (AlarmIndicator) | AlarmIndicator (multi-level, N levels sets size) | ❌ MISSING |
|
||
| ReconSeq | SequenceController (animation sequence) | ❌ MISSING |
|
||
| ReconFiltered / FilteredScalar | **AverageOf<Scalar>** (15-sample running avg) | ✅ AVERAGE.HPP |
|
||
| ReconFiltered (mechNameFilter) | NameFilter | ❌ MISSING |
|
||
| ReconChain<Subsystem*> | ChainOf<Subsystem*> | ✅ CHAIN.HPP |
|
||
| ReconMatrix / Matrix34 | AffineMatrix / Matrix | ✅ |
|
||
| StateIndicator | StateIndicator | ✅ STATE.HPP |
|
||
| Reticle | Reticle | ✅ RETICLE.HPP |
|
||
| BTVal (turretBase, mechName, torsoAim*, aimRate, headPitch, torsoTwist) | animated value/quaternion — **UNIDENTIFIED**; BT411 BTVal is a no-op placeholder. Most BTVal members are < 0x328 = BASE-class pose fields (re-attribute per §"Consequences"), so their type is a base concern, not Mech's. |
|
||
|
||
### CRITICAL new finding — 3 embedded helper classes are missing
|
||
|
||
`AlarmIndicator`, `SequenceController`, `NameFilter` do **not** exist anywhere in the 4.10
|
||
CODE archive (confirmed by full-tree grep; no *alarm*/*filter*/*sequen* headers either).
|
||
They are additional helper classes the milestone must reconstruct from BT411's decomp, and
|
||
their sizes set the embedded-member offsets. (`AverageOf` was initially flagged missing but
|
||
DOES survive — AVERAGE.HPP, same SIGNATURED lineage BT411 preserved — so telemetryFilter[5]'s
|
||
type is available.) The alarm sizing: the
|
||
`masterAlarm@0x39C`/`heatAlarm@0x450`/`stabilityAlarm@0x4C4`/`statusAlarm@0x714` spacing
|
||
DERIVES the AlarmIndicator per-level size (e.g. masterAlarm 33 levels spans 0x39C..0x450 =
|
||
0xB4; heatAlarm 3 levels spans 0x450..0x4C4 = 0x74 — a fixed header + N-level array; solve
|
||
the two equations for header size + per-level stride). Same method sizes AverageOf from
|
||
telemetryFilter[5]@0x7E0..0x81C (0x3C/5 = 0xC each) and SequenceController from the
|
||
legAnimation/bodyAnimation spacing.
|
||
|
||
### Subsystem roster source availability (VDATA 0xBxx ClassIDs)
|
||
|
||
- Full .CPP/.HPP in 4.10: **GAUSS, PPC, SENSOR**
|
||
- .TCP partial survivors (authoritative where present): **AMMOBIN, EMITTER, GNRATOR, HEAT,
|
||
MISSILE, PROJTILE, PROJWEAP**
|
||
- Decomp-only (BT411): MechSubsystem base, gyro, torso, hud, myomers, mechweap, mislanch,
|
||
powersub, + the rest of the "917 missing functions".
|
||
|
||
### Revised reconstruction order
|
||
|
||
1. ~~**Helper classes** (block the layout): AlarmIndicator, SequenceController, NameFilter~~
|
||
**DONE 2026-07-19** — all 3 reconstructed + compile-verified under BC4.52:
|
||
MUNGA/ALARM.HPP (AlarmIndicator = StateIndicator subclass, header-only),
|
||
BT/SEQCTL.HPP+CPP (SequenceController struct + Init real; gait methods staged),
|
||
BT/NAMEFILT.HPP (NameFilter struct + Initialize, header-only). AverageOf survives.
|
||
BTVal is mostly base-class pose fields (re-attribute during layout, not Mech's).
|
||
2. **MechSubsystem base + roster** (GAUSS/PPC/SENSOR + .TCP partials + decomp).
|
||
3. **Finalize MECH.HPP** per the offset map; probe sizeof(Mech)==0x854.
|
||
4. **Mech ctor** (@004a1674): embedded construction + segment-table walk.
|
||
5. Per-frame path (mech2/3/4) + damage/weapon handlers.
|