From 060078e4aef9880d140ba261a311a2e8cbe99daa Mon Sep 17 00:00:00 2001 From: Cyd Date: Tue, 28 Jul 2026 09:09:04 -0500 Subject: [PATCH] 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 --- emulator/render-bridge/pod_render_rec.conf | 67 +++++++++++++++++ emulator/render-bridge/pod_render_shp.conf | 72 +++++++++++++++++++ restoration/source410/BT_L4/BTL4VID.CPP | 23 +++++- restoration/source410/RENDER-ROADMAP.NOTES.md | 59 +++++++++++++++ 4 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 emulator/render-bridge/pod_render_rec.conf create mode 100644 emulator/render-bridge/pod_render_shp.conf diff --git a/emulator/render-bridge/pod_render_rec.conf b/emulator/render-bridge/pod_render_rec.conf new file mode 100644 index 00000000..a1be7bcd --- /dev/null +++ b/emulator/render-bridge/pod_render_rec.conf @@ -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 + +echo GAME-RC=%errorlevel% >> RC.TXT +32rtm.exe -u +echo ALPHA1-RUN-DONE +pause + diff --git a/emulator/render-bridge/pod_render_shp.conf b/emulator/render-bridge/pod_render_shp.conf new file mode 100644 index 00000000..b0dc3398 --- /dev/null +++ b/emulator/render-bridge/pod_render_shp.conf @@ -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 + diff --git a/restoration/source410/BT_L4/BTL4VID.CPP b/restoration/source410/BT_L4/BTL4VID.CPP index 28e91767..cc9b3aa9 100644 --- a/restoration/source410/BT_L4/BTL4VID.CPP +++ b/restoration/source410/BT_L4/BTL4VID.CPP @@ -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); } diff --git a/restoration/source410/RENDER-ROADMAP.NOTES.md b/restoration/source410/RENDER-ROADMAP.NOTES.md index 58402692..2a62e250 100644 --- a/restoration/source410/RENDER-ROADMAP.NOTES.md +++ b/restoration/source410/RENDER-ROADMAP.NOTES.md @@ -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: 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.