Files
TeslaRel410/restoration/source410/BT/MECH-LAYOUT.md
T
CydandClaude Fable 5 f3668d6dbf Mech milestone: foundational layout analysis + proxy-layer resolution
Begins the Mech reconstruction milestone (analysis phase). Extends the existing
MECH-LAYOUT.md worksheet with the findings needed to build MECH.HPP + the ctor:

- Resolved the BT411 mechrecon.hpp proxy layer to real 1995 types (ReconAlarm ->
  AlarmIndicator, ReconSeq -> SequenceController, ReconFiltered -> AverageOf<
  Scalar>/NameFilter, ReconChain -> ChainOf, ReconMatrix -> AffineMatrix;
  StateIndicator/Reticle survive as-is; BTVal mostly base-class pose fields).
- CRITICAL: AlarmIndicator, SequenceController, NameFilter, AverageOf are ALSO
  absent from the 4.10 archive -- additional helper classes the milestone must
  reconstruct first (their sizes set the embedded-member offsets).
- Subsystem source availability mapped: full (GAUSS/PPC/SENSOR), .TCP partials
  (AMMOBIN/EMITTER/GNRATOR/HEAT/MISSILE/PROJTILE/PROJWEAP), decomp-only (rest).
- Key tractability insight: StateIndicator is fixed-size (level count stored, not
  arrayed), so a FUNCTIONAL fresh build needs only the right member set/types in
  order -- byte-exact offset matching is a later refinement for network wire
  format, not required to boot.
- Revised reconstruction order: helpers -> MechSubsystem+roster -> finalize
  MECH.HPP (probe sizeof==0x854) -> ctor+segment walk -> per-frame path.

Everything below the Mech ctor runs real reconstructed code; the ctor is the
live frontier (spawn factory validated last commit).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:40:43 -05:00

121 lines
7.6 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.
# 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 0x0D00x1C4: playerLink@0x190 ✓, subsystem roster @0x124/0x128 ✓) |
| Mover | 0x300 | (⇒ Mover-own 0x1C40x300: localOrigin@0x260 ✓) |
| **JointedMover** | **0x328** | **⇒ Mech's own region = 0x3280x854 (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 @0x3F80x40C, rearFiring@0x410, missionReview@0x414,
messageManager@0x434, torsoCache@0x438, lastInflictingID@0x43C, damageLookupTable@0x444,
weaponCount@0x448, collisionTemporaryState@0x44C, heatAlarm@0x4500x464, throttleState@0x4A4,
fallDirection@0x4A8, fallScalar@0x4B4(+collisionSpeed), templateBottomLift@0x4B8,
stabilityAlarm@0x4C40x4D8, standing/duckedTemplateMaxY@0x518/0x51C (≡heatLevel/Capacity —
CONFLICT, resolve), gyroSubsystem@0x528, gait caps @0x52C0x548, look angles @0x5640x570,
turn rates @0x574/0x578, jump flags @0x5800x588, motionEventName@0x598, motionEventArmed@0x5A4,
time scales @0x5A80x5B0, hudSubsystem@0x5B4, cycle rates @0x5B80x5C0, gyroRumbleTimer@0x5C4,
footStepRootJoint@0x5C8, animationClips@0x5CC(+namedClip alias @0x5E0, crash clips
@0x5D40x5DC), 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 @0x7680x770,
creationTime@0x778, poseSyncLatch@0x77C, heatLevelSnapshot@0x780, unstable tuning @0x7840x798,
reverseSpeedMax2@0x7A0, heatableSubsystems@0x7AC, weaponRoster@0x7BC, damageableSubsystems@0x7CC,
sensorSubsystem@0x7DC, telemetryFilter@0x7E0, linearSpeed@0x81C, resource names @0x8440x84C,
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) | ❌ MISSING |
| 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 — embedded helper classes are ALSO missing
`AlarmIndicator`, `SequenceController`, `NameFilter`, `AverageOf` do **not** exist anywhere in
the 4.10 CODE archive (confirmed by full-tree grep). They are additional helper classes the
milestone must reconstruct, and their sizes set the embedded-member offsets — so 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,
AverageOf<Scalar> — sizes solved from the offset-spacing equations above; identify BTVal.
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.