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:
+28
-25
@@ -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
|
||||
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
|
||||
rest black. 640×480×16 is 600 KB accessed through a 64 KB window; the game
|
||||
pages it by **calling a hardcoded far pointer** from `L4GAUGE.INI`:
|
||||
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.
|
||||
|
||||
```
|
||||
[640x480x16]
|
||||
mode=273 ;0111h
|
||||
pageFcnPtr=796182 ;C000:2616 <- STB Horizon+ VESA bank-switch routine
|
||||
```
|
||||
`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.
|
||||
|
||||
`C000:2616` is the STB card's VESA `WinFuncPtr`. On our emulated S3 that
|
||||
address is not the bank-switch function, so paging fails and only the first
|
||||
bank(s) (~top 50–100 lines) render. Until this is fixed there is no complete
|
||||
framebuffer to divide into the six displays.
|
||||
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 options (next):
|
||||
1. **Point `pageFcnPtr` at our card's real `WinFuncPtr`** — query VESA
|
||||
GetModeInfo (int 10h/4F01) for mode 0x111 under our S3 and put that far
|
||||
pointer in `L4GAUGE.INI` (`special`/`pageFcnPtr` fields), or force the
|
||||
game to use the queried pointer instead of the baked-in one.
|
||||
2. **Use a linear-framebuffer (LFB) mode** (VESA 2.0, mode 0x111|0x4000) so
|
||||
no bank switching is needed — requires the SVGA16 paging path to target
|
||||
the LFB.
|
||||
3. **Route bank switches through int 10h/4F05** (portable VESA windowing)
|
||||
instead of the direct pointer — a small game patch.
|
||||
**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.)
|
||||
|
||||
Once the full 640×480 buffer renders, splitting it into the six VDB display
|
||||
regions is straightforward (the VDB device already models the splitter).
|
||||
Next: with the full 640×480 buffer rendering correctly, split it into the six
|
||||
VDB display regions (the VDB device already models the splitter).
|
||||
|
||||
Reference in New Issue
Block a user