4.10 reconstruction: real spawn factory path -> Mech ctor frontier

BTPlayer::CreatePlayerVehicle reconstructed (faithful; BT411's BT_SPAWN_XZ/
BT_SPAWN_ENEMY bring-up scaffolding dropped): builds the Mech::MakeMessage from
the mission game-model resource and hands it to MakeAndLinkViewpointEntity.
Mech::Make = new Mech(creation_message); a staged Mech ctor chains the real
JointedMover base (so the model skeleton/segments stream from BTL4.RES) then
Fails.

This validates the entire spawn factory chain live: CreatePlayerVehicle ->
MakeAndLinkViewpointEntity -> registry -> Mech::Make -> new Mech -> JointedMover
base ctor (streams the mech model) -> halts at the Mech ctor (mech.cpp:66).

The Mech ctor (@004a1674, 5690 bytes -- the largest function in the game) plus
the subsystem roster is the next MAJOR milestone, not a brick: it needs the full
1995 Mech member layout derived first (MECH.HPP is still reserved[331]; BT411's
decomp uses raw offset pokes that can't compile fresh), the subsystem class
hierarchy (only GAUSS/PPC/SENSOR survive in the 4.10 archive; the rest are the
measured "917 missing functions"), and the segment-table walk. Plan + scope in
MECH.NOTES.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-19 20:33:15 -05:00
co-authored by Claude Fable 5
parent 956fc57681
commit e610a2a3aa
3 changed files with 166 additions and 7 deletions
+74 -4
View File
@@ -39,6 +39,22 @@
# include <dropzone.hpp> # include <dropzone.hpp>
#endif #endif
#if !defined(MECH_HPP)
# include <mech.hpp>
#endif
#if !defined(RESOURCE_HPP)
# include <resource.hpp>
#endif
#if !defined(HOSTMGR_HPP)
# include <hostmgr.hpp>
#endif
#if !defined(MISSION_HPP)
# include <mission.hpp>
#endif
// //
//############################################################################# //#############################################################################
// Shared data support // Shared data support
@@ -278,14 +294,68 @@ void
// //
//############################################################################# //#############################################################################
// Vehicle creation -- pulls in the Mech subsystem (Mech::Make), not yet // CreatePlayerVehicle Build the player's mech from the mission game-model
// reconstructed. This is the current boot frontier. // resource and bind it as the viewpoint entity. (An observer player gets a
// MUNGA camera ship from the base Player::CreatePlayerVehicle instead.)
//
// Constructs the Mech::MakeMessage and hands it to MakeAndLinkViewpointEntity,
// which routes through the registry to Mech::Make -> the Mech ctor (the mech
// subsystem, not yet reconstructed -- current boot frontier).
//############################################################################# //#############################################################################
// //
void void
BTPlayer::CreatePlayerVehicle(Origin) BTPlayer::CreatePlayerVehicle(Origin mech_location)
{ {
Fail("BTPlayer::CreatePlayerVehicle -- btplayer.cpp not yet reconstructed"); Check(this);
Check(application);
ResourceFile *resources = application->GetResourceFile();
Check(resources);
Check_Pointer(playerMission->GetGameModel());
HostManager *host_manager = application->GetHostManager();
Check(host_manager);
//
// Make any MUNGA-level vehicle (a camera ship for an observer player).
//
Player::CreatePlayerVehicle(mech_location);
//
// If the player still has no vehicle, build him a mech and link to it.
//
if (!playerVehicle)
{
ResourceDescription *mech_res =
resources->FindResourceDescription(
playerMission->GetGameModel(),
ResourceDescription::ModelListResourceType
);
Check(mech_res);
mech_res->Lock();
Mech::MakeMessage
create_player(
Mech::MakeMessageID,
sizeof(Mech::MakeMessage),
EntityID(host_manager->GetLocalHostID()),
(Entity::ClassID)MechClassID,
EntityID::Null,
mech_res->resourceID,
Mech::DefaultFlags,
mech_location,
Motion::Identity,
Motion::Identity,
playerMission->GetBadgeName(),
playerMission->GetColorName(),
((BTMission *)playerMission)->GetPatchName()
);
mech_res->Unlock();
playerVehicle = application->MakeAndLinkViewpointEntity(&create_player);
Register_Object(playerVehicle);
}
} }
void void
+24 -3
View File
@@ -43,10 +43,31 @@ Mech::SharedData
//############################################################################# //#############################################################################
// //
Mech* Mech*
Mech::Make(MakeMessage *) Mech::Make(MakeMessage *creation_message)
{
return new Mech(creation_message);
}
//
//#############################################################################
// Mech ctor -- the heart of the entity (walks the model segment table and
// instantiates the full subsystem roster: power, heat, weapons, actuators,
// controls, tech, damage zones). This is the largest single function in the
// game and the current reconstruction frontier; see MECH.NOTES.md. Chains to
// the JointedMover base so the skeleton/segments stream before it Fails.
//#############################################################################
//
Mech::Mech(
MakeMessage *creation_message,
SharedData &shared_data
):
JointedMover(creation_message, shared_data)
{
Fail("Mech::Mech -- mech.cpp not yet reconstructed");
}
Mech::~Mech()
{ {
Fail("Mech::Make -- mech.cpp not yet reconstructed");
return NULL;
} }
void void
+68
View File
@@ -0,0 +1,68 @@
# MECH.CPP / .HPP — reconstruction notes
**Status: `Mech::Make` (factory) reconstructed; the Mech constructor and the
entire mech subsystem are the CURRENT FRONTIER — the largest remaining
milestone in the reconstruction.**
## What is reconstructed
- `Mech::Make(MakeMessage *)` = `return new Mech(creation_message);` — the
factory the registry / `MakeAndLinkViewpointEntity` calls.
- The static shared data (ClassDerivations / DefaultData) — from the earlier
staging.
- A staged Mech ctor that chains the real `JointedMover` base ctor (so the
model skeleton/segments stream from BTL4.RES) and then Fails.
The spawn factory path is now validated live: `BTPlayer::CreatePlayerVehicle`
builds the `Mech::MakeMessage`, `Application::MakeAndLinkViewpointEntity` routes
it through the registry to `Mech::Make` -> `new Mech` -> the JointedMover base
ctor (real engine code, streams the mech model) -> the Mech ctor Fail. Boot
reaches `mech.cpp:66`.
## Why the Mech ctor is a milestone, not a brick
`Mech::Mech` is `@004a1674`, **5690 bytes** — the largest single function in the
game. It walks the model's segment table and instantiates the full subsystem
roster (power, heat, weapons, actuators, controls, tech, damage zones), and
primes ~150 members. Reconstructing it requires three things the tree does not
yet have:
1. **The complete 1995 Mech member layout as named fields.** MECH.HPP currently
carries `int reserved[331]` (1324 bytes) as a placeholder. BT411's Ghidra
reconstruction sidesteps the layout entirely by writing raw offset pokes
(`Wword(0x104)`, `*(void**)((char*)this + 0x388)`, `this[0x14a]`) — a
WinTesla-port technique that CANNOT compile into a fresh 1995 build, where
BC4.52 assigns offsets from the header declarations. So the layout must be
derived as real members first.
2. **The subsystem class hierarchy.** MechSubsystem + derived: sensor, generator
(gnrator), gyro, torso, HUD, myomers, plus the weapon subsystems (mechweap,
ppc, gauss, projweap, mislanch, ammobin...). Of these, only GAUSS, PPC,
SENSOR survive as source in the 4.10 archive (CODE/BT/BT); GNRATOR is a
partial .TCP. The rest are part of the measured "917 missing functions" and
come only from BT411's decomp.
3. **The segment-table walk** that reads the model resource and instantiates +
wires each subsystem.
BT411's mech reconstruction is ~12,255 lines across mech.cpp / mech2 / mech3 /
mech4 / mechsub alone, before the subsystem TUs — this is the bulk of the
remaining game.
## Reconstruction plan (for the dedicated mech milestone)
1. **Derive the Mech member layout.** Turn `reserved[331]` into named members.
Sources: BT411's offset comments (`this[0x14a]` gyroSubsystem, `+0x388`
target entity, etc.) give the binary offsets; the embedded member types
(NameFilter, AlarmIndicator, Slot/Socket, Reticle, Filter, CString,
StateIndicator) come from the surviving MUNGA headers. Cross-check total size
against the binary's `new Mech` allocation.
2. **Reconstruct MechSubsystem base + the subsystem roster**, backdating BT411
mechsub.cpp + the per-subsystem TUs; fold in the surviving 4.10 GAUSS/PPC/
SENSOR source where it exists (authoritative over the decomp).
3. **Reconstruct the Mech ctor** against the named layout: embedded-member
construction, the segment-table walk, subsystem instantiation + wiring.
4. Then the per-frame path (mech2 animation SM, mech3, mech4 locomotion/
targeting) and the damage/weapon handlers.
Until then the ctor Fails cleanly at the frontier; everything below it (engine,
app, network, mission, player, factory, jointed-mover base) runs real
reconstructed code.