BT410 5.3.43: full pod rig -- geometry loads, ladder advances to the audio watchers
Under the documented rig (launch_pod.ps1 with the GL bridge up) the 'couldn't load object' count went to ZERO. .BGF loading was never a reconstruction problem, only a missing bridge. What blocks now is a series of authored AttributeWatchers: BTL4.RES binds them BY NAME and the engine Fails outright on any that does not resolve, so each is a name our subsystems must publish. Five rungs climbed, each run-verified: UnstablePercentage, SpeedEffect (Myomers table), AnimationState + CollisionState/CollisionNormal + ReduceButton (Mech), and the full Torso table (all six authentic names mapped onto existing members). The method that makes this cheap is banked: the shipped binary's string pool carries each class's attribute names CONTIGUOUSLY in ID ORDER after the class name, and in every case so far our member declarations sit in the same order -- which confirms the layout and lets ids be pinned rather than guessed. Intersecting those names with BTL4.RES gives the exact work list. A THIRD miswired SharedData found on the way: Myomers carried Subsystem's tables where it derives from PoweredSubsystem, the same defect as MissileLauncher (5.3.33). Worth a sweep across every subsystem. Staged member TYPES are provisional and documented as such: AttributeWatcherOf reads *(T*)attributePointer and the instantiation comes from the resource, which the string pool does not reveal. Nothing drives them yet, so settle the types with the models that write them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
[sdl]
|
||||
output=opengl
|
||||
# higher,higher not highest: HIGH_PRIORITY_CLASS starved the host desktop;
|
||||
# with the retry patches a rare dropout self-recovers (see gauge_rio.conf).
|
||||
priority=higher,higher
|
||||
[dosbox]
|
||||
memsize=32
|
||||
machine=svga_s3
|
||||
[cpu]
|
||||
core=dynamic
|
||||
cputype=pentium
|
||||
cycles=max
|
||||
[sblaster]
|
||||
sbtype=sb16
|
||||
sbbase=220
|
||||
irq=5
|
||||
dma=1
|
||||
hdma=5
|
||||
[mixer]
|
||||
# match the EMU8000s' native rate (no resample) and buffer ~60ms so brief
|
||||
# emulation-thread stalls (RIO retry recovery) don't audibly chop
|
||||
rate=44100
|
||||
blocksize=1024
|
||||
prebuffer=60
|
||||
[serial]
|
||||
# RIO on COM1 with the low-latency options (rxpollus/rxburst) so the board's
|
||||
# few-ms ACK deadline is met; plasma display on COM2 (real pod has both).
|
||||
# VWE fork namedpipe backend (com0com/realport retired -- COM1/COM2 gone):
|
||||
# DOSBox = pipe client (retry), vRIO/vPLASMA apps = servers; an unconnected
|
||||
# pipe behaves as an unplugged cable so the mission still runs. serialnamedpipe.h
|
||||
serial1=namedpipe pipe:vrio rxpollus:100 rxburst:16
|
||||
serial2=namedpipe pipe:vplasma
|
||||
[autoexec]
|
||||
mount c "C:\VWE\TeslaRel410\ALPHA_1"
|
||||
c:
|
||||
cd \REL410\BT
|
||||
set VIDEOFORMAT=svga
|
||||
rem production pod card init (PARAMETR.BAT:181-186): DIAGNOSE + AWEUTIL per
|
||||
rem card -- AWEUTIL /S does the EMU8000 bring-up and DRAM detect the HMI SOS
|
||||
rem driver relies on; skipping it left the cards uninitialized (silent).
|
||||
rem aweutil /s SKIPPED for now: it verifies the AWE32 GM ROM, which the
|
||||
rem emulated cards lack (hangs in a retry loop) -- restore once the ROM is
|
||||
rem dumped from a real card. diagnose /s kept (passes, sets mixer config).
|
||||
set BLASTER=A220 I5 D1 H5 P330 T6
|
||||
c:\sb16\diagnose /s
|
||||
set BLASTER=A240 I7 D3 H6 P300 T6
|
||||
c:\sb16\diagnose /s
|
||||
set BLASTER=A220 I5 D1 H5 P330 T6
|
||||
set TEMP=c:\
|
||||
rem arena1 city mission (TESTARN.EGG: map=arena1, time=day) with the RIO
|
||||
rem attached; stdout redirected so mission-load progress survives kills.
|
||||
set HEAPSIZE=15000000
|
||||
set L4GAUGE=640x480x16
|
||||
call setenv.bat r f s p
|
||||
32rtm.exe -x
|
||||
BTL4REC.EXE -egg testarn.egg > OUTREC.TXT
|
||||
32rtm.exe -u
|
||||
echo ALPHA1-RUN-DONE
|
||||
pause
|
||||
|
||||
@@ -101,7 +101,16 @@ const Mech::IndexEntry
|
||||
ATTRIBUTE_ENTRY(Mech, LinearSpeed, currentBodySpeed),
|
||||
ATTRIBUTE_ENTRY(Mech, MaxRunSpeed, reverseStrideLength),
|
||||
ATTRIBUTE_ENTRY(Mech, DuckState, duckState),
|
||||
ATTRIBUTE_ENTRY(Mech, EyepointRotation, eyepointRotation)
|
||||
ATTRIBUTE_ENTRY(Mech, EyepointRotation, eyepointRotation),
|
||||
ATTRIBUTE_ENTRY(Mech, UnstablePercentage, unstablePercentage),
|
||||
ATTRIBUTE_ENTRY(Mech, CollisionSpeed, collisionSpeed),
|
||||
ATTRIBUTE_ENTRY(Mech, DistanceToMissile, distanceToMissile),
|
||||
ATTRIBUTE_ENTRY(Mech, FootStep, footStep),
|
||||
ATTRIBUTE_ENTRY(Mech, IncomingLock, incomingLock),
|
||||
ATTRIBUTE_ENTRY(Mech, CollisionState, collisionState),
|
||||
ATTRIBUTE_ENTRY(Mech, CollisionNormal, collisionNormal),
|
||||
ATTRIBUTE_ENTRY(Mech, AnimationState, animationState),
|
||||
ATTRIBUTE_ENTRY(Mech, ReduceButton, reduceButton)
|
||||
};
|
||||
|
||||
Mech::AttributeIndexSet
|
||||
@@ -224,6 +233,12 @@ Mech::Mech(
|
||||
radarLinearPosition = &localOrigin.linearPosition;
|
||||
radarAngularPosition = &localOrigin.angularPosition;
|
||||
duckState = 0;
|
||||
unstablePercentage = 0.0f; // staged: no instability model yet
|
||||
collisionSpeed = 0.0f; // staged: audio watcher set (see MECH.HPP)
|
||||
distanceToMissile = 0.0f;
|
||||
footStep = 0;
|
||||
incomingLock = 0;
|
||||
reduceButton = 0;
|
||||
lastInflictingDamage = 0.0f;
|
||||
|
||||
//
|
||||
|
||||
@@ -190,6 +190,26 @@
|
||||
// was missing.
|
||||
//
|
||||
EyepointRotationAttributeID,
|
||||
//
|
||||
// Bound BY NAME by an authored AttributeWatcher (BTL4.RES); the
|
||||
// shipped binary carries the same string in its pool.
|
||||
//
|
||||
UnstablePercentageAttributeID,
|
||||
CollisionSpeedAttributeID,
|
||||
DistanceToMissileAttributeID,
|
||||
FootStepAttributeID,
|
||||
IncomingLockAttributeID,
|
||||
//
|
||||
// The remaining names BTL4.RES binds watchers to. The two
|
||||
// state indicators already existed as members -- only the
|
||||
// publication was missing, same as EyepointRotation.
|
||||
// AnimationState is bound 307 times in the resource: it is how
|
||||
// the audio system follows the gait.
|
||||
//
|
||||
CollisionStateAttributeID,
|
||||
CollisionNormalAttributeID,
|
||||
AnimationStateAttributeID,
|
||||
ReduceButtonAttributeID,
|
||||
NextAttributeID
|
||||
};
|
||||
|
||||
@@ -502,6 +522,40 @@
|
||||
Point3D *radarLinearPosition;
|
||||
Quaternion *radarAngularPosition;
|
||||
int duckState;
|
||||
//
|
||||
// STAGED VALUE (the instability model is not reconstructed).
|
||||
// The mech streams the authored unstable* effect constants in its
|
||||
// resource (maxUnstableAcceleration and friends) but nothing yet
|
||||
// computes how close the mech is to going over. It is PUBLISHED
|
||||
// because an authored AttributeWatcher in BTL4.RES binds
|
||||
// "UnstablePercentage" by name and the engine Fails outright when
|
||||
// the name does not resolve (WATCHER.CPP:141). Holds 0 = stable
|
||||
// until the model lands.
|
||||
//
|
||||
Scalar unstablePercentage;
|
||||
//
|
||||
// The AUDIO watcher set, staged alongside unstablePercentage.
|
||||
// BTL4.RES binds exactly six attribute watchers by name --
|
||||
// UnstablePercentage, CollisionSpeed, FootStep, IncomingLock,
|
||||
// DistanceToMissile (Mech) and SpeedEffect (Myomers) -- and the
|
||||
// engine Fails outright on any that does not resolve.
|
||||
// These are the sound triggers: impact volume, footfalls, the
|
||||
// missile-lock warning, the myomer whine.
|
||||
//
|
||||
// TYPES ARE PROVISIONAL. AttributeWatcherOf<T> reads
|
||||
// *(T*)attributePointer (WATCHER.HPP:288) and the instantiation
|
||||
// comes from the resource, which we cannot read off the string
|
||||
// pool. Nothing drives these yet, so nothing ever changes and no
|
||||
// watcher can fire -- settle the types WITH the models that write
|
||||
// them (collision response, the gait FSM, the missile threat
|
||||
// track), not before.
|
||||
//
|
||||
Scalar collisionSpeed;
|
||||
Scalar distanceToMissile;
|
||||
int footStep;
|
||||
int incomingLock;
|
||||
UnitVector collisionNormal; // staged with collisionSpeed
|
||||
int reduceButton; // staged: cockpit button feed
|
||||
|
||||
//
|
||||
// The model's authored look-view angles (rad; deg in the resource).
|
||||
|
||||
@@ -25,11 +25,38 @@ Derivation
|
||||
"Myomers"
|
||||
);
|
||||
|
||||
const Myomers::IndexEntry
|
||||
Myomers::AttributePointers[]=
|
||||
{
|
||||
ATTRIBUTE_ENTRY(Myomers, SpeedEffect, speedEffect),
|
||||
ATTRIBUTE_ENTRY(Myomers, CurrentSeekVoltageIndex, currentSeekVoltageIndex),
|
||||
ATTRIBUTE_ENTRY(Myomers, RecommendedSeekVoltageIndex,
|
||||
recommendedSeekVoltageIndex),
|
||||
ATTRIBUTE_ENTRY(Myomers, MinSeekVoltageIndex, minSeekVoltageIndex),
|
||||
ATTRIBUTE_ENTRY(Myomers, MaxSeekVoltageIndex, maxSeekVoltageIndex),
|
||||
{ (int)Myomers::SeekVoltageAttributeID, "SeekVoltage",
|
||||
(Simulation::AttributePointer)&Myomers::seekVoltage }
|
||||
};
|
||||
|
||||
Myomers::AttributeIndexSet
|
||||
Myomers::AttributeIndex(
|
||||
ELEMENTS(Myomers::AttributePointers),
|
||||
Myomers::AttributePointers,
|
||||
PoweredSubsystem::AttributeIndex
|
||||
);
|
||||
|
||||
//
|
||||
// The shared data must carry the POWERED tables, not Subsystem's -- the
|
||||
// same miswiring found on MissileLauncher (5.3.33). Myomers derives from
|
||||
// PoweredSubsystem, so wiring it to Subsystem's dropped every powered
|
||||
// attribute AND the powered message handlers (ToggleSeekVoltage and the
|
||||
// generator-select family) on the way past.
|
||||
//
|
||||
Myomers::SharedData
|
||||
Myomers::DefaultData(
|
||||
Myomers::ClassDerivations,
|
||||
Subsystem::MessageHandlers,
|
||||
Subsystem::AttributeIndex,
|
||||
PoweredSubsystem::MessageHandlers,
|
||||
Myomers::AttributeIndex,
|
||||
Subsystem::StateCount
|
||||
);
|
||||
|
||||
|
||||
@@ -69,6 +69,33 @@
|
||||
);
|
||||
~Myomers();
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Attribute publication. The shipped binary's string pool lists this
|
||||
// class's attribute names contiguously, immediately after the class name
|
||||
// "Myomers" and its ToggleSeekVoltage message:
|
||||
//
|
||||
// SpeedEffect CurrentSeekVoltageIndex RecommendedSeekVoltageIndex
|
||||
// MinSeekVoltageIndex MaxSeekVoltageIndex SeekVoltage
|
||||
//
|
||||
// -- which is EXACTLY the order of the members below, so the
|
||||
// reconstruction's layout matches the original and the ids can be
|
||||
// pinned faithfully rather than guessed. SpeedEffect is the one an
|
||||
// authored AttributeWatcher in BTL4.RES binds (the myomer whine).
|
||||
//
|
||||
public:
|
||||
enum {
|
||||
SpeedEffectAttributeID = PoweredSubsystem::NextAttributeID,
|
||||
CurrentSeekVoltageIndexAttributeID,
|
||||
RecommendedSeekVoltageIndexAttributeID,
|
||||
MinSeekVoltageIndexAttributeID,
|
||||
MaxSeekVoltageIndexAttributeID,
|
||||
SeekVoltageAttributeID,
|
||||
NextAttributeID
|
||||
};
|
||||
|
||||
static const IndexEntry AttributePointers[];
|
||||
static AttributeIndexSet AttributeIndex;
|
||||
|
||||
protected:
|
||||
Scalar speedEffect;
|
||||
int currentSeekVoltageIndex;
|
||||
|
||||
@@ -29,11 +29,29 @@ Derivation
|
||||
"Torso"
|
||||
);
|
||||
|
||||
const Torso::IndexEntry
|
||||
Torso::AttributePointers[]=
|
||||
{
|
||||
ATTRIBUTE_ENTRY(Torso, RotationOfTorsoVertical, currentElevation),
|
||||
ATTRIBUTE_ENTRY(Torso, RotationOfTorsoHorizontal, currentTwist),
|
||||
ATTRIBUTE_ENTRY(Torso, HorizontalLimitRight, horizontalLimitRight),
|
||||
ATTRIBUTE_ENTRY(Torso, HorizontalLimitLeft, horizontalLimitLeft),
|
||||
ATTRIBUTE_ENTRY(Torso, SpeedOfTorsoVertical, baseElevationRate),
|
||||
ATTRIBUTE_ENTRY(Torso, SpeedOfTorsoHorizontal, baseTwistRate)
|
||||
};
|
||||
|
||||
Torso::AttributeIndexSet
|
||||
Torso::AttributeIndex(
|
||||
ELEMENTS(Torso::AttributePointers),
|
||||
Torso::AttributePointers,
|
||||
Subsystem::AttributeIndex
|
||||
);
|
||||
|
||||
Torso::SharedData
|
||||
Torso::DefaultData(
|
||||
Torso::ClassDerivations,
|
||||
Subsystem::MessageHandlers,
|
||||
Subsystem::AttributeIndex,
|
||||
Torso::AttributeIndex,
|
||||
Subsystem::StateCount
|
||||
);
|
||||
|
||||
|
||||
@@ -100,6 +100,35 @@
|
||||
);
|
||||
~Torso();
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Attribute publication. The shipped string pool lists this class's
|
||||
// attribute names contiguously after the class name "Torso":
|
||||
//
|
||||
// RotationOfTorsoVertical RotationOfTorsoHorizontal
|
||||
// HorizontalLimitRight HorizontalLimitLeft
|
||||
// SpeedOfTorsoVertical SpeedOfTorsoHorizontal
|
||||
//
|
||||
// (the TorsoUp/Down/Left/Right/Center that follow are MESSAGES, not
|
||||
// attributes). All six map onto members we already carry. An
|
||||
// authored AttributeWatcher binds SpeedOfTorsoHorizontal.
|
||||
//
|
||||
// The chain -- PowerWatcher -> HeatWatcher -> MechSubsystem -- publishes
|
||||
// nothing of its own, so these start at Subsystem::NextAttributeID.
|
||||
//
|
||||
public:
|
||||
enum {
|
||||
RotationOfTorsoVerticalAttributeID = Subsystem::NextAttributeID,
|
||||
RotationOfTorsoHorizontalAttributeID,
|
||||
HorizontalLimitRightAttributeID,
|
||||
HorizontalLimitLeftAttributeID,
|
||||
SpeedOfTorsoVerticalAttributeID,
|
||||
SpeedOfTorsoHorizontalAttributeID,
|
||||
NextAttributeID
|
||||
};
|
||||
|
||||
static const IndexEntry AttributePointers[];
|
||||
static AttributeIndexSet AttributeIndex;
|
||||
|
||||
protected:
|
||||
int isDamagedCopy;
|
||||
int statusFlags;
|
||||
|
||||
@@ -177,3 +177,65 @@ NEXT RUNG: run under the documented full rig (render-bridge/launch_pod.ps1,
|
||||
see LAUNCH.md) so the bridge is up and geometry actually loads. Only then is
|
||||
it worth writing real MakeEntityRenderables content -- until the bridge is in
|
||||
the loop there is nothing to see even if the scene graph is correct.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
THE FULL POD RIG: geometry loads, and the ladder is now the AUDIO WATCHER SET
|
||||
--------------------------------------------------------------------------------
|
||||
Run under the documented rig (render-bridge/launch_pod.ps1 with the GL bridge
|
||||
up) the geometry complaint COUNT WENT TO ZERO -- .BGF loading was never a
|
||||
reconstruction problem, only a missing bridge, exactly as predicted.
|
||||
|
||||
emulator/render-bridge/gauge_arena_rec.conf = gauge_arena_sound.conf with
|
||||
the exe swapped to BTL4REC.EXE (our build, staged into ALPHA_1/REL410/BT
|
||||
beside the shipped BTL4OPT.EXE, which is NOT touched).
|
||||
Launch: .\launch_pod.ps1 -Conf ...\gauge_arena_rec.conf
|
||||
|
||||
What blocks now is a SERIES of authored AttributeWatchers. BTL4.RES binds
|
||||
watchers BY NAME and the engine Fails outright on any that does not resolve
|
||||
(WATCHER.CPP:141) -- these are the sound triggers, so every one of them is a
|
||||
name our subsystems must publish.
|
||||
|
||||
RUNGS CLIMBED THIS PASS (each one run-verified, ~6 min per cycle):
|
||||
UnstablePercentage Mech, staged member (no instability model yet)
|
||||
SpeedEffect Myomers -- member existed, table published
|
||||
AnimationState Mech -- member existed (bound 307x in the RES!)
|
||||
CollisionState/Normal Mech -- state existed, normal staged
|
||||
ReduceButton Mech, staged
|
||||
SpeedOfTorsoHorizontal Torso -- all six names mapped to real members
|
||||
|
||||
THE METHOD THAT MAKES THIS CHEAP (use it instead of one rung per run):
|
||||
The shipped binary's string pool carries each class's attribute names
|
||||
CONTIGUOUSLY, in ID ORDER, right after the class name and its message names.
|
||||
So: strings -a BTL4OPT.EXE | grep -n -A14 '^Torso$' gives the authentic
|
||||
table for that class, and in every case so far our member declarations sit in
|
||||
the SAME ORDER -- which both confirms the reconstruction's layout and lets the
|
||||
ids be pinned rather than guessed. Cross-reference against the resource with
|
||||
|
||||
comm -12 <(strings BTL4.RES|grep -x '[A-Z][A-Za-z0-9]\{3,\}'|sort -u) <(strings BTL4OPT.EXE|...|sort -u)
|
||||
|
||||
which returns 59 candidate names; the attribute-like ones are the work list.
|
||||
|
||||
STILL TO PUBLISH (from that intersection, owner in brackets where known):
|
||||
MotionState [Torso? -- sits between StickPosition and
|
||||
TorsoHorizontalEnabled in the pool, but that region MIXES attribute
|
||||
names with resource-field names, so confirm before publishing]
|
||||
LocalVelocity, LocalAcceleration [Mover/Entity]
|
||||
AmmoState [AmmoBin] CondenserState [Condenser]
|
||||
ReservoirState [Reservoir] GeneratorState [Generator]
|
||||
SimulationState [Subsystem] DisplayMode [ControlsMapper]
|
||||
LookForward/Left/Right/Down/Behind [MechControlsMapper]
|
||||
LaserOn, ReportLeak, FireCountdownStarted, TargetRangeExponent,
|
||||
ConfigureActivePress, StickPosition
|
||||
|
||||
A THIRD MISWIRED SharedData FOUND ON THE WAY: Myomers carried
|
||||
Subsystem::MessageHandlers + Subsystem::AttributeIndex where it derives from
|
||||
PoweredSubsystem -- the same defect as MissileLauncher (5.3.33), dropping
|
||||
every powered attribute AND the powered message handlers. Torso is wired to
|
||||
Subsystem's too, but there the chain (PowerWatcher -> HeatWatcher ->
|
||||
MechSubsystem) genuinely publishes nothing, so only its AttributeIndex moved.
|
||||
WORTH A SWEEP: check every subsystem's DefaultData against its actual parent.
|
||||
|
||||
TYPES ARE PROVISIONAL on the staged members. AttributeWatcherOf<T> reads
|
||||
*(T*)attributePointer (WATCHER.HPP:288) and the instantiation comes from the
|
||||
resource, which the string pool does not reveal. Nothing drives these yet so
|
||||
no watcher can fire -- settle the types WITH the models that write them.
|
||||
|
||||
Reference in New Issue
Block a user