Files
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

168 lines
9.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 2 — Boot Protocol Emulation: Progress
**Status: boot handshake + i860 download + FIFO transport solved; blocked on one
unknown constant in `velocirender_sync`. Phase 5 (RIO) validated on real hardware.**
## Update 2 (2026-07-02): FIFO transport working; RIO validated
- **Phase 5 — RIO passthrough validated with real hardware.** A physical RIO
was attached to the host's COM1 (Prolific USB-serial). With
`serial1=directserial realport:COM1` (see `rio.conf`) and `L4CONTROLS=RIO`,
the game's 1996 RIO driver (`L4RIO.CPP`, 9600 baud) talks to the real board:
the `RIO never came back from check request?` error **disappears**, and the
**expected activity was observed on the RIO board**. The cockpit control path
works end-to-end, unmodified, through DOSBox-X serial passthrough.
- **FIFO fast path decoded and implemented (send side).** The board is
dual-register: the render protocol switches to a FIFO channel after the i860
boots. From `OUTSW.ASM` + the capture: each message writes an `outsw` tag byte
to `outputData`, then pumps the payload as 16-bit words to the FIFO data port,
which DOSBox-X sees as byte writes to **0x154 (low) / 0x155 (high)**. The
payload begins with the 4-byte action. The device now parses this and
extracts the action of each FIFO message (confirmed: `vr_init`=0 with the
`/device~…` args string, then `vr_create`=1 with node-type `0x2D`).
- **Handler-specific reply actions (from board source).** `velocirender_receive`
reads replies on the **slow path** (already served); the device echoes the
sent action, with per-handler exceptions found in `VRENDER/VR_REMOT.C`:
`velocirender_init` and `velocirender_statistics` do `*data = 1`, so their
reply action is **1**, not the sent action. The device implements this map.
- **Remaining blocker — one constant.** The game reaches `velocirender_sync`,
which sends `vr_init` (action 0) and checks the reply action against a
specific value that is **neither 0 (echo) nor 1 (the DPL3 board's `init`
return)** — so the Rel 4.10 board returns a different value than the DPL3
dev-tree source. Determining it needs the Rel 4.10 LIBDPL/VRENDER source or a
disassembly of `BTL4OPT.EXE` around the format string at file offset
**0x107772** (`"unexpected action %d returned in velocirender_sync"`). The
device has an experiment hook (`VPX_INIT_REPLY=<n>`) to try candidate values.
Original Update 1 analysis (handshake + i860 download) follows.
---
**Status: substantial progress; boot handshake + i860 download solved; render
transport (FIFO fast path) identified as the remaining sub-protocol.**
The VPX device (`vpx-device/vpxlog.cpp`, env `VPX_RESPOND=1`) now drives the
production **BattleTech v4.10** (ALPHA_1 image) through the entire transputer/i860
boot sequence — far past the Phase 1 wall — and reaches the live renderer
protocol. Each layer below was solved by reading the normative sources on the
drive (`sda4/DPL3/VR_COMMS.C`, `DPL_HOST.C`, `VRENDER/VR_REMOT.C`, `LINKIO.C`,
`OUTSW.ASM`) and iterating against the running binary.
## Solved
### 1. iserver boot handshake
After the monitor (`VRENDMON.BTL`) download, `boot_xputer()` calls
`startup_handshake()`, which does **3 iserver transactions** (Phil's comment in
`VR_COMMS.C`: "the C run-time boots up and does 3 iserver transactions"). Each
is a `receive_protocol()` read of a 4-byte little-endian length/route word
(bit31=iserver, low16=payload length) + payload, answered by `iserver_action()`;
only success is checked. The device feeds **3 well-formed iserver "version"
requests** (tag 42, no request-content dependency) and the handshake completes.
### 2. i860 renderer download
`boot_860()` then streams the i860 image (`VRNOSTEX.MNG`) as framed renderer
messages on the slow byte path: `vr_860args` (21), `vr_860code` (18, ×118),
`vr_860data` (19, ×37), `vr_860bss` (20, ×9). The device parses the outbound
frame stream (`[length_word:4][action:4][data]`, `nb = length_word & 0xffff`)
and absorbs them, staying byte-aligned throughout.
### 3. The echo-action reply model (validated against board source)
Renderer request/reply calls (`velocirender_create`/`delete`/`flush`/`sync` in
`DPL_HOST.C`) send an action and require the **same action echoed back**. The
board side confirms this exactly: `VRENDER/VR_REMOT.C remote_velocirender()`
replies with its `data` buffer whose first word is still the received action
(`reply()``dN_send`). The device tracks the last outbound action and echoes
it; this is the general model for every render call, not a one-off.
## The remaining sub-protocol: the FIFO fast path
After the i860 boots, the host stops using the slow byte path and switches to a
**FIFO fast path** for the render protocol. This is why the current build still
stops at `velocirender_sync` — the device only implements the slow path
(0x1500x153).
Discovered mechanics (from the capture + `OUTSW.ASM` + `LINKIO.C`):
- The VPX board is **dual-register**: beyond the C012 slow link
(0x150 inputData / 0x151 outputData / 0x152 inputStatus / 0x153 outputStatus),
there is a **FIFO data port** reached at **0x154/0x155** (observed) and an
`ok_to_fifo` status at **0x160**.
- `send_FIFO_protocol()` / `velocirender_transmit()` (when `use_fifo`) call the
assembly `outsw()` (`OUTSW.ASM`): it writes a `0x40` "use fifo" tag byte, then
`add dx,3` and `REP OUTSW` — pumping the message as **16-bit words** into the
FIFO port. In the capture these land as alternating byte writes to 0x154/0x155
and decode to the init/args string (e.g. `/device~0x150~/video~svga~…`).
- The host switches to `use_fifo` once the board asserts `ok_to_fifo`
(`fifo_ok_status()` reads 0x160 bit0); see the commented wait loop in
`boot_xputer()`.
### Next step (concrete)
Extend the device to implement the FIFO transport:
1. Answer `ok_to_fifo` (0x160 bit0) at the right time so the host enables `use_fifo`.
2. Accept FIFO writes: the `0x40` tag, then word-stream data at the FIFO port
(0x154/0x155). Reassemble into `[length_word][action][data]` messages
(same framing as the slow path).
3. Serve FIFO reads for replies: `velocirender_receive()` in FIFO mode reads the
reply (length_word + `[action][node]`) from the FIFO/status ports. Echo the
sent action (model already validated), returning meaningful node handles for
`vr_create` so later `vr_delete`/geometry ops have valid remotes.
4. Then the render loop (`vr_draw_scene` + frame-ack, `velocirender_frameack()`)
— the Phase 3 boundary, where geometry/material/texture commands can be
decoded into the OpenGL backend (formats already implemented in
`restoration/divformats.py`).
## Reproduce
```
set VPXLOG=C:\VWE\TeslaRel410\emulator\vpxresp.txt
set VPX_RESPOND=1
emulator\src\src\dosbox-x.exe -conf emulator\respond.conf
```
Console progression now: `BattleTech v4.10``BTL4Application` → RIO check →
(handshake, i860 download succeed) → `unexpected action N in velocirender_sync`
(the FIFO-path render handshake, the next target). The log's `#` note lines
trace the device's decisions (handshake requests fed, frames parsed, actions
echoed, mystery ports resolved to 0x154/0x155).
## Update 3 (2026-07-03): full VPX protocol working — game reaches content load
Disassembling `BTL4OPT.EXE` (a PE-in-DOS32RTM binary; CODE @VA 0x401000,
`velocirender_sync` @0x48D220) cracked the last protocol unknowns and the
emulated board now carries the game through the **entire** boot + render
protocol into its own game logic:
1. **velocirender_sync** (was the blocker): from the disassembly, it sends
action **0x2D** (a Rel4.10 sync/ping outside the DPL3 enum, which is why my
`<24` filter dropped it) with data `[token,0]`, then checks
`cmp token, reply.node[0]` at 0x48D271 — the "unexpected action %d" message
only *prints* the received action; the real test is the echoed **data
token**. Device now replies to 0x2D with `node[0] = token`. **Sync passes.**
2. **Speculative-poll gating**: `velocirender_transmit` calls
`handle_iserver_stuff()` which polls inputStatus once and proceeds if
not-ready. Feeding a reply into those polls corrupted alignment. The device
now only feeds a reply after several *consecutive* empty polls (a blocking
`inRecord` spin), not single speculative checks.
3. **Frame-ack**: `velocirender_frameack` expects a message with action
**9 (vr_draw_scene)**. The device tracks an outstanding `draw_scene` send and
replies 9 to the frame-ack. **Frame-ack passes.**
With these, the game now: passes sync, loads the renderer config, builds the
scene (create/flush/list_add/draw_scene), completes frame-ack, and enters its
own content loader (`L4VIDEO.cpp`), where it tries to load BattleTech models
(`buttee.bgf`, `mslr.bgf`, …). The remaining errors are **content packaging /
paths** (the minimal `test.egg` lacks these objects) and an **empty renderer
config** (`dpldflt.ini`) — *not* VPX protocol issues.
**The VPX board emulation is functionally complete for boot + scene setup +
frame-ack.** Next: (a) run against a full mission/content set (a real `.egg`
or the pod's content tree) so objects load; (b) provide a proper DPL config;
(c) Phase 3 — decode the geometry/material/texture commands already flowing over
the FIFO into the OpenGL backend (formats in `restoration/divformats.py`) to put
actual pixels on screen.