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
+21 -2
View File
@@ -111,8 +111,27 @@ void
}
void
BTL4VideoRenderer::LoadMissionImplementation(Mission *)
BTL4VideoRenderer::LoadMissionImplementation(Mission *mission)
{
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 /
RecurseSKLFile over the .SKL skeleton pages (VIDEO/*.SKL are in the mount),
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.