Commit Graph
39 Commits
Author SHA1 Message Date
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
CydandClaude Opus 4.8 981d98d784 VDB: dump captured palettes (VDB_PALDUMP) + swatch renderer
VDB_PALDUMP=<prefix> writes each completed 768-byte palette load to
<prefix>N.rgb (256 RGB entries per VDB display group). render_vdb_palettes.py
renders each as a 16x16 swatch grid + linear ramp.

First capture: pal1 (aux1) is a structured red/green/olive/black color map
(2-bit R x 2-bit G) -- likely the color display's status coloring; pal0
(secondary, dynamic ~29 reloads) and pal2 (aux2) are grayscale, sampled black
mid-animation. Palettes are the per-display color maps the VDB applies when
splitting the framebuffer to the six monitors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 18:27:10 -05:00
CydandClaude Opus 4.8 6b62bf9613 VDB: fix palette port offsets -- now captures the display color maps
The VDB device was only logging the splitter-clock strobe; the gauge code's
palette writes were hitting the handler but being dropped. Cause: I mapped the
palette register groups at Adam's base offsets (0x300/0x308/0x310, sub 0-3),
but per L4VB16.CPP's "+2" convention and L4SVGA16.ASM SVGAWriteFullPalette
(mov dx,base; add dx,2 -> write-addr; inc dx -> data) the real registers are
at base+2: secondary 0x302-0x305, aux1 0x30A-0x30D, aux2 0x312-0x315, VGA-DAC
layout within each (0 mask, 1 read-addr, 2 write-addr, 3 data).

With the offsets corrected the device now captures the full palettes -- e.g.
"VDB pal0 loaded 768 data bytes" (256 RGB) + pal1 -- the per-display color
maps the VDB uses to colorize each of the six monitors. Foundation for
reconstructing the individual displays.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 18:15:48 -05:00
CydandClaude Opus 4.8 e8876e521d Gauges: fix bank-switching (window-granularity mismatch)
The garbled top-strip render was a paging bug, not the video mode. The
pageFcnPtr in L4GAUGE.INI (C000:2616) is a red herring -- the driver's direct-
pointer path is commented out ("THIS DOES NOT WORK"); it pages via portable
VESA int 10h/4F05, which our S3 handles.

Real cause: window granularity. SVGASetPage passes the bank in granularity
units; the blit advances by pageDelta = pageSize/granularity per 64KB window
crossed. The INI's granularityInKB=4 is the Cirrus CL-GD5434's 4KB window
granularity (the pod's actual video card; the "STB Horizon+" board was
Cirrus-based). Our emulated S3 uses 64KB banks, so pageDelta=16 -> every bank
landed 16x too far -> the smear.

Fix (config only): L4GAUGE.INI [640x480x16] granularityInKB=64 (=sizeInKB, so
pageDelta=1, matching the S3's 64KB banks). Full framebuffer now pages
correctly -- 315+ frames, VDB splitter stays ON, display renders as expected
(blank between missions; user confirmed "that is the screen I expect").
ALPHA_1 is git-ignored so the INI edit isn't committed; reproduction + backup
(L4GAUGE.INI.orig) documented in GAUGE-NOTES.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 18:03:29 -05:00
CydandClaude Opus 4.8 b2e4c5eaa6 Gauges: fix out-of-memory crash (HEAPSIZE), draw instrument panels
Enabling gauges crashed (null-this, illegal 0x478). Root cause was NOT video:
the MUNGA main heap (fixed 6MB default) exhausted loading gauge images. The
heap size comes from getenv("HEAPSIZE") (BTL4OPT.EXE @0x401076; default
0x600000); the pod's PARAMETR.BAT sets it (:POD=15MB, :REVIEW/:LOOP=32MB) but
our minimal setenv launch never did. memsize is irrelevant (it's the game's
own heap, not DOS memory -- verified memsize=127 still gave 6MB). Pods have
32MB RAM so 15MB fits.

Fix (no binary patch): set HEAPSIZE=15000000 + L4GAUGE=640x480x16 in
gauge.conf. Game now runs sustained with gauges on (500+ frames); the VESA
640x480x16 mode switches fine on our emulated S3 and the cockpit instrument
panels draw (DISPLAY/PROGRAM/ENG DATA/TRIGGER CONFIG...).

patch_btl4opt.py also gained Verify_Failed (DEBUG-build assertion) neutral-
ization -- release-equivalent robustness, separate from the heap fix.

Known-open (GAUGE-NOTES.md): the framebuffer renders only a top strip,
garbled -- the game bank-switches via a hardcoded far pointer in L4GAUGE.INI
(C000:2616, the STB Horizon+ card's VESA WinFuncPtr) that isn't valid on our
emulated S3, so only the first bank(s) page in. Fixing bank-switching (or an
LFB mode) is next; then the full buffer can be split into the six displays.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 17:48:07 -05:00
CydandClaude Opus 4.8 08f71eb471 Phase 3f: lighting from wire normals; defuse shipped-in debug crash
Lighting: stride-8/9 vertices carry a normal (floats 3-5, uv at 6-7). The
backend transforms normals by the instance rotation and lights with a single
directional sun (GL_LIGHT0, smooth, two-sided, GL_COLOR_MATERIAL). Terrain
and hulls shade instead of reading flat.

LOD: the lod flush has no switch distances -- the host keeps the active LOD
at the child-list head and re-orders over the wire, so children[0] is right
and LOD changes come through as the sim runs.

The crash that halted the game once the RIO drove the sim was not ours: fault
at 0047E1D1 writing 0xFFFFFFFF is the RIO driver's DISABLE_AND_DIE debug
macro (PCSPAK.ASM, DIE_ON_ERROR=1), which deliberately faults on a serial-tx
anomaly -- error 3 = body char >0x7F during a RIO packet, i.e. a glitch on a
board reset. Release build (DIE_ON_ERROR=0) compiles it out and recovers
(and al,07Fh). patch_btl4opt.py NOPs all 12 sites by signature (with .orig
backup) = release behavior; game then survives RIO resets (1200+ frames).
(ALPHA_1 is git-ignored, so the tool ships, not the patched binary.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 17:13:46 -05:00
CydandClaude Opus 4.8 0bb493dd5f Phase 3e: live texturing + serial receive-latency fixes for the RIO
Texturing (validated live -- game-live-textured.png, the ravine's brown dirt
terrain): the wire model is Division's intensity+ramp scheme. action 26
uploads 8-bit intensity texels ([node][nbytes][w][h] + rows; type 13 =
texture); texmap (12) references the texture; material (11) references its
texmap and a ramp (14: lo/hi RGB); texel color = lerp(lo, hi, i/255). The
backend bakes RGBA per material, uploads to GL, maps with wire UVs
(stride-5: floats 3-4; stride-8/9: floats 6-7).

Serial (directserial fork options, tracked in vpx-device/serialport/):
- rxpollus:<us> -- receive poll tick (stock 1ms); 100us discovers inbound
  bytes ~10x sooner. Validated: sim advanced, camera moved with real RIO.
- rxburst:<n>  -- stock DOSBox re-serializes received bytes at emulated wire
  speed (~1ms/byte at 9600) though they already paid wire time on the real
  cable; a 15-byte analog reply gained ~14ms, blowing the RIO's few-ms ACK
  window and dropping the game into its 15-second retry fallback
  (L4CTRL.CPP limit=15.0 //0.2). rxburst:16 delivers buffered bytes 16x
  faster. game_rio.conf: realport:COM1 rxpollus:100 rxburst:16.

Crash-on-advance fixed: *_TSHD.BGF terrain shadows live only in arena
subdirs the search path misses; null shadow renderable was dereferenced once
the sim moved. All 11 copied into VIDEO/GEO in the working image; game now
runs sustained (560+ frames, textured, no crash). Details in RIO-NOTES.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:43:21 -05:00
CydandClaude Opus 4.8 99652d894b Phase 3d: game world decodes and renders -- offline and LIVE
The full DPL hierarchy the game uses (vs flyk's flat scene) is now decoded
and rendered:
- stride-aware set_geom_verts (header word 3 = floats/vertex: 3/4/5/8/9;
  mech meshes carry normals + UVs)
- instances are list_add children of DCS nodes; instance flush field 4 ->
  object; object->lod->geogroup->geometry; dcs_link builds the articulation
  tree of 4x4s (payload floats 4..19, row-major, row 3 = translation)
- game world is y-down (DCS matrices carry a reflection); projection flips
  x (Division mirror) and y

render_game.py reconstructs a captured game stream offline: the mission
arena (10km, 246 instances, 330 geometries), the player's Thor at the
camera, six enemy mechs 1.5km north -- game-mech-decoded.png shows one with
real hull/armor/glass materials; game-cockpit-decoded.png the cockpit view.

The live backend (vpxlog.cpp) gained the same traversal and now draws the
game's out-the-window view in real time (game-live-gl.png): sky, arena
floor to the horizon, own gun barrels at frame bottom.

Next: texturing (action-26 texel maps + UVs), lighting from wire normals,
per-frame articulation once the RIO drives the sim.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:22:35 -05:00
CydandClaude Opus 4.8 47fe174c6e Add VDB (VWE LBE4 video splitter) device + fault disassembly findings
The VDB is the ISA card that fans the PC's Cirrus Logic framebuffer to the six
secondary cockpit displays (5 mono + 1 color), dividing the pixel clock. From
the driver (CODE/RP/MUNGA_L4/L4SVGA16.ASM, L4VB16.CPP; "Adam's port decoder
design" -- Adam G., VWE hardware):
  0x300/0x308/0x310  three VGA-DAC-style palette groups
  0x31A / 0x319      splitter high-color clock divider ON / OFF

New emulated VDB device in vpxlog.cpp at I/O 0x300-0x31A (active when logging,
disable with VDB=0): decodes palette write-address/data/mask/read-address and
the clock strobes, recording palette contents + splitter state so the six-
display encoding can be decoded later. Validated: with gauges enabled
(gauge.conf, setenv arg4=g) the game issues "splitter clock ON (0x31A)" ->
captured. The board is write-only (game never reads it, per driver + owner),
so its absence is not the crash.

Crash diagnosis (BTL4OPT.EXE CODE+0x123B): the faulting routine is a heap
free() with boundary-tag coalescing; it was handed a garbage block pointer
(value 2). Symptom of upstream corruption, reached only when the RIO is in
sync and the sim advances. HISTORY.md gains a "Cockpit display hardware -- the
VDB" section with the attribution.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:55:00 -05:00
CydandClaude Opus 4.8 833fe85d63 RIO passthrough: solve analog-poll latency (core=dynamic + cycles=max)
The RIO drops comms if the analog-reply ACK is late by more than a few ms.
Empirically a slower CPU failed sooner, so the latency was dominated by how
fast the game processes the RIO packet and ACKs -- core=dynamic (recompiler)
+ cycles=max keeps the board in sync (user-confirmed). game_rio.conf passes
the real RIO through serial1=directserial realport:COM1.

With real control input the sim advances and then faults (null-ptr deref at
BTL4OPT.EXE CODE+0x123B) -- downstream of the minimal test.egg not setting the
arena objectpath, so VIDEO/GEO/ARENA/thr_tshd.bgf isn't found. That is content
config, separate from the now-working VPX protocol / renderer / RIO. Details
in RIO-NOTES.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:08:39 -05:00
CydandClaude Opus 4.8 57524d4a68 Phase 3c: fix production vr_sync abort; full game runs through renderer
Root cause: vpx_max_postboot_acks=200, a Phase-2 bring-up guard, capped how
many post-boot replies the device would ever feed. A real BattleTech session
issues an unbounded stream of sync/frame/render replies and aborted with
"velocirender_receive timed out - sends_wo_rcv" at exactly the 200th ack
(143 sync + 55 frame-ack + 2 render). Cap is now effectively unlimited
(0x7fffffff; override VPX_MAX_ACKS for diagnostics).

After the fix the full game (game.conf, RIO disabled, cycles=max) runs
indefinitely: 2500+ syncs, 1264+ frame-acks, no abort, into L4VIDEO content
load (Thor mech + terrain from ALPHA_1/REL410/BT/VIDEO/GEO -- 841 real .bgf
models; test.egg is only mission params). Window still shows background:
the game uses the full DPL hierarchy (instance/object/lod/geogroup + DCS
transforms) which the flat flyk-tuned scene walk doesn't traverse yet -- that
is Phase 3d, documented in PHASE3-PROGRESS.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 14:45:20 -05:00
CydandClaude Opus 4.8 dce89a8571 Phase 3b: live OpenGL render backend in DOSBox-X (VPX_RENDER=1)
The emulated VPX board now draws frames in real time. The FIFO burst
assembler feeds an in-process DPL scene store; each vr_draw_scene publishes a
frame snapshot to a dedicated WGL window thread that renders it fixed-function.

- vpxlog.cpp: scene_burst() decode + VScene store + rt_main GL window thread;
  glFrustum from the view-node window rect, glScalef(-1,1,1) for Division's
  mirrored screen-x, action-31 camera as modelview. No build change (opengl32
  already linked).
- Validated: flyk divrgb.scn opens the "VPX VelociRender (emulated)" window
  and draws the SMPTE bars live via the real camera.spl spline camera
  (divrgb-live-gl.png), matching the offline render_capture.py decode.
- Game path (alpha1.conf) opens the window + draws background but hits the
  pre-existing production btdpl.ini vr_sync timeout (sends_wo_rcv) -- not a 3b
  issue. Remaining work tracked in PHASE3-PROGRESS.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 14:27:58 -05:00
CydandClaude Opus 4.8 4b6d910f7b Phase 3a: decode captured VPX render stream to pixels (SMPTE bars)
- vpxlog.cpp: VPX_FIFODUMP=<path> records every FIFO burst ('VPXM' records)
- decode_fifodump.py: action census + payload dumps of a capture
- render_capture.py: reconstruct the DPL scene graph from a capture and
  software-render each draw_scene frame (camera, view, materials, geometry
  all taken from the wire)
- divrgb.conf + divrgb.fifodump: flyk divrgb.scn capture fixture
- divrgb-decoded.png / divrgb-frame0.png: first images ever produced from
  the Rel 4.10 VPX protocol without a real board -- the textbook SMPTE
  color-bar pattern, validating verts/conns/materials/camera in one shot
- PHASE3-PROGRESS.md: the established Rel 4.10 wire protocol (action map,
  node types, message layouts); RENDER-HARNESS.md updated

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 14:13:02 -05:00
CydandClaude Fable 5 2c29bf928d Add FLYK render harness from VWETEST diagnostic suite
The production image's VWETEST diagnostic suite provides a clean,
game-independent render harness. FLYK (VGLTEST, 32rtm build, newer
token-based sync) + clear.scn drives the ENTIRE VPX protocol through
the emulated board with zero errors: boot, iserver handshake, i860
download, token sync, scene build, draw_scene, frame-ack, clean exit
('Exiting rendering'). This validates the VPX emulation for an
arbitrary DPL renderer, not just the game.

Notes: the CYCLE flyk is a DOS/4GW build using the OLDER DPL3-style
velocirender_sync (action-check) and needs separate handling; the
VPX/DBE0151 iserver board test + reference TGAs are a future
golden-image validation avenue.

Adds RENDER-HARNESS.md and harness configs (flyk/cycle/alpha1).
Next (Phase 3): flyk DIVRGB.SCN color bars -> decode FIFO geometry
(same DIV-BIZ2 formats as restoration/divformats.py) -> OpenGL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 09:27:52 -05:00
CydandClaude Fable 5 939ea17d17 Phase 2 COMPLETE: full VPX protocol working; game reaches content loader
Disassembled BTL4OPT.EXE (PE-in-DOS32RTM) to crack the last unknowns:

- velocirender_sync (@0x48D220): sends action 0x2D with a data token and
  checks cmp token, reply.node[0] (the 'unexpected action' text only prints
  the action; the real check is the echoed token). Device now echoes the
  token in node[0]. Sync passes.
- Speculative-poll gating: only feed a reply after consecutive empty polls
  (a blocking inRecord spin), not single handle_iserver_stuff() checks.
- Frame-ack: velocirender_frameack expects action 9 (vr_draw_scene); device
  tracks outstanding draw_scene and replies 9. Frame-ack passes.

The game now passes sync, loads renderer config, builds the scene
(create/flush/list_add/draw_scene), completes frame-ack, and enters its own
content loader (L4VIDEO.cpp) loading BattleTech models. Remaining issues are
content packaging/paths and an empty DPL config -- not VPX protocol. The
board emulation is functionally complete for boot + scene setup + frame-ack.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 00:04:33 -05:00
CydandClaude Fable 5 e13575d3ac Phase 2: FIFO transport working + RIO validated on real hardware
RIO (Phase 5) validated with real hardware: with a physical RIO on
COM1 and serial1=directserial realport:COM1, the game's 1996 RIO
driver talks to the board — the 'RIO never came back' error is gone
and expected activity was seen on the RIO board.

VPX FIFO fast path decoded (OUTSW.ASM + capture): after i860 boot the
render protocol pumps 16-bit words to a FIFO data port seen as
0x154/0x155 byte writes, payload starting with the 4-byte action. The
device now extracts FIFO message actions (confirmed vr_init=0 with the
args string, vr_create=1 with node type 0x2D) and echoes replies with
handler-specific overrides from board source VR_REMOT.C (init/statistics
reply action = 1).

Blocked on one unknown: velocirender_sync checks the init reply against
a constant that is neither 0 nor 1, so the Rel 4.10 board differs from
the DPL3 dev source. Needs the Rel 4.10 LIBDPL source or disassembly of
BTL4OPT.EXE at the format string (file offset 0x107772). Device has a
VPX_INIT_REPLY experiment hook for candidate values.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 23:41:49 -05:00
CydandClaude Fable 5 f236d15d51 Phase 2 progress: boot handshake + i860 download solved; FIFO path mapped
The VPX responder device now drives production BattleTech v4.10
through the full transputer/i860 boot, far past the Phase 1 wall:

- iserver boot handshake solved: feeds 3 well-formed 'version' (tag 42)
  iserver requests, satisfying startup_handshake()'s 3 transactions.
- i860 download solved: parses the outbound framed renderer messages
  (vr_860args/code/data/bss) and absorbs them, staying byte-aligned.
- echo-action reply model validated against board source
  (VRENDER/VR_REMOT.C reply() echoes the received action); device
  tracks and echoes the last outbound action generally.

Remaining sub-protocol identified and characterized: after i860 boot
the host switches to a FIFO fast path (OUTSW.ASM: 0x40 tag + REP OUTSW
16-bit words to FIFO port 0x154/0x155, gated by ok_to_fifo at 0x160).
The current build stops at velocirender_sync because the device only
implements the slow byte path. PHASE2-PROGRESS.md documents the exact
next steps (FIFO transport + render loop -> Phase 3 OpenGL backend).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 23:18:45 -05:00
CydandClaude Fable 5 e3c090695d Phase 1 complete: captured VPX boot conversation from shipped binary
Built DOSBox-X from source with a custom VPX link-adapter logging
device (vpx-device/vpxlog.cpp) and captured the game's outbound boot
sequence. Findings:

- Register map confirmed against LINKIO.C: outputData 0x151,
  outputStatus 0x153 (polled bit0), resetRoot 0x160, analyseRoot 0x161.
- Reset preamble captured exactly (analyse=0, reset 0->1->0 + status inits).
- The game streams 85298 bytes to outputData that are BYTE-FOR-BYTE
  identical to VRENDMON.BTL; first byte 0xF0 = transputer boot-from-link
  primary-bootstrap length. Protocol stage 1 (reset + monitor download)
  fully characterized; no hidden bulk/interrupt path.
- Production cockpit dump ALPHA_1 added (git-ignored): its BT is v1.1.0.6
  with a VRENDMON.BTL byte-identical to the captured stream, so this
  result reflects the exact cockpit software. ALPHA_1 is the reference
  image going forward (carries RP + production pod/network boot chain).

Adds analyze_capture.py, capture.conf, PHASE1-RESULTS.md. DOSBox-X
source tree and capture artifacts are git-ignored.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 22:46:20 -05:00
CydandClaude Fable 5 f680ed0585 Phase 0 complete: DOS game boots to VPX link protocol on Windows 10
Baseline boot test under DOSBox-X confirms the emulation architecture
empirically. Key findings:

- Borland 32RTM/DPMI runtime works under DOSBox-X (risk retired).
- BTLIVE ships a version-mismatched BTL4.RES (1.0.1.2 vs EXE 1.0.1.4);
  BTRAVINE (1.1.0.6) is self-consistent and matches this repo's source
  (BTL4VER.HPP), so it is the development image.
- With the matched image the game boots through the resource check and
  BTL4Application construction, polls the RIO on COM1, then reads the
  VPX link at port 0x150, gets 0xffffffff, and fails rcv_protocol with
  'length 65535 too big' — the exact VR_COMMS.C path the plan predicted.

Adds emulator/baseline.conf (repro) and emulator/PHASE0-RESULTS.md.
Working binaries (dosbox-x/, image/) are git-ignored.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 19:33:34 -05:00
CydandClaude Fable 5 f7ebde2e0b Add VPX emulation implementation plan for Windows 10 cockpits
emulator/PLAN.md: run the unported DOS Rel 4.10 games in the
surviving cockpits via a DOSBox-X fork with an HLE device
impersonating the Division VPX board at its C012/B004 link
interface (I/O port 0x150 per BTLIVE SETENV.BAT), rendering the
frame stream in OpenGL. Cockpit RIO (COM1) and plasma (COM2) pass
through to the game's original serial drivers (L4RIO.CPP).
Eight phases with acceptance criteria, evidence table, protocol
appendices, risks, and test strategy. Gauge displays deferred.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 19:09:33 -05:00
CydandClaude Fable 5 326d29b72a Extract all recoverable Division scenes; add Scene Archive gallery
Cracks the DIV-BIZ2 binary format (BGF/BMF) using Division's own
reader source (DPL3/BIZREAD.C) as reference: block stream, 14 vertex
layouts, pmesh/strip connectivity, LOD nesting, embedded materials.
Adds SVT raw-texture decoding, 1995-dialect VGF support (implicit
CONNECTION_LIST, header SCALE), and a whole-drive scene audit.

108 of 241 scenes on the Glaze drive are recoverable; 26 are curated
into restoration/vwe-archive.html, a self-contained WebGL gallery:
Star Trek, Hull Pressure, BattleTech (incl. the polar-map mech
lineup), Red Planet's Mars-canal raceway, and the Canyon demos.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 18:03:12 -05:00
CydandClaude Fable 5 5e9f191e0b Add TREK.SCN restoration: converter and WebGL viewer
Parses the DIV-VIZ2 formats (VGF geometry, VMF materials, TGA
textures, SPL splines, SCN scenes) from the STDAVE directory of the
Glaze drive and re-renders VWE's unreleased 1996 Star Trek pod
scenes in a self-contained WebGL page: the Enterprise-D among
drifting starfields (TREK.SCN) and the Klingon flyby (KLNGVID.SCN).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 15:19:52 -05:00
CydandClaude Fable 5 ce1b4ca9de Document the Glaze developer drive findings in HISTORY.md
Records the contents of the recovered VWE developer hard drive
(git-ignored sda4/): pod lab infrastructure, Division renderer
source with i860/Pixel-Planes 5 code, runnable game builds, and
unreleased projects (Star Trek prototype, Hull Pressure, Renegade
Legion, and the Starship Troopers pitch that became DisneyQuest's
Invasion!). Includes a source-completeness analysis showing the
engine libraries are rebuildable but most game-logic sources are
absent from this release cut.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:50:38 -05:00
CydandClaude Fable 5 ae768d3849 Ignore sda4/ developer hard-drive dump
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 13:59:18 -05:00
CydandClaude Fable 5 fdd9ac9d97 Initial import: Tesla Release 4.10 (Tesla:BattleTech & Tesla:Red Planet)
Archival snapshot of the Virtual World Entertainment Tesla cockpit
software, 1994-1996: MUNGA engine and L4 pod layer source (Borland
C++ 5.0), BT/RP game code, and game content (models, audio, maps,
gauges, Division renderer data). Includes third-party libraries:
Division dVS/DPL graphics, HMI SOS audio, WATTCP networking.

Files are preserved byte-for-byte (.gitattributes disables all
line-ending conversion). README.md documents the layout, target
hardware, and toolchain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 13:21:58 -05:00