Files
TeslaRel410/emulator/GAUGE-NOTES.md
T
CydandClaude Opus 4.8 b2e4c5eaa6 Gauges: fix out-of-memory crash (HEAPSIZE), draw instrument panels
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>
2026-07-03 17:48:07 -05:00

3.4 KiB
Raw Blame History

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 50100 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).