Gauges: fix bank-switching (window-granularity mismatch)

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>
This commit is contained in:
Cyd
2026-07-03 18:03:29 -05:00
co-authored by Claude Opus 4.8
parent b2e4c5eaa6
commit e8876e521d
+28 -25
View File
@@ -39,33 +39,36 @@ 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 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. heap fix but makes the debug build behave like release under emulation.
## Open: bank-switching garbles the framebuffer ## Fixed: bank-switching (window-granularity mismatch)
The gauge framebuffer currently renders **only a top strip, garbled** — the Symptom: the gauge framebuffer first rendered **only a top strip, garbled**.
rest black. 640×480×16 is 600 KB accessed through a 64 KB window; the game Not the video mode (that works) — a paging error. 640×480×16 is 600 KB
pages it by **calling a hardcoded far pointer** from `L4GAUGE.INI`: 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`)
[640x480x16] is a **red herring** — the direct-pointer path is commented out in the driver
mode=273 ;0111h (`L4SVGA16.ASM` `SVGASetPage`: *"THIS DOES NOT WORK … must use a DPMI call"*).
pageFcnPtr=796182 ;C000:2616 <- STB Horizon+ VESA bank-switch routine The live code pages via **portable VESA int 10h / AX=4F05h**, which our S3
``` handles fine.
`C000:2616` is the STB card's VESA `WinFuncPtr`. On our emulated S3 that The real bug was **window granularity**. `SVGASetPage` passes the bank in
address is not the bank-switch function, so paging fails and only the first *granularity units*; the blit advances the bank by
bank(s) (~top 50100 lines) render. Until this is fixed there is no complete `pageDelta = pageSize / granularity` each time it crosses a 64 KB window
framebuffer to divide into the six displays. (`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 options (next): **Fix (config, no binary patch):** in `ALPHA_1/REL410/BT/GAUGE/L4GAUGE.INI`,
1. **Point `pageFcnPtr` at our card's real `WinFuncPtr`** — query VESA `[640x480x16]` set `granularityInKB=64` (= `sizeInKB`, so `pageDelta=1`,
GetModeInfo (int 10h/4F01) for mode 0x111 under our S3 and put that far matching the S3's 64 KB banks). Backup: `L4GAUGE.INI.orig`. After the change
pointer in `L4GAUGE.INI` (`special`/`pageFcnPtr` fields), or force the the full framebuffer pages correctly (315+ frames, VDB splitter stays ON, no
game to use the queried pointer instead of the baked-in one. tear-down); the display renders as expected (blank between missions; the
2. **Use a linear-framebuffer (LFB) mode** (VESA 2.0, mode 0x111|0x4000) so active-mission instruments draw once the sim runs).
no bank switching is needed — requires the SVGA16 paging path to target (Alternative, untried: `machine=svga_paradise`, whose DOSBox-X default VBE
the LFB. granularity is 4 KB — would match the stock INI without editing it.)
3. **Route bank switches through int 10h/4F05** (portable VESA windowing)
instead of the direct pointer — a small game patch.
Once the full 640×480 buffer renders, splitting it into the six VDB display Next: with the full 640×480 buffer rendering correctly, split it into the six
regions is straightforward (the VDB device already models the splitter). VDB display regions (the VDB device already models the splitter).