control mode: Basic re-centre used the STICKY held-button cell -- and the elevation-limit swap was never ported
Sauron: "toggled through advanced controls from standard to advanced and back
to standard -- lost torso control."
The cycle is 0 Basic -> 1 Standard -> 2 Veteran -> WRAPS TO BASIC, so getting
from "advanced" back to Standard PASSES THROUGH BASIC, whose arm re-centres the
torso. @004afbe0 is a complete spec and the port got three things wrong:
iVar1 = mech+0x438 (TORSO) iVar2 = mech+0x5b4 (HUD)
if (mode == 0) { // BASIC
*(iVar1 + 0x1f0) = 0; // analogTwistAxis
*(iVar1 + 0x274) = 1; // recenterActive
*(iVar1 + 0x220) = *(iVar1 + 0x228); // vertLimitTop
*(iVar1 + 0x224) = *(iVar1 + 0x22c); // vertLimitBottom
*(iVar2 + 0x2a0) = 1; // HUD flickerActive
} else if (mode - 1U < 2) { // STANDARD/VETERAN
*(iVar1 + 0x220) = *(iVar1 + 0x230);
*(iVar1 + 0x224) = *(iVar1 + 0x234);
}
1. WRONG CELL. Basic called CommandRecenter() -> centerCommand (@0x208), the
HELD-BUTTON cell: TorsoSimulation re-arms recenterActive from it EVERY frame
it is non-zero, and only the input path clears it -- a mode switch has no
button release to follow. Digital twist commands are processed BEFORE the
centerCommand block, so while it is set they are overridden as fast as they
are applied: the torso stops responding. The binary sets recenterActive
(@0x274) directly -- a ONE-SHOT that self-clears on settle
(`recenterActive = Recenter(dt)`) and is cancelled by any twist input.
2. THE ELEVATION-LIMIT SWAP WAS MISSING ENTIRELY. Two authored pairs exist --
BASIC @0x228/@0x22C (full top, HALF bottom) vs STANDARD/VETERAN @0x230/@0x234
(the full pair) -- and all four members were ctor-written and read by NOTHING.
Basic never restricted downward travel; the assisted modes never restored it.
3. Basic also raises the HUD's flickerActive (@0x2A0) so the horizon re-settles
with the torso it just re-centred. Not ported. (New BTSetHudFlickerActive
bridge in hud.cpp -- mechmppr sees Subsystem*, not HUD.)
Also removed an invented SetAnalogElevationAxis(0); the binary zeroes only 0x1F0.
MEASURED A/B (scratchpad/night13/modecycle.sh, LEGACY=1 for the old path;
BT_LEGACY_MODE_RECENTER=1 is the revert switch):
ctrCmd=1 samples legacy 26 fixed 0
vLim pairs fixed run shows BOTH -- (-0.698..0.349) = -40..20 deg
assisted, and (-0.349..0.349) = -20..20 deg Basic.
Before this commit only the ctor pair ever appeared.
WHAT IS *NOT* PROVEN. I did not reproduce Sauron's PERMANENT loss. In this
bench the legacy latch is periodic, not sticky:
..........LLLL......LLLL......LLLL......LLLL......LLLL......LL
because the desktop key bridge writes centerCommand every frame and zeroes it
when no button is held, so it self-recovers. The torso IS locked while the cell
is set, which is the symptom -- but whether it stays locked depends on the input
path OWNING that cell. On the glass/pad route (Sauron's) nothing may clear it,
which would make it permanent. So: mechanism fixed and binary-grounded, exact
field persistence unverified. Field-verify by cycling modes on a pad build.
Probe: the BT_TORSO_LOG gate line now carries ctrCmd / recen / vLim.
Bench hook: BT_MODECYCLE_EVERY=<n> cycles the mode from the mapper (the pod's
own route is console key 0x13d -- not a RIO button, so BT_BTNTEST cannot press
it, and mech4's BT_MODECYCLE_TEST counter did not advance in a solo run).
NOTE the bench needs BT_KEY_BRIDGE=1: with a PadRIO present the key-bridge
block that consumes the cycle is skipped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018SgmXGNMXavXiafKXf9MDC
This commit is contained in:
co-authored by
Claude Opus 5
parent
43777569f9
commit
4ccc2a7eec
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
# =========================================================================
|
||||
# Sauron: "toggled through advanced controls from standard to advanced and
|
||||
# back to standard -- lost torso control."
|
||||
#
|
||||
# THE MECHANISM (@004afbe0, the binary's CycleControlModeMessageHandler):
|
||||
# the mode cycles 0 Basic -> 1 Standard -> 2 Veteran -> WRAPS TO BASIC. So
|
||||
# getting from Veteran/"advanced" back to Standard PASSES THROUGH BASIC, and
|
||||
# the Basic arm re-centres the torso.
|
||||
#
|
||||
# The port set that re-centre with CommandRecenter() -> centerCommand (@0x208).
|
||||
# That is the HELD-BUTTON cell: TorsoSimulation re-arms `recenterActive` from
|
||||
# it EVERY frame it is non-zero and only the input path clears it -- and a mode
|
||||
# switch has no button release to follow. One visit to Basic pinned it at 1
|
||||
# forever. Digital twist commands are processed BEFORE the centerCommand
|
||||
# block, so they were overridden as fast as they were applied = "lost torso
|
||||
# control". The binary writes recenterActive (@0x274) instead: a ONE-SHOT that
|
||||
# self-clears on settle and is cancelled by any twist input.
|
||||
#
|
||||
# THE MEASUREMENT. BT_MODECYCLE_EVERY=<n> cycles the control mode every n mapper ticks
|
||||
# frames from that frame. BT_TORSO_LOG's gate probe now prints the two cells:
|
||||
# [torso] ... ctrCmd=<centerCommand> recen=<recenterActive> vLim=(lo..hi)
|
||||
#
|
||||
# PASS: ctrCmd stays 0 across every cycle (the one-shot is used instead), and
|
||||
# vLim SWAPS between the Basic pair and the assisted pair as the mode
|
||||
# changes -- proving the elevation-limit swap (@0x228/@0x22C vs
|
||||
# @0x230/@0x234) that the port previously never implemented.
|
||||
# FAIL: ctrCmd latches to 1 after the first pass through Basic and never
|
||||
# returns to 0 -> the torso re-centres forever.
|
||||
#
|
||||
# Single node: this is entirely local control state, no peer needed.
|
||||
# =========================================================================
|
||||
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 mc_a.log
|
||||
bt_expert_egg MP.EGG MC.EGG
|
||||
sed -i "s/^map=.*/map=grass/; s/^time=.*/time=day/; s/^vehicle=.*/vehicle=madcat/" MC.EGG
|
||||
|
||||
( export BT_MODECYCLE_EVERY=400
|
||||
export BT_TORSO_LOG=1 BT_KEY_NOFOCUS=1 BT_KEY_BRIDGE=1 ${LEGACY:+BT_LEGACY_MODE_RECENTER=1}
|
||||
bt_launch mc_a.log MC.EGG 0x03 )
|
||||
sleep 150
|
||||
bt_kill_ours; sleep 2; taskkill //F //IM btl4.exe > /dev/null 2>&1; sleep 3
|
||||
|
||||
echo "=================== CONTROL-MODE TORSO STATE ==================="
|
||||
echo "--- the mode cycles that happened ---"
|
||||
grep -a "\[mode\] control mode" mc_a.log | head -10
|
||||
echo
|
||||
echo "--- centerCommand must NEVER latch (ctrCmd=1 with no button = the bug) ---"
|
||||
echo -n " samples with ctrCmd=1 : "; grep -ao "ctrCmd=[0-9]*" mc_a.log | grep -c "ctrCmd=1"
|
||||
echo -n " samples with ctrCmd=0 : "; grep -ao "ctrCmd=[0-9]*" mc_a.log | grep -c "ctrCmd=0"
|
||||
echo
|
||||
echo "--- the elevation-limit SWAP (should differ between Basic and assisted) ---"
|
||||
grep -ao "vLim=([^)]*)" mc_a.log | sort | uniq -c | sort -rn | head -5
|
||||
echo
|
||||
echo "--- torso state around each mode change ---"
|
||||
grep -aE "\[mode\] control mode|ctrCmd=" mc_a.log | grep -aA1 "\[mode\]" | head -12
|
||||
Reference in New Issue
Block a user