BT410 5.3.123: the coolant shares itself -- BalanceCoolant lands on the heatable chain, and the valve system finds its true home
The mech's BalanceCoolant handler (0x16, @0049f728) and the share renormalizer (@0049f788) land on a newly populated heatableSubsystems chain (the binary ctor's GUID sweep, part_012.c:15774): every heatable carries the coolant-allocation trio (priority +0x1d0 born 1, share +0x15c = priority/total, balance alarm +0x1dc blipping 2/1-then-0 as the gauge flash -- ctor evidence @004ae568). The ctor tail and Reset both renormalize, exactly as the binary's four call sites do. The reservoir draw (@004aefa4) weights each heatable's feed by the share -- that consumer wires in with the heat-economy pass. Soak: 20 heatables renormalize to 0.05 at ctor AND on a BT_PRESS_BALANCE press through the normal dispatch, crash-sig 0 (pod_render_bal.conf). Identified for 5.3.124: the binary's MoveValve is @004ae464 on the HEATABLE base (name table @0x50e534), novice-locked via mapper+0x274 (FUN_004ac9c8 -- our NoviceLockout gate was right), stepping the SAME +0x1d0 ladder then calling the mech redistribute: our Condenser-scoped MoveValve/RecomputeValves/valveState triple is this mechanism writ small and gets unified onto the new cells. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# pod_render_norio.conf -- pod_render_rec with the RIO serial port OFF.
|
||||
#
|
||||
# The emulator log shows a steady stream of serial1 RX OVERRUN errors on
|
||||
# the RIO pipe, and controls post their events at HighEventPriority
|
||||
# UNCONDITIONALLY (CONTROLS.HPP:250) -- so a chattering RIO port would
|
||||
# flood a priority the background pump always serves first, starving the
|
||||
# priority-0 renderer events the load gate waits on. This conf tests that
|
||||
# by removing the port entirely. Everything else is identical to the rec
|
||||
# conf, so a launch here and a hang there isolates the RIO.
|
||||
#
|
||||
[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=disabled
|
||||
serial2=namedpipe pipe:vplasma
|
||||
# live UNBUFFERED game output: DOS char devices are not buffered, so
|
||||
# redirecting stdout to COM3 lands every line immediately. A normal
|
||||
# '> file' redirect stays 0 bytes until the process exits, which hides
|
||||
# all progress on a run that does NOT crash.
|
||||
serial3=file file:C:\VWE\TeslaRel410\emulator\render-bridge\podlog.txt
|
||||
[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 BT_JOINTS=1
|
||||
set L4VIEWEXT=1
|
||||
set BT_STACK_LOG=1
|
||||
set BT_MECH_LOG=1
|
||||
set BT_PRESS_BALANCE=1
|
||||
set BT_GAUGE_LOG=1
|
||||
set BT_FORCE_THROTTLE=0
|
||||
set BT_FORCE_TURN=0
|
||||
set HEAPSIZE=15000000
|
||||
set L4GAUGE=640x480x16
|
||||
call setenv.bat r s n p
|
||||
32rtm.exe -x
|
||||
BTL4REC.EXE -egg testarn.egg > COM3
|
||||
|
||||
echo GAME-RC=%errorlevel% >> RC.TXT
|
||||
32rtm.exe -u
|
||||
echo ALPHA1-RUN-DONE
|
||||
pause
|
||||
|
||||
@@ -101,6 +101,14 @@ HeatableSubsystem::HeatableSubsystem(
|
||||
{
|
||||
Check(owner);
|
||||
Check_Pointer(subsystem_resource);
|
||||
|
||||
//
|
||||
// The balance alarm arms once at birth (binary ctor @004ae568:
|
||||
// FUN_0041b9ec(+0x1dc, 3)); the priority/share rest state rides
|
||||
// ResetToInitialState below.
|
||||
//
|
||||
balanceAlarm.Initialize(3);
|
||||
|
||||
ResetToInitialState();
|
||||
Check_Fpu();
|
||||
}
|
||||
@@ -123,6 +131,14 @@ void
|
||||
Check(this);
|
||||
currentTemperature = 300.0f;
|
||||
heatLoad = 0.0f;
|
||||
|
||||
//
|
||||
// Binary rest state (@004ae568 ctor / the @004ae4d8-family reset):
|
||||
// priority 1 (the equal split), share 0 until the owning mech's
|
||||
// redistribute computes the first real fractions.
|
||||
//
|
||||
coolantPriority = 1;
|
||||
coolantShare = 0.0f;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -122,6 +122,27 @@
|
||||
CurrentTemperatureOf()
|
||||
{ Check(this); return currentTemperature; }
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// The coolant-allocation trio (binary heatable +0x1d0/+0x15c/+0x1dc,
|
||||
// ctor @004ae568). PUBLIC: the owning Mech's redistribute walks the
|
||||
// heatable chain and writes all three (the duckCommand precedent).
|
||||
//
|
||||
// coolantPriority the draw-weight rung, born 1; the per-subsystem
|
||||
// priority button (@004ae464, id TBD) steps it 0 -> 1 -> 5 ->
|
||||
// 50 -> 0, and the mech's BalanceCoolant (0x16) resets every
|
||||
// heatable to 1 (the equal split).
|
||||
// coolantShare priority / total, written ONLY by the mech's
|
||||
// RedistributeCoolantShares (@0049f788); the reservoir draw
|
||||
// (@004aefa4) weights each heatable's coolant feed by it.
|
||||
// balanceAlarm 3 levels (binary FUN_0041b9ec(+0x1dc, 3)); the
|
||||
// redistribute blips it -- 2 = share shrank or held, 1 = grew,
|
||||
// then back to 0 -- the cockpit gauge flash.
|
||||
//
|
||||
public:
|
||||
int coolantPriority;
|
||||
Scalar coolantShare;
|
||||
AlarmIndicator balanceAlarm;
|
||||
|
||||
protected:
|
||||
Scalar currentTemperature;
|
||||
Scalar heatLoad;
|
||||
|
||||
@@ -90,6 +90,7 @@ const Receiver::HandlerEntry
|
||||
MESSAGE_ENTRY(Mech, RealMaxSpeed),
|
||||
MESSAGE_ENTRY(Mech, SetBurningState),
|
||||
MESSAGE_ENTRY(Mech, ClearBurningState),
|
||||
MESSAGE_ENTRY(Mech, BalanceCoolant),
|
||||
MESSAGE_ENTRY(Mech, DuckRequest)
|
||||
};
|
||||
|
||||
@@ -551,6 +552,31 @@ Mech::Mech(
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
// THE HEATABLE CHAIN (binary ctor sweep, part_012.c:15774: every roster
|
||||
// subsystem derived from HeatableSubsystem -- GUID 0x50e4fc -- joins the
|
||||
// mech+0x7cc chain), then the first coolant shares (the binary calls the
|
||||
// redistribute at the very ctor end, after the "Mechs" group add; the
|
||||
// ordering between is inert). The weapon (+0x7bc) and Myomers (+0x7ac)
|
||||
// sweeps land with their consumers.
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
{
|
||||
for (int hs = 2; hs < subsystemCount; ++hs)
|
||||
{
|
||||
if (
|
||||
subsystemArray[hs] != NULL &&
|
||||
subsystemArray[hs]->IsDerivedFrom(
|
||||
HeatableSubsystem::ClassDerivations)
|
||||
)
|
||||
{
|
||||
heatableSubsystems.Add(subsystemArray[hs]);
|
||||
}
|
||||
}
|
||||
}
|
||||
RedistributeCoolantShares();
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
// Source the authentic per-mech locomotion params from the GameModel
|
||||
@@ -925,6 +951,87 @@ void
|
||||
AlwaysExecute();
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
// BalanceCoolantMessageHandler -- binary @0049f728 (authentic name from the
|
||||
// handler table). A positive press resets every heatable's coolant
|
||||
// priority to 1 -- the equal split -- and renormalizes the shares.
|
||||
//#############################################################################
|
||||
//
|
||||
void
|
||||
Mech::BalanceCoolantMessageHandler(Receiver::Message *message)
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(message);
|
||||
|
||||
if (((int *)(message + 1))[0] > 0)
|
||||
{
|
||||
ChainIteratorOf<Subsystem*> mark_walk(heatableSubsystems);
|
||||
HeatableSubsystem *heatable;
|
||||
while ((heatable = (HeatableSubsystem *)mark_walk.ReadAndNext()) != NULL)
|
||||
{
|
||||
heatable->coolantPriority = 1;
|
||||
}
|
||||
RedistributeCoolantShares();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
// RedistributeCoolantShares -- binary @0049f788: total the priorities, give
|
||||
// each heatable share = priority / total (0.0 when the total is empty --
|
||||
// the data word @0049f850), blip its balance alarm with the direction
|
||||
// (2 = shrank or held, 1 = grew, then back to 0), store the share. The
|
||||
// reservoir draw weights each heatable's coolant feed by the share.
|
||||
//#############################################################################
|
||||
//
|
||||
void
|
||||
Mech::RedistributeCoolantShares()
|
||||
{
|
||||
Check(this);
|
||||
|
||||
int total = 0;
|
||||
{
|
||||
ChainIteratorOf<Subsystem*> sum_walk(heatableSubsystems);
|
||||
HeatableSubsystem *heatable;
|
||||
while ((heatable = (HeatableSubsystem *)sum_walk.ReadAndNext()) != NULL)
|
||||
{
|
||||
total += heatable->coolantPriority;
|
||||
}
|
||||
}
|
||||
|
||||
int share_count = 0;
|
||||
Scalar first_share = 0.0f;
|
||||
|
||||
ChainIteratorOf<Subsystem*> share_walk(heatableSubsystems);
|
||||
HeatableSubsystem *heatable;
|
||||
while ((heatable = (HeatableSubsystem *)share_walk.ReadAndNext()) != NULL)
|
||||
{
|
||||
Scalar share = 0.0f;
|
||||
if (total > 0)
|
||||
{
|
||||
share = (Scalar)heatable->coolantPriority / (Scalar)total;
|
||||
}
|
||||
heatable->balanceAlarm.SetLevel(
|
||||
(share <= heatable->coolantShare) ? 2 : 1);
|
||||
heatable->coolantShare = share;
|
||||
heatable->balanceAlarm.SetLevel(0);
|
||||
|
||||
if (share_count == 0)
|
||||
{
|
||||
first_share = share;
|
||||
}
|
||||
++share_count;
|
||||
}
|
||||
|
||||
if (getenv("BT_MECH_LOG"))
|
||||
{
|
||||
DEBUG_STREAM << "[coolant] shares renormalized: " << share_count
|
||||
<< " heatables, total priority " << total
|
||||
<< ", first share " << first_share << endl << flush;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
// The collision-volume swap (binaries @004ac04c / @004ac064): write the
|
||||
@@ -1371,6 +1478,12 @@ void
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The binary Reset (@0049fb74 tail) renormalizes the coolant shares
|
||||
// after the roster's per-subsystem resets restored every priority.
|
||||
//
|
||||
RedistributeCoolantShares();
|
||||
|
||||
SetPreRunFlag();
|
||||
|
||||
if (getenv("BT_MECH_LOG"))
|
||||
@@ -2169,6 +2282,19 @@ void
|
||||
}
|
||||
}
|
||||
//
|
||||
// BT_PRESS_BALANCE: one mech-level BalanceCoolant press (0x16)
|
||||
// through the normal dispatch -- the equal-split button.
|
||||
//
|
||||
if (getenv("BT_PRESS_BALANCE"))
|
||||
{
|
||||
ReceiverDataMessageOf<int> balance_press(
|
||||
Mech::BalanceCoolantMessageID,
|
||||
sizeof(ReceiverDataMessageOf<int>),
|
||||
1
|
||||
);
|
||||
Dispatch(&balance_press);
|
||||
}
|
||||
//
|
||||
// BT_PRESS_GEN=1..4: SelectGenerator<N> at the first Emitter
|
||||
// (the generator panel re-tap); BT_PRESS_SEEK: ToggleSeekVoltage
|
||||
// at the first Emitter (the seek dial).
|
||||
|
||||
@@ -980,6 +980,18 @@
|
||||
SetBurningStateMessageHandler(Receiver::Message *message);
|
||||
void
|
||||
ClearBurningStateMessageHandler(Receiver::Message *message);
|
||||
void
|
||||
BalanceCoolantMessageHandler(Receiver::Message *message);
|
||||
|
||||
//
|
||||
// The coolant-share renormalizer (binary @0049f788): share =
|
||||
// priority / total across the heatable chain, blipping each
|
||||
// heatable's balance alarm with the change direction. Callers in
|
||||
// the binary: the 0x16 handler, the ctor tail, Reset, and the
|
||||
// per-subsystem priority stepper (@004ae464, not yet landed).
|
||||
//
|
||||
void
|
||||
RedistributeCoolantShares();
|
||||
void
|
||||
SetStandingCollisionVolume(); // binary @004ac04c... see .CPP
|
||||
void
|
||||
|
||||
@@ -299,26 +299,20 @@ simulationFlags bit 1 == DontExecuteFlag (SIMULATE.HPP) -- the binary's
|
||||
|
||||
Still to land from the roster:
|
||||
|
||||
* **BalanceCoolant @0049f728** (decoded): if payload > 0, mark item+0x1d0=1
|
||||
across the mech+0x7cc roster, then the redistribute pass @0049f788: total
|
||||
the marks, per item fraction = mark/total (0.0 @0049f850 when empty),
|
||||
blip the item's alarm at +0x1dc (level 2 if fraction <= stored else 1,
|
||||
then 0 -- the gauge flash), store fraction at item+0x15c. UNBLOCKED (same sitting): the ctor's chain sweeps
|
||||
(part_012.c:15760..) pin the triple by derivation GUID, names resolved
|
||||
by static-layout adjacency to each TU's string pool: **+0x7ac =
|
||||
MYOMERS** (GUID 0x51155c, string @0x51166d -- so the mobility scale IS
|
||||
max leg-muscle effectiveness, item+0x31c), **+0x7bc = MECHWEAPON
|
||||
roster** (0x511830; the ctor ORs weapon+0x334 mappable-button masks
|
||||
into mech+0x410 as it fills it), **+0x7cc = HEATABLE SUBSYSTEMS**
|
||||
(0x50e4fc == our heatableSubsystems chain; 0x50e604 = the HeatSink-side
|
||||
derivation whose members get a post-ctor vcall+0x38 -- the conduction
|
||||
link resolve). BalanceCoolant therefore marks EVERY heatable (+0x1d0),
|
||||
and the stored fraction +0x15c is the item's coolant ALLOCATION SHARE:
|
||||
the reservoir draw @004aefa4 weights each item's draw by it
|
||||
(rate = -(reservoir+0x224) x share x dt, clamped, with mass/capacity
|
||||
bookkeeping at item+0x12c/+0x128). Land as: three HeatableSubsystem
|
||||
members (balanceMark/coolantShare/balanceAlarm, +0x1d0/+0x15c/+0x1dc)
|
||||
+ the handler on heatableSubsystems.
|
||||
* **BalanceCoolant @0049f728 -- LANDED 5.3.123** (equal-split press +
|
||||
RedistributeCoolantShares @0049f788 + the heatable ctor sweep that
|
||||
populates the heatableSubsystems chain + ctor/Reset redistribute calls;
|
||||
soak: 20 heatables, first share 0.05, ctor + BT_PRESS_BALANCE both
|
||||
renormalize, crash-sig 0). UNIFICATION OWED (5.3.124): the binary's
|
||||
MoveValve handler is @004ae464 registered on the HEATABLE base (the
|
||||
0x50e534 name table in the heatable statics region), novice-locked via
|
||||
mapper+0x274 == 0 (FUN_004ac9c8 -- our NoviceLockout is correct),
|
||||
stepping heatable+0x1d0 through 0 -> 1 -> 5 -> 50 -> 0 then calling the
|
||||
MECH redistribute -- i.e. our Condenser::MoveValve / RecomputeValves /
|
||||
valveState triple is the SAME mechanism scoped to condensers only;
|
||||
retire it onto coolantPriority/RedistributeCoolantShares and re-home
|
||||
the handler on HeatableSubsystem (ValveSetting attribute retargets to
|
||||
the share/priority cells).
|
||||
* **EjectPilot @0049f854** (head read): gated on payload > 0 AND
|
||||
**mech+0x414** -- THE EFFECTIVENESS-CENSUS CONSUMER FOUND: you can only
|
||||
eject a CRIPPLED mech (@0049fa1c's weapons/coolant/generator/limp
|
||||
|
||||
Reference in New Issue
Block a user