Enabling gauges crashed (null-this, illegal 0x478). Root cause was NOT video:
the MUNGA main heap (fixed 6MB default) exhausted loading gauge images. The
heap size comes from getenv("HEAPSIZE") (BTL4OPT.EXE @0x401076; default
0x600000); the pod's PARAMETR.BAT sets it (:POD=15MB, :REVIEW/:LOOP=32MB) but
our minimal setenv launch never did. memsize is irrelevant (it's the game's
own heap, not DOS memory -- verified memsize=127 still gave 6MB). Pods have
32MB RAM so 15MB fits.
Fix (no binary patch): set HEAPSIZE=15000000 + L4GAUGE=640x480x16 in
gauge.conf. Game now runs sustained with gauges on (500+ frames); the VESA
640x480x16 mode switches fine on our emulated S3 and the cockpit instrument
panels draw (DISPLAY/PROGRAM/ENG DATA/TRIGGER CONFIG...).
patch_btl4opt.py also gained Verify_Failed (DEBUG-build assertion) neutral-
ization -- release-equivalent robustness, separate from the heap fix.
Known-open (GAUGE-NOTES.md): the framebuffer renders only a top strip,
garbled -- the game bank-switches via a hardcoded far pointer in L4GAUGE.INI
(C000:2616, the STB Horizon+ card's VESA WinFuncPtr) that isn't valid on our
emulated S3, so only the first bank(s) page in. Fixing bank-switching (or an
LFB mode) is next; then the full buffer can be split into the six displays.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
72 lines
3.4 KiB
Markdown
72 lines
3.4 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.
|
||
|
||
## Open: bank-switching garbles the framebuffer
|
||
|
||
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`:
|
||
|
||
```
|
||
[640x480x16]
|
||
mode=273 ;0111h
|
||
pageFcnPtr=796182 ;C000:2616 <- STB Horizon+ VESA bank-switch routine
|
||
```
|
||
|
||
`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.
|
||
|
||
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.
|
||
|
||
Once the full 640×480 buffer renders, splitting it into the six VDB display
|
||
regions is straightforward (the VDB device already models the splitter).
|