Files
TeslaRel410/restoration/source410/RENDER-ROADMAP.NOTES.md
T
CydandClaude Fable 5 1b204de6d3 BT410: the 3-D path runs to mission load -- btl4vid's next brick is named
Run against the emulated Division card, our build reaches the mission scene
load and stops at the one method we stubbed:

  btl4vid.cpp(42): BTL4VideoRenderer::LoadMissionImplementation
                   -- btl4vid.cpp not yet reconstructed

That proves MakeVideoRenderer, the BTL4VideoRenderer ctor over the engine's
DPLRenderer, the board boot (transputer + i860 firmware, ~858K wire
transactions through the VPX HLE) and Renderer::LoadMission all work in our
build.  btl4vid is not a from-scratch climb; the engine half was always
linked and what is missing is the mission-load hook and its renderables.

Banked the reproduction rig (emulator/vidtest.conf + the host VPX env --
VPX_RESPOND alone is not enough, the iserver handshake dies without
VPX_RENDER), the authentic contract from CODE/RP/MUNGA/RENDERER.CPP:263, and
a note that the BT411 donor restructured this hook so the contract comes from
the 1995 engine and only the renderables come from the donor.

Also corrected today's earlier note: the transient 3-D frame seen during a
gauge run was NOT the dPL path.  MakeVideoRenderer returns NULL without
DPLARG and no gauge conf sets it, so no video renderer exists in those runs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 23:32:06 -05:00

7.9 KiB

The render roadmap — from headless to visible (researched 2026-07-24)

Four-dossier workflow synthesis (card protocol / video-TU delta / emulator side / gauge path). The headline: the render seam is far closer than expected — the engine half of BOTH render paths already compiles and links into our btl4opt.exe from the CODE originals, and the emulator's board-side device is EXE-agnostic.

The two independent render paths (either can run without the other)

  1. The 3D main view (division card): the game speaks dPL — a RETAINED-mode scene graph API (never pixels, never transformed polys) — through the statically linked libDPL, which frames every call into vr_action messages on the INMOS C012 link adapter at port 0x150 (FIFO fast path: body as REP OUTSW words to 0x154, trailing length word to 0x151 commits). Gate: DPLARG env (set by SETENV.BAT when L4VIDEO != OFF); NULL DPLARG = the headless shape we run today (MakeVideoRenderer() returns NULL, tolerated).
    • Per-frame submission: engine codeDPLRenderer:: ExecuteImplementation (CODE/RP/MUNGA_L4/L4VIDEO.CPP:5065) walks the dplRenderableSocket; renderables (L4VIDRND.CPP, ~30 classes) set DCS matrices; dpl_FlushDCSArticulations = wire action 0x1f (batched poses, absolute 3x3+T or [sin,cos] joint records); vr_draw_scene (9) kicks the frame; velocirender_sync (0x2d, exe @0x48D220) is the ack-less bulk-op fence.
    • Our build ALREADY COMPILES this whole engine layer (mungal4.lib: l4video/l4vidrnd/l4dplmem + prebuilt 1995 STARTDPL.obj + LIBDPL.LIB; see build410 obj logs). The missing piece is GAME code: btl4vid (BTL4VideoRenderer — MakeEntityRenderables/MakeMechRenderables/ effects/wreck swap/material substitution; BT411 donor 3039/848 lines with per-method @ADDR evidence, binary extent @4cc40c..@4d2bbc; our stub Fails at LoadMissionImplementation).
  2. The gauge path (cockpit instruments): completely separate hardware — the PC's own SVGA (VESA 0x111, 640x480x16, L4SVGA16.ASM banked blits), split across VGA heads by the VDB board (port 0x300, palette groups; the octopus-cable 5-mono-MFDs + color-radar decode). Gate: L4GAUGE env. The plasma readout is a gauge-renderer graphics port (PlasmaDisplay on COM2), not a separate renderer.
    • Engine half (GaugeRenderer/L4GaugeRenderer/the 5171-line L4GAUGE widget interpreter/GAUGMAP/L4VB16) already compiles + links in build410; one documented deviation (interpreter table 46864 -> 262144 for BT's larger CFG).
    • Missing: the 6 BT gauge TUs — btl4gaug (130 fn) / btl4gau2 (77) / btl4gau3 (46) / btl4rdr (36) / btl4grnd (13, ours is a 4-fn stub) / btl4galm — ~302 functions/~43KB, binary extent 0x4c19fc-0x4cc40c, the largest function-count block left in btl4.lib. BT411 donors are COMPLETE (semantic .cpp/.hpp with @ADDR evidence, ~5900 donor lines); the work is RE-HOSTING onto 1995 engine APIs, not fresh decompilation. Class inventory per TU in the dossier (widget primitives / composite clusters / MP-HUD / radar MapDisplay / the renderer / alarm manager).

The emulator side is READY and EXE-agnostic

The DOSBox-X fork's VPX device (emulator/vpx-device/vpxlog.cpp, ports 0x150-0x161 + VDB 0x300-0x31A) implements the BOARD side purely at the wire level: blind firmware absorb, iserver handshake (VPX_RESPOND=1), generic acks, the 0x2d sync echo, draw_scene frame-acks with a REAL raycast reticle pick against its own decoded scene, and the GL renderer (VPX_RENDER=1) that draws the main view + cockpit windows. It never reads game memory and keys only on wire contents — our reconstructed exe drives it unmodified once it emits the same traffic. The AWE32 pair is mandatory for any timed run (SOS FAST clock); gauges also render live on the emulated S3 with the shipped exe (GAUGE-NOTES.md: HEAPSIZE=15000000 + granularityInKB=64).

The plan (order of value)

  1. Gauges-only first (decisively cheaper): set L4GAUGE=640x480x16 (+ HEAPSIZE), reconstruct the 6 gauge TUs from the BT411 donors. Built-in oracle: the shipped exe renders reference output from the SAME GAUGE content — per-head diffable. Live instruments need the attribute sources, which the 5.3.x waves have largely built (weapon states, heat, power, damage, radar).
  2. Then btl4vid (the 3D world renderer) + DPLARG on: the engine DPLRenderer + libDPL do the wire; btl4vid builds the renderables per entity; verify against the VPX device's GL window and the dpl3-revive bridge.
  3. The review/playback pair (btl4pb + the BTL4.CPP review branch) closes the last absent TUs.

Message-id / protocol quick refs: vr_create=1 (host-assigned handles), vr_flush=3 (node structs; VIEW proves 832x512), geometry 0x17/0x19/0x1a (texel word [pad,B,G,R]), artics 0x1f, draw 9, sync 0x2d, fire 0x23, reticle 0x26. DPLARG reference value in emulator/baseline.conf:21.

================================================================================ 2026-07-27 -- THE 3-D PATH RUNS TO MISSION LOAD (measured, not estimated)

Our reconstruction, run against the emulated Division card, gets ALL THE WAY to the mission scene load before it stops -- at the one method we stubbed.

c:/.../bt_l4/btl4vid.cpp(42): BTL4VideoRenderer::LoadMissionImplementation
                              -- btl4vid.cpp not yet reconstructed

What that single line proves is working end to end in OUR build:

  • BTL4Application::MakeVideoRenderer builds a BTL4VideoRenderer
  • the BTL4VideoRenderer ctor chains the engine's DPLRenderer
  • the board boots: transputer + i860 firmware upload, ~858K wire transactions logged by the VPX device HLE
  • Renderer::LoadMission runs (RENDERER.CPP:273) and calls the hook

So btl4vid is NOT a from-scratch climb. The engine half was always linked; what is missing is the game's mission-load hook and the renderables it builds.

HOW TO REPRODUCE (this is the rig, and it is cheap): emulator/vidtest.conf -- baseline.conf with the mount made absolute and BTL4REC.EXE (our build, staged beside the shipped BTL4OPT.EXE which is NOT touched) instead of the shipped exe. Host env before launching dosbox-x:

  VPX_RESPOND=1  VPX_RENDER=1  VPX_NOMAIN=1  VPXLOG=<file>  VPX_DUMPDIR=<dir>

VPX_RESPOND alone is NOT enough -- with only that, the board boot dies at "Protocol error : length 65535 too big / rcv_protocol fail during iserver handling", which is the iserver handshake reading a floating bus. VPX_NOMAIN=1 keeps it from opening windows; add VPX_EXPLODE=1 only when you want the 7-display pentapus. The full documented pod launch is render-bridge/launch_pod.ps1 (LAUNCH.md) when the GL bridge is wanted.

THE CONTRACT for the next brick (authentic, CODE/RP/MUNGA/RENDERER.CPP:263): Renderer::LoadMission verifies InactiveRendererStatus, sets LoadingRendererStatus, stamps nextRenderTime, calls GetRendererManager()->StartRenderer(this), THEN LoadMissionImplementation. The base implementation Fails ("should never reach here") -- every concrete renderer must override it.

DONOR: BT411 game/reconstructed/btl4vid.cpp, 3188 lines / 27 methods, carrying the renderable family (BTReticleRenderable, BTTranslocationRenderable, the pending-wrecks map). NOTE it does not contain a LoadMissionImplementation by that name -- the WinTesla port restructured the hook -- so take the CONTRACT from the 1995 engine above and the CONTENT from the donor's renderables.

CORRECTION to the note earlier today: a transient 3-D cockpit frame captured during a gauge-rig run was NOT evidence of the dPL path emitting anything. MakeVideoRenderer returns NULL unless DPLARG is set (BTL4APP.CPP:152), and no gauge conf sets it -- so no video renderer exists in those runs at all. That frame was almost certainly attract/loading art out of BTL4.RES. The evidence above is the real thing, and it came from setting DPLARG deliberately.