#!/usr/bin/env bash
# Launch Xenia Canary with the settings this title actually needs.
#
# Four of these are not preferences — they are measured requirements, and every
# one of them cost a debugging session before it was pinned down:
#
#   --apu=sdl + SDL_AUDIODRIVER=dummy
#       There is no PulseAudio here, so `--apu=nop` looks like the safe muted
#       choice. It is not: the log then fills with "CreateDriver failed for
#       index=0", the guest never gets past the intro movie, and the window
#       stays black for 8+ minutes. The SDL driver against a dummy device is
#       both silent AND lets the title advance.
#
#   NO --audio flag
#       The RE notes say "--audio --apu=sdl". `--audio` is NOT a cvar in this
#       tree, and an unknown argument is not a friendly error: xenia calls
#       ShowSimpleMessageBox from ParseLaunchArguments, BEFORE logging is
#       initialised, and that SDL dialog blocks on XIfEvent forever. Headless,
#       the symptom is a 10x10 window, an empty log, and no guest memory —
#       which reads like a hang deep in the emulator rather than a typo.
#       If this ever appears to hang at startup, suspect a bad flag first.
#
#   --hid=file --pad_file=...
#       The old vgamepad path made its device through /dev/uinput, which is NOT
#       namespaced — a pad created inside a container registers with the HOST's
#       input stack and every scripted press leaks to the user's desktop. This
#       driver reads a text file instead. Drive it with tools/re-capture/pad.py.
#       Trap worth remembering: 360 menus poll XamInputGetKeystrokeEx, not
#       GetState, so a stubbed GetKeystroke looks like a completely dead pad.
#
#   one instance at a time
#       Two emulators (or ours + canary) at once perturbs both and the box.
#       Enforced with a lockfile rather than left to discipline.
#
# Usage:  run-canary [extra xenia flags...]
#   ISO from $SYLPH_ISO, else the first *.iso under $PROJECT_DIR.
#   Binary from $XENIA_BIN, else the container build, else the repo build.
set -u

LOCK=/tmp/xenia-canary.lock
exec 9>"$LOCK"
if ! flock -n 9; then
  echo "run-canary: an emulator is already running (lock $LOCK)." >&2
  echo "  Only one at a time — kill it first:  pkill -x xenia_canary" >&2
  exit 1
fi

PROJECT_DIR="${PROJECT_DIR:-/work}"

# ── Binary ───────────────────────────────────────────────────────────────────
pick_bin() {
  [ -n "${XENIA_BIN:-}" ] && { echo "$XENIA_BIN"; return; }
  for c in \
      "${XENIA_BUILD_DIR:-/sylph-home/re/canary-build}/bin/Linux/Release/xenia_canary" \
      "${XENIA_BUILD_DIR:-/sylph-home/re/canary-build}/bin/Linux/Debug/xenia_canary" \
      "$PROJECT_DIR/xenia-canary/build/bin/Linux/Release/xenia_canary" \
      "$PROJECT_DIR/xenia-canary/build/bin/Linux/Debug/xenia_canary"; do
    [ -x "$c" ] && { echo "$c"; return; }
  done
}
BIN="$(pick_bin)"
if [ -z "${BIN:-}" ]; then
  echo "run-canary: no xenia_canary binary found. Build one with:  build-canary" >&2
  exit 1
fi

# ── ISO ──────────────────────────────────────────────────────────────────────
ISO="${SYLPH_ISO:-}"
if [ -z "$ISO" ]; then
  # Prefer a REAL file over a symlink and take the largest: the tree carries
  # `xenia-rs/sylpheed.iso` as a symlink to the retail image, and a symlink has
  # already cost a session once (Wine could not resolve it -> "path invalid").
  ISO="$(find "$PROJECT_DIR" -maxdepth 2 -type f -iname '*.iso' -printf '%s\t%p\n' 2>/dev/null \
         | sort -rn | head -1 | cut -f2-)"
fi
if [ -z "$ISO" ] || [ ! -f "$ISO" ]; then
  echo "run-canary: no ISO. Set SYLPH_ISO=/path/to/game.iso" >&2
  exit 1
fi
ISO="$(readlink -f "$ISO")"

export SDL_AUDIODRIVER="${SDL_AUDIODRIVER:-dummy}"
export DISPLAY="${DISPLAY:-:98}"
PAD="${XENIA_PAD_FILE:-/tmp/xenia_pad.txt}"
: > "$PAD"

# Guest memory is backed by /dev/shm; a stale file from a killed run confuses
# the memory readers (gmem.py finds two candidates and picks the dead one).
rm -f /dev/shm/xenia_memory_* /dev/shm/xenia_code_cache_* 2>/dev/null || true

echo "run-canary: $BIN" >&2
echo "       iso: $ISO" >&2
echo "       pad: $PAD   display: $DISPLAY   shm: $(df -h /dev/shm | awk 'NR==2{print $2}')" >&2

exec "$BIN" "$ISO" \
  --apu=sdl \
  --hid=file --pad_file="$PAD" \
  --mute=true \
  "$@"
