BT410 5.3.50: geometry loads -- the bring-up no-op was suppressing the base

DPLRenderer::LoadMissionImplementation (L4VIDEO.CPP:6007) is not empty: it
calls DPLReadEnvironment (which opens L4DPLCFG/btdpl.ini and sets the dPL
object/material/texmap paths from the objectpath= entries) and then
LoadNameBitmaps.  The 'bring-up no-op' installed earlier therefore did not do
nothing -- it REPLACED that, so the loader never learned where the art lives
and every dpl_LoadObject returned NULL.

I justified that no-op by pointing at VideoRenderer's bare Tell and
GaugeRenderer's identical one; neither is our base.  Check the ACTUAL base
before overriding in this engine and chain it unless there is a reason not
to.  DPLReadEnvironment is private to DPLRenderer, so chaining is the only
way a game renderer can reach it at all.

  before: 40x 'couldn't load object', 'NULL instance', run ends,
          wire ~24 bytes/sec
  after:  0 failures, run continues, wire ~12 KB/s (1.17MB climbing),
          bridge live at 88fps

Proved it was ours and not the rig by running the SHIPPED exe under the same
conf: it loaded every object.  That A/B is cheap and is the right first move
whenever the pod misbehaves.

Still black: the bridge camera sits at its default (0,10,0), so the wire
carries state and object loads rather than a populated scene.  The mech and
arena entities still need MakeEntityRenderables bodies.

Rig improvements, both from the user: nosound is fine on the SLOW clock (it
is the FAST SOS clock that needs the AWE32), which saves ~4 min and ~300MB of
audio taps per run; and serial3=file + '> COM3' gives a live unbuffered log,
so a run that does NOT crash is finally readable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-28 09:09:04 -05:00
co-authored by Claude Fable 5
parent ed7843b89f
commit 060078e4ae
4 changed files with 219 additions and 2 deletions
@@ -0,0 +1,67 @@
[sdl]
output=opengl
# higher,higher not highest: HIGH_PRIORITY_CLASS starved the host desktop;
# with the retry patches a rare dropout self-recovers (see gauge_rio.conf).
priority=higher,higher
[dosbox]
memsize=32
machine=svga_s3
[cpu]
core=dynamic
cputype=pentium
cycles=max
[sblaster]
sbtype=sb16
sbbase=220
irq=5
dma=1
hdma=5
[mixer]
# match the EMU8000s' native rate (no resample) and buffer ~60ms so brief
# emulation-thread stalls (RIO retry recovery) don't audibly chop
rate=44100
blocksize=1024
prebuffer=60
[serial]
# RIO on COM1 with the low-latency options (rxpollus/rxburst) so the board's
# few-ms ACK deadline is met; plasma display on COM2 (real pod has both).
# VWE fork namedpipe backend (com0com/realport retired -- COM1/COM2 gone):
# DOSBox = pipe client (retry), vRIO/vPLASMA apps = servers; an unconnected
# pipe behaves as an unplugged cable so the mission still runs. serialnamedpipe.h
serial1=namedpipe pipe:vrio rxpollus:100 rxburst:16
serial2=namedpipe pipe:vplasma
# live UNBUFFERED game output: DOS char devices are not buffered, so
# redirecting stdout to COM3 lands every line immediately. A normal
# '> file' redirect stays 0 bytes until the process exits, which hides
# all progress on a run that does NOT crash.
serial3=file file:C:\VWE\TeslaRel410\emulator\render-bridge\podlog.txt
[autoexec]
mount c "C:\VWE\TeslaRel410\ALPHA_1"
c:
cd \REL410\BT
set VIDEOFORMAT=svga
rem production pod card init (PARAMETR.BAT:181-186): DIAGNOSE + AWEUTIL per
rem card -- AWEUTIL /S does the EMU8000 bring-up and DRAM detect the HMI SOS
rem driver relies on; skipping it left the cards uninitialized (silent).
rem aweutil /s SKIPPED for now: it verifies the AWE32 GM ROM, which the
rem emulated cards lack (hangs in a retry loop) -- restore once the ROM is
rem dumped from a real card. diagnose /s kept (passes, sets mixer config).
set BLASTER=A220 I5 D1 H5 P330 T6
c:\sb16\diagnose /s
set BLASTER=A240 I7 D3 H6 P300 T6
c:\sb16\diagnose /s
set BLASTER=A220 I5 D1 H5 P330 T6
set TEMP=c:\
rem arena1 city mission (TESTARN.EGG: map=arena1, time=day) with the RIO
rem attached; stdout redirected so mission-load progress survives kills.
set HEAPSIZE=15000000
set L4GAUGE=640x480x16
call setenv.bat r s n p
32rtm.exe -x
BTL4REC.EXE -egg testarn.egg > COM3
@@ -0,0 +1,72 @@
[sdl]
output=opengl
# higher,higher not highest: HIGH_PRIORITY_CLASS starved the host desktop;
# with the retry patches a rare dropout self-recovers (see gauge_rio.conf).
priority=higher,higher
[dosbox]
memsize=32
machine=svga_s3
[cpu]
core=dynamic
cputype=pentium
cycles=max
[sblaster]
sbtype=sb16
sbbase=220
irq=5
dma=1
hdma=5
[mixer]
# match the EMU8000s' native rate (no resample) and buffer ~60ms so brief
# emulation-thread stalls (RIO retry recovery) don't audibly chop
rate=44100
blocksize=1024
prebuffer=60
[serial]
# RIO on COM1 with the low-latency options (rxpollus/rxburst) so the board's
# few-ms ACK deadline is met; plasma display on COM2 (real pod has both).
# VWE fork namedpipe backend (com0com/realport retired -- COM1/COM2 gone):
# DOSBox = pipe client (retry), vRIO/vPLASMA apps = servers; an unconnected
# pipe behaves as an unplugged cable so the mission still runs. serialnamedpipe.h
serial1=namedpipe pipe:vrio rxpollus:100 rxburst:16
serial2=namedpipe pipe:vplasma
# live UNBUFFERED game output: DOS char devices are not buffered, so
# redirecting stdout to COM3 lands every line immediately. A normal
# '> file' redirect stays 0 bytes until the process exits, which hides
# all progress on a run that does NOT crash.
serial3=file file:C:\VWE\TeslaRel410\emulator\render-bridge\podlog_shipped.txt
[autoexec]
mount c "C:\VWE\TeslaRel410\ALPHA_1"
c:
cd \REL410\BT
set VIDEOFORMAT=svga
rem production pod card init (PARAMETR.BAT:181-186): DIAGNOSE + AWEUTIL per
rem card -- AWEUTIL /S does the EMU8000 bring-up and DRAM detect the HMI SOS
rem driver relies on; skipping it left the cards uninitialized (silent).
rem aweutil /s SKIPPED for now: it verifies the AWE32 GM ROM, which the
rem emulated cards lack (hangs in a retry loop) -- restore once the ROM is
rem dumped from a real card. diagnose /s kept (passes, sets mixer config).
set BLASTER=A220 I5 D1 H5 P330 T6
c:\sb16\diagnose /s
set BLASTER=A240 I7 D3 H6 P300 T6
c:\sb16\diagnose /s
set BLASTER=A220 I5 D1 H5 P330 T6
set TEMP=c:\
rem arena1 city mission (TESTARN.EGG: map=arena1, time=day) with the RIO
rem attached; stdout redirected so mission-load progress survives kills.
set HEAPSIZE=15000000
set L4GAUGE=640x480x16
call setenv.bat r s n p
32rtm.exe -x
btl4opt.exe -egg testarn.egg > COM3
echo GAME-RC=%errorlevel% >> RC.TXT
32rtm.exe -u
echo ALPHA1-RUN-DONE
pause
+21 -2
View File
@@ -111,8 +111,27 @@ void
} }
void void
BTL4VideoRenderer::LoadMissionImplementation(Mission *) BTL4VideoRenderer::LoadMissionImplementation(Mission *mission)
{ {
Check(this); Check(this);
Tell("BTL4VideoRenderer::LoadMissionImplementation -- empty scene (bring-up)\n"); //
// CHAIN THE BASE. DPLRenderer::LoadMissionImplementation
// (L4VIDEO.CPP:6007) is NOT empty -- it reads the renderer environment
// and loads the name bitmaps. DPLReadEnvironment opens the
// notation file named by L4DPLCFG (SETENV.BAT defaults it to
// btdpl.ini) and hands its "main" page to DPLReadINIPage, which walks
// the compare/branch pages for this location/time and calls
// dpl_SetObjectFilePath / material / texmap from the objectpath=
// entries (L4VIDEO.CPP:1852). It is PRIVATE to DPLRenderer, so the
// game renderer reaches it only by chaining -- which is the whole
// point: an override here REPLACES the base, it does not extend it.
//
// WITHOUT IT every dpl_LoadObject returns NULL. The live pod run
// failed all 40 arena objects (sky / aw01..aw04 / afloor / bcor1 /
// bdet1 / bdet2 / bpip1) and ended in "NULL instance", while the
// SHIPPED binary on the SAME rig loaded every one of them. The
// models were never missing -- the loader simply had no paths, because
// the bring-up no-op that used to live here SUPPRESSED the base.
//
DPLRenderer::LoadMissionImplementation(mission);
} }
@@ -472,3 +472,62 @@ NEXT: the mech (MechClassID 3001) and the arena/terrain entities are what
actually need renderables -- MakeEntityRenderables -> ReadSKLFile / actually need renderables -- MakeEntityRenderables -> ReadSKLFile /
RecurseSKLFile over the .SKL skeleton pages (VIDEO/*.SKL are in the mount), RecurseSKLFile over the .SKL skeleton pages (VIDEO/*.SKL are in the mount),
building a dpl_DCS hierarchy and loading the .BGF geometry per node. building a dpl_DCS hierarchy and loading the .BGF geometry per node.
--------------------------------------------------------------------------------
THE NO-OP WAS THE BUG: an override REPLACES the base, it does not extend it
--------------------------------------------------------------------------------
DPLRenderer::LoadMissionImplementation (L4VIDEO.CPP:6007) is NOT empty:
DPLReadEnvironment(mission); // opens L4DPLCFG (btdpl.ini), walks the
// compare/branch pages for this
// location/time and calls
// dpl_SetObjectFilePath / material /
// texmap from the objectpath= entries
LoadNameBitmaps();
The "bring-up no-op" installed earlier therefore did not do nothing -- it
SUPPRESSED the engine's own mission load, so the dPL library never learned
where the art lives and every dpl_LoadObject returned NULL. That is the whole
explanation for the 40 failed arena objects and the NULL instance.
Justifying the no-op by pointing at VideoRenderer::LoadMissionImplementation
(a bare Tell) and GaugeRenderer's (the same) was the error: neither is OUR
base. Check the ACTUAL base before overriding anything in this engine, and
chain it unless there is a reason not to. (DPLReadEnvironment is private to
DPLRenderer, so chaining is the only way a game renderer can reach it -- more
evidence the authentic btl4vid chained too.)
BEFORE AFTER
40x "couldn't load object" 0
"NULL instance", run ends runs on
wire ~24 bytes/sec (keep-alive) ~12 KB/s (1.17MB and climbing)
bridge live at 88fps
PROVED IT WAS OURS, NOT THE RIG: the SHIPPED binary was run under the same
conf on the same rig and loaded every object (0 failures). That A/B is cheap
now and is the right first move whenever the pod misbehaves.
STILL BLACK. The bridge renders nothing yet and its camera sits at the
default (0,10,0) rather than the mech's eyepoint, so what is going over the
wire is state plus object loads, not a populated scene. The mech
(MechClassID 3001) and the arena entities still need MakeEntityRenderables
bodies -- ReadSKLFile / RecurseSKLFile over the .SKL pages into a dpl_DCS
hierarchy -- and the view/eyepoint flush wants checking once something is
actually in the zone.
--------------------------------------------------------------------------------
RIG: fast, observable pod runs (use this from now on)
--------------------------------------------------------------------------------
emulator/render-bridge/pod_render_rec.conf + `launch_pod.ps1 -NoSound`
* NOSOUND IS FINE ON THE SLOW CLOCK. The old note "--no-sound FREEZES
bt/rp" is half the story: it is the FAST SOS clock that needs the AWE32.
setenv.bat args are `r s n p` (RIO, SLOW clock, NOSOUND, plasma+gauges).
Saves the ~4 minute SoundFont upload AND the ~300MB of awe_*.wav taps
each run.
* LIVE UNBUFFERED LOG: serial3=file file:<path> plus `> COM3` instead of
`> OUTREC.TXT`. DOS char devices are not buffered, so the log is
readable WHILE the game runs. A plain file redirect stays 0 bytes until
the process exits normally -- which is why every readable log before this
came from a run that crashed.
* pod_render_shp.conf is the same conf running the SHIPPED exe, for the A/B.