#152: the real hole -- glass/RIO rigs had NO torso-centre control; wire pod button 0x42

The reported "torso no longer recentres on its own" decomposed into two parts:
the auto-recentre in Mid/Adv was never authentic (it was the stuck-centerCommand
bug acting as a phantom feature since ~674 -- analysis on the ticket, awaiting
Oracle's 1995-memory verdict), but underneath it sat a REAL defect: with the
phantom gone, a glass/RIO player had no way to recentre the torso at all.

WHY.  The only centerCommand writer lived inside the desktop key-bridge block,
which is OFF whenever a RIO/PadRIO is present -- glass and the pod both.  The
pod's dedicated CENTER button (0x42, "the shipped .RES name", UP arrow via
bindings.txt) reached nothing: benched two scripted 0x42 holds on the RIO path,
ctrCmd=0 throughout, twist parked forever.  (Keyboard X/NumPad5 recentred only
as a side effect of ALL-STOP -- you could not recentre without stopping.)

FIX, two pieces, both existing patterns:
  * L4PADRIO::EmitButton -- the documented single chokepoint every button
    source funnels through -- publishes the 0x42 HOLD state
    (gBTTorsoCenterHeld), exactly the 0x3F ReverseThrust precedent.
  * mechmppr gains ONE unified centerCommand writer, deliberately OUTSIDE the
    key-bridge gate (the same placement lesson as the mode-cycle hook):
    hold = torsoCenter(@0x154 databound) OR gBTTorsoCenterHeld(0x42) OR the
    one-frame X pulse; asserts while held, clears on release.  Single writer
    == the sources can never stomp each other's clear.

BENCHED (scratchpad/night14/center42.sh, RIO path, bridge off):
  before: ctrCmd=0 in all samples across two 0x42 holds; twist parked at 1.478
  after:  hold -> ctrCmd=1 recen=1, twist slews 2.22->0.44 at the authored
          0.87 rad/s; twist input DURING the hold cancels sim-side (authentic);
          release clears; no button -> aim holds (authentic Std/Vet).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018SgmXGNMXavXiafKXf9MDC
This commit is contained in:
Joe DiPrima
2026-08-09 17:26:27 -05:00
co-authored by Claude Opus 5
parent aa250c4e22
commit 2b6b0276fd
3 changed files with 73 additions and 15 deletions
+12
View File
@@ -36,6 +36,7 @@ int gBTPadViewToggleEdges = 0;
// desktop bridge, which owns `reverseThrust` (mapper attr 6 @0x124) every frame.
//
int gBTReverseHeld = 0;
int gBTTorsoCenterHeld = 0; // button 0x42 hold (#152; same seam as 0x3F)
//
// The desktop per-MFD preset-page cycle edges (J/K/L -> Mfd1/2/3), consumed
@@ -458,6 +459,17 @@ void
// via SetScreenButton), so the desktop bridge can honour the button exactly
// like the pod's RIO board did.
//
// TORSO CENTER (pod button 0x42, 'the shipped .RES name' -- UP arrow via
// bindings.txt). Same chokepoint pattern as 0x3F below: publish the HOLD
// state so the mapper's unified recenter writer (#152) can honour it on
// every rig. Before this, no RIO/glass path reached centerCommand at all
// -- bench: two scripted 0x42 holds, ctrCmd=0 throughout.
if (address == 0x42)
{
extern int gBTTorsoCenterHeld;
gBTTorsoCenterHeld = pressed ? 1 : 0;
}
if (address == 0x3F)
{
gBTReverseHeld = pressed ? 1 : 0;
+35 -15
View File
@@ -727,6 +727,35 @@ void
CycleControlModeNow();
}
}
// (#152) TORSO-CENTER -- the ONE writer of the torso's centerCommand
// (@0x208, HELD-button semantics: writer asserts while held, clears on
// release; TorsoSimulation re-arms recenterActive from it each frame).
// Sources OR'd here, deliberately OUTSIDE the key-bridge gate:
// * torsoCenter (@0x154) -- this mapper's databound "TorsoCenter" cell,
// the streamed pod-button route (button 0x42);
// * gBTTorsoRecenter -- the desktop 'X' one-frame pulse (mech4 key poll).
// The old writer lived INSIDE the key-bridge block, so on any rig with a
// RIO/PadRIO present (glass + the pod -- the bridge is off there) NO path
// could reach centerCommand: with the stuck-cell phantom auto-recentre
// fixed, those players had no way to recentre the torso in Std/Vet at all
// (Oracle's #152 report). Single-writer here also means the two sources
// can never stomp each other's clear.
{
Mech *rcMech = GetMech();
Torso *rcTorso = (rcMech != 0) ? (Torso *)rcMech->GetTorsoSubsystem() : 0;
if (rcTorso != 0)
{
int hold = (torsoCenter != 0);
extern int gBTTorsoRecenter;
extern int gBTTorsoCenterHeld; // pod button 0x42 (L4PADRIO chokepoint)
if (gBTTorsoCenterHeld) hold = 1;
if (gBTTorsoRecenter) { gBTTorsoRecenter = 0; hold = 1; }
if (hold)
rcTorso->CommandRecenter();
else
rcTorso->ClearRecenterCommand();
}
}
{
// STAND-DOWN (glass-cockpit step 2c): BT_KEY_BRIDGE unset = AUTO --
// the bridge runs only when NO live cockpit device (serial RIO /
@@ -938,21 +967,12 @@ void
// centerCommand is a pod BUTTON state, so the writer clears
// it while unpressed (Basic's own path re-asserts every
// frame; this branch owns it in Standard/Veteran).
{
Torso *rcTorso = (Torso *)mech->GetTorsoSubsystem();
if (rcTorso != 0)
{
if (gBTTorsoRecenter)
{
gBTTorsoRecenter = 0;
rcTorso->CommandRecenter();
}
else
{
rcTorso->ClearRecenterCommand();
}
}
}
// (#152) the recenter writer moved OUT of this key-bridge
// block to the unified consumer below -- inside here it was
// DEAD on every RIO/glass rig (bridge off), which left those
// players with no torso-centre control at all once the
// stuck-cell phantom auto-recentre was fixed. Bench: two
// scripted 0x42 holds on the RIO path, ctrCmd=0 throughout.
}
}
// (stickPosition.y no longer zeroed here -- the bridge above
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
# #152: is the AUTHENTIC torso-CENTER button (0x42) alive on the RIO/glass path
# (key bridge OFF)? Cycle to Standard, deflect/release the twist axis, and
# hold 0x42 during release windows. ctrCmd=1 while held + twist slewing to 0
# = route works (ticket becomes player education). ctrCmd stuck 0 = the
# streamed 0x42 route is dead on glass and needs the forward implemented.
set -x
. /c/git/bt411/scratchpad/night6/bench_common.sh
cd /c/git/bt411/content || exit 1
taskkill //F //IM btl4.exe > /dev/null 2>&1
sleep 2
rm -f c42_a.log
bt_expert_egg MP.EGG C42.EGG
sed -i "s/^map=.*/map=grass/; s/^time=.*/time=day/; s/^vehicle=.*/vehicle=madcat/" C42.EGG
( export BT_MODECYCLE_EVERY=400 BT_TWIST_PULSE=150
export BT_BTNTEST=0x42,900,1150 BT_BTNTEST2=0x42,1500,1750
export BT_TORSO_LOG=1 BT_KEY_NOFOCUS=1 BT_KEY_BRIDGE=0
bt_launch c42_a.log C42.EGG 0x03 )
sleep 130
bt_kill_ours; sleep 2; taskkill //F //IM btl4.exe > /dev/null 2>&1; sleep 3
echo "============ RESULT ============"
grep -a "\[mode\] control mode" c42_a.log | head -4
echo "--- ctrCmd seen (want some =1 during the 0x42 holds) ---"
grep -ao "ctrCmd=[01]" c42_a.log | sort | uniq -c
echo "--- twist trajectory around the first hold ---"
grep -aE "twistpulse|ctrCmd=1" c42_a.log | head -8