Commit Graph
74 Commits
Author SHA1 Message Date
CydandClaude Fable 5 c13613e259 GL fog: per-fragment factor -- terrain/cloud no longer escape the fog
Fog was computed per VERTEX; vertices behind the eye clamped to factor
zero, and the terrain/cloud triangles are large enough to span the
camera, so interpolation dragged the whole ground to unfogged (bright
terrain through the pre-drop blackout and the respawn reveal). The
eye-space depth now rides the varying (perspective-correct) and the
factor is computed per fragment, where clipping guarantees valid depth.

Verified offline: pre-drop hold renders solid black + HUD only (matches
the period screenshot exactly); the respawn fade shows the authentic
near-first reveal from the operator's VHS (ground clear, fog wall at
distance, sky still white).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 20:32:38 -05:00
CydandClaude Fable 5 bb8978c127 Retire the near-eye cull by default: the eye-shroud is authentic content
The death sequence re-flushes the view with hither=1/yon=2 -- a thin
render shell that reveals geometry parked around the camera: the
escape-pod interior and the "blue swirly" ring dome (period VHS stills
of a 4.10 death match: violet concentric ripples, drifting center,
static canopy silhouette at the frame edge). Normal play clips the
shroud via the standard hither plane, so nothing leaks; the cull was
only masking authentic content. VRVIEW_NEARCULL=1 re-enables it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 19:53:52 -05:00
CydandClaude Fable 5 7ae11f174c HUD: dpl2d Y grows down -- unflip the whole 2D layer
Period VHS footage of a 4.10 game (operator's capture) shows the twist
dial UNDER the reticle and the range bar filling top-to-bottom; our
mapping of dpl2d Y straight onto GL's Y-up NDC (and the software path's
"y up" projection) rendered the entire HUD vertically flipped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 19:37:29 -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 817c3ad4a4 Renderer: VRVIEW_NEARCULL toggle for the near-eye cull A/B
The first-person canopy cull can now be disabled (VRVIEW_NEARCULL=0)
to study the always-armed cockpit/bay assembly from the true chain
eye -- part of the pilot-view attachment investigation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 18:24:23 -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 e7e1d72a66 Move 410console to the TeslaSuite repo
The 4.10 operations-console archive and the BattleTech-port hand-off
spec now live in C:\VWE\TeslaSuite\410console, alongside the
modernized .NET TeslaConsole they feed into.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 00:09:18 -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 afc3fd839e Vendor dpl3-revive: the Division/DPL3 renderer, now ours
Bring the graphics-dev collaborator's dpl3-revive into the repo as first-class
project code (they've handed it off; it's ours now). This is the proven
Division renderer that our in-process rt_draw has been trying to be.

What's here:
- parser/  B2Z/V2Z/SVT/SCN/SPL/BGF/BMF/BSL decoders (pure Python).
- spec/    reverse-engineered format + the definitive VelociRender wire
           protocol (from the original DIVISION source, matches our live
           VPX node/action tables exactly).
- source-ref/  read-only copies of the original DIVISION C (BIZREAD.C,
           DPLTYPES.H, DPL.H) that define the formats.
- patha/   the "virtual VelociRender board": vrboard.py (24-action protocol
           server), vrview.py (numpy software rasterizer, the reference),
           vrview_gl.py (moderngl GPU backend, 832x512@60Hz), plus the
           run/replay/regress tooling and evidence renders. Drives FLYK/BLADE/
           Star Trek demos AND our btl4opt/rpl4opt game binaries.
- viewer/  WebGL archive generators (.py); prebuilt HTML/data regeneratable.
- samples/ small test models/textures.
- bt*.raw.bin  real BTL4OPT arena wire captures (kept for offline renderer
           testing/regression against OUR game).

.gitignore keeps the multi-hundred-MB demo capture dumps + debug logs +
regeneratable viewer bundles out of history (they stay on disk).

Phase 0 of the integration is validated: their board decodes our bt8 capture
with zero errors (3748 nodes, 507 instances, 4 mechs) and renders our arena
(terrain/dome/sky, correct Division DAC gamma). Plan + status in memory;
integration continues in emulator/RENDERER-COLLAB.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 22:06:25 -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
CydandClaude Fable 5 e1d44251da Networking: decode egg-delivery protocol from source; archive console SW
Decoded the console<->pod message layout from the MUNGA framework headers
(the send/recv impl did not survive -- only headers + a test harness):
NetworkPacket = 16B NetworkPacketHeader + a Receiver::Message; the egg is
delivered as ReceiveEggFileMessage chunks (seq/totalLen/thisLen +
notationData[1000]), a full egg packet = 1040B (matches the VPX nb<=1040
cap). Console splits the mission notation file into <=1000B chunks; pod
reassembles + ACKs. Two bytes-on-the-wire details (stream framing +
PPC/x86 endianness) flagged for the first live capture. Full byte tables
in NET-NOTES.md.

Also moves the extracted console software (Console 4.10 PPC app + per-venue
Console.ini + fonts/logs, resource forks preserved) into
410console/4_10-console-extracted/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 22:21:06 -05:00
CydandClaude Fable 5 5b44ede702 Networking: console SW extracted, TCP port 1501 found, pod = Puck
Console 4.10 (PowerPC PEF/CodeWarrior) + Console.ini extracted from the
.sit. Console.ini answers the open protocol question: the console<->pod
TCP port is 1501. Full cockpit endpoint roster recorded; our emulated pod
200.0.0.113 is the cockpit Puck. The real 6100 does not boot but is no
longer needed -- run Console 4.10 under SheepShaver. Only remaining
protocol unknown is the on-stream message framing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 22:12:49 -05:00
CydandClaude Fable 5 3e838bd4c7 Networking notes: console emulator = SheepShaver (real HW is a 6100/66)
The ops console is a Power Macintosh 6100/66 (PowerPC) -> SheepShaver, with
the caveat that the 6100 ROM is incompatible (use a 7100/7500/8500 old-world
ROM; PPC apps are ROM-agnostic). Plan to leverage the real 6100: image its
drive for a faithful SheepShaver console and/or bridge it live to the
pcap-pod to capture the real egg protocol.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 22:07:10 -05:00
Cyd 49bc526732 Networking M1: pod boots on the network path (no -egg) under emulation
NE2000 + Novell ODI chain (lsl/NE2000 MLID/odipkt) works against the
emulated card (odipkt at SINT 0x60, Ethernet_II). netnub -f btl4opt spawns
the game as btl4opt
2026-07-04 21:43:00 -05:00
CydandClaude Fable 5 5e0f9c8061 Networking recon: map WATTCP/NetNub pod stack + emulator bring-up plan
The pods do TCP/IP over Ethernet (WATTCP + NetNub real-mode server;
ops console is master, pushes mission eggs to pods over TCP). Pod is a
static host on an isolated 200.0.0.0/24 LAN (200.0.0.113, console
200.0.0.1); -egg is the dev bypass of this path. Fork already has NE2000
+ pcap/slirp backends; since the emulated card is NE2000 not PCI Lance we
skip the Novell ODI chain and load a Crynwr NE2000 packet driver directly.
NET-NOTES.md has the full architecture + milestone plan (headline goal:
host-side stand-in console pushes an egg over the wire, no -egg bypass).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 21:27:10 -05:00
CydandClaude Fable 5 3d5892c00f RIO firmware: build + verify patched image (reply-wedge fix)
make_patch.py applies the two-site fix to RIOv4_2.bin (asserting original
bytes first) -> RIOv4_2_patched.bin (23 bytes changed). Re-disassembling
and diffing confirms the change is confined to $D9DD, $DA21-$DA2E, and the
$DFF0 stub with no downstream desync. Clears the reply-in-progress latch
$2521 on every teardown so a stress collision no longer leaves the board
mute to analog. Flash directly to the DIP-28 W27C512; static verification
only -- dynamic RIO_TAP mash test pending the burned chip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 21:14:07 -05:00
CydandClaude Fable 5 9fa5d101e7 RIO firmware: drop stray disasm.stderr, ignore *.stderr
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 20:42:49 -05:00
CydandClaude Fable 5 34383f3f2c RIO firmware: disassemble v4.2, find the reply-wedge root cause
68HC11 recursive-descent disassembler (disasm_6811.py, follows the
pointer-based RX/TX state dispatch) + full disassembly + analysis doc.

Root cause of the stress wedge: an orphaned reply-in-progress latch
($2521). It gates every analog request ($D758); it is set when a reply is
generated ($D84C) but the 4-retry give-up path ($D9DD -> $DA2F) tears down
reply state without clearing it, and the success teardown ($DA00) clears
it only conditionally on $2522. Once leaked, all analog requests are
dropped -> board mute, while RX/event stays alive; only the game-start
host-reset command ($C686) clears it -- matching the field button-resync
ritual exactly. Proposed minimal in-place fix (clear $2521 on every
teardown) documented with byte patches and a hardware validation plan;
untested pending a spare EPROM. RIOv4_2-ANALYSIS.md has the details.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 20:42:37 -05:00
CydandClaude Fable 5 d0b53e93dd RIO firmware notes: exact EPROM part (AM27C512-150) + replacement pick
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 20:22:14 -05:00
CydandClaude Fable 5 673cebf3b8 RIO: firmware v4.2 dump (Toshiba TMP68HC11) + first-look analysis
RIOv4_2.bin dumped from our own board EPROM (64KB, code $C000-$FFFF).
Vector table confirms 68HC11: RESET->$C000, SCI serial interrupt->$D630 =
the protocol state machine entry for the planned disassembly. Board patch
plan steps 1-2 done (RIO-NOTES.md updated); next: disassemble from the
SCI handler, find the reply-path wedge (button/event path survives it),
patch, burn to a fresh EPROM, preserve the original.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 20:21:42 -05:00
CydandClaude Fable 5 db7745fcd0 sda4: commit the Glaze developer hard-drive dump
Un-ignored: the dev drive is the ground truth the restoration and
emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer
source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio
content). Kept in-repo for the pod-owner community.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 19:41:15 -05:00
CydandClaude Fable 5 504aef88d4 ALPHA_1: commit the live production-system working tree
Un-ignored: this is the working copy the emulator actually boots (patched
BTL4OPT.EXE v4 lineage + .orig/.nop14/.pre_idle/.pre_limit backups,
TESTARN.EGG arena1 test egg, REL410 BT+RP trees, VGL_LABS pod boot bats,
VWETEST factory test suites, SB16 Creative utilities). The pristine
untouched image remains ALPHA_1.zip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 19:40:34 -05:00
CydandClaude Fable 5 a0a4260fd4 Sound: dual-AWE32 EMU8000 emulation -- the pod has audio
Vendored 86Box EMU8000 core (GPL-2, emu8k.cpp/.h + shim) plus vweawe.cpp:
two cards at the production addresses (0x620/0x640 register triplets),
rear-card DSP/mixer stub at 0x240, synthesis on an autonomous render
thread with direct winmm output so sustained voices ride through
emulation-thread stalls (RIO staging retries) like the real silicon did.
WC sample-counter interpolation between render chunks keeps HMI SOS
busy-waits fast. VWE_AWE32/VWE_AWE_ROM/VWE_AWE_RAM_KB/VWE_AWE_SHIFT/
VWE_AWE_LEAD_MS/VWE_AWE_DUMP/VWE_AWE_LOG env knobs.

emulator/roms: the AWE32 1MGM GM ROM dumped from our own pod card (SF2)
plus the reconstructed raw image the emulated EMU8000 loads. The HMI
driver refuses the AUDIO*.RES SoundFont upload without it (banks declare
irom=1MGM) -- that was the root cause of the first silent runs; full
debug chain in SOUND-NOTES.md. Repo serves the pod-owner community only.

.gitignore: drop the ROM excludes and un-ignore ALPHA_1/ and sda4/
(committed separately).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 19:40:15 -05:00
CydandClaude Fable 5 dabc204d0d VPX render: port the restoration gallery shading model; renderer collab doc
Device renderer (vpxlog.cpp, commit-copy of the fork source):
- View-flush fog decode (enable/near/far/rgb at d+72.., mode 5 linear,
  garbage-guarded; VPX_NOFOG=1 diagnostic) applied per fragment.
- Full dpl_MATERIAL parse: emissive/ambient/diffuse/opacity/specular/
  shininess (opacity+specular parsed, not yet applied); fixed-offset
  texture/ramp refs with lazy resolution, rebake on material/ramp reflush.
- Gallery shading model (restoration/gallery_template.html) as a GLSL 1.10
  program over the existing immediate-mode path, fixed-function fallback:
  c = (matAmb*sceneAmb + matDiff*mix(ramp.lo,ramp.hi,acc))*tex + matEmis,
  linear fog with immunity knob. Textured polys use an identity light-ramp
  (texels already baked through the material ramp). Newell flat normals for
  polys without wire normals. Interim sun/ambient until the light node is
  decoded: VPX_AMBIENT / VPX_SUN env overrides.

RENDERER-COLLAB.md: shared working doc with the external-renderer team --
verified FIFO action/node tables, struct offsets, scene assembly and
coordinate conventions, available data taps, open questions (incl. the
type-7 object-vs-light flush conflict).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 16:41:16 -05:00
CydandClaude Fable 5 e2005502ff RIO: gauge confs to priority=higher,higher
highest,highest (HIGH_PRIORITY_CLASS) starved the host desktop; with the
v3 idle-window and v4 retry patches a rare dropout self-recovers, so
ABOVE_NORMAL both ways is the better trade.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 16:41:02 -05:00
CydandClaude Fable 5 301f381305 VDB: exploded 7-display desktop mode (VPX_EXPLODE=1)
New layout mode showing every cockpit display as its own desktop
window -- the two MFD heads split into their individual color wires,
which is what the pentapus cable does on the real pod:

- wins 5-9 = the five mono MFDs (win5 LL = HEAD A red, win6 LR =
  HEAD A green, win7 UL = HEAD B red, win8 UC = HEAD B green,
  win9 UR = HEAD B blue), each decoding framebuffer bits 8-15 through
  its head's palette and rendering its single wire as green-phosphor
  brightness (G=v, R=B=v/8).
- Radar (win0) rotated 90 degrees clockwise and shown portrait
  480x640 -- the pod's radar CRT is mounted sideways -- centered
  between the two lower MFDs.
- All displays at native size: MFDs 640x480, uppers at
  (20,20)/(680,20)/(1340,20), lowers at (20,560)/(1340,560) aligned
  under the outer uppers; radar at (760,560); Division main 800x600
  at (2020,20).
- The DOSBox SDL main screen is auto-parked centered under the
  Division window (one-shot EnumWindows by title + SetWindowPos).
- Geometry overridable per window via VPX_WIN<g>/VPX_MAIN as usual;
  win<g>.bmp dumps cover g=5-9, radar dumps rotated as displayed.
  VPX_COCKPIT takes precedence if both modes are set; cockpit and
  debug layouts unchanged (regression-checked).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 00:46:54 -05:00
CydandClaude Fable 5 377047f37d RIO working: serial wire tap, conf tuning, four-patch writeup
The RIO cockpit board now runs sustained sessions with button mashing;
dropouts self-heal in ~1-3s. Documented in RIO-NOTES.md:

- directserial RIO_TAP=<path> (host env): logs every TX/RX byte with
  host-us + emu-ms timestamps, plus config/RTS/DTR/break lines. This
  instrument found every root cause below.
- Confs: rxburst:16 restored (no-burst reply pacing made the game ACK
  ~14ms late -> board dropped on the first long analog stream; the old
  'rxburst corrupts boot' belief was the then-unpatched PCSPAK crash).
  priority=highest,highest (unfocused DOSBox was demoted and blew the
  ACK deadline).
- BTL4OPT.EXE patch lineage (in ALPHA_1/, zip left pristine):
  v2 full DISABLE_AND_DIE NOPs (v1 left the IRQ/RTS-retract prologue
  live -> first protocol error deafened the driver), v3 TXMAXIDLE 4->32
  (kills the button-press ACK-window livelock), v4 analog retry limit
  15s->0.5s (dev value was 0.2s; recovery now near-instant).
- Board firmware patch plan recorded for the EPROM-dump route.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 00:22:14 -05:00
CydandClaude Fable 5 aea8b3eab4 Archive the Mac operations console (410console)
410consoleArchive.sit is the StuffIt archive of the 4.10 operations
console that ran the show floor for both BattleTech and Red Planet on a
classic Mac. Preserved as-is; extraction/porting comes later.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 00:19:35 -05:00
CydandClaude Fable 5 fa895afc0f Preserve ALPHA_1.zip (production-system image); ignore __pycache__
ALPHA_1.zip is the archived resource behind the git-ignored ALPHA_1/
working directory (the patched production hard-drive image the
emulator mounts). Also ignore Python __pycache__/ dirs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 22:35:09 -05:00
CydandClaude Fable 5 7670d40b37 VDB heads: 4-head cockpit layout (VPX_COCKPIT=1), drop exploratory windows
- VPX_COCKPIT=1 places the four VGA heads as borderless windows:
  Division main 800x600 @ 0,0; radar (win0) 640x480 @ 800,0; MFD heads
  win3/win4 640x480 @ 1440,0 / 2080,0 (heads 3+4 are driver-spanned
  into one 1280x480 canvas). VPX_MAIN / VPX_WIN<g> = x,y[,w,h]
  overrides any window without a rebuild; default debug layout kept.
- Remove exploratory win1/win2 (bits 0-7 via static palettes); keep the
  0/3/4 numbering so win<g>.bmp dump names stay stable.
- Sync commit copy with the build tree: per-head palette decode in
  pal_draw() and device-side BMP capture (VPX_DUMPDIR).
- RIO-NOTES: document the PCSPAK DISABLE_AND_DIE patch (error-3 crash
  on RIO resets); restore the terrain-shadow section heading it ate.
- Add gauge_rio{,_log}.conf launch configs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 22:30:33 -05:00
CydandClaude Opus 4.8 12d2952e9f VDB: palette-reload delta probe (test palette-animation hypothesis)
On each palette reload, diff against the previous captured palette and log how
many of the 256 entries changed plus the first few index:old->new. Confirms
the static/dynamic split: pal1/pal2 load once (static base structure -- red in
odd entries, etc.), pal0 is rewritten ~28x. In this capture pal0 is doing the
intro FadeToWhite -- ~216/256 entries ramping in lockstep from 0 to ~60/63 --
i.e. animating the whole display brightness via the palette without redrawing
the framebuffer. Selective per-element flashing (targeted small deltas) would
need an active mission to observe; this probe is the instrument for it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 20:31:51 -05:00
CydandClaude Opus 4.8 e75913b5d3 VDB windows: radar (bits 0-7) + per-bit fan-out of bits 8-15
Refine the display decode for pairing: window 0 renders the color radar from
bits 0-7 (3:3:2 RGB); windows 1-8 each render a single bit (8..15) as
white/black. Each bit turns out to be a recognizable display plane -- e.g.
bits 8 & 12 are both the weapons panel, bits 9/11/13 the systems panel -- so
the mono displays' 2-bit fields are scattered (out of order) across the word.
This fan-out lets the bits be re-paired into their six displays by eye.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 20:17:47 -05:00
CydandClaude Opus 4.8 7a615449c5 VDB decode SOLVED: six displays bit-packed in the 16bpp pixel
The gauge framebuffer is an encoded stream: each 16bpp pixel packs all six
cockpit displays. Decoded live into per-display windows:
  bits 0-5   = the COLOR radar/tactical display, as 6-bit RGB (2 bits/channel)
  bits 6-7   = mono display 1 (nav scope)
  bits 8-9   = mono display 2 (weapons/systems)
  bits 10-11 = mono display 3 (sensor cluster)
  bits 12-13 = mono display 4
  bits 14-15 = mono display 5
That's 6 + 5x2 = 16 bits exactly -> six displays (1 color + 5 mono), matching
the pod hardware. A 7th window (bits 16-17) confirms the budget: it's black.

Each display now renders in its own 640x480 window from the shared framebuffer
(vga.mem.linear). Mono screens show as brightness; the three VDB palettes are
the per-display color maps (next: apply them).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 20:09:36 -05:00
CydandClaude Opus 4.8 1b973917fa VDB windows: render the actual gauge framebuffer (similar output)
Replace the palette-swatch windows with ones that render DOSBox's live gauge
framebuffer -- the M_LIN16 16bpp video memory (vga.mem.linear, 640x480, 5:6:5,
start=vga.config.real_start) via glDrawPixels. Each window now shows the real
gauge image, matching the DOSBox screen ("similar output"), confirmed live.
Diagnostic: the VDB splitter-on log now prints the framebuffer mode
(0x111 / M_LIN16 / 640x480) -- confirming direct color, so the palettes are
not index LUTs.

All three windows currently show the shared framebuffer identically; the
per-display palette decode (how the VDB carves the encoded 16bpp stream into
the six monitor outputs) is the next step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 19:55:53 -05:00
CydandClaude Opus 4.8 7fead4f493 VDB palettes: three dedicated 640x480 live windows (not strips)
Replace the in-render-window palette strips with three separate 640x480
windows, one per VDB display palette (secondary/aux1/aux2). Each has its own
GL context (rt_main wglMakeCurrent-s each per tick) and shows the palette as a
16x16 color grid, redrawn every 50ms so it animates live regardless of the VPX
render cadence. make_gl_window() factored out; strips + VPX_VDBSTRIP removed.

Confirmed live: aux1 = red/green/olive/black status checkerboard, aux2 = a
4-region color map (green/blue/red/purple, 64 entries each), secondary = the
animated one (black between flashes).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 19:30:25 -05:00
CydandClaude Opus 4.8 68e595c5a2 VDB: live palette strips in the render window (real-time view)
Draw the three VDB display palettes as 256-color bars along the bottom of the
GL render window, updated every frame straight from the VDB storage -- a live
view (like the Division output) instead of static snapshots. This matters
because pal0 (secondary) animates and the earlier file dumps caught pal0/pal2
at their SVGAZeroPalette init (all black); live, pal2 is actually a rich
4-region color map (green/blue/red/gray-purple, 64 entries each) and pal1 the
red/green/olive status palette. Toggle with VPX_VDBSTRIP=0.

Also: VDB_PALDUMP now keeps the most-lit snapshot per group (max non-black
bytes) so file dumps no longer capture the zero-init. VDBPalette storage moved
above the render thread so rt_draw can read it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 19:00:55 -05:00