All 10 surviving original TUs plus the reconstructed BTL4APP.CPP pilot build clean with the authentic OPT.MAK flags (compile410.sh --sweep). First time the 4.10 BattleTech source has compiled since 1996. - layout_probe.cpp: the period compiler measures 1995 layouts from the surviving headers; validated 3/3 against binary alloc sizes (BTMission 0xFC, BTL4ModeManager 0xC, BTRegistry 0x10). Base boundary: Simulation 0xD0 / Entity 0x1C4 / Mover 0x300 / JointedMover 0x328 => Mech-own region 0x328-0x854 (MECH-LAYOUT.md staging worksheet). - 13 staged headers close the family ([T3] reserved[]-parked layouts; interfaces PROVEN by the surviving consumers): MECH, MECHSUB, HEAT, POWERSUB, MECHWEAP, EMITTER, MECHMPPR, BTPLAYER (BTPlayer__MakeMessage = Player's 8 args + roleName/teamName [T1 via BTREG]), PROJTILE, MISSILE, BTL4MPPR, BTL4VID + the round-2 BTCNSL/BTSCNRL. - compile410.sh: PCH gate retired (bt.hpp/mungal4.hpp full include sets), DPL SDK roots on the include line. - BTL4APP.CPP: appmgr include + GetApplicationManager()->GetFrameRate() + ResourceDescription:: scoping; Fail() held at its recorded line 400. - Evidence ledgers: STAGED-HEADERS.NOTES.md, MECH-LAYOUT.md, BACKFILLS, BTCNSL (binary-recovered console wire IDs), BTSCNRL. Remaining for a linkable BTL4OPT: the ~40 missing TU bodies (917-function manifest) - the header skeleton they grow into now exists and compiles. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4.5 KiB
4.5 KiB
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
- Extend layout_probe.cpp with offsetof checks on public base members to re-attribute the sub-0x328 pose fields to their true base classes.
- Untangle the three offset CONFLICTs above (decomp reads).
- Write the first staged MECH.HPP (interface + mapped runs + reserved[] filler) and compile-verify sizeof(Mech)==0x854 with the probe.