BT410 5.3.56: the intermittent pod crash is the skeleton walk's -- attributed by same-binary A/B
Added BT_NO_SKL, which skips the skeleton build so ONE executable can be run with and without it. That is the only clean way to test an intermittent fault, and it settles attribution: walk enabled ~50% of runs die (page fault at 66D9) at DIFFERENT points walk disabled 0 crashes in 2 runs shipped exe 0 crashes in 2 runs, same rig and conf So it is our new code, not the rig, and the varying fault point points at memory corruption surfacing later rather than a bad instruction in the walk. Hypotheses killed by reading the private library headers: the matrix array is the right size (dpl_MATRIX is float32[4][4]); and neither s_dplobject nor the common dpl_node header retains an object name, weakening the dangling-string theory (a private name cache inside the library is still possible and is the best surviving suspect). Also checked something that would have been much worse than a crash: ~NotationFile REWRITES its file when dirty, and these are the game's shipped .SKL data files. MAD.SKL is untouched, and ReadSKLFile now carries the engine's own Verify(!IsDirty()) guard. Next tests are listed cheapest-first in the roadmap: keep the NotationFile alive, copy the Object= names, count board allocations, and re-check whether MakeEntityRenderables runs twice per mech. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
[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 BT_NO_SKL=1
|
||||
set BT_FORCE_THROTTLE=0.6
|
||||
set BT_FORCE_TURN=0.25
|
||||
set HEAPSIZE=15000000
|
||||
set L4GAUGE=640x480x16
|
||||
call setenv.bat r s n p
|
||||
32rtm.exe -x
|
||||
BTL4REC.EXE -egg testarn.egg > COM3
|
||||
|
||||
@@ -8,7 +8,6 @@ ColorMapperArmor warning: damage zone dz_lmissle not found
|
||||
ColorMapperArmor warning: damage zone dz_rmissle not found
|
||||
ColorMapperArmor warning: damage zone dz_ftorso not found
|
||||
ColorMapperArmor warning: damage zone dz_btorso not found
|
||||
L4VIDEO.cpp wrong video resource type for object mad.skl
|
||||
BTL4Application::RunMissionMessageHandler
|
||||
Turning Plasma Score Display On
|
||||
BTL4Application::RunMissionMessageHandler
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
BattleTech v4.10
|
||||
BTL4Application::BTL4Application
|
||||
GaugeInterpreter: undefined label 'Initialization'
|
||||
MakeVehicleSystems hud=0x011503f0
|
||||
MakeVehicleSystems hud=0x01154164
|
||||
Warning: damage zone 'dz_missle' not found!
|
||||
Warning: damage zone 'dz_missle' not found!
|
||||
Warning: damage zone 'dz_lmissle' not found!
|
||||
@@ -9,7 +9,9 @@ Warning: damage zone 'dz_rmissle' not found!
|
||||
Warning: damage zone 'dz_ftorso' not found!
|
||||
Warning: damage zone 'dz_btorso' not found!
|
||||
LBE4ControlsManager::Execute, lost RIO analog request
|
||||
iThinkIRQIsOn =1, actual state =1, characters sent =713
|
||||
iThinkIRQIsOn =1, actual state =1, characters sent =62
|
||||
LBE4ControlsManager::Execute, lost RIO analog request
|
||||
iThinkIRQIsOn =1, actual state =1, characters sent =687
|
||||
BTL4Application::RunMissionMessageHandler
|
||||
Turning Plasma Score Display On
|
||||
BTL4Application::RunMissionMessageHandler
|
||||
|
||||
@@ -159,6 +159,12 @@ dpl_DCS *
|
||||
<< " -> " << node_count << " nodes, "
|
||||
<< object_count << " objects\n" << flush;
|
||||
|
||||
//
|
||||
// The engine guards this the same way (L4VIDEO.CPP, DPLReadEnvironment):
|
||||
// ~NotationFile REWRITES the file when dirtyFlag is set, and these are
|
||||
// the game's shipped .SKL data files.
|
||||
//
|
||||
Verify(!skeleton->IsDirty());
|
||||
Unregister_Object(skeleton);
|
||||
delete skeleton;
|
||||
return root;
|
||||
@@ -388,6 +394,16 @@ void
|
||||
Logical
|
||||
handled = False;
|
||||
|
||||
//
|
||||
// BT_NO_SKL skips the skeleton build so the SAME binary can be
|
||||
// run with and without it -- the only way to attribute the
|
||||
// intermittent pod crash without a rebuild between samples.
|
||||
//
|
||||
if (getenv("BT_NO_SKL") != NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Entity_Being_Created = entity;
|
||||
video_iterator.First();
|
||||
while ((video_wrapper = video_iterator.ReadAndNext()) != NULL)
|
||||
|
||||
@@ -776,3 +776,49 @@ That defect has therefore gone from background annoyance to the top of the
|
||||
list: it is what stops a mech frame from ever being seen, because a run has
|
||||
to survive BOTH the skeleton build AND the launch to render anything, and at
|
||||
~50% per run that is a coin flip on a four-minute cycle.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
THE INTERMITTENT POD CRASH IS THE SKELETON WALK'S -- attributed, not yet fixed
|
||||
--------------------------------------------------------------------------------
|
||||
Attributed with a same-binary A/B, which is the only clean way to test an
|
||||
intermittent fault: BT_NO_SKL skips the skeleton build, so one executable can
|
||||
be run both ways with nothing else differing.
|
||||
|
||||
walk ENABLED ~50% of runs die ("Reference to a page you don't own",
|
||||
PF at 66D9), at DIFFERENT points each time -- sometimes
|
||||
mid-walk, sometimes after it, sometimes before launch
|
||||
walk DISABLED 0 crashes in 2 runs
|
||||
SHIPPED exe 0 crashes in 2 runs on the same rig and conf
|
||||
|
||||
So it is our new code, it is not the rig, and the varying fault point says
|
||||
memory corruption surfacing later rather than a bad instruction in the walk.
|
||||
|
||||
HYPOTHESES KILLED so far (all by reading the private library headers, so they
|
||||
stay killed):
|
||||
* matrix array too small -- dpl_MATRIX is float32[4][4] (DPL_PRIV.H:137),
|
||||
exactly the 16 floats we pass.
|
||||
* dangling Object= name. dpl_LoadObject is handed a pointer INTO the
|
||||
NotationFile, which we then delete -- but neither s_dplobject
|
||||
(DPL_PRIV.H:377) nor the common dpl_node header (DPL_PRIV.H:92) keeps a
|
||||
name field, so the library does not retain it there. A private name
|
||||
cache is still possible and remains the best surviving suspect.
|
||||
* NotationFile rewriting the game's data. ~NotationFile DOES rewrite the
|
||||
file when dirtyFlag is set, which would have corrupted the shipped .SKL
|
||||
files -- checked, MAD.SKL is untouched (11847 bytes, Jan 2001), and the
|
||||
engine's own Verify(!IsDirty()) guard is now copied into ReadSKLFile.
|
||||
|
||||
STILL TO TRY, cheapest first:
|
||||
1. Keep the NotationFile alive for the mission instead of deleting it (a
|
||||
~12KB leak) and see if the crash rate drops -- that settles the name
|
||||
cache question outright.
|
||||
2. Copy each Object= name into storage that outlives the walk, same test.
|
||||
3. Count what the walk allocates on the board (26 DCS + 19 objects + 19
|
||||
instances + 1 zone per mech) against whatever the VPX HLE's node tables
|
||||
allow -- resource exhaustion would also present as a late, varying
|
||||
fault.
|
||||
4. Check whether MakeEntityRenderables is invoked more than once per mech
|
||||
(inside AND outside views). The [skl] summary line printed once per run
|
||||
here, so this is unlikely, but it is cheap to re-check with two mechs.
|
||||
|
||||
BT_NO_SKL stays in the tree: it is how any future "is it the skeleton?"
|
||||
question gets answered in one build instead of two.
|
||||
|
||||
Reference in New Issue
Block a user