diff --git a/emulator/VDB-NOTES.md b/emulator/VDB-NOTES.md index 64f65113..5faae8c8 100644 --- a/emulator/VDB-NOTES.md +++ b/emulator/VDB-NOTES.md @@ -21,6 +21,71 @@ The game renders cockpit gauges to the Cirrus SVGA in a **640x480x16bpp** mode (VBE mode 0x111; `L4GAUGE=640x480x16`). The Division/VPX card is separate (the out-the-window 3D). So the SVGA framebuffer the VDB taps = GAUGES ONLY. +## Data-flow overview: one canvas → six displays + +*(Narrative on-ramp; the register-level detail is in the sections below.)* + +The pod has **two independent video systems**, which are easy to conflate: + +- **Out-the-window 3D** comes from the **Division VelociRender** card (i860 + + PXPL IGC/EMC rasterizer) on its own monitor — nothing to do with the VDB. + See [[division-card-hardware]]. +- **The six cockpit gauge displays** — 5 monochrome MFDs + 1 color radar — all + come from the VDB, fanned out from a **single framebuffer**. + +The game never renders "six displays." The MUNGA_L4 gauge renderer draws every +instrument into **one 640×480×16bpp image** on a commodity Cirrus SVGA card. +All the intelligence is in how that one canvas is *packed*; the VDB itself does +no computing — it is a dumb byte-lane splitter. + +```mermaid +flowchart TD + G["Gauge renderer (MUNGA_L4)
draws ALL instruments"] --> FB["Cirrus CL-GD5434 SVGA
640x480x16bpp framebuffer
VBE mode 0x111 - one packed image"] + FB -->|"26-pin VGA feature-connector ribbon"| VDB{{"VDB splitter - MACH130 CPLD
high-color clock divider ON
(dumb: no framebuffer, no compute)"}} + + VDB -->|"LOW byte - bits 0-7"| SEC["Secondary palette
I/O 0x302 - Bt477 #1
full-color CLUT"] + VDB -->|"HIGH byte - bits 8-15"| AUX1["Aux1 palette
I/O 0x30A - Bt477 #2
brightness-ramp CLUT"] + VDB -->|"HIGH byte - bits 8-15"| AUX2["Aux2 palette
I/O 0x312 - Bt477 #3
brightness-ramp CLUT"] + + SEC --> HA["Head A - full RGB"] + AUX1 --> HB["Head B"] + AUX2 --> HC["Head C"] + + HA -->|"octopus / DB25 cable"| R1["Color RADAR"] + HB -->|"R wire"| M1["Lower-left MFD"] + HB -->|"G wire"| M2["Lower-right MFD"] + HC -->|"R wire"| M3["Upper-left MFD"] + HC -->|"G wire"| M4["Upper-center MFD"] + HC -->|"B wire"| M5["Upper-right MFD"] +``` + +**How one 16-bit pixel becomes six displays:** + +1. **The two bytes are two index streams.** In 16bpp mode the VDB's high-color + clock divider (I/O `0x31A`) clocks the **low byte** and **high byte** of + every pixel into *separate* palette lanes. Low byte → the color radar; + high byte → the five mono MFDs. +2. **Five mono MFDs share the high byte** by owning **disjoint bit groups** + (`bitMask`) and driving **different DAC color channels** (`channelEnable` = + R/G/B). A mono MFD only needs a brightness ramp, so `BuildAuxiliaryPalette` + writes a linear intensity ramp into that display's channel of the shared + 256-entry CLUT. The radar keeps true colors via `BuildSecondaryPalette`. +3. **Three RAMDACs → three heads.** Each palette group is a real Brooktree + Bt477 (6-bit/channel — hence the driver's `shr al,2` on writes). + Secondary→Head A (radar), Aux1→Head B, Aux2→Head C. +4. **The octopus cable splits heads into wires.** A mono MFD needs only one + color channel, so the DB25 "octopus/pentapus" fan-out routes each head's + individual R/G/B wire to its own monitor: Head B → 2 lower MFDs (R,G; no + blue), Head C → 3 upper MFDs (R,G,B). Head A drives the radar as full RGB. + **2 + 3 MFDs + 1 radar = the six cockpit displays.** + +**Why it was built this way:** in 1994 you couldn't cheaply drive six arcade +monitors from one PC. This lets a **single commodity SVGA card render one +image**, and a **cheap dumb splitter** (one CPLD + three RAMDACs, no memory) +reconstruct six independent displays — with per-gauge brightness ramps, blink, +and radar fade all handled "for free" by loading palettes (see *Palette flash + +fade* below). The register/CLUT detail follows. + ## Register map (definitive, from L4SVGA16.ASM) I/O 0x300-0x31A. Three palette groups, each a 6-bit VGA-DAC-style CLUT. The