pvision solved (texture-value ramp) + i860/hardware reverse-engineering

Predator/IR vision: reverse-engineered from the original firmware and
confirmed by the build team -- it is the Division board's TEXTURE-VALUE RAMP
mode (a "check your texture maps" diagnostic the devs hijacked), NOT a
grayscale squash or a false-colour palette. Located in VREND.MNG (effect
handler @0xe6c0, wire action 0x1b, type -1 ON / -2 OFF); ramp colours from
VR_DRAW.C. Renderer reworked to match: vrview_gl now does the 4-ramp
lerp(color0,color1,luminance(texel)) in the mesh pass (grayscale+defog
removed). Live-rendered on a new night-clear arena egg; crew A/B verdict
pending.

Firmware-decomp toolchain (emulator/firmware-decomp/), all built from the
project's own artifacts and validated:
- coff860.py    i860 COFF reader (symbols/sections), names match AS860 source
- derive860.py  derives the i860 opcode map from matched .S<->.O pairs
- dis860.py     i860 disassembler (98% on clean ground truth; proven on
                VREND.MNG -- velocirender_statistics decodes correctly)
- sigmatch860.py reloc-invariant signature matcher onto the stripped image
- i860-encoding.md / FIRMWARE-SYMBOLS.txt / README.md

PVISION-IMPLEMENTATION-GUIDE.md: self-contained hand-off for the BT411 team.

HARDWARE-ARCHITECTURE.md + hardware-photos/ (15 board shots): the Division
VelociRender card is a 2-board stack driving a 3-processor pipeline --
INMOS IMS T425-J25S (comms/control, runs vrendmon.btl) + Intel i860 XP-50 (FP
geometry, runs vrender.mng) + Division PXPL IGC 5.2 ASIC with ~48x PXPL EMC
5.1 (UNC Pixel-Planes-5 SIMD array; "EMC" = the firmware's configEMCs) +
Analog Devices ADV7150 RAMDAC + NTSC. Plus the VWE Video Distribution Board
(P/N 1404: AMD MACH130 + 3x Brooktree Bt477) for the 3-VGA-head cockpit split.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-14 22:29:53 -05:00
co-authored by Claude Fable 5
parent 5593d57d48
commit 1323397a50
28 changed files with 2436 additions and 27 deletions
@@ -498,3 +498,90 @@ first appear in the 0x1f stream -- next session, have the pilot narrate
("holding hat-left NOW") and read the log; if nothing appears during holds,
compare against a 7/07-style run (gauge_arena_sound.conf, no net stack) to
isolate what enables the eyepoint emission.
---
## 2026-07-14: Where the IR / thermal palette actually lives (source hunt)
Operator question: does the game tell the Division card *which* palette to use
for IR/predator vision, or is the card's firmware around to decompile? Answer:
**the game specifies no palette at all -- it just flips a switch; the palette
is baked into the i860 board firmware.**
Chain of evidence (all from THIS project's primary sources -- OUR dump is the
authority; BT411 is a downstream reconstruction *of* this and is NOT cited):
1. **Our own game source: `CODE/RP/MUNGA_L4/L4VIDEO.CPP:5535`,
`DPLRenderer::DPLTogglePVision()`** -- the real, shipped, non-stubbed
implementation (the engine `DPLRenderer` is shared by BT and RP). Comment
reads `toggles the state of dpl "predator" vision`. Verbatim:
```cpp
static Logical pvision_on = 0;
dpl_EXPLOSION_EFFECT_INFO sfx_info;
sfx_info.x = sfx_info.y = sfx_info.z = 0;
if ((pvision_on ^= 1) != 0) { ... sfx_info.type = -1; } // pvision ON
else { ... sfx_info.type = -2; } // pvision OFF
dpl_Effect(dpl_effect_type_explosion, NULL, &sfx_info);
```
Pvision is sent as a **special "explosion" effect at the origin with
`type = -1 / -2`**. The struct (`CODE/RP/MUNGA_L4/libDPL/dpl/DPLTYPES.H:278`,
`{float x,y,z; int32 type; dpl_TEXTURE *tex;}`) has **no colour field** --
so the game hands the board zero palette information. (This also corrects an
earlier disasm misread that thought an RGB triple + matrix was being sent;
there is none.)
2. **DPL3 SDK source (`sda4/DPL3`, `sda4/DPL3RLS`).** The board effect
dispatcher `PAZsfx()` (`VRENDER/SFX.C:751`) only handles explosion codes
`0/1/2`; there is **no `-1/-2` branch and no DAC/palette flip anywhere in
this source**. This VRENDER source is the 1994-95 vintage (DPL3RLS build
dirs `VR_40826`..`VR_50329`) -- it **predates the pvision feature**.
3. **The exe itself.** Same as (1): the on/off flag is all that crosses the
wire. Nothing selects a colour.
So the palette is the **board's built-in response to explosion type -1/-2**,
i.e. it lives in the i860 firmware, not in the game, the SDK, or the exe.
### Is the firmware around / decompilable? Yes.
The board-load images are in the dump as `VRENDMON.BTL` (plus the `VREND2..9`
overlays per game). Dated build tree `sda4/VREND/` runs **Oct 1995 -> Jun 1996**
(`51019` ... `60623EDO`), newer than the source we have; the production images
are `sda4/BTLIVE/` and `sda4/RPLIVE/`. The newest (`VREND/60623EDO/
VRENDMON.BTL`, 13 Jun 1996, 85 KB) is **raw i860 machine code** -- opens
`f0 b4 d1 d1 ...`, no COFF/ELF wrapper, no symbol/string table (grep for
vision/pred/therm/heat/palette = nothing; strings are stripped/packed).
Bottom line for the crew:
- The **exact** IR palette can only come from **reversing the i860
`VRENDMON.BTL`** (Ghidra has an i860 module; same workflow the BT411 team
already runs). Target: the colour/DAC transform gated by the effect
`type == -1`. It's a real RE effort (stripped code) but the binary is here.
- Until then our `heat` palette is an educated interim; the IR-vision-options
sheet (heat/green/amber/mono) is the fast path if a crew member simply
*recognises* the original look.
- Empirical cross-check: hitting the cockpit IR button in the live sim already
drives `board.pvision` through action `0x1b` mode `-1/-2` -- exactly the
explosion-type encoding above -- so the mechanism is confirmed end to end;
only the colour LUT is unknown.
### Revised model (operator, 2026-07-14): grayscale squash + fog off, not a palette
Operator's read: predator vision is probably **not** a false-colour palette
swap -- it's a **per-pixel squash to grayscale plus fog turned OFF** (so
targets read through night/weather). This fits everything: the game sends no
colour, and "see through the murk" is the same family of trick as the
searchlight (which turned out to be a view-fog push-back, not a light cone).
`heat`/`green`/`amber` were only ever an interim guess at the *name*
"predator".
Renderer changed to match (`dpl3-revive/patha/vrview_gl.py`):
- default `VRVIEW_PVISION_PALETTE` flipped `heat` -> `mono` (grayscale squash).
- when pvision is active, the **scene pass forces `fog_on = 0`** (a present-
pass recolour alone cannot undo fog already baked into the pixels).
- green/amber/heat ramps retained purely as opt-in crew A/B (`VRVIEW_
PVISION_PALETTE=green|amber|heat`).
Still a hypothesis pending a live look + crew memory; the ground-truth remains
recoverable by reversing the i860 `VRENDMON.BTL` (colour/DAC transform gated by
effect `type == -1`).
@@ -0,0 +1,78 @@
[sdl]
output=opengl
# higher,higher not highest: HIGH_PRIORITY_CLASS starved the host desktop;
# with the retry patches a rare dropout self-recovers (see gauge_rio.conf).
priority=higher,higher
[dosbox]
memsize=32
machine=svga_s3
[cpu]
core=dynamic
cputype=pentium
cycles=max
[sblaster]
sbtype=sb16
sbbase=220
irq=5
dma=1
hdma=5
[mixer]
# match the EMU8000s' native rate (no resample) and buffer ~60ms so brief
# emulation-thread stalls (RIO retry recovery) don't audibly chop
rate=44100
blocksize=1024
prebuffer=60
[ne2000]
# real pods loaded the ODI stack in AUTOEXEC before ANY game launch --
# weapons-fire test: bare -egg run WITH the packet stack resident (the game's
# WATTCP identity is 200.0.0.113 from REL410\BT\WATTCP.CFG). nicbase 340:
# 300 clashes with the VDB and blanks heads. backend=slirp: THIS build lacks
# pcap ("Backend not supported"); slirp = user-mode NAT, no LAN peers, but
# the packet driver functions and accepts sends -- enough for a solo fire
# test. For pod<->console runs use a pcap-enabled build (net_full.conf).
ne2000=true
nicbase=340
nicirq=3
backend=slirp
[serial]
# RIO on COM1 with the low-latency options (rxpollus/rxburst) so the board's
# few-ms ACK deadline is met; plasma display on COM2 (real pod has both).
serial1=namedpipe pipe:vrio rxpollus:100 rxburst:16
serial2=namedpipe pipe:vplasma
[autoexec]
mount c "C:\VWE\TeslaRel410\ALPHA_1"
mount d "C:\VWE\TeslaRel410\emulator\net-boot"
d:
echo === loading NE2000 packet-driver stack (as production AUTOEXEC did) ===
d:\lsl
d:\ne2000
d:\odipkt
c:
cd \REL410\BT
set VIDEOFORMAT=svga
rem production pod card init (PARAMETR.BAT:181-186): DIAGNOSE + AWEUTIL per
rem card -- AWEUTIL /S does the EMU8000 bring-up and DRAM detect the HMI SOS
rem driver relies on; skipping it left the cards uninitialized (silent).
rem aweutil /s SKIPPED for now: it verifies the AWE32 GM ROM, which the
rem emulated cards lack (hangs in a retry loop) -- restore once the ROM is
rem dumped from a real card. diagnose /s kept (passes, sets mixer config).
set BLASTER=A220 I5 D1 H5 P330 T6
c:\sb16\diagnose /s
set BLASTER=A240 I7 D3 H6 P300 T6
c:\sb16\diagnose /s
set BLASTER=A220 I5 D1 H5 P330 T6
set TEMP=c:\
rem arena1 city mission (TESTARN.EGG: map=arena1, time=day), RIO attached,
rem bare -egg launch (no netnub) = the user's real-world test-egg setup.
set HEAPSIZE=15000000
set L4GAUGE=640x480x16
call setenv.bat r f s p
32rtm.exe -x
rem stdout -> log: this optimized build still emits DEBUG_STREAM lines (the
rem RIO retry spam proved it) -- capture the weapon fire-refusal reason.
rem DOS flushes in 4KB chunks; the tail lands on clean exit (mission timer).
btl4opt.exe -egg testnclr.egg > c:\weaponlog.txt
32rtm.exe -u
echo ALPHA1-RUN-DONE
pause