The crash that has killed lifecycle2.conf since somewhere in 5.3.26..120
was never in the missile code. The map named Missile::MoveAndCollide
because it resolves the nearest preceding symbol; the instruction bytes
named the truth: mov eax,[ebx+0x128]; mov eax,[eax]; mov eax,[eax+0xFC]
= mech->subsystemArray[0]->member through a NULL slot 0.
Roster slot 0 is the CONTROLS MAPPER, and the BT_SPAWN_ENEMY dev enemy
never got one -- SetMappingSubsystem is only called on the player's
viewpoint mech. The binary never NULL-checks that slot (mech2's
advancers, the master perf's duck evaluation and the effectiveness
census all deref it bare, correctly: a real mech always has its mapper),
so the enemy faulted the first frame it reached one of those reads.
Nothing dereferenced a non-player mech's mapper before the gait arc,
which is exactly why it lay hidden.
The object was proven by the fault-address rule this project already
learned: the faulting member offset MOVED 0xFC -> 0x100 across the
5.3.125 build, which added ejectLatch to MechControlsMapper -- a 4-byte
layout shift in the very class being dereferenced.
The dev enemy now installs a plain MechControlsMapper (inert without
device input), preserving the binary's contract. VERIFIED end to end:
kill -> respawn -> second kill -> OUT OF LIVES -> mission end -> clean
DOS exit, zero exceptions -- the full lifecycle is green for the first
time since 5.3.25.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>