vehicleSubSystems: reconstruct the stubbed connection helpers from decomp

Replace the return-0 stubs with the real functions:
- ResolveLink (FUN_00417ab4) = SubsystemConnection::Resolve (two-level deref of the
  plug's bound link); an unbound plug resolves to 0, the authentic no-source branch.
- FindLinkedSubsystem (FUN_0041bf44) = GetAttributePointer(index) via the engine
  Simulation attribute-index system (the cooling-loop master at slot 3).
- IsGeneratorDerived (FUN_0041a1a4) = the real IsDerivedFrom(PoweredSubsystem
  ClassDerivations 0x50f4bc) via a new powersub.cpp bridge BTIsPoweredSubsystem
  (shared with the aux-screen filter) -> the generator stateLamp now builds.

So the cooling/power/voltage connections resolve real data when the plug is bound,
instead of always reading 0.  Build clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-07 07:45:57 -05:00
co-authored by Claude Opus 4.8
parent 8a31abb07d
commit dc6af8cef6
2 changed files with 43 additions and 19 deletions
+35 -16
View File
@@ -124,13 +124,21 @@ static void *AttributePointerOf(void *subsystem, const char *name)
}
//
// FUN_00417ab4 -- follow a SharedData/plug link to the resolved subsystem (voltage
// source / cooling master). The reconstruction stubs this everywhere (see
// emitter.cpp) because the roster plug-binding pass is not yet reconstructed;
// matched here so the cluster connections read the safe "no source" branch
// (*destination = 0) until the plug binding lands. BEST-EFFORT (marked).
// FUN_00417ab4 -- SubsystemConnection::Resolve: follow the plug's bound link to the
// resolved subsystem. The link is `*(plug+8)`; the resolved subsystem is
// `*(link+8)`. An unbound plug (link == 0) resolves to 0 -- the authentic
// behaviour when a subsystem has no attached voltage source / cooling master (the
// connection then reads its "no source" branch, *destination = 0).
//
static void *ResolveLink(void *plug) { (void)plug; return 0; }
static void *ResolveLink(void *plug)
{
if (plug == 0)
return 0;
void *link = *(void **)((char *)plug + 8);
if (link == 0)
return 0;
return *(void **)((char *)link + 8);
}
//
// Bridge (defined in powersub.cpp) that reads the engineering-screen assignment
@@ -143,20 +151,31 @@ static void *ResolveLink(void *plug) { (void)plug; return 0; }
extern bool BTGetSubsystemAuxScreen(Subsystem *sub, int *screen, int *placement, char *label64);
//
// FUN_0041bf44 -- fetch the subsystem linked at slot N (used by the cooling-loop
// lamp to find its cooling master). Stubbed to match ResolveLink above.
// FUN_0041bf44 -- GetAttributePointer(index): a pointer to the subsystem's Nth
// attribute member (the cooling-loop lamp reaches its cooling-master link at
// attribute slot 3), or 0 if the index is out of range. The engine exposes this
// via Simulation::GetAttributePointer(AttributeID); a miss returns &NullAttribute,
// normalised to 0.
//
static void *FindLinkedSubsystem(void *subsystem, int slot) { (void)subsystem; (void)slot; return 0; }
static void *FindLinkedSubsystem(void *subsystem, int slot)
{
if (subsystem == 0)
return 0;
void *p = ((Simulation *)subsystem)->GetAttributePointer((Simulation::AttributeID)slot);
if (p == (void *)&Simulation::NullAttribute)
return 0;
return p;
}
//
// FUN_0041a1a4 IsDerivedFrom(0x50f4bc == Generator's ClassDerivations). Gates the
// SubsystemCluster's generator stateLamp. BEST-EFFORT: the Generator
// ClassDerivations object is owned by the (separately-reconstructed) gnrator TU
// which must not be pulled into this gauge TU (stub-collision, see btl4gaug.hpp),
// so the check is stubbed to False -- the generator-only stateLamp is simply not
// built. Lands with a shared IsDerivedFrom accessor.
// FUN_0041a1a4 IsDerivedFrom(0x50f4bc == PoweredSubsystem's ClassDerivations).
// Gates the SubsystemCluster's generator stateLamp. Every subsystem that reaches
// a SubsystemCluster passed the vehicleSubSystems type filter (BTGetSubsystemAuxScreen
// -> the SAME IsDerivedFrom(PoweredSubsystem) check), so this is always True here;
// the real check is done in powersub.cpp via BTIsPoweredSubsystem for robustness.
//
static Logical IsGeneratorDerived(Subsystem *) { return False; }
extern bool BTIsPoweredSubsystem(Subsystem *sub);
static Logical IsGeneratorDerived(Subsystem *sub) { return BTIsPoweredSubsystem(sub) ? True : False; }
//###########################################################################
+8 -3
View File
@@ -1269,11 +1269,16 @@ Subsystem *CreatePoweredSubsystem(Mech *owner, int id, void *seg)
// non-PoweredSubsystem-derived subsystems (== the FUN_0041a1a4 / 0x50f4bc type
// filter the vehicleSubSystems Make applies before dispatch).
//
// FUN_0041a1a4(sub->classDerivations, 0x50f4bc) -- is the subsystem PoweredSubsystem-
// derived? (The vehicleSubSystems type filter + the generator stateLamp gate.)
bool BTIsPoweredSubsystem(Subsystem *sub)
{
return sub != NULL && sub->IsDerivedFrom(*PoweredSubsystem::GetClassDerivations());
}
bool BTGetSubsystemAuxScreen(Subsystem *sub, int *screen, int *placement, char *label64)
{
if (sub == NULL)
return false;
if (!sub->IsDerivedFrom(*PoweredSubsystem::GetClassDerivations())) // FUN_0041a1a4(...,0x50f4bc)
if (!BTIsPoweredSubsystem(sub)) // FUN_0041a1a4(...,0x50f4bc)
return false;
PoweredSubsystem *ps = (PoweredSubsystem *)sub;
if (screen != NULL) *screen = ps->auxScreenNumber; // +0x104