#!/usr/bin/env bash # Launch the AGI interpreter in the named platform's emulator with a # staged AGI v2 game directory. The game's data files are copied flat # alongside the binary so AGI's CWD-relative default ("./LOGDIR" etc.) # works on platforms whose autostart can't pass argv. # # scripts/run-agi.sh [game] [room] # platform : dos | amiga | atarist | iigs # game : subdirectory under examples/agi/gamedata/ (default kq3) # room : starting room number 1..255. Skips logic.0's hardcoded # title-room target and jumps straight to the named room. # Only forwarded to DOS today -- the Atari ST / Amiga # autostart paths can't pass argv to the binary; their # AGI starts at the title screen until we wire a stage- # time config-file fallback or implement enough title # opcodes for the title to advance on its own. # # Required files in the game directory (others are ignored): # LOGDIR PICDIR VIEWDIR SNDDIR VOL.0 [VOL.1 ...] [OBJECT] [WORDS.TOK] # # IIgs is not yet wired (needs the disk packager extended to a larger # 2mg volume plus case-folded ProDOS file names); the script reports # what's missing rather than launching. set -euo pipefail if [[ $# -lt 1 || $# -gt 3 ]]; then echo "usage: $0 [game-name] [starting-room]" >&2 exit 2 fi platform=$1 game=${2:-kq3} room=${3:-0} if ! [[ $room =~ ^[0-9]+$ ]] || (( room > 255 )); then echo "starting-room must be 0..255 (got '$room')" >&2 exit 2 fi repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) gamedata=$repo/examples/agi/gamedata/$game support=$repo/toolchains/emulators/support if [[ ! -d $gamedata ]]; then echo "$gamedata: not an AGI v2 game directory" >&2 if [[ -d $repo/examples/agi/gamedata ]]; then echo "available games:" >&2 find "$repo/examples/agi/gamedata" -maxdepth 1 -mindepth 1 -type d -printf ' %f\n' >&2 fi exit 1 fi if [[ ! -f $gamedata/LOGDIR ]]; then echo "$gamedata: no LOGDIR -- not an AGI v2 game directory" >&2 exit 1 fi # stageGameData WORKDIR # Copies the subset of files AGI v2 reads (DIR files, VOL.x, OBJECT, # WORDS.TOK) into WORKDIR. Leaves Sierra's original AGI binary, OVL # graphics drivers, and platform-specific launchers behind so a flat # stage doesn't clash with our binary's name on case-insensitive # filesystems (e.g. Amiga FFS: "AGI" vs our "Agi"). stageGameData() { local destDir=$1 local f for f in LOGDIR PICDIR VIEWDIR SNDDIR OBJECT WORDS.TOK; do if [[ -f $gamedata/$f ]]; then cp "$gamedata/$f" "$destDir/$f" fi done for f in "$gamedata"/VOL.*; do [[ -f $f ]] && cp "$f" "$destDir/$(basename "$f")" done } runDos() { local bin=$repo/build/dos/bin/AGI.EXE local conf=$repo/scripts/dosbox-386sx16.conf local work if [[ ! -f $bin ]]; then echo "$bin not built. Run 'make -f make/dos.mk EXAMPLE=agi' first." >&2 exit 1 fi # Sweep any leftover staging dirs from previous runs that # didn't reach their trap (DOSBox window close, SIGKILL, etc.). # We're about to make a new one anyway; freshly leftover dirs # serve no purpose and just leak ~1 MB each. rm -rf /tmp/joeylib-agi-dos.* 2>/dev/null || true rm -f /tmp/joeylib-agi-dos-last.log 2>/dev/null || true work=$(mktemp -d -t joeylib-agi-dos.XXXXXX) # Cleanup trap: copy DJGPP's diagnostic log out (DOS uppercases # so the file lands as JOEYLOG.TXT, not joeylog.txt), then nuke # the staging dir. Hook EXIT plus the common interrupt signals # so the cleanup fires even when the user closes the DOSBox # window or Ctrl-Cs the terminal -- both bypass plain EXIT in # some bash configurations. cleanupDos() { local log for log in "$work/JOEYLOG.TXT" "$work/joeylog.txt"; do if [[ -f $log ]]; then cp "$log" /tmp/joeylib-agi-dos-last.log break fi done rm -rf "$work" } trap cleanupDos EXIT INT TERM HUP cp "$bin" "$work/AGI.EXE" stageGameData "$work" # AGI.EXE reads game data from its CWD (we mount $work as C: and # cd there first), so argv[1] is "." -- the starting-room override # lives in argv[2]. Skip the argv when room=0 so the binary # exercises its default code path. local agi_cmd="AGI.EXE" if (( room != 0 )); then agi_cmd="AGI.EXE . $room" fi cat <&2 exit 1 fi if [[ ! -f $tos ]]; then echo "TOS ROM missing: $tos" >&2 echo "Run ./toolchains/install.sh (EmuTOS should have been staged)." >&2 exit 1 fi rm -rf /tmp/joeylib-agi-atarist.* 2>/dev/null || true work=$(mktemp -d -t joeylib-agi-atarist.XXXXXX) trap 'rm -rf "$work"' EXIT INT TERM HUP cp "$bin" "$work/AGI.PRG" stageGameData "$work" cat <&2 exit 1 fi rm -rf /tmp/joeylib-agi-amiga.* 2>/dev/null || true work=$(mktemp -d -t joeylib-agi-amiga.XXXXXX) trap 'rm -rf "$work"' EXIT INT TERM HUP mkdir -p "$work/s" cp "$bin" "$work/Agi" stageGameData "$work" # ':' prefix anchors to volume root so AmigaDOS doesn't search C:. echo ":Agi" > "$work/s/startup-sequence" local fsargs=( --amiga_model=A500 --fast_memory=2048 --hard_drive_0="$work" --hard_drive_0_label=JOEYLIB --automatic_input_grab=0 --middle_click_ungrab=1 --mouse_integration=1 --floppy_drive_speed=800 ) if [[ -f $kickstart ]]; then fsargs+=(--kickstart_file="$kickstart") fi if [[ -f $workbench ]]; then # If a Workbench floppy is staged it boots from DF0: instead of # the HD, so the startup-sequence never fires. Skip Workbench # for AGI to keep the launch one-shot; user can still launch # manually with run-amiga.sh if they want the GUI. echo "(skipping workbench.adf so the JOEYLIB HD boots Agi directly)" fi cat <&2 IIgs AGI run is not wired up yet. The existing IIgs disk packager (toolchains/iigs/package-disk.sh) builds joey.2mg from build/iigs/bin/* only; it doesn't accept arbitrary game data, the disk size is fixed at 800K (KQ3's ~1.5 MB of resources won't fit), and ProDOS case-folding for game-data file names has not been audited. To wire this up the package-disk.sh tool needs a larger volume option and an "extra data" path argument, and run-iigs.sh needs an AGI mode that points GSplus at the resulting 2mg. Tracked separately. Workaround for now: build with 'make -f make/iigs.mk EXAMPLE=agi' to prove the IIgs link still works, but launch via run-iigs.sh and pick JOEYLIB:AGI in Finder -- it will fail to find LOGDIR (no game data on disk), which is the expected current state. EOF exit 1 } case "$platform" in dos) runDos ;; atarist) runAtariST ;; amiga) runAmiga ;; iigs) runIigs ;; *) echo "$platform: unknown platform (expected dos, amiga, atarist, or iigs)" >&2 exit 2 ;; esac