Render bridge (live_bridge.py, vrview_gl.py): - Hat glances render (left/right frame the canopy, hat-down = clean rear). Root bug was a stale _ckpt['fix'] key -> KeyError every glance frame -> render aborted (screen froze on hold, snapped back on release). The glance itself is the authentic eye-DCS action-0x1f reflush fp_cam already applies. - Torso twist turret-true (root-axis yaw, zero parallax); lasers follow torso. - Rear glance drops the canopy shell for a clean view (original-hardware behavior); mission-fade shroud 9fd hidden. - Wireframe debug mode (VRVIEW_WIREFRAME / 'w' key), scene-pass scoped. - Renderer output = 832x512, the dPL3 board's native framebuffer res. DOSBox-X fork: namedpipe serial backend (serialnamedpipe.cpp/.h) for vRIO/vPLASMA, replacing com0com; overlapped non-blocking I/O; typed frames (0x00 data / 0x01 DTR+RTS). Tracked copies + apply steps in vpx-device. Docs: COCKPIT-CAGE-NOTES (full glance/twist/rear forensics), XP-PORT-PLAN (back-burnered), RIO-NOTES (namedpipe + keypad), pipe/egg conf variants. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pod-launch
The supervising launch entry-point for the two DOSBox titles (BattleTech /
Red Planet 4.10). TeslaConsole → TeslaLauncher invokes this exe in the game dir
with args selecting game/mode; it is the single authoritative handle for the
whole session. See ../DEPLOYMENT-PLAN.md.
Why an exe, not a batch/script
The entry-point must own the child processes' lifetime, not hand off and
exit. pod-launch:
- Creates a Windows Job Object with
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE. - Launches DOSBox-X and the render bridge into the job.
- Blocks on DOSBox for the whole mission.
Kill this process (TeslaLauncher force-killing a hung DOSBox on a console
command) → the job's last handle closes → the kernel kills DOSBox + the
renderer. This holds even on a hard TerminateProcess, where no cooperative
shutdown can run. When DOSBox exits on its own (mission end) the supervisor
tears the job down and returns DOSBox's exit code.
A batch file / cmd.exe / start / Start-Process can't do this: they decouple
from the child, which then survives the parent. Verified: hard-killing the
supervisor reaps its child via the kernel (see the job-object cascade test).
Build
Dev (needs the .NET 8 runtime present):
dotnet build -c Release
Deploy — self-contained single-file, so the air-gapped pod needs no .NET runtime installed:
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true
Console argument reference
pod-launch [mode] [options] — the single installed entry-point. The product is
installed once; the console activates features by the args it passes. The per-rig
layout is fixed at postinstall time, so a typical call is just pod-launch bt.
Mode — the primary feature selector (positional, or --mode <name>)
| Arg | Activates | Status |
|---|---|---|
bt |
BattleTech, networked cockpit (net_loop.conf, looped) |
wired |
rp |
Red Planet, networked cockpit (net_rp.conf, looped) |
wired |
review |
mission-review PLAYBACK of last.spl |
recognized, exits 3 (DOS arg TBD) |
test-plasma |
plasma-display diagnostic | recognized, exits 3 |
reset-rio |
RIO reset diagnostic | recognized, exits 3 |
audio-test |
audio test diagnostic | recognized, exits 3 |
Camera ship and LIVE mission-review are not modes — same bt/rp boot; the
console sets the role per-IP via the egg hostType (0 pod / 1 camera / 2 review),
see ../CAMERA-REVIEW-NOTES.md. Default mode: bt.
Feature toggles
| Arg | Effect |
|---|---|
--no-sound |
skip the ~4-min AWE32 SoundFont upload — freezes bt/rp: no AWE32 = no SOS ticks, and the default confs use the FAST (SOS) clock, so BTL4 hangs in the RIO-reset busy-wait (L4RIO.cpp SetDTR/Now(); root-caused 2026-07-10). Only safe with a SLOW-clock conf (setenv arg2=s) |
--mipmap |
mip-filter minified textures (fixes RP floor shimmer; non-authentic) |
--layout cockpit|explode |
cockpit = borderless VDB head windows (default); explode = 7-window debug |
--no-bridge |
pod only, no GL render window |
--no-focus |
skip the renderer-topmost / DOSBox-focus pass |
Window placement (per-rig; normally fixed, overridable per-launch)
| Arg | Effect |
|---|---|
--bridge-pos x,y |
main render window position (default 0,0) |
--bridge-size w,h |
main render size (default 832,512 — the dPL3 board's native framebuffer res; see ../LAUNCH.md) |
--dosbox-xy x,y |
DOSBox window position + focus (default 10,10) |
Path / asset overrides (dev / edge — postinstall already wires these)
--root <dir> · --conf <path> · --dosbox <exe> · --renderer <exe> ·
--bridge-script <py> · --awe-rom <raw> · --work <dir>
Diagnostics
--dry-run (resolve + print the launch plan, don't launch) · -h / --help
pod-launch bt --root C:\VWE\TeslaRel410\emulator --dry-run
Exit codes the console reads back
- normal run → returns DOSBox's exit code = the game's
ExitCodeID, passed straight through (the same remote-ops code the pod loop dispatched on). 2→ bad arguments (usage on stderr).3→ recognized mode not yet wired (reason on stderr).
Deploy layout it expects (under the game dir / --root)
pod-launch.exe dosbox-x.exe net_loop.conf net_rp.conf
renderer.exe (frozen) roms\awe32.raw <game content + net-boot drivers>
postinstall.bat lays this out and renders the net_*.conf (paths, realnic,
WATTCP my_ip = bayIP+100). This exe just selects + launches.
TODO (tracked in DEPLOYMENT-PLAN.md OPEN items)
- Wire the distinct non-networked modes once their DOS launch args are
confirmed:
review(playback app +last.spl) and the diagnostics. (The mode table inModes.csis the single place to add each.) - Swap the dev
pyw live_bridge.pyfor the frozen renderer exe once packaging is decided (freeze vs embedded Python — with David). - Per-rig cockpit head RECTS (currently the
pod_deploy.ps1defaults).