410console: BattleTech egress-hold addendum -- issue closed (~3s hold)

Decoded/disassembled finding from the TeslaRel410 side, verified against
a live DOSBox BTL4OPT pod driven by this console: the post-mission egress
window is a compiled ~3 s (stage-1 timer), not ~30 s, and byte-identical
across all four BTL4OPT builds. Marked won't-fix -- the floor egress lamps
no longer exist on any surviving cockpit. Console takeaway unchanged: send
StopMission promptly at timer end; the pod handles its own (short) close,
no egress delay to implement.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-10 16:30:28 -05:00
co-authored by Claude Fable 5
parent 13f8e0456b
commit f07df88acb
@@ -0,0 +1,109 @@
# Addendum: mission-close / egress-hold — decoded + disassembled (2026-07-10)
From the TeslaRel410 side. Verified against a live DOSBox BTL4OPT pod run
BY THIS .NET CONSOLE over the host bridge (it works). Full writeup:
TeslaRel410/emulator/NET-NOTES.md.
> **ISSUE CLOSED 2026-07-10 (won't-fix, operator decision).** The floor
> egress lamps no longer exist on any surviving cockpit, so the hold has
> no restoration value. FINAL, corrected finding (supersedes the "~30s"
> phrasing below): the pod's post-mission egress window is a compiled
> **~3 seconds** — the game exits at its stage-1 timer (Step-0 proven:
> a no-loop single-shot boot still held 3.9s then the game self-exited),
> and the deeper 30s timer is never reached. Byte-identical across all
> four BTL4OPT builds, so nothing regressed. **Console takeaway is
> unchanged and simple: send StopMission(RunBattleTech) promptly at your
> timer end; the pod handles its own (short) close. No egress delay to
> implement.** The rest of this file is preserved for the record.
## Bottom line for TeslaConsole
**The customer-egress window is a HARDCODED ~30s timer inside the GAME,
not the console.** You do NOT need to implement the egress delay. Just
send `Application__StopMissionMessage` promptly at mission end with
`RunBattleTechExitCodeID` (=3), and the pod runs the whole authentic
sequence itself: egress lamps ON -> ~30s hold -> lamps OFF -> exit ->
GO.BAT relaunch. The console's only timing responsibility is not to send
StopMission too EARLY (let the mission actually end first).
## The sequence (game side)
1. Mission end -> game fades to black hold, sends the wrap-up
(ConsolePlayerMechScoreUpdate / ConsoleBTTeamScoreUpdate /
RankAndScore). Its StateResponse to your 1/s StateQuery flips state
0 -> 2 (mission-over/hold). It waits INDEFINITELY here for you.
**CAUTION — "mission end" is NOT the pod's own clock.** Bench-confirmed
2026-07-09 (12s mission via this console): the pod does NOT self-end;
the egg `length=` only drives the cockpit clock DISPLAY, which hits 0
and counts back UP while play continues. The console is the game's
sole timekeeper — this hold state is only ever entered off the
console's close (or an in-game end condition), so in practice steps
1-2 collapse: the console's StopMission at ITS timer end triggers the
fade/wrap-up/lamps directly (see step 3).
2. You send `Application__StopMissionMessage(ExitCodeID)`.
3. `StopMissionMessageHandler` (BTL4OPT.EXE @0x47b864, disassembled):
- calls mission-shutdown/EndMission (0x44eeb4)
- turns the RIO egress lamps ON (routine @0x47bba8, flag=1; lamps
0x16/0x17/0x1e = the floor/entry cluster; the "LightsOut" string
@0x4fd5ac names this family)
- schedules the lights-out+exit for `now + 30.0*timebase + 0.5`
(30.0f constant @0x47b8e4) -- the customer-egress hold
4. ~30s later the timer fires -> lamps swept off -> game exits with the
exit code -> pod's BAT loop dispatches it (RunBattleTech = relaunch).
## Console message set + exit codes (from CODE/RP/MUNGA/APPMSG.HPP)
Messages: StateQuery, CheckLoad, RunMission, **StopMission**, KeyCommand,
SuspendMission, ResumeMission, LoadMission, Abort.
`ExitCodeID` (the game's exit status = what the pod's BAT loop runs next):
```
Null=0, Abort, RunRedPlanet, RunBattleTech, RunSinglePlayerRedPlanet,
RunSinglePlayerBattleTech, DisplayMainTestPattern, DisplayAuxTestPattern,
TestPlasmaDisplay, ResetRIO, RunAudioTest, RunNortonDiskDoctor,
CheckDiskUsage, RefreshRedPlanet, RefreshBattleTech, ChangeScreenMode,
SoftwareReset, ClearCrashlog, KillSpoolFile, RunRedPlanetCamera,
RunBattleTechCamera, RunRedPlanetMissionReview, RunBattleTechMissionReview
```
= a whole remote-operations menu the console UI could expose (RIO reset,
test patterns, plasma test, disk tools, camera/mission-review launches).
## Notes / open
- A configurable *pre*-StopMission delay is still fine to expose, but the
~30s customer window itself is the game's and is authentic at 30s.
- Measured lamp-on-to-sweep was only ~3.4s in two live runs; that sweep
was likely the teardown GeneralReset, with the real 30s timer firing
past the tap window. To confirm on the TeslaRel410 side: one mission
with a 90s+ RIO serial tap past mission end (btdis2.py found the
constant; a live tap confirms wall-time).
- Bonus authenticity: the floor lamp is ALSO entry lighting -- on from
game-ready until the mission drops (customer climbs in lit).
- Bench 2026-07-09 (12s mission): pod clock counted UP past 0 with play
continuing until the console's stop — confirms the console is the sole
timekeeper and step 1 never fires off the pod's own clock. If a
self-end path exists in the binary it wasn't reachable with our egg.
- Cross-ref: the BT411 up-port source (engine/MUNGA/APP.cpp ~1634) has a
TWO-stage StopMissionMessageHandler (stop#1 while Running -> EndingMission
+ lamps; stop#2 while Ending -> Stop()/exit; +30s LightsOut = lamps off
only). The shipping BTL4OPT.EXE disassembly above (one stop -> lamps +
scheduled exit at +30s) is authoritative for the DOSBox pod; the up-port
evidently diverges — worth knowing if BT411-built binaries ever drive a
real pod.
- A console-side "egress hold delay" (wait between console timer zero and
the StopMission send) was prototyped in TeslaConsole 2026-07-09 and
REVERTED: since the pod plays until stopped, that window is overtime
play, not lamps-on time. The game's own 30s window is the authentic
egress hold.
- CROSS-BUILD DISASM (TeslaRel410 side, 2026-07-10, stopmission_cmp3.py):
the StopMission close is BYTE-IDENTICAL across all four BTL4OPT builds
-- BTLIVE (May-96), BTRAVINE (Sep-96), BTDAVE, Rel410 -- so no build
regressed it (this settles the operator's "did Rel410 cut the hold?"
question: no). Each build's dispatched outer handler (Rel410 @0x47c2c4)
is the re-entrant two-stage one and carries BOTH a 3.0f and (via the
inner @0x47b864) a 30.0f constant. Confirms the up-port's two-stage
structure at the binary level. Whether 30s is honored live is still
open: our RIO tap saw only ~3.4s of lamp-on (the 3.0f stage) before the
exe recycled -- the 30s LightsOut may be pre-empted by teardown in the
loop-conf flow. Not console-actionable either way (prompt StopMission is
correct); noted for completeness.