Finding REMAINING OB in RAM means getting to the escort stage, and launch_mission.sh exists for exactly that. It carried three of the dead patterns this session has been clearing: six vgamepad calls (the command no longer exists, so the entire scripted route pressed nothing), the XUID E0300000EFBEA3D4 which has no profile behind it and therefore opens the sign-in dialog that swallows every keystroke, and the emulator's stdout going to /dev/null. wait_flight.sh had a fourth, in the tap that skips the launch cinematic. Fixed, the route works far past where it used to stop: boot -> title -> LOAD GAME -> slot 01 -> READY ROOM -> TAKE OFF -> the Stage 02 briefing map, with ACROPOLIS labelled on it. And it stops there: 384 dumps at PC 0x82307128 and no flight HUD within 300s. The briefing is still animating (two shots a minute apart differ by RMSE 2986), so the emulator is not frozen - flight simply never starts. One discriminator worth recording: the TUTORIAL reaches flight and has run completely crash-free, while this path crashes during the briefing, which is where the stage content loads. That is consistent with the cache-flush shape the crash has always had, and points at WHAT is being loaded rather than at how far the navigation gets. REMAINING OB is therefore still not found - the mission was never entered.
46 lines
2.0 KiB
Bash
Executable File
46 lines
2.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Wait until the game is actually FLYING, then return — do not guess with sleeps.
|
|
#
|
|
# `launch_mission.sh` used to allow a fixed 75 s for the launch cinematic, the
|
|
# stage load and the objective card. Under lavapipe that is not a constant: one
|
|
# run needed 75 s, the next was still in Raymond's dialogue at 140 s, so the A
|
|
# meant for the OBJECTIVE card was swallowed by the cutscene and the card sat
|
|
# there forever.
|
|
#
|
|
# The in-flight HUD is unmistakable: the SHIELD bar is a solid bright green
|
|
# block at the bottom of the screen, and no cutscene or menu has anything green
|
|
# there. So poll that pixel, and tap A every few seconds until it appears (which
|
|
# dismisses the objective card whenever it happens to be up).
|
|
#
|
|
# Same liveness rule as skip_intro.sh, for the same reason: a failed screenshot
|
|
# leaves r/g/b unset, they default to 0, the green test fails, and waiting for
|
|
# the HUD becomes indistinguishable from waiting for a dead emulator.
|
|
set -u
|
|
export HOME=/sylph-home/re
|
|
DISP="${DISPLAY:-:98}"
|
|
alive(){ ps -o pid=,stat= -C xenia_canary 2>/dev/null | awk '$2 !~ /^Z/ {print $1}'; }
|
|
DEADLINE=$(( SECONDS + ${1:-240} ))
|
|
PX=450; PY=640 # inside the SHIELD bar of the flight HUD
|
|
last_tap=0
|
|
while [ $SECONDS -lt $DEADLINE ]; do
|
|
rm -f /tmp/wf.png
|
|
if ! screenshot /tmp/wf.png >/dev/null 2>&1 || [ ! -s /tmp/wf.png ]; then
|
|
xdpyinfo -display "$DISP" >/dev/null 2>&1 \
|
|
|| { echo "DISPLAY LOST at ${SECONDS}s"; exit 3; }
|
|
sleep 2; continue
|
|
fi
|
|
[ -n "$(alive)" ] || { echo "EMULATOR GONE at ${SECONDS}s"; exit 4; }
|
|
read -r r g b < <(convert /tmp/wf.png -format \
|
|
"%[fx:int(255*p{$PX,$PY}.r)] %[fx:int(255*p{$PX,$PY}.g)] %[fx:int(255*p{$PX,$PY}.b)]" info:)
|
|
if [ "${g:-0}" -gt 140 ] && [ $(( g - r )) -gt 60 ] && [ $(( g - b )) -gt 60 ]; then
|
|
echo "IN FLIGHT at ${SECONDS}s (HUD shield bar visible)"
|
|
exit 0
|
|
fi
|
|
if [ $(( SECONDS - last_tap )) -ge 6 ]; then
|
|
python3 "$(dirname "${BASH_SOURCE[0]}")/pad.py" tap A 0.3
|
|
last_tap=$SECONDS
|
|
fi
|
|
sleep 2
|
|
done
|
|
echo "NO FLIGHT HUD within ${1:-240}s"; exit 1
|