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>
75 lines
3.9 KiB
Markdown
75 lines
3.9 KiB
Markdown
# Gauge / secondary-display path (cockpit instruments)
|
||
|
||
The cockpit's six secondary displays (5 mono + 1 color) show instruments,
|
||
driven by the PC's own SVGA video (an STB Horizon+ / S3-class card on the
|
||
pod) in **VESA mode 0x111 = 640×480×16**, which the VDB splits across the
|
||
monitors (see RIO-NOTES.md / HISTORY.md). Enabled by `L4GAUGE=640x480x16`
|
||
(pod `PARAMETR.BAT :POD`) or `setenv.bat … g`. Config layout, instrument
|
||
images, and gauge scripts live in `ALPHA_1/REL410/BT/GAUGE/`
|
||
(`L4GAUGE.INI`, `L4GAUGE.CFG`, hundreds of `.GIM`/`.PCC`/`.PCX`).
|
||
|
||
## Fixed: the gauge crash was out-of-memory, not video
|
||
|
||
Enabling gauges crashed the game (`Exception 0E … illegal address 0x478`,
|
||
a null-`this`). Root cause, from the game's own debug log:
|
||
|
||
```
|
||
Requested 2808 bytes from MUNGA Heap
|
||
Largest block remaining is 1100 bytes
|
||
Heap size was set to 6291432 bytes
|
||
d:\tesla_bt\munga\HEAP.CPP(342): No remaining block large enough!
|
||
Failing to debugger
|
||
```
|
||
|
||
The MUNGA main heap (`UserHeap MainStorage`, fixed size, no growth) exhausted
|
||
loading the gauge images. It reads its size from the **`HEAPSIZE` environment
|
||
variable** (BTL4OPT.EXE @VA 0x401076: `getenv("HEAPSIZE")`; else default
|
||
`0x600000` = 6 MB). The pod's `PARAMETR.BAT` sets it (`:POD` → 15000000,
|
||
`:REVIEW`/`:LOOP` → 32000000); our minimal `setenv.bat` launch never did, so
|
||
the game used the 6 MB default and starved. **`memsize` does not affect it —
|
||
it is the game's own heap, not DOS memory** (verified: `memsize=127` still
|
||
gave 6 MB). The pod machines have **32 MB RAM**, so a 15 MB heap fits.
|
||
|
||
Fix (no binary patch): `set HEAPSIZE=15000000` before launch (see
|
||
`gauge.conf`). The game then runs sustained with gauges on (500+ frames), the
|
||
VESA mode switches (DOSBox screen blanks into graphics), and it draws the
|
||
instrument panels — the VESA 640×480×16 mode works fine on our emulated S3.
|
||
|
||
Separately, `patch_btl4opt.py` now also neutralizes the general `Verify_Failed`
|
||
debug-assertion crash (this is a `DEBUG_LEVEL 1` build); not required for the
|
||
heap fix but makes the debug build behave like release under emulation.
|
||
|
||
## Fixed: bank-switching (window-granularity mismatch)
|
||
|
||
Symptom: the gauge framebuffer first rendered **only a top strip, garbled**.
|
||
Not the video mode (that works) — a paging error. 640×480×16 is 600 KB
|
||
accessed through a 64 KB window, so the game pages video memory as it blits.
|
||
|
||
`L4GAUGE.INI`'s `pageFcnPtr` (`C000:2616`, the pod card's VESA `WinFuncPtr`)
|
||
is a **red herring** — the direct-pointer path is commented out in the driver
|
||
(`L4SVGA16.ASM` `SVGASetPage`: *"THIS DOES NOT WORK … must use a DPMI call"*).
|
||
The live code pages via **portable VESA int 10h / AX=4F05h**, which our S3
|
||
handles fine.
|
||
|
||
The real bug was **window granularity**. `SVGASetPage` passes the bank in
|
||
*granularity units*; the blit advances the bank by
|
||
`pageDelta = pageSize / granularity` each time it crosses a 64 KB window
|
||
(`L4VB16.CPP` ~3947). The INI carried `granularityInKB=4` — the **Cirrus
|
||
CL-GD5434**'s 4 KB window granularity (the pod's video card; the "STB
|
||
Horizon+" board was Cirrus-based). Our emulated **S3 uses 64 KB banks** (its
|
||
CR6A bank register selects 64 KB pages, and DOSBox-X's default VBE granularity
|
||
for S3 is 64 KB). So `pageDelta = 64/4 = 16` and every bank landed 16× too
|
||
far → the smear.
|
||
|
||
**Fix (config, no binary patch):** in `ALPHA_1/REL410/BT/GAUGE/L4GAUGE.INI`,
|
||
`[640x480x16]` set `granularityInKB=64` (= `sizeInKB`, so `pageDelta=1`,
|
||
matching the S3's 64 KB banks). Backup: `L4GAUGE.INI.orig`. After the change
|
||
the full framebuffer pages correctly (315+ frames, VDB splitter stays ON, no
|
||
tear-down); the display renders as expected (blank between missions; the
|
||
active-mission instruments draw once the sim runs).
|
||
(Alternative, untried: `machine=svga_paradise`, whose DOSBox-X default VBE
|
||
granularity is 4 KB — would match the stock INI without editing it.)
|
||
|
||
Next: with the full 640×480 buffer rendering correctly, split it into the six
|
||
VDB display regions (the VDB device already models the splitter).
|