diff --git a/emulator/render-bridge/gauge_arena_rec.conf b/emulator/render-bridge/gauge_arena_rec.conf new file mode 100644 index 00000000..ae8f4ca7 --- /dev/null +++ b/emulator/render-bridge/gauge_arena_rec.conf @@ -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 + diff --git a/restoration/source410/BT/MECH.CPP b/restoration/source410/BT/MECH.CPP index 05f0f07c..0065c6e1 100644 --- a/restoration/source410/BT/MECH.CPP +++ b/restoration/source410/BT/MECH.CPP @@ -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; // diff --git a/restoration/source410/BT/MECH.HPP b/restoration/source410/BT/MECH.HPP index d6a2fe90..32c7d008 100644 --- a/restoration/source410/BT/MECH.HPP +++ b/restoration/source410/BT/MECH.HPP @@ -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 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). diff --git a/restoration/source410/BT/MYOMERS.CPP b/restoration/source410/BT/MYOMERS.CPP index 13906b23..99d96f91 100644 --- a/restoration/source410/BT/MYOMERS.CPP +++ b/restoration/source410/BT/MYOMERS.CPP @@ -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 ); diff --git a/restoration/source410/BT/MYOMERS.HPP b/restoration/source410/BT/MYOMERS.HPP index 0743956b..0c39e693 100644 --- a/restoration/source410/BT/MYOMERS.HPP +++ b/restoration/source410/BT/MYOMERS.HPP @@ -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; diff --git a/restoration/source410/BT/TORSO.CPP b/restoration/source410/BT/TORSO.CPP index c4c7ebbd..0cf43829 100644 --- a/restoration/source410/BT/TORSO.CPP +++ b/restoration/source410/BT/TORSO.CPP @@ -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 ); diff --git a/restoration/source410/BT/TORSO.HPP b/restoration/source410/BT/TORSO.HPP index 57886b99..8a9bd710 100644 --- a/restoration/source410/BT/TORSO.HPP +++ b/restoration/source410/BT/TORSO.HPP @@ -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; diff --git a/restoration/source410/RENDER-ROADMAP.NOTES.md b/restoration/source410/RENDER-ROADMAP.NOTES.md index c93589bd..01a0a5d8 100644 --- a/restoration/source410/RENDER-ROADMAP.NOTES.md +++ b/restoration/source410/RENDER-ROADMAP.NOTES.md @@ -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 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.