#!/bin/sh
# Installed-package launcher for the Namco System 2x decompilations (System 22 / Super 22; Cyber Sled is System 21, Time Crisis 2 and Crisis Zone System 23, Angler King Super System 23).
#   namco-2x-launch prop [0-3] [args]     Prop Cycle (a number = straight to that level)
#   namco-2x-launch rave [1-9] [args]     Rave Racer (a number = window scale)
#   namco-2x-launch tokyo [1-9] [args]    Tokyo Wars (a number = window scale)
#   namco-2x-launch dirt [1-9] [args]     Dirt Dash (a number = window scale)
#   namco-2x-launch am [1-9] [args]       Armadillo Racing (a number = window scale; the mouse is the trackball)
#   namco-2x-launch tc [1-9] [args]       Time Crisis (a number = window scale; the mouse is the gun)
#   namco-2x-launch ace [1-9] [args]      Ace Driver (a number = window scale)
#   namco-2x-launch cc [1-9] [args]       Cyber Commando (a number = window scale)
#   namco-2x-launch r2 [1-9] [args]       Ridge Racer 2 (a number = window scale)
#   namco-2x-launch cs [1-9] [args]       Cyber Sled (a number = window scale)
#   namco-2x-launch tc2 [1-9] [args]      Time Crisis 2 (a number = window scale; the mouse is the gun)
#   namco-2x-launch csz [1-9] [args]      Crisis Zone (a number = window scale; the mouse is the gun)
#   namco-2x-launch ak [1-9] [args]       Angler King (a number = window scale; the mouse aims the rod)
# Options for any game (GitHub #85), with or without the window-scale number:
#   --fullscreen                          start fullscreen
#   --set KEY=VALUE                       any setting of the game's settings file, for this run only, e.g.
#                                         --set widescreen=1 --set volume=50 --set frame_rate=60 (repeat as needed)
# Time Crisis 2 / Crisis Zone also take (two copies on one PC, a LAN game set up from a launcher):
#   --host | --join | --server ADDR       host a LAN game / join one found on the LAN / connect to a server, at start-up
#   --name NAME | --instance N | --pos X,Y[,SCALE]   online name / a second copy's own settings / the window's place and size
# Each game plays from its own folder under ~/.local/share/namco-2x-systems/ (or the older
# ~/.local/share/namco22/ when that exists, so 0.6 settings and scores carry over), which holds
# its roms/, the unpacked chips, the settings, scores and recordings. The ROM zips
# (MAME sets) go in that roms/ folder; ~/Downloads is checked on first start.
# AppImage: zips next to the .AppImage (or in a roms/ folder beside it) are found too,
# and PORTABLE MODE -- a folder named namco-2x-systems-data (or the older namco22-data) next to the .AppImage, or the AppImage standard's
# <name>.AppImage.home -- keeps everything there instead of ~/.local/share (one disk for a Steam Deck and a PC).
LIB=${NAMCO2X_LIB:-${NAMCO22_LIB:-/usr/lib/namco-2x-systems}}      # an AppImage points this at its own copy
game="$1"; [ $# -gt 0 ] && shift
extra=""                                    # optional companion zips, copied when present (never "missing")
case "$game" in
    prop|propcycle) title="Prop Cycle"; dir=propcycle; zips="propcycl.zip" ;;
    rave|raverace)  title="Rave Racer"; dir=raverace;  zips="raverace.zip namcoc74.zip" ;;
    tokyo|tokyowar|tokyowars|tw) title="Tokyo Wars"; dir=tokyowar; zips="tokyowar.zip" ;;
    dirt|dirtdash|dd) title="Dirt Dash"; dir=dirtdash; zips="dirtdash.zip"; extra="dirtdasha.zip" ;;   # a SPLIT MAME set keeps the
                                                    # DT2 Ver.A program chips (dt2vera.1/.2) in dirtdasha.zip (GitHub #8)
    am|adillor|armadillo|armadilloracing) title="Armadillo Racing"; dir=adillor; zips="adillor.zip" ;;
    tc|timecris|timecrisis|crisis) title="Time Crisis"; dir=timecris; zips="timecris.zip" ;;
    ace|acedriver|ad) title="Ace Driver"; dir=acedriver; zips="acedrive.zip namcoc74.zip" ;;
    cc|cybrcomm|cybercommando|commando) title="Cyber Commando"; dir=cybrcomm; zips="cybrcomm.zip namcoc74.zip" ;;
    r2|ridgera2|ridgeracer2|rr2) title="Ridge Racer 2"; dir=ridgera2; zips="ridgera2.zip namcoc74.zip" ;;
    cs|cybsled|cybersled|sled) title="Cyber Sled"; dir=cybsled; zips="cybsled.zip namcoc67.zip namcoc68.zip" ;;
    tc2|timecrs2|timecrisis2|crisis2) title="Time Crisis 2"; dir=tc2; zips="timecrs2.zip"; extra="namco_tssio.zip" ;;
    csz|crszone|crisiszone|zone) title="Crisis Zone"; dir=crszone; zips="crszone.zip"; extra="namco_csz1.zip" ;;
    ak|aking|anglerking|angler) title="Angler King"; dir=aking; zips="aking.zip" ;;
    *) sed -n '2,26p' "$0" | sed 's/^# \?//'; exit 1 ;;
esac
# $APPIMAGE is the .AppImage's own path (set by the AppImage runtime, also with --appimage-extract-and-run)
appdir=""; [ -n "${APPIMAGE:-}" ] && appdir=$(dirname "$APPIMAGE")
# the folders are named namco-2x-systems since 0.7; one named namco22 (0.6 and before) is used when it is there, so nothing is lost
pdir=""; [ -n "$appdir" ] && for p in "$appdir/namco-2x-systems-data" "$appdir/namco22-data"; do [ -d "$p" ] && { pdir=$p; break; }; done
if [ -n "$pdir" ]; then
    data="$pdir/$dir"                                  # portable: the folder travels with the AppImage
    echo "[launch] portable mode: $data" >&2
elif [ -n "${APPIMAGE:-}" ] && { [ -d "$APPIMAGE.home" ] || [ -d "${APPIMAGE%.AppImage}.home" ]; }; then
    # the AppImage standard's portable folder, GitHub #23: <name>.AppImage.home (or <name>.home, as users name it). The
    # runtime moves $HOME into it, but the user who tried it still found the data under ~/.local/share (an
    # $XDG_DATA_HOME in the environment, or a runtime without the feature), so the launcher looks for it itself.
    h="$APPIMAGE.home"; [ -d "$h" ] || h="${APPIMAGE%.AppImage}.home"
    data="$h/namco-2x-systems/$dir"; [ ! -d "$data" ] && [ -d "$h/namco22/$dir" ] && data="$h/namco22/$dir"
    echo "[launch] portable mode: $data" >&2
else
    share="${XDG_DATA_HOME:-$HOME/.local/share}"
    data="$share/namco-2x-systems/$dir"
    if [ ! -d "$data" ]; then
        if [ -d "$share/namco22/$dir" ]; then data="$share/namco22/$dir"
        elif [ "$dir" = tc2 ] && [ -d "$share/tc2" ]; then data="$share/tc2"     # Time Crisis 2's own AppImage (0.1.0-rc1) kept it here
        fi
    fi
fi
mkdir -p "$data/roms" || exit 1
cd "$data" || exit 1

hidden=" ~/.local is hidden: press Ctrl+H in a file manager."
case "$data" in "${XDG_DATA_HOME:-$HOME/.local/share}"/*) ;; *) hidden="" ;; esac
missing=""
for z in $zips; do
    [ -f "roms/$z" ] && continue
    for s in ${appdir:+"$appdir/$z" "$appdir/roms/$z"} "$HOME/Downloads/$z" "$HOME/$z"; do
        if [ -f "$s" ]; then cp "$s" roms/ && break; fi
    done
    [ -f "roms/$z" ] || missing="$missing $z"
done
for z in $extra; do
    [ -f "roms/$z" ] && continue
    for s in ${appdir:+"$appdir/$z" "$appdir/roms/$z"} "$HOME/Downloads/$z" "$HOME/$z"; do
        if [ -f "$s" ]; then cp "$s" roms/ && break; fi
    done
done
# Once unpacked the zips are no longer needed, so only complain before that.
if [ -n "$missing" ] && [ -z "$(ls -A extracted 2>/dev/null)" ]; then
    msg="$title needs its ROM files (no game data is included).

Missing:$missing

Copy the MAME ROM zip(s) into this folder, then start the game again:
    $data/roms${appdir:+
(or next to the AppImage: $appdir)}

(This folder is now open.$hidden)"
    echo "$msg" >&2
    if [ -n "$DISPLAY$WAYLAND_DISPLAY" ]; then
        if command -v zenity >/dev/null 2>&1; then zenity --error --title="$title" --text="$msg" 2>/dev/null
        elif command -v kdialog >/dev/null 2>&1; then kdialog --title "$title" --error "$msg" 2>/dev/null
        elif command -v notify-send >/dev/null 2>&1; then notify-send "$title" "$msg"; fi
        command -v xdg-open >/dev/null 2>&1 && xdg-open "$data/roms" >/dev/null 2>&1 &
    fi
    exit 1
fi

# the PLAY options (GitHub #85): when every argument is one of these the game starts in its window with them; anything else
# (a headless test run, a ROM folder) is passed to the program as it is
q() { printf "'%s'" "$(printf %s "$1" | sed "s/'/'\\\\''/g")"; }
split_play() {
    PLAY=1; SCALE=""; ARGS=""
    while [ $# -gt 0 ]; do
        case "$1" in
            [1-9]) SCALE=$1 ;;
            --window) ;;
            --fullscreen|--host|--join|--set=*) ARGS="$ARGS $(q "$1")" ;;
            --set|--server|--name|--instance|--pos) [ $# -ge 2 ] || { PLAY=0; return; }; ARGS="$ARGS $(q "$1") $(q "$2")"; shift ;;
            *) PLAY=0; return ;;
        esac
        shift
    done
}
split_play "$@"

case "$dir" in
    propcycle)
        case "${1:-}" in
            0|1|2|3) c="$1"; shift; exec "$LIB/propcycl" extracted --autostart "$c" "$@" ;;
            *)       PROPCYCL_NO_AUTOSTART=1 exec "$LIB/propcycl" extracted "$@" ;;
        esac ;;
    raverace)
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/rr\" extracted --window $SCALE $ARGS"
        exec "$LIB/rr" extracted "$@" ;;
    tokyowar)
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/tw\" extracted --window $SCALE $ARGS"
        exec "$LIB/tw" extracted "$@" ;;
    dirtdash)
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/dd\" extracted --window $SCALE $ARGS"
        exec "$LIB/dd" extracted "$@" ;;
    adillor)
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/am\" extracted --window $SCALE $ARGS"
        exec "$LIB/am" extracted "$@" ;;
    timecris)
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/tc\" extracted --window $SCALE $ARGS"
        exec "$LIB/tc" extracted "$@" ;;
    acedriver)
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/ad\" extracted --window $SCALE $ARGS"
        exec "$LIB/ad" extracted "$@" ;;
    cybrcomm)
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/cc\" extracted --window $SCALE $ARGS"
        exec "$LIB/cc" extracted "$@" ;;
    ridgera2)
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/r2\" extracted --window $SCALE $ARGS"
        exec "$LIB/r2" extracted "$@" ;;
    cybsled)
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/cs21\" extracted --window $SCALE $ARGS"
        exec "$LIB/cs21" extracted "$@" ;;
    tc2)                                            # finds extracted/ and roms/ itself; it unpacks on first start
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/tc2\" --window $SCALE $ARGS 2>\"\$data/tc2.log\""
        exec "$LIB/tc2" "$@" ;;
    crszone)                                        # Time Crisis 2's host: finds extracted/ and roms/ itself, unpacks on first start
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/crszone\" --window $SCALE $ARGS 2>\"\$data/crszone.log\""
        exec "$LIB/crszone" "$@" ;;
    aking)                                          # the same host (aking_subtitles.txt beside the binary)
        [ "$PLAY" = 1 ] && eval "exec \"\$LIB/aking\" --window $SCALE $ARGS 2>\"\$data/aking.log\""
        exec "$LIB/aking" "$@" ;;
esac
