All 25 opcodes now have meanings. Ops 2/4/6/8 are integer compound assignment (+= -= *= /=) and 3/5/7/9 the float versions; 10 and 11 are integer and float compare writing three condition bits; 13-18 are je/jne/jl/jle/jg/jge; 21-24 are push.i/push.f/pop.i/pop.f over deques at phase+44 and phase+64. The shared-handler question is answered: the dispatcher leaves the opcode in r4 and the shared thunks never overwrite it, so those helpers take an extra opcode argument and index a secondary table (0x82271448, 0x8227152C). CORRECTION to my own tool and note: the branch/jump base is [phase+232], which the phase initialiser sets to 0x24 + the phase's entry from the mission-level stream -- 0xE4 / 0x14AA8 / 0x24B4C for Stage 02's three phases, not the file's 0x24. Measured on phase 1: base 0xE4 puts 525 of 525 branch targets on an instruction boundary; base 0x24 manages 188. isl.py had been using 0x24 for every phase, so its jump targets were wrong throughout. Fixed via isl.phase_bases(). That also settles two things mission-script-ssb.md left open: offsets ARE code-base-relative, and 0x1883's operand IS a code pointer -- the earlier worry that some 'land on IEEE floats' was an artefact of adding the wrong base.
52 lines
2.2 KiB
Bash
Executable File
52 lines
2.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Find what WRITES the trigger-queue count, by watching the word rather than
|
|
# hunting the instruction statically.
|
|
#
|
|
# The static hunt failed (isl-builtins.md): the only writes to `+20` in the
|
|
# container's code are block initialisations, yet the count demonstrably moves
|
|
# 0 -> 1 -> 2 during a mission. A watchpoint names the writer directly.
|
|
#
|
|
# The address translation is the fiddly part, so it is explicit:
|
|
# guest VA -> file offset via gmem.va_to_off
|
|
# file offset -> HOST address via the /dev/shm/xenia_memory_* mapping in
|
|
# /proc/<pid>/maps: host = map_start - map_off + off
|
|
# gdb debugs the HOST process, so a guest VA cannot be watched directly.
|
|
set -u
|
|
export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98
|
|
export PYTHONPATH=/sylph-home/.local/lib/python3.12/site-packages
|
|
export XENIA_BIN=/sylph-home/re/bin/gdb-wrap/xenia_canary
|
|
SD="$(cd "$(dirname "$0")" && pwd)"; export SD
|
|
CMD=/tmp/gdb-cmd; OUT=/tmp/gdb-out.log
|
|
WATCH_S="${1:-240}"
|
|
sleepfor(){ python3 -c "import time,sys; time.sleep(float(sys.argv[1]))" "$1"; }
|
|
|
|
"$SD/launch_mission.sh" fly || { echo "BOOT FAILED"; exit 1; }
|
|
CFG=/tmp/nav-tw.json
|
|
for t in 1 2 3; do
|
|
python3 "$SD/pad.py" set "rt=1" >/dev/null 2>&1; sleepfor 3
|
|
python3 "$SD/pad.py" clear >/dev/null 2>&1
|
|
if python3 "$SD/entities2.py" self 0x130 "$CFG" >/dev/null 2>&1; then
|
|
SYLPH_HUNT=1 SYLPH_KEEPOUT=1400 nohup python3 "$SD/pilot.py" "$CFG" 900 \
|
|
</dev/null >/tmp/tw-pilot.log 2>&1 & echo "--- pilot flying"; break
|
|
fi
|
|
done
|
|
|
|
HOSTADDR=$(python3 "$SD/host_addr.py" 2>/tmp/tw-addr.err)
|
|
echo "--- translation: $(cat /tmp/tw-addr.err)"
|
|
echo "--- host addr: $HOSTADDR"
|
|
case "$HOSTADDR" in 0x*) ;; *) echo "could not translate"; exit 2;; esac
|
|
|
|
pid=$(pgrep -x gdb | head -1); before=$(wc -c < "$OUT")
|
|
kill -INT "$pid"; sleepfor 3
|
|
{ echo 'echo === WATCH SET ===\n'
|
|
echo "watch *(unsigned int*)$HOSTADDR"
|
|
echo "continue"; } >> "$CMD"
|
|
echo "--- watching ${WATCH_S}s"
|
|
sleepfor "$WATCH_S"
|
|
kill -INT "$pid"; sleepfor 3
|
|
{ echo 'echo === WHO WROTE IT ===\n'; echo 'bt 8'; echo 'x/3i $pc'
|
|
echo 'echo === END ===\n'; echo 'delete'; echo 'continue'; } >> "$CMD"
|
|
sleepfor 10
|
|
tail -c +$((before + 1)) "$OUT" | grep -vE '^\s*$' | tail -60
|
|
echo "TRIGGER WATCH DONE"
|