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>
3.4 KiB
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):
- Point
pageFcnPtrat our card's realWinFuncPtr— query VESA GetModeInfo (int 10h/4F01) for mode 0x111 under our S3 and put that far pointer inL4GAUGE.INI(special/pageFcnPtrfields), or force the game to use the queried pointer instead of the baked-in one. - 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.
- 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).