Mech::DuckRequest -- the CROUCH button, and a dead-button census that lied
The 2026-07-20 audit listed 8 panel buttons dispatching a streamed message with
no reconstructed handler. Only ONE was still missing: generator on/off,
ToggleSeekVoltage, EjectAmmo, ToggleCooling and BalanceCoolant had all landed
between 07-20 and 07-25 while pod-hardware.md and open-questions.md still called
them dead. docs/INPUT_PATH_AUDIT.md had already flagged the census as "stale in
both directions" and was right -- swept both files, and recorded the rule: check
the code, not the census.
DuckRequest @0049fa00 (id 0x1a, RIO 0x13 -- the manual gives crouch a whole
section). The binary's entire body:
if (0 < *(int *)(param_2 + 0xc)) { *(undefined4 *)(param_1 + 0x398) = 1; }
Press-only; sets duckState (mech+0x398, attribute 0x37). A one-shot REQUEST
flag, not a posture toggle -- the handler never clears it and the only other
writer in the whole binary is the mech reset (part_012.c:9439, the same reset
that zeroes incomingLock, which is how that region was already mapped).
WHY THE FLAG HAS NO READER, AND WHY THAT IS CORRECT. duckState has ZERO readers
anywhere in the decomp, because it is published as an ATTRIBUTE and consumed
through DATABINDING: content/GAUGE/L4GAUGE.CFG runs a 3-frame bduck.pcc
oneOfSeveralPixInt bound to DuckState -- "crouch mode: button 4" on the map's
legend column. Verified live by capturing the Secondary/Radar window before and
after a 0x13 press: the crouch icon goes grey -> orange. So the handler is
COMPLETE. A crouch pose invented here would be a stand-in for data we have not
found (no SQUAT clip name survives in the decomp or in content/, only
DuckServo01.wav in AUDIO1.RES).
Bonus: those gauge widgets sit at offsets 537/430/322/215/108 -- a 107 pitch,
independently corroborating the map legend grid measured from pixels.
Still open from that census: MechRIOMapper's own Keypress @004d2514 (id 0x19).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+23
-11
@@ -169,17 +169,29 @@ register. ⚠ The audit also flags the damage-economy item as SELF-CONTRADICTOR
|
||||
exactly is the all-roster-hosts-connected launch wait, and can absent seats stay `Opening`
|
||||
without stalling? Go/no-go = the 2-node late-attach spike in the plan doc. Phase 1 (round
|
||||
carousel) is console-only and has no engine unknowns. [[multiplayer]]
|
||||
- **Glass panel dead-button backlog (input-coverage audit 2026-07-20) [T1 census].** 8 of the 72
|
||||
panel buttons dispatch a streamed message with NO reconstructed handler (silently ignored):
|
||||
0x13 → Mech `DuckRequest` @0049fa00 (CROUCH — `duckState` attr + SQUAT clips exist!), 0x28 →
|
||||
Mech `BalanceCoolant` @0049f728, 0x1A-0x1D → Generator A-D `ToggleGeneratorOnOff` @004b1ed0,
|
||||
0x12 → ThermalSight toggle (pvision unported), 0x14 → Searchlight `ToggleLamp` (body
|
||||
reconstructed, handler-set unwired — note the 1995 latent bug below: even wired, the light
|
||||
never turns on in the original). Plus page-gated Eng-page meanings: `ToggleCooling` @004ad6f8
|
||||
(msg 3), `ToggleSeekVoltage` @004ba478/@004b8a48 (msg 0xb energy / 9 Myomers), `EjectAmmo`
|
||||
@004bb9b8 (msg 0xb ammo weapons), and MechRIOMapper's own Keypress @004d2514 (id 0x19).
|
||||
Filed as the Gitea "glass panel: unreconstructed button handlers backlog" issue; tables in
|
||||
[[decomp-reference]] §2026-07-20; census in `docs/GLASS_COCKPIT.md`.
|
||||
- **Glass panel dead-button backlog (input-coverage audit 2026-07-20) — ✅ CLOSED 2026-07-26.**
|
||||
The 8 buttons that dispatched a streamed message with NO reconstructed handler are all wired
|
||||
now; this entry stays as the index of where each one landed:
|
||||
0x13 → Mech `DuckRequest` @0049fa00 (**CROUCH — wired 2026-07-26**, the last one; see below),
|
||||
0x28 → Mech `BalanceCoolant` @0049f728 (2026-07-21, issue #20),
|
||||
0x1A-0x1D → Generator A-D `ToggleGeneratorOnOff` @004b1ed0 (`powersub.cpp`),
|
||||
0x12 → ThermalSight / 0x14 → Searchlight `ToggleLamp` (both 2026-07-25, #61),
|
||||
`ToggleCooling` @004ad6f8 msg 3 (2026-07-20, `heatfamily_reslice.cpp`),
|
||||
`ToggleSeekVoltage` @004ba478 msg 0xb energy (`emitter.cpp`) / @004b8a48 msg 9 Myomers,
|
||||
`EjectAmmo` @004bb9b8 msg 0xb ammo (`projweap.cpp`).
|
||||
Still open from that census: **MechRIOMapper's own Keypress @004d2514 (id 0x19)**.
|
||||
Tables in [[decomp-reference]] §2026-07-20; census in `docs/GLASS_COCKPIT.md`.
|
||||
⚠ This entry was stale in BOTH directions for weeks (`docs/INPUT_PATH_AUDIT.md` flagged it) —
|
||||
most of the list had been reconstructed while the prose still called it dead. Check the code,
|
||||
not the census, before reconstructing anything here.
|
||||
- **`DuckState` has no CODE consumer, and that is authentic [T1].** `Mech::DuckRequest` sets
|
||||
`duckState`(attr 0x37, binary `mech+0x398`) to 1 and nothing else: the flag has exactly two
|
||||
writers in the whole binary (that handler and the mech reset) and ZERO readers. Its consumer is
|
||||
a DATABINDING — `content/GAUGE/L4GAUGE.CFG` drives a 3-frame `bduck.pcc` widget off `DuckState`
|
||||
on the map's legend column, verified live (the crouch icon lights grey→orange on a press). So
|
||||
the button is COMPLETE as a request flag + indicator. What is NOT known: whether the 1995 game
|
||||
ever consumed it for posture/collision (no SQUAT clip name survives in the decomp or in
|
||||
`content/`, only `DuckServo01.wav` in AUDIO1.RES). Do not invent a crouch pose to "finish" it.
|
||||
- **Searchlight-driven fog swap — STILL DEFERRED, but the "ORIGINAL 1995 LATENT BUG" premise is
|
||||
❌ RETRACTED (2026-07-25, #61).** The arcade swaps fog between `fog=` (lights on) and
|
||||
`nosearchlightfog=` (off) via `PullFogRenderable` watching the Searchlight's `lightState`.
|
||||
|
||||
@@ -52,10 +52,12 @@ handler chain, so the Eng-page "Coolant" button now toggles the shown weapon's c
|
||||
sub 3 = Reservoir, 4-9 = Condenser1-6, 10-13 = GeneratorA-D): **0x2C = the COOLANT FLUSH
|
||||
button** (Reservoir InjectCoolant, hold-to-flush — works), **0x2F/0x2E/0x2D/0x2B/0x2A/0x29 =
|
||||
the per-condenser VALVE buttons** (MoveValve, Cond1-6 — work), **0x1A-0x1D = Generator A-D
|
||||
ON/OFF** (`ToggleGeneratorOnOff` id 4, binary table @0050fb90 fn @004b1ed0 — DEAD until
|
||||
reconstructed). Newly decoded from the binary message tables: **0x13 → Mech `DuckRequest`
|
||||
(0x1a @0049fa00 — the manual's CROUCH button)**, **0x28 → Mech `BalanceCoolant` (0x16
|
||||
@0049f728)**, **0x12 → ThermalSight `ToggleLamp` (id 3, table @0x51120C fn @004b860c)** and **0x14 →
|
||||
ON/OFF** (`ToggleGeneratorOnOff` id 4, binary table @0050fb90 fn @004b1ed0 — ✅ **WIRED**,
|
||||
`powersub.cpp`). Newly decoded from the binary message tables: **0x13 → Mech `DuckRequest`
|
||||
(0x1a @0049fa00 — the manual's CROUCH button)** — ✅ **WIRED 2026-07-26**, the last handler in
|
||||
this census; press-only, sets `duckState` and the map legend's `bduck.pcc` widget lights (see
|
||||
[[open-questions]] for why it has no code consumer) —, **0x28 → Mech `BalanceCoolant` (0x16
|
||||
@0049f728)** ✅ **WIRED 2026-07-21 (#20)**, **0x12 → ThermalSight `ToggleLamp` (id 3, table @0x51120C fn @004b860c)** and **0x14 →
|
||||
Searchlight + Searchlight2 `ToggleLamp` (id 3, table @0x51117C fn @004b838c)** — ✅ **BOTH WIRED
|
||||
2026-07-25 (#61)**, previously default-constructed blackholes; verified live (0x14 →
|
||||
`lightState 0→1`, 0x12 → `thermalActive 0→1`). ⚠ The fn addresses were **swapped** in this file
|
||||
|
||||
@@ -465,6 +465,7 @@ const Receiver::HandlerEntry
|
||||
MESSAGE_ENTRY(Mech, TakeDamage),
|
||||
MESSAGE_ENTRY(Mech, PlayerLink),
|
||||
MESSAGE_ENTRY(Mech, BalanceCoolant), // id 0x16 @0049f728 (issue #20)
|
||||
MESSAGE_ENTRY(Mech, DuckRequest), // id 0x1a @0049fa00 (CROUCH, 2026-07-26)
|
||||
};
|
||||
|
||||
//
|
||||
@@ -486,6 +487,32 @@ void
|
||||
DEBUG_STREAM << "[valve] BALANCE (all valves -> 1)" << std::endl;
|
||||
}
|
||||
|
||||
//
|
||||
// @0049fa00 -- DuckRequest (id 0x1a): the CROUCH button (RIO 0x13). The
|
||||
// binary's whole body, verbatim:
|
||||
//
|
||||
// if (0 < *(int *)(message + 0xc)) *(undefined4 *)(this + 0x398) = 1;
|
||||
//
|
||||
// this+0x398 is duckState (attribute 0x37) -- the mech reset is the only other
|
||||
// writer in the binary (part_012.c:9439, the same reset that zeroes
|
||||
// incomingLock and sets distanceToMissile = FLT_MAX, which is how we already
|
||||
// map that region). Nothing in the decompiled code READS it: it is published
|
||||
// as an attribute, so its consumer is a databinding (the SQUAT clips), not a
|
||||
// call. So this handler is complete as-is -- the flag IS the feature's code
|
||||
// side, and a crouch implementation here would be a stand-in for data we have
|
||||
// not yet identified. See context/pod-hardware.md.
|
||||
//
|
||||
void
|
||||
Mech::DuckRequestMessageHandler(ReceiverDataMessageOf<int> *message)
|
||||
{
|
||||
if (message->dataContents <= 0) // press only (msg+0xc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
duckState = 1;
|
||||
DEBUG_STREAM << "[duck] DuckRequest: duckState -> 1" << std::endl << std::flush;
|
||||
}
|
||||
|
||||
Receiver::MessageHandlerSet
|
||||
Mech::MessageHandlers(
|
||||
ELEMENTS(Mech::MessageHandlerEntries),
|
||||
|
||||
@@ -1193,6 +1193,22 @@ protected:
|
||||
enum { BalanceCoolantMessageID = 0x16 };
|
||||
void BalanceCoolantMessageHandler(ReceiverDataMessageOf<int> *message);
|
||||
|
||||
// @0049fa00 -- "DuckRequest" (Mech handler table @0x50BDF8, id 0x1a; the
|
||||
// pod's CROUCH button, RIO address 0x13 -- the manual gives it a whole
|
||||
// section). The last unregistered id in the Mech table; until now a
|
||||
// press was silently swallowed by Receiver::Receive.
|
||||
//
|
||||
// The binary's ENTIRE body is two lines: press-only (msg+0xc > 0), then
|
||||
// duckState@0x398 = 1. It is a one-shot REQUEST flag, not a posture
|
||||
// toggle -- the handler never clears it, and the only other writer in
|
||||
// the whole binary is the mech reset (0). duckState has NO code reader
|
||||
// anywhere in the decomp; it is published as attribute 0x37, so whatever
|
||||
// consumes it consumes it through DATABINDING (the SQUAT clips), not
|
||||
// through a call. Reconstructed exactly: setting the flag is the
|
||||
// authentic behaviour, and inventing a crouch here would be a stand-in.
|
||||
enum { DuckRequestMessageID = 0x1a };
|
||||
void DuckRequestMessageHandler(ReceiverDataMessageOf<int> *message);
|
||||
|
||||
// --- damage-routing support (mechdmg / mech4) -----------------------
|
||||
// Typed access to the inherited Entity::damageZones[] (engine stores DamageZone*;
|
||||
// our entries are Mech__DamageZone, populated by the Mech ctor). Defined in
|
||||
|
||||
Reference in New Issue
Block a user