#96: the sim TIME MODEL closed from bytes -- myomer kinetic term restored to the faithful 28 Hz
The open question under every heat bracket was what the 1995 sim does with time. Answered at the byte level: * FUN_0041c018 IS the arcade Simulation::PerformAndWatch: slice = (till.ticks - last.ticks) / DAT_0052140c, stored, Perform(slice) -- VARIABLE-STEP in real SECONDS, line-for-line the WinTesla SIMULATE.cpp body. Every dt-carrying reconstruction is unit-faithful; no tick/second gap exists anywhere. * The myomer heat term's ONE caller is the unexported MyomersSimulation body @0x4b8b9a (E8-scan + raw disasm; export gap): once per Perform, raw slice, gated measuredVoltage>0 only. The dt-less kinetic pulse therefore fires at the FRAME cadence -- 28 Hz nominal, sagging under load (emergent hardware, not a code constant). * Mover velocity is u/s (dead-reckoner @0x421f7c: pos += vel x ticksD/28), so the v operand is unit-faithful too. The 0.5 "loaded-rate" witness bracket is RETIRED -- it modeled the sag as a constant, wrong in exactly the reported scenario (open-field cruising is a light scene; the pod held ~28 there). kSeekHeatCalib = 1.0. Measured at the faithful rate (madcat cruise benches): recommended gear equilibrates ~1450 -- inside the authored degradation band as a SOFT 20% output governor (heatFactor = 1 - d^2/range^2), weapons untouched at ~110-150, ZERO jams, zero bay fires from movement alone; supercharge ~1770 (deep governor -- the manual's own expert-mode warning). That is the authored system: degradeT=1000 is governor onset, failT=2000 the cliff, and the coolant-loop controls are the player's lever. New leads filed in open-questions: the climb term's gravity operand samples 0 (bridge points at a dead cell); the engine Mover's own gravity subtraction is per-frame dt-less (port impact unread); gait-noise phantom acceleration feeds the accel term. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
d3de5f94ee
commit
e1ae92264a
@@ -762,35 +762,36 @@ void Myomers::MyomersDriveHeat(Scalar time_slice)
|
||||
// exists because the binary's per-tick value depends on the pod's frame
|
||||
// rate, which our port does not run at.
|
||||
//
|
||||
// THE CLOCK ORIGIN, traced 2026-08-02 (was the open question here):
|
||||
// the DOS binary keeps its engine frame rate in the global DAT_0052140c,
|
||||
// set once at startup --
|
||||
// 0x401ace: mov [0x52140c], 0x41E00000 = 28.0f (nominal)
|
||||
// 0x401ada: mov [0x52140c], 0x4191A6E0 = 18.2065f (BIOS-tick fallback)
|
||||
// -- and consumed by ~90 fmul/fdiv sites across the image as THE
|
||||
// per-frame<->per-second conversion. The DOS main passes it straight into
|
||||
// the ApplicationManager ctor (0x401189: push [0x52140c]). So the pod's
|
||||
// nominal Performance cadence was 28 Hz, byte-proven. [T1]
|
||||
// THE CLOCK -- CLOSED 2026-08-02, all [T1] from bytes:
|
||||
// * DAT_0052140c = SystemClock ticksPerSecond, 28.0 nominal (0x401ace) /
|
||||
// 18.2065 BIOS fallback (0x401ada).
|
||||
// * The arcade Simulation::PerformAndWatch is FUN_0041c018:
|
||||
// slice = (till.ticks - lastPerformance.ticks) / DAT_0052140c;
|
||||
// lastPerformance = till; (*performance)(this, slice);
|
||||
// -- VARIABLE-STEP, slice in real SECONDS, line-for-line the WinTesla
|
||||
// SIMULATE.cpp body. Every dt-carrying term is frame-rate independent
|
||||
// in BOTH the binary and the port; no unit conversion is missing.
|
||||
// * This term's ONE caller is the unexported MyomersSimulation body
|
||||
// (0x4b8b9a-0x4b8d0d, raw disasm 2026-08-02 -- the export gap hid it):
|
||||
// it calls 0x4b8d18 once per Perform with the RAW slice, gated only on
|
||||
// measuredVoltage > 0. So the kinetic energy pulse fires once per
|
||||
// FRAME, and the pod's frame cadence is its tick rate: 28 Hz when
|
||||
// holding the deadline, sagging under load (fewer pulses/s -- an
|
||||
// EMERGENT hardware mercy, not a constant in the code).
|
||||
//
|
||||
// CALIBRATION FACTOR 0.5 -- the pod's EFFECTIVE rate under load, now
|
||||
// corroborated from three directions (2026-08-02):
|
||||
// * Oracle (pod veteran), asked if the frame rate was rock solid:
|
||||
// "I think I could do as well with a flipbook"; heavy fights "would
|
||||
// turn to a slide show".
|
||||
// * Lynx (original-era): "RP had a target frame rate of 30FPS. It
|
||||
// wasn't hard coded or locked. BT never had a locked frame rate in
|
||||
// 1st release testing... coming from 3.0, where 20FPS was a miracle."
|
||||
// * The engine's own pacer DESIGN: end_of_frame = Now() + frameDuration
|
||||
// with background fill and NO overrun catch-up (APPMGR.cpp, T0) --
|
||||
// "target 28 but allowed to slip" is the construction, and the
|
||||
// 18.2065 BIOS fallback anticipated degraded timing.
|
||||
// Corollary: a choking 486 generated LESS heat/s exactly during the
|
||||
// biggest fights -- veteran memory of seek-4 endurance encodes the LOADED
|
||||
// rate, so bracketing by their consensus is the correct instrument.
|
||||
// Effective default 28 * 0.5 = 14 Hz [T2 multi-witness]; BT_MYO_HZ=<hz>
|
||||
// overrides absolutely for bracketing.
|
||||
// The faithful reference is therefore the binary's own nominal cadence,
|
||||
// 28 Hz, full stop. The old 0.5 "loaded-rate" calibration [T3 witness
|
||||
// bracket] is RETIRED: it modeled the sag as a constant, which is wrong in
|
||||
// exactly the reported scenario (open-field cruising is a LIGHT scene --
|
||||
// the pod held ~28 there). Measured at 28 Hz (cruise benches 2026-08-02):
|
||||
// recommended gear equilibrates ~1450 (soft 20% output governor inside the
|
||||
// authored degradation band, weapons unaffected, zero jams); supercharge
|
||||
// ~1770 (deep governor, the manual's own warning). That IS the authored
|
||||
// system: degradeT=1000 is a governor onset, failT=2000 the cliff, and the
|
||||
// pod's coolant-loop controls (flush/balance, Myomers on loop 5) are the
|
||||
// player's lever. BT_MYO_HZ=<hz> remains as the bracketing override.
|
||||
static const Scalar kPodFrameHz = 28.0f; // byte-proven nominal [T1]
|
||||
static const Scalar kSeekHeatCalib = 0.5f; // Oracle bracket 2026-08-02 [T3]
|
||||
static const Scalar kSeekHeatCalib = 1.0f; // faithful (0.5 bracket retired 2026-08-02)
|
||||
static Scalar s_hz = -1.0f;
|
||||
if (s_hz < 0.0f)
|
||||
{
|
||||
@@ -800,7 +801,7 @@ void Myomers::MyomersDriveHeat(Scalar time_slice)
|
||||
if (getenv("BT_MYO_LOG"))
|
||||
DEBUG_STREAM << "[myoheat] kinetic-term reference rate: " << s_hz
|
||||
<< " Hz (pod nominal 28 [T1] x calib " << kSeekHeatCalib
|
||||
<< " [T3]" << (hv ? ", ENV OVERRIDE" : "") << ")" << std::endl;
|
||||
<< (hv ? ", ENV OVERRIDE" : "") << ")" << std::endl;
|
||||
}
|
||||
|
||||
Scalar termClimb = velComplement * vy * mass * gravity * time_slice;
|
||||
|
||||
Reference in New Issue
Block a user