Commit Graph
91 Commits
Author SHA1 Message Date
CydandClaude Opus 4.8 e65ff3f8d7 Deploy: RP loops (no single-shot) + confirm DOSBox needs no bundled DLLs
- net-boot/loop_rp.bat: GO.BAT-style netnub loop for RP (mirror of loop.bat,
  retargeted to rpl4opt). deploy/net_rp.conf.tmpl now calls it instead of the
  single-shot netnub + DOS pause -- the deployable runs in a loop until the
  supervisor kills DOSBox (per operator: no single-shot in the product).
- DLL closure resolved: dosbox-x.exe is a 182MB STATIC build -- import table is
  only Windows system DLLs, delay-import table empty, libpng/SDL/zlib embedded.
  Nothing to bundle; wpcap.dll comes from the Npcap install. package.ps1's "no
  DLLs" case is now informational, and the plan/README note the static build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 12:06:49 -05:00
CydandClaude Opus 4.8 9df87f2c01 Deploy: pod install scaffold -- supervisor entry-point, postinstall, packaging
Network-agnostic, air-gapped pod install for the two DOSBox titles (BT/RP 4.10),
fitting the existing TeslaConsole/TeslaLauncher pod-bay architecture.

emulator/DEPLOYMENT-PLAN.md
  Full design: bridge on the one NIC (pods form a source-proven P2P TCP mesh, so
  NAT/slirp is out); launcher keeps the bay IP, the DOSBox guest bridges at
  bayIP+100 (egg/mesh/game endpoint); two-edit +100 convention (postinstall +
  console DOSBox flag); static, air-gapped, <=32 pods.

emulator/pod-launch/  (C# net8 supervising entry-point)
  Creates a Job Object (KILL_ON_JOB_CLOSE), launches DOSBox-X + the render bridge
  into it and blocks -- kill this process and both die (kernel-enforced, even on
  a hard TerminateProcess of a hung session; verified). Mode dispatch: bt/rp
  wired (also serve camera + live mission-review via egg hostType); review +
  diagnostics recognized but fail clean until their DOS launch args are known.

emulator/deploy/  (install side)
  postinstall.bat (thin elevated wrapper) + configure.ps1 (NIC detect, realnic
  bind as a contiguous letter-leading GUID fragment, game IP = bayIP+100, stable
  MAC, render net_*.conf templates, stamp WATTCP.CFG my_ip) + tokenized conf
  templates + package.ps1 (assemble the zip). Render/bind/stamp + packaging
  verified against a scratch tree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 10:36:30 -05:00
CydandClaude Fable 5 d1635d4694 Deploy: drop -SwapMFD switch -- edit the RECTS x-coords to swap MFD heads (simpler)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 19:55:06 -05:00
CydandClaude Fable 5 2d5f1562bd Deploy: -SwapMFD flag to trade the two MFD head positions (win3<->win4)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 19:53:46 -05:00
CydandClaude Fable 5 125d835a05 Deploy: pod_deploy.ps1 cockpit window layout + focus_dosbox.ps1 (renderer topmost, DOSBox focused)
Real-pod deployment launcher for the original VDB + octopus 4-head wiring:
VPX_COCKPIT borderless head windows (radar/win0 800,0; 3-color MFD/win4 1440,0;
2-color MFD/win3 2080,0; all 640x480) + the GL bridge as the main out-the-window
view (0,0, 800x600 via new BRIDGE_W/BRIDGE_H in live_bridge.py). Editable RECTS
at the top of the script for other rigs.

focus_dosbox.ps1 restores the deployment window state: renderer -> always-on-top
(WS_EX_TOPMOST, game view never covered) + DOSBox-X -> 10,10 with foreground
focus (keeps the emu thread at foreground priority so the RIO doesn't starve).
Coexist cleanly: topmost renderer stays above the focused-but-non-topmost DOSBox.
pod_deploy calls it last; re-run anytime the stack is disturbed. LAUNCH.md
documents both.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 19:44:45 -05:00
CydandClaude Fable 5 97028fc983 collab: RP runs full pod; open renderer item = RP track-decal z-fighting + vrview_gl merge points for David
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 19:31:46 -05:00
CydandClaude Fable 5 e1b63775e6 VDB-NOTES: RP heads fully verified -- all MFDs + radar correct (RP VDB DONE)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 19:24:00 -05:00
CydandClaude Fable 5 3db666f8ee Add emulator/ENV-VARS.md -- pod (L4*/DPLARG) + host emulator env var catalog
Documents L4VIDEO/VIDEOFORMAT/L4GAUGE/L4PLASMA/L4TIMER/L4SOUND/L4CONTROLS/L4DPLCFG/L4EYES/DPLARG (values, meanings, which are getenv-read vs batch-only, the L4VIDEO two-script gotcha) + the VPX_/VWE_/VDB_/VRVIEW_ host vars.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 19:09:29 -05:00
CydandClaude Fable 5 8b0933bc16 Add emulator/LAUNCH.md -- pod launch cheat-sheet (net/RP/egg confs, flags, mirror, shutdown)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 18:52:02 -05:00
CydandClaude Fable 5 ee7f680f79 NET-NOTES: one-console-at-a-time (netnub -p single session); Mac vs .NET conflict
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 18:26:22 -05:00
CydandClaude Fable 5 6a595cc565 RP VDB SOLVED: gauge bank granularity 4KB->64KB (L4GAUGE.INI) -- full displays
RP's cockpit displays decoded near-empty (top-strip only, a copy off-screen at
VRAM 0x100000) while BT's were full. Root cause was NOT the VDB decode (byte
split/palettes/stride all correct, proven by BT) but an SVGA bank-switch
GRANULARITY mismatch: RP's REL410/RP/GAUGE/L4GAUGE.INI [640x480x16] used
granularityInKB=4 vs BT's 64 on the same STB Horizon+ (CL-GD5434). DOSBox-X's
CL-GD5434 bank emulation handles 64KB granularity (BT full) but mishandles the
4KB-granular paged gauge writes, scattering them off-screen.

FIX (config, no rebuild): RP L4GAUGE.INI granularityInKB 4->64 (matches BT,
same card). VERIFIED live: VRAM content scan went from 0x0+0x100000 (top-strip
+ off-screen) to the FULL framebuffer 0x0..0x90000 populated; radar +
upper-center MFD confirmed correct, rest under reference check.

Also commits the VDB diagnostic tooling that found it (vpxlog.cpp, all
default-off): VDB_SCAN (VRAM content locator -- decisive), VDB_PALDUMP,
pixel-mask value logging, VDB_REALSTRIDE + live mode/stride/start logging,
VDB_BASE read-base override, VDB_APPLYMASK DAC-mask honoring. Full writeup in
VDB-NOTES.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 16:57:12 -05:00
CydandClaude Fable 5 1ceb0dc90f VDB-NOTES: real hardware (Jaton CL-GD5434 + MACH130 CPLD + 3x Bt477 RAMDAC)
Operator documented the physical VDB + companion card: Jaton KY2-JAX-CVGA54PCI
(Cirrus CL-GD5434) feeds a 26-pin feature-connector ribbon to an AMD/Lattice
MACH130-15JC CPLD (the ISA 0x300-0x31A port decoder + hardwired byte-lane
splitter), which drives 3x Brooktree Bt477KPJ80 RAMDACs -> one VGA stream to
the color radar + a DB25 fan-out to the 5 mono MFDs. Confirms the RE (3 DACs =
3 palette groups; Bt477 6-bit DAC = the driver's shr al,2). A component tied in
parallel to the PC front-panel reset (remote reboot or VDB known-state on
reset) is under operator research. Also: RP uses the FULL 640x480 on all 6
displays (so our top-strip decode = a framebuffer READ bug, stride/page, not
sparse RP content).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 15:52:42 -05:00
CydandClaude Fable 5 2261dd804a VDB-NOTES: full board documentation (RE from driver + HLE; physical sample exists)
Comprehensive VWE Video Display/splitter Board writeup: what it is (dumb ISA
splitter tapping the companion Cirrus Logic SVGA feature connector), the
definitive I/O register map from L4SVGA16.ASM (Secondary 0x302 / Aux1 0x30A /
Aux2 0x312, each +0 mask/+1 read/+2 write/+3 data, 6-bit DAC; clock divider
0x319 off / 0x31A on), the byte-lane split (low byte->Secondary, high
byte->Aux1/Aux2 -> separate VGA heads -> octopus cable -> 5 mono MFDs + color
radar), the driver's bitMask+channelEnable CLUT-build trick that packs multiple
displays into one framebuffer, the pixel-mask flash + Secondary-only fade, our
emulation, the OPEN RP decode problem, and a physical-sample verification
checklist (port-decoder PAL, 3 RAMDACs, octopus pinout, Cirrus chip id).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 15:28:24 -05:00
CydandClaude Fable 5 e1b43fb6d5 Bridge: VRVIEW_MIPMAP option + launch_pod -Mipmap flag (RP checkerboard shimmer)
RP's high-frequency checkerboard track floor aliases/moires without mipmaps
(reads as "flashing geometry" in motion; user's texture-interpolation call).
vrview_gl _tex() now builds mipmaps + trilinear/anisotropic filtering under
VRVIEW_MIPMAP=1 (keeps point-sample look up close; off by default = authentic
i860, BT-identical). launch_pod.ps1 gains -Mipmap so it's set at BOOT -- never
restart the bridge mid-mission (GL-context churn starves the RIO ACK deadline).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 15:04:35 -05:00
CydandClaude Fable 5 68ca9b6f15 VDB: honor the VGA-DAC pixel-mask (RP drives it; BT left it 0xFF); park Mac mirror
RP experiment finding: RP runs on the BT pod emulator (shared MUNGA stack) but
its cockpit VDB heads mis-decode. Root causes captured live (VDB_PALDUMP +
vpxresp log): (1) framebuffer identical to BT (mode 0x111, 640x480); (2) RP
loads pal0 (BT's dynamic color-radar palette) as ALL ZEROS -> radar head black;
(3) RP actively drives the VGA-DAC pixel-mask register that BT leaves at 0xFF,
and pal_draw ignored it -> likely the MFD garble.

Device change: pixel-mask writes now log their VALUE on change
("# VDB pixel-mask[gN] = 0xXX"); pal_draw ANDs the palette index with the
group mask under VDB_APPLYMASK=1 (default off = BT-identical); masks default to
0xFF in vdb_reset so an un-driven group still decodes. Built clean under MINGW64.

Also: Mac Console 4.10 retired from regular use (host .NET console is the daily
driver); tap2_mirror.py PARKED with revive notes for console A/B only. The
SendToRxAdapters registry stays set (serves the .NET host console).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 14:53:22 -05:00
CydandClaude Fable 5 dd2ae57647 RP 4.10 runs on the pod emulator: net_rp.conf (netnub -f rpl4opt, shared MUNGA stack)
Red Planet 4.10 checks in to the console, accepts the egg, launches, RIO drives it, AWE sound plays -- the whole BT pod stack (VPX board, netnub, RIO, sound, plasma, IRQ10 NIC) carries over unchanged. Main out-the-window render is flyable; VDB secondary heads black/frozen (RP inits the VDB differently) and the renderer needs RP-specific work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 14:13:38 -05:00
CydandClaude Fable 5 2555c34a44 Egress hold: CLOSED (won-t-fix) -- floor lamps gone from surviving cockpits; findings preserved
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 14:00:36 -05:00
CydandClaude Fable 5 f1fdc68f5d Egress hold: Step 0 result -- ~3s is in-game (not the loop); Step 1 (3.0f->30.0f patch) confirmed as the fix
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 13:52:39 -05:00
CydandClaude Fable 5 54101957fd Egress hold: back-burner fix plan (Step0 diagnose / Step1 one-const patch / Step3 device fallback)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 13:45:23 -05:00
CydandClaude Fable 5 c93b2ed786 NET-NOTES: egress delay is compiled + two-phase; cross-build identical (no regression)
Answering "why doesn't the binary honor the 30s -- it exits in a few seconds":
disassembled the StopMission close in all four BTL4OPT builds (BTLIVE May-96,
BTRAVINE Sep-96, BTDAVE, Rel410) -- BYTE-IDENTICAL, so nothing regressed. The
dispatched (outer) handler is a re-entrant two-stage close: first StopMission
schedules itself +~3s (3.0f) and returns; the +3s re-entry runs cleanup then
calls the inner L4Application handler which lights the egress lamps and
schedules a +30s LightsOut/exit (30.0f). The 30s is scheduled after teardown
begins, so the exe is recycled by GO.BAT before it fires -- observed egress
window = ~3.4s = the 3.0f stage. The operator's remembered ~20-30s "lights on"
is entry lighting (floor lamp on game-ready->drop, 21s measured) + the
between-games boot gap, not a post-mission hold. Corrects my earlier
"authentic 30s hold" note. Tools: scratchpad btdis2.py + stopmission_cmp3.py.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 13:17:13 -05:00
CydandClaude Fable 5 6a4a46c897 NET-NOTES: egress delay FOUND in the binary -- hardcoded ~30s in the game
Disassembled BTL4OPT.EXE StopMissionMessageHandler (@0x47b864): it turns
the RIO egress lamps on (the "LightsOut"-named routine, flag=1) and
schedules the lights-out/exit for now + 30.0*timebase + 0.5 (30.0f const
@0x47b8e4). So the customer-egress window is a hardcoded ~30s timer in
the GAME, not the console and not any INI/env value -- exactly matching
the operator's memory (StopMission -> floor lights on -> ~30s hold ->
lights off -> exit -> BAT restart). Answers "the delay must be somewhere":
it is compiled in. Noted the reconcile-with-3.4s-measured task (the
tapped 154.9s sweep was likely teardown; a 90s+ tap past mission end
settles wall-time). Disasm helper: scratchpad btdis2.py.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 13:00:42 -05:00
CydandClaude Fable 5 97d73612a4 NET-NOTES: Mac console egress window also 3.4s -- venue delay = print time
Measured Console 4.10 through the mirror: mission end to lights-off is
3.4s, identical to the TeslaConsole, with the Mac printer spooling to a
file. No egress-delay key exists in any console INI. Best explanation
for the remembered venue window: the console closes after spooling the
score sheet, and on period hardware that was a 9600-baud serial print
taking tens of seconds -- the floor lights stayed on for the print
duration. The hold itself is genuinely console-gated (pod holds
indefinitely when no close arrives).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 12:24:50 -05:00
CydandClaude Fable 5 9e922ecd89 net-tools: tap2_mirror -- both console generations on the pod at once
With SendToRxAdapters serving the host .NET console, the SheepShaver Mac
console was deaf (pod frames go up instead of out to TAP members). The
mirror daemon turns TAP2's free application side into a userspace bridge
port: pod frames destined for the Mac are written into TAP2 (bridge
forwards them to TAP1/SheepShaver), and a reader thread drains the
unicasts the bridge's poisoned MAC table steers into TAP2 and re-injects
them where the pod's pcap hears them. Loop guards: no pod-sourced
re-injection + short frame-hash dedup. Verified live: Console 4.10
readied the pod through the mirror while the .NET console path stayed
intact -- operator can now alternate between the 1996 Mac console and
the modern one without touching the driver config.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 12:16:50 -05:00
CydandClaude Fable 5 eef8784030 NET-NOTES: floor-lamp choreography measured -- egress window = console's call
RIO tap capture of a full TeslaConsole mission cycle: LampFloor 0x3E +
entry cluster (0x16/0x17/0x1e) bright at game-ready (customer entry),
off at mission drop, bright again at mission end (the state=2 hold),
all swept off the moment StopMission arrives, then game exit. The
egress window is purely the gap between mission end and the console's
StopMission send (measured 3.4s with TeslaConsole vs Console 4.10's
proper customer-exit delay) -- not a game timer, not the exit code.
Confirms the operator's remembered sequence byte for byte and pins the
TeslaSuite fix: a configurable delay before StopMission.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 12:02:43 -05:00
CydandClaude Fable 5 cfd368381b NET-NOTES: post-mission egress hold decoded (RIO lamps + StopMission exit codes)
Wire + source answer to "what happens after the mission ends": the game
fades to the black hold, commands the RIO egress lamps (T 84 LampRequest
caught on the serial tap), and holds while its StateResponse to the
console's 1/s StateQuery flips to state 2. The hold ends only when the
console sends Application__StopMissionMessage with an ExitCodeID -- a
full remote-operations menu (run game/test patterns/ResetRIO/Norton/
SoftwareReset/camera/mission review) that the game hands to netnub as
its exit code for the pod loop to dispatch. The egress-hold length is
entirely the console's decision. Also documented the seat-trim-inside-
hull z-fighting lookalike (not a render bug).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 11:02:18 -05:00
CydandClaude Fable 5 a8eb10dc33 NET-NOTES: modern .NET console milestone -- hands-free mission loop
The TeslaSuite console connected near-instantly over the new host
bridge, queued and ran a real 2-minute mission on the DOSBox pod, and
the mission exited on time. Wire-logged recycle: clean FIN/RST teardown
at mission end, console SYN-retrying 11s later, riding through dead-air
and connection-refused (pre-TCP_LISTEN) phases, reconnected 54s after
teardown with zero operator interaction. Modern console + net_loop.conf
pod = fully autonomous mission loop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 10:51:37 -05:00
CydandClaude Fable 5 384418f385 NET-NOTES: host-side console bridging WORKING (bridge IP + Npcap SendToRx)
Windows host apps can now talk to the pod directly: static 200.0.0.1/24
on the Network Bridge adapter plus the Npcap SendToRxAdapters registry
value for the bridge GUID (driver-start read, so bounce the npcap
service and relaunch the pod). Verified with a host TCP connect to
200.0.0.113:1501. Documented the trade (pod frames go up to the host
stack INSTEAD of out to the TAP members -- SheepShaver console is deaf
while set), the revert, and the future both-at-once fix (Npcap >=1.83
user-mode DLLs + a second per-handle MODE_SENDTORX send handle in the
fork's pcap backend). Groundwork for the TeslaSuite .NET console
driving the DOSBox pod.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 10:44:45 -05:00
CydandClaude Fable 5 a1c3363f0b NET-NOTES: console between-missions behavior characterized + host bridge plan
Three-mission live session on net_loop.conf: the pod side is fully
retail-faithful (netnub auto-relaunches on mission end AND console
disconnect, ~60s cycle). Console 4.10's between-missions dead-end is
app-level: its TCP receives FIN+RST from the fresh netnub yet the app
never re-queries; only an app relaunch (endpoints rebuilt from the INI)
recovers it. Selecting a printer in the Chooser makes the app launch
much faster (Printing Manager stalls without one) but does not change
the dead-end. Documented the working operator rhythm and the plan for
bridging the host-side .NET console onto the pod LAN (bridge adapter
IP 200.0.0.1/24, possible Npcap SendToRx for pod->host hairpin).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 10:24:17 -05:00
CydandClaude Fable 5 162fa39117 Death camera: forensics, capture, and probes (fix not yet applied)
Pilot sees the escape-pod/wreck interior at death instead of the portal
ride. Findings (DEATH-SEQUENCE-NOTES.md): two death variants exist --
respawn deaths transit the chain camera to the portal at the origin
(fp_cam's <100m vehicle-distance guard rejects exactly that ride = the
fix target); mission-end deaths (tonight's capture) have no transit on
the wire at all, just the fog fade at the wreck. At death the 0x1f
articulation batches switch to driving origin-anchored nodes = the
portal diorama animating; type-3 view flushes decode as projection+fog
only (hither/yon at floats 12/13). Reference capture
captures/netdeath-20260708.fifodump (full networked mission incl. death)
+ replay probes in probes/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 00:13:12 -05:00
CydandClaude Fable 5 1b041d5a9e Bridge: frame coalescing -- the view can no longer fall behind real time
The main loop rendered EVERY draw_scene in arrival order, so any render
slowdown played the mission slower than real time and the view drifted
seconds behind the game (user: "renderer fell way out of sync"); the
backpressure hides in the socket, so backlog= stayed 0. Now each pass
slices all complete records, applies every state record in order, and
presents only the newest frame; superseded presents are counted in the
new skipped= report field. Live verdict over a full mission:
frames=10169 skipped=3 backlog=0B -- locked to the wire.

Also from the tuner session: seat trim granularity 0.1 (0.5 was too
jumpy) and a HUD size trim (vrview_gl u_scale + VRVIEW_HUDSCALE env,
live +/- keys) -- tuners stay enabled for pilot feedback; seat trim
turns out to be per-mech (Mad Cat vs Thor want different values).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 00:13:11 -05:00
CydandClaude Fable 5 2233441812 Net: NIC off IRQ 3 (plasma COM2 owns it) -- pod no longer goes deaf in-game
The plasma serial2 addition put COM2 (IRQ 3) in conflict with nicirq=3:
netnub phase worked, then BTL4OPT opened the plasma port and NIC RX died,
so the pod never checked in to the console. NIC now on IRQ 10 in all net
confs + NET.CFG INT 10 (both sides must agree). Verified live: two full
console missions with plasma running.

Also: launch_pod.ps1 prepends the Npcap dir to PATH itself (a bare shell
gave "NO PACKET DRIVER FOUND"); net_diag.conf = packet-stack-only boot
with the NCSA Telnet suite on E: for DOS-side TCP tests; net_loop.conf
promoted to full production parity (sound + plasma + IRQ 10) -- the
GO.BAT-style instant netnub relaunch is also what lets the console
recover its zombie TCP session between missions (see NET-NOTES).
NET-NOTES: full 7/08-09 forensics writeup (TAP RX counter lie, console
IP .10, SBK re-upload measured, zombie-session mechanics).
LAST.EGG = the operator's missions from tonight's runs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 00:13:11 -05:00
CydandClaude Fable 5 419c7d5d63 Pick: authentic per-instance INTERSECT mask replaces the interim gates
Instance body word 9 is the INTERSECT mask (verified live: terrain,
sky, buildings and enemy replicant mechs carry 0xffffffff; the player's
own mech parts, laser beams, missiles and effects carry 0). The raycast
now ANDs it against the query mask from the 0x26 arm -- exactly the
real board's exclusion. The min-range and hidden-until-armed gates
retire: point-blank enemy hulls are targetable again, and own-ordnance
exclusion is authored by the game itself.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 20:46:40 -05:00
CydandClaude Fable 5 c5659b8d3e Bridge: pre-movement camera, munga yaw fix, fogged background; net conf plasma
- fp_cam works before the first vehicle articulation (a freshly dropped
  mech sends no 0x1f until it moves; bailing out left the raw chain
  convention showing the inside of the mech at every drop)
- The FLYK stand-in +90-deg yaw correction no longer applies to munga
  content (it yawed the player's own mech -- and every animated model --
  90 degrees: "looking through the right shoulder")
- With fog on, the clear colour saturates to the fog colour (background
  at infinite distance); the pre-drop hold is FULLY black, as period
  pilots confirm
- net_full.conf: COM2 plasma passthrough + setenv plasma flag

Networked console session verified live: black hold at ready, flash +
fade on console launch, drop-bay doors present, own mech visible, and
the full death sequence captured on the wire (fade-to-black, escape-pod
interior via near-fog exemption, world reload, white flash, blue-violet
respawn fade = the blue swirly's home).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 19:15:04 -05:00
CydandClaude Fable 5 e6ebef071d Pick geometry completeness + the audio crackle root cause
Device raycast/scene parser (vpxlog.cpp):
- Connection lists: accumulate the WHOLE batch before slicing (records
  straddling burst boundaries were dropped + misaligned the rest), do
  not wipe polys per batch header (floor ships tri batch + quad batch;
  only the last survived), keep every loop index (closing-dup drop
  halved each quad). Together these were the "holey ground" the
  range-finder fell through.
- Own-mech exclusion by minimum pick range (15) instead of the
  dcs_parent ancestry walk: sibling link edges made the FLOOR and SKY
  read as the player's subtree, so ground/sky aims never resolved.
  Measured: own barrels/flash live within ~8 of the eye; sky/ground
  are real pickable entities (sky.mod, afloor) -- firing into them
  fires and misses, per the operator's arcade experience.

EMU8000 core (emu8k.cpp): clamp the oscillator output after cubic
interpolation. Crest overshoot on UNFILTERED voices overflowed int32
in the volume multiply and wrapped the crest negative for 1-3 samples
-- the speech/effects crackle (recorded signature: +0.7 flipping to
-0.7 at crests, random phase vs the chunk grid). Filter paths already
clamped; the bypass path now matches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 15:16:40 -05:00
CydandClaude Fable 5 d88d9212c0 Aim pipeline: all-LODs raycast, always-answer picks, own-mech exclusion
The stale-aim saga, root-caused live with the operator:

- The device raycast walked only lod[0] of each object; BT content is
  authored ADDITIVE_LODS (arena wall = posts lod + panel lod), so the
  aim ray flew BETWEEN the skeleton pieces of whatever was targeted --
  94% miss rate (pick stats now log this).
- Misses fell back to a plain frame ack carrying no sect data, so the
  game kept a seconds-old target: "aim updates every few seconds",
  stationary shots stale. The pick is now answered EVERY armed frame;
  a miss is a valid all-zero reply that clears targetEntity (aiming at
  open sky un-targets -- authentic misfire, not stale fire).
- Raycast walks ALL lod children; own-articulation exclusion via the
  CAM backchannel 7th field (vehicle root DCS) stops mid-volley picks
  of the player's own muzzle flash / arms.

Renderer: same ADDITIVE_LODS fix -- when every LOD switch window is
the degenerate (0,1e9) fallback, draw the union of all lods. The
arena wall ring (user-confirmed live) went from floating post slivers
to the full textured wall. Bridge reports its wire backlog.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 14:33:50 -05:00
CydandClaude Fable 5 351cce26b3 AWE32: VWE_AWE_WAV crackle-hunt recording taps
Three WAVs written from the render thread: per-card PRE-limiter
streams as float32 (clipping baked in upstream shows as flat tops
above full scale) and the POST-limiter int16 mix (what the user
hears). Headers re-patched every second so files survive a hard
kill. launch_pod.ps1 arms it into the work dir by default.

Diagnosis logic: flat tops in a card tap = per-voice clipping inside
the EMU8000 core; clean cards + dirty mix = limiter artifact; all
clean = winmm path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 14:06:11 -05:00
CydandClaude Fable 5 ab4a5b8702 Ravine mission egg + conf (the WALLED arena, per BTL4.RES map decode)
BT411's mapscan (full RES container format) run against our RES settles
the walls question: arena1/arenall and arena2/arenall2 place the open
city set only; the wall1/2/3 segments belong to the RAV map (18+8+5
placements: a canyon maze), and cavern/grass/dbase carry the wall10k
outer ring. Nothing was ever dropped by the renderer.

TESTRAV.EGG = TESTARN.EGG with map=rav; gauge_rav_sound.conf boots it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 13:38:29 -05:00
CydandClaude Fable 5 b2f0becbd4 Document Live Cam + Mission Review architecture (CAMERA-REVIEW-NOTES.md)
Researched from the readable RP MUNGA source (BT shares the engine):
host roles are assigned per-IP in the mission egg (hostType= on each
pilot page); a CameraShip/MissionReview host gets a CameraDirector
player that auto-cuts to the top-ranked pilot every 10s, with manual
flight via the same cockpit hardware as pods (CameraRIOMapper) and
fixed clamped trackside cameras authored in-game into MAPS/<map>.cam.
Mission Review records raw NetworkPackets (SpoolFile -> last.spl) and
replays them through a networkless playback app with timestamp bias --
the replay re-simulates the battle from replication traffic.

Same BTL4OPT.EXE serves every role; standing up Live Cam on the
emulated pod LAN is an egg edit, not a build.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:21:46 -05:00
CydandClaude Fable 5 6853b123ed Confs: default L4TIMER to FAST (setenv arg2 s->f, all 14 launch confs)
L4TIMER selects the game clock (L4TIME.CPP): FAST = HMI SOS interrupt
clock at 28 Hz, unset = polled 18.2 Hz BIOS tick. Not a speed switch --
finer time quantum, smoother sim dt and timing cadences.

Per the operator: the flag tracked the deployed fleet's hardware --
original Tesla pods ran Pentium Pro 90s (SLOW), later fleets Pentium
Pro 200s (FAST). The emulated pod has no ISR-headroom constraint, so
FAST is our default from here on.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:10:08 -05:00
CydandClaude Fable 5 cbf7015620 Weapon visuals + aim: beams render from the guns; pick self-target fixes
Renderer (dpl3-revive/patha):
- Instance visibility honored at DRAW time (stored word 4 = live
  dpl_SetInstanceVisibility field): laser beams (4-frame pulses) and
  missile models now render; cache tags w3 0/1 instances 'gated'
- PSFX world bursts (dcs=0 muzzle/impact/explosion) rendered; psfx
  storage list-based so one-shot bursts stop collapsing onto one key
- fix_degenerate applied to INSTANCE chains (was camera-only): the
  beam chain rides four rank-2 rig DCSs; composed rank-2 drew beams
  away from the guns. Offline f1635 now shows both arm beams
  converging on the aim point
- First-person canopy cull: the always-armed cockpit model at the
  head drew as a vertical line down screen center (user-confirmed
  fixed live)

Device (vpx-device/vpxlog.cpp):
- CAM backchannel on the fifosock: bridge streams its validated
  camera (+ vehicle root DCS); raycast_pick aims along the player's
  real look instead of the static view-node pose, which had locked
  every missile/beam onto one fixed wrong world point
- raycast_pick skips hidden-until-armed instances and the player's
  own articulation subtree: picking own beams created a target
  feedback loop, picking own missiles retargeted salvos mid-flight,
  and a picked missile's deleted DCS froze the game (arena2 crash)

Sound (vpx-device/vweawe.cpp): stereo-linked peak limiter replaces
the hard output clamp (the "generator out" crackle); VWE_AWE_LOG
reports pre-limit peaks + duck counts, enabled in launch_pod.ps1.
Missile-fire crackle persists: per-voice EMU8000 clamp suspected.

Eggs/confs: TESTAR2.EGG + gauge_arena2_sound.conf (map=arena2 city
variant); cavern.egg (console-era reference); plasma display on COM2
in the gauge confs; gauge_arena_net_sound.conf (slirp net stack).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 00:09:03 -05:00
CydandClaude Opus 4.8 2bb2ff7302 Weapons fire; hat-glance + MFD fixes; windowless bridge
vpx-device/vpxlog.cpp -- WEAPONS FIRE. The game's fire gate is
targetReticle.targetEntity (mech+0x388), filled every frame by a Division-board
reticle pick (dpl_RapidSectPixel) our HLE never answered, so every shot
misfired. The device now casts the camera centre ray against the live scene
(Moller-Trumbore) and returns the full hit -- instance + DCS + geogroup +
geometry -- piggybacked on the draw_scene reply; terrain is a valid target so
you can fire and miss. Sending geogroup=0 was hanging the game (GetAppSpecific
on a null); returning the real geogroup fixed it. Pick is default-on with a
single VPX_NO_PICK escape hatch. Also swaps the upper-left/right MFD explode
windows (screen location only -- decode untouched, real cause TBD on a pod).

dpl3-revive/patha/vrview.py -- HAT-GLANCE fix at the source. One cockpit DCS
(0xa2c) flushes a rank-2 rotation (shifted body -> wrong read window) that
collapsed the camera chain to rank 2 and smeared the head glance onto the wrong
axis (left/right hat read as pitch). chain_matrix(fix_degenerate) treats a
degenerate chain DCS as identity: preserves the look exactly and keeps stick-Y
torso pitch working (an earlier bridge-level yaw/pitch swap broke stick-Y and
was reverted). User-verified live: hat all 4 dirs + stick-Y both correct.

render-bridge/launch_pod.ps1 -- launch the bridge with pyw (windowless) so no
console window parks over the cockpit displays (Start-Process ignores
-WindowStyle once stdout/stderr are redirected).

render-bridge/live_bridge.py -- surface bridge render errors, flush the status
line; reverted glance-swap note.

Also vendored HUD (dpl2d) renderer work in vrboard/vrview_gl and RENDERER-COLLAB
/ RIO notes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 09:53:14 -05:00
CydandClaude Fable 5 c18c253658 RIO: document the board init handshake (test-mode + version) for vRIO
Decoded from L4RIO.CPP/HPP and verified byte-for-byte against a real
v4.2 board tap: CheckRequest 80 -> board must send TestModeChange ENTER
(8C 01 0D), self-test status stream (85 <status> <unit> <ck>), EXIT
(8C 00 0C), then answer VersionRequest 81 with 86 <maj> <min> <ck>.
Full command map 80-8C both directions, ACK/retransmit rules, and the
~1ms/byte 9600-baud pacing requirement. This is the implementation spec
for the user's vRIO (virtual RIO on COM1): its missing 8C packets are
exactly why the game logs 'RIO never came back from check request!'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 13:35:37 -05:00
CydandClaude Fable 5 1872799c7a VPX device: dpl3-revive shading port + wire lights; fix game-path yaw mirror
- rt_draw shading replaced with the dpl3-revive software-rasterizer model
  (vrview.py draw(), proven on our own arena captures): lit = sceneAmb +
  sum |N.L|*col double-sided; c = emis + diff*lit (tex*base*1.275 when
  textured); Division 10-bit-DAC gamma 1/1.25 on output. Default light rig
  matches theirs (ambient 0.35 + one 0.65 sun) until wire lights arrive.
- Real wire lights decoded per their SceneCache.rebuild(): lmodel type-6 /
  light type-0xe bodies (dcs @d+12, type @d+16: 2=ambient 3=directional,
  rgb @d+20), directional aim = light DCS +Z row, sanity-clamped; frame
  carries summed ambient + up to 2 suns.
- Projection: the hardcoded post-projection X flip (SMPTE-era) made the
  game view steer mirrored (turn right, view swings left). Game path
  (ydown) now projects without it -- matches dpl3-revive, which has no
  lateral mirror; demo/test path keeps the flip. User-verified: native
  window steering now correct.

Fork source (emulator/src/src/hardware/vpxlog.cpp) in sync; rebuilt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 13:34:17 -05:00
CydandClaude Fable 5 0f5b2e28da Renderer: vendor live-bridge scripts; GPU backend unblocked (60fps)
- emulator/render-bridge/: the pod->Dave's-renderer live bridge (rescued
  from session scratchpad): live_bridge.py (first-person cam from the 0x1f
  pose, arrow-key eye-height trim), fp/chase offline renders, fifobridge,
  diagnostics, gauge_arena[_sound].conf, and launch_pod.ps1 (one-command
  pod+bridge restart: pentapus VPX_EXPLODE + AWE32 sound + GL bridge).
- _backend.py: renderer selection -- vrview_gl.GLRenderer (moderngl) by
  default, VRVIEW_SOFT=1 for the software reference; backend-agnostic
  frame save via last_frame.
- GPU backend runs on side-by-side CPython 3.13 (moderngl/glcontext cp313
  wheels; no MSVC needed): 63fps headless / 60.7 windowed vs 21fps software
  on the same scene, and the GL path also draws the vertex-alpha cloud dome.
- vrview.py: VRVIEW_GAMMA env selects DAC gamma (1.25 live-renderer legacy
  vs 1.7 per the original GAMMA.C) for A/B against the real pod.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 13:34:02 -05:00
CydandClaude Fable 5 9536d4cbc0 NET: full networked mission runs end-to-end; fix blank VDB heads (NIC/VDB port clash)
Console queues a mission -> egg over the wire -> pod loads + runs it -> all
cockpit heads render -> mission ends on the console timer. Four fixes:

1. ne2000.cpp: don't BX_PANIC on the TCR inhibit-CRC / auto-tx-disable bits.
   A full production boot runs the packet driver's internal loopback
   self-test, which sets those bits; Bochs' NE2000 aborted the whole
   emulator. Record them in TCR state instead (harmless for an emulated NIC;
   pcap/host does framing+CRC). Also fixes a latent coll_prio bit-4 vs bit-3
   round-trip bug. Committed copy in vpx-device/.

2. Confirmed the mission-load page fault (00FF:219D) was RIO-OFF; booting
   with the RIO live (net_full.conf) loads and runs the mission cleanly.

3. net_loop.conf + net-boot/loop.bat: GO.BAT-style loop so the pod stays
   connected to the console and picks up missions as they're queued (the
   real pod relaunches netnub after each mission/idle disconnect).

4. HEADLINE: blank MFD/radar heads were an I/O port collision. The VDB
   video splitter is hardwired at 0x300-0x31A (palettes 0x300/0x308/0x310);
   the NE2000 at nicbase=300 swallowed the game's VDB palette writes ->
   vdb_pal stayed zero -> pal_draw decoded every head to black. Same VDB
   spam corrupted NIC RX, dropping the console EndMission (mission overran
   its timer). Fix: move the NIC to 0x340 (DOSBox nicbase=340 + DOS NET.CFG
   PORT 340; must agree). VDB keeps 0x300. Config-only, no rebuild.

Adds: net_full.conf, net_loop.conf, net-boot/ (ODI drivers, NET.CFG@340,
loop.bat, README), vpx-device/{ne2000,ethernet_pcap}.cpp; updates NET-NOTES.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 21:18:42 -05:00
CydandClaude Opus 4.8 e12bfe1d3a NET milestone: real console->pod mission egg over the wire (+ mission-load crash)
Captured a real mission egg delivered from the SheepShaver console to the
DOSBox pod on TCP 1501, no -egg bypass: 8x ReceiveEggFileMessage chunks,
7514 bytes, reassembled byte-perfect (declared notationFileLength=7514).
The egg is the operator's own mission (BattleTech / cavern / night /
freeforall, pilot "cyd", vehicle madcat). This closes the networking
workstream end to end.

- net-tools/decode_egg.py: reassemble an egg from a captured console->pod
  TCP payload hex dump (skips interleaved StateQuery polls).
- net-tools/captured_cavern_mission.egg: the delivered egg.
- NET-NOTES.md: milestone writeup + the pod's mission-LOAD crash. The pod
  faults loading the mission (page fault, wild ptr 0xFF008B5B, exception
  000E at game 00FF:219D, NetNub Munga exit 14) -- a game-side bug in the
  mission-load path, separate from networking. Leading suspect: RIO was
  disabled for this run and the player vehicle/control setup derefs null.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 17:41:34 -05:00
CydandClaude Fable 5 bda2f7b8b3 Networking WORKS: real console <-> real pod over the emulated wire
The emulated SheepShaver console and DOSBox pod now exchange the live
console protocol on TCP 1501. Required chain: rebuild the DOSBox pcap
backend + launch with C:\Windows\System32\Npcap on PATH (npcap DLL
location); a two-TAP Windows bridge (single shared TAP fails); TAP2
MediaStatus=Always-Connected; and binding the pod's pcap to the BRIDGE
MINIPORT (not a member TAP -- member-injected frames aren't re-forwarded),
via realnic=DB5521D (letter-leading GUID fragment; leading-digit is parsed
as an interface index). Captured + decoded the real protocol values
(StateResponse clientID=5/flags=1/host=0/state=1/app=1=BattleTech), which
corrects the earlier synthetic guesses. Full writeup in NET-NOTES.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 17:14:48 -05:00
CydandClaude Fable 5 929b6bc267 Networking: add egg_capture.py — console->pod protocol capture tool
Listens on TCP 1501 as a stand-in pod, logs the console's egg-delivery
bytes, and auto-decodes each NetworkPacket in both byte orders to pin the
framing + PPC/x86 endianness (the two open caveats). Works whether the
console reaches it via a slirp gateway redirect or a bridged segment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 23:17:15 -05:00
CydandClaude Fable 5 5a2c4b589f Networking: note console VM standup (SheepShaver/OS9.0.4) + TAP bridge plan
Records that Router mode is NAT (won't reach the pod) and the console<->pod
link needs bridged TAP on both ends: console TCP/IP manual 200.0.0.1, pod
DOSBox-X switched from slirp to pcap on the same segment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 23:11:46 -05:00
CydandClaude Fable 5 b86fea71e0 Networking: determine Console 4.10 OS compatibility from the binary
PEF imports (InterfaceLib/MathLib/ObjectSupportLib only; no AppearanceLib,
no Open Transport libs) plus the resource-fork "MacTCP or OpenTransport"
Gestalt check show it is a classic PPC PowerPlant app: runs System 7.1.2
through Mac OS 9 (practical floor 7.5), classic MacTCP API but happy with
either stack. Recommended SheepShaver target: System 7.5.5/7.6.1 with a
7100/7500/8500 old-world ROM, TCP/IP set to 200.0.0.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 22:35:01 -05:00