`SYLPHEED_DB` is the documented contract for the static-analysis database —
`docker/decoder/sylph-decoder` sets it, and `docs/agents/CONTAINER-NOTES.md` and
`decoder-loop.md` list it — but no reader honoured it:
isl_cmdtab.py, name_block_bases.py hardcoded `/work/xenia-rs/sylpheed.db`, a
path that has not existed anywhere since
`/work` became a clone. Both failed on
every machine, before and after the
database moved.
zq.py used `$SYLPH_XEXDB`, a name invented in
#39 without grepping for the existing one.
All three now resolve `$SYLPHEED_DB`, then `$SYLPH_XEXDB` (kept as an alias so
nothing already written against it breaks), then `<repo root>/sylpheed.db`, and
refuse with exit 1 naming both variables and the build command otherwise.
`grab_tutorial.sh` hardcoded its helpers into the retired `sylpheed-reborn`
checkout. That copy's `skip_intro.sh` still calls the removed `vgamepad` and
exits 0 having pressed nothing — the failure this repository's own copy was
rewritten to make loud. So the script was already running a silently broken
helper; it now resolves its helpers from its own directory. Nothing exists only
in reborn's `tools/re-capture` (checked: 0 reborn-only files).
Verified against the same database, output compared byte for byte with the
ORIGINAL scripts (path-substituted copies, sibling imports resolvable):
resolution path isl_cmdtab name_block_bases
default (root) identical identical
$SYLPHEED_DB identical identical
$SYLPH_XEXDB identical identical
bad path exit 1 exit 1 (zq.py: exit 1 too)
and `isl_cmdtab`'s output is byte-identical to the body of the committed
`docs/re/data/isl-command-table.txt`.
⚠️ `name_block_bases`'s output does NOT reproduce the committed
`docs/re/data/name-block-bases.txt` (2,609 lines differ, `strings in the image:
7366` vs `7140`). That is the database, not this change: the artefact was
generated from the agent box's older 586 MB database, and this machine's is the
current generator's. Two databases are in circulation. Not regenerated here.
⚠️ Also not fixed, because it is a different bug: `name_block_bases.py` globs
`/work/sylph_extract/**/*.pak`, another path that exists nowhere now; that part
of its report is silently empty. It should read `$SYLPHEED_DISC`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
74 lines
3.2 KiB
Bash
Executable File
74 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Capture one tutorial's unit definitions: cold-boot Canary, walk
|
|
# title -> TUTORIAL -> the Nth entry, wait for the stage to load, snapshot RAM.
|
|
#
|
|
# One emulator per tutorial on purpose: backing out of a loaded mission via
|
|
# PAUSE -> BACK TO MENU wedged the emulator (log stops, CPU spins), while a
|
|
# cold boot here is ~15 s. The unit definitions are all parsed at stage load,
|
|
# so a single snapshot right after the load is everything this needs.
|
|
set -u
|
|
N="${1:?usage: grab_tutorial.sh <index 0..5> <outfile>}"
|
|
OUT="${2:?}"
|
|
export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98
|
|
SD="$(cd "$(dirname "$0")" && pwd)"
|
|
# This script lives in the helpers' own directory. It used to hardcode the
|
|
# retired `sylpheed-reborn` checkout, whose `skip_intro.sh` still calls the
|
|
# removed `vgamepad` and exits 0 having pressed nothing.
|
|
RC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
# The container entrypoint's Xvfb/openbox do NOT restart on their own, and a
|
|
# dead Xvfb leaves a <defunct> entry that still matches `pgrep` -- so test the
|
|
# display with xdpyinfo, never by process name.
|
|
ensure_display(){
|
|
if ! xdpyinfo -display "$DISPLAY" >/dev/null 2>&1; then
|
|
echo "[grab] $DISPLAY is down -> restarting Xvfb + openbox"
|
|
setsid nohup Xvfb "$DISPLAY" -screen 0 1280x720x24 -ac -nolisten tcp \
|
|
+extension GLX +extension RANDR </dev/null >/tmp/xvfb98.log 2>&1 &
|
|
for _ in $(seq 1 50); do xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 && break; sleep 0.2; done
|
|
setsid nohup env DISPLAY="$DISPLAY" HOME=/sylph-home openbox </dev/null >/tmp/openbox98.log 2>&1 &
|
|
sleep 1
|
|
fi
|
|
xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 || { echo "DISPLAY UNAVAILABLE"; exit 1; }
|
|
}
|
|
|
|
step(){ vgamepad dpad "$1"; sleep 0.2; vgamepad dpad center; sleep 0.6; }
|
|
shot(){ screenshot "$SD/$1" >/dev/null 2>&1; }
|
|
|
|
# Container PID 1 is `sleep infinity`, which never reaps, so every killed
|
|
# emulator stays as a <defunct> entry that `pgrep` still matches. Ask ps for the
|
|
# state and ignore anything zombie, or this always thinks one is running.
|
|
alive(){ ps -o pid=,stat= -C xenia_canary 2>/dev/null | awk '$2 !~ /^Z/ {print $1}'; }
|
|
pkill -x xenia_canary 2>/dev/null; sleep 2
|
|
[ -n "$(alive)" ] && { kill -9 $(alive) 2>/dev/null; sleep 2; }
|
|
rm -f /dev/shm/xenia_memory_* /dev/shm/xenia_code_cache_* 2>/dev/null
|
|
|
|
ensure_display
|
|
|
|
cd /sylph-home/re
|
|
setsid nohup run-canary --apu=sdl --log_mask=13 \
|
|
--logged_profile_slot_0_xuid=E0300000EFBEA3D4 </dev/null >/dev/null 2>&1 &
|
|
sleep 5
|
|
"$RC/skip_intro.sh" 600 || { echo "BOOT FAILED"; exit 1; }
|
|
# The main menu is not input-ready for ~10 s after the title tap under lavapipe;
|
|
# d-pad presses before that are silently dropped, and the A then lands on NEW
|
|
# GAME instead of TUTORIAL. This wait is the whole fix.
|
|
sleep 14
|
|
shot "nav-$N-menu.png"
|
|
|
|
step down; step down # NEW GAME -> TUTORIAL
|
|
vgamepad tap A 250; sleep 8
|
|
shot "nav-$N-list.png"
|
|
|
|
i=0; while [ "$i" -lt "$N" ]; do step down; i=$((i+1)); done
|
|
shot "nav-$N-pick.png"
|
|
vgamepad tap A 250
|
|
|
|
# the stage load takes ~25-45 s under lavapipe; wait for the screen to settle
|
|
sleep 50
|
|
shot "nav-$N-loaded.png"
|
|
|
|
MEM=$(ls /dev/shm/xenia_memory_* 2>/dev/null | head -1)
|
|
[ -n "$MEM" ] || { echo "NO SHM"; exit 1; }
|
|
cp --sparse=always "$MEM" "$SD/$OUT" || exit 1
|
|
echo "SNAPSHOT $OUT ($(du -h "$SD/$OUT" | cut -f1))"
|