diff --git a/port/android/STEAM_FRAME.md b/port/android/STEAM_FRAME.md index 1b464ae5..340994b2 100644 --- a/port/android/STEAM_FRAME.md +++ b/port/android/STEAM_FRAME.md @@ -29,9 +29,14 @@ the release job of `.github/workflows/build.yml`) and runs its shortcut replaced; - the maps folder out of the disc image (`steam_frame_xiso.py`, the app's `XisoExtractor.java` in Python), unless `maps/ui.map` is there; -- the Steam shortcut (`shortcuts.vdf` as below, with `OpenVR` set, and the - library pictures), unless it is there: Steam is closed for that, as it - writes its shortcuts back when it quits. +- the Steam shortcut, unless it is there: added by Steam itself + (`steam://addnonsteamgame`, as SteamOS's "Add to Steam" does) from + `Ringfall Mjolnir VR.desktop` beside the game, then the library pictures + under the id Steam gave it. Steam is not closed: on the Frame, Desktop + Mode runs inside Gaming Mode's session, and closing Steam ends it (and the + installer with it). An old "Halo VR" shortcut is left for the player to + remove (Steam would write it back); +- what it did in `install.log` beside the game. `HALO_VR_UNATTENDED=1` (and `HALO_VR_IMAGE=`) runs it without dialogs, for testing over adb; it leaves Steam and its shortcuts alone. diff --git a/port/android/steam_frame_install.sh b/port/android/steam_frame_install.sh index 6c9a9d22..6cc5d4e6 100644 --- a/port/android/steam_frame_install.sh +++ b/port/android/steam_frame_install.sh @@ -13,9 +13,12 @@ # original Xbox game (.iso or .xiso) found in Downloads, Documents, the # Desktop or on a memory card, or chosen, unless it is there already; # - the game in the Steam library, with its pictures, unless it is there -# already (the shortcut of the builds before the name replaced): Steam is -# closed for that (it keeps its shortcuts in memory and writes them back -# when it quits), and started again in Gaming Mode. +# already: added by Steam itself (steam://addnonsteamgame, as SteamOS's +# "Add to Steam" does), from a desktop file beside the game. Steam is not +# closed: it keeps its shortcuts in memory and writes them back, and on the +# Steam Frame Desktop Mode runs inside Gaming Mode's session, which ends +# with Steam. The shortcut of the builds before the name ("Halo VR") is +# left for the player to remove (Steam would write it back). # RINGFALL_UNATTENDED=1 answers every question with its default and prints # instead of showing dialogs (RINGFALL_IMAGE: the disc image to use), for # testing over adb; it never closes Steam. @@ -29,10 +32,11 @@ NAME="Ringfall: Mjolnir VR" APK_NAME="RingfallMjolnirVR.apk" LAUNCHER="ringfall-mjolnir-vr.sh" EXE="\"$GAME_DIR/$LAUNCHER\"" +# (the desktop file Steam adds the game from) +NAME_FILE="Ringfall Mjolnir VR" # the builds before the name: their folder and Steam shortcut OLD_DIR="$HOME/Documents/HaloCE" OLD_NAME="Halo VR" -OLD_EXE="\"$OLD_DIR/halo-vr.sh\"" # what the installer did, for looking into problems: written to /tmp while # it runs, then kept beside the game as install.log @@ -115,41 +119,36 @@ extract_maps() rm -f "$log" } -# the shortcut's id as Steam makes it for a non-Steam game: its pictures in -# config/grid are named after it +# the Steam users' shortcut files (userdata/0 is no user) +shortcut_files() +{ + local config + for config in "$STEAM_DIR"/userdata/*/config; do + case "$config" in */userdata/0/*) continue ;; esac + [ -f "$config/shortcuts.vdf" ] && echo "$config/shortcuts.vdf" + done +} + +# whether a Steam user's library holds the launcher given +have_shortcut_to() +{ + local file + while read -r file; do + grep -qaF "$1" "$file" && return 0 + done < <(shortcut_files) + return 1 +} + +have_shortcut() { have_shortcut_to "$GAME_DIR/$LAUNCHER"; } + +# the id Steam gave the shortcut whose Exe is $2, in shortcuts.vdf $1 (Steam +# picks it; its library pictures in config/grid are named after it) shortcut_id() { - python3 -c 'import sys, zlib; print(zlib.crc32((sys.argv[1] + sys.argv[2]).encode()) | 0x80000000)' "$1" "$2" -} + python3 - "$1" "$2" <<'PYTHON' +import struct, sys -# whether every Steam user's shortcuts.vdf already holds the game -have_shortcut() -{ - local found=1 config - for config in "$STEAM_DIR"/userdata/*/config; do - [ -d "$config" ] || continue - case "$config" in */userdata/0/*) continue ;; esac - grep -qaF "$GAME_DIR/$LAUNCHER" "$config/shortcuts.vdf" 2>/dev/null || return 1 - found=0 - done - return $found -} - -# the game added to every Steam user's shortcuts.vdf (Steam closed), as a VR -# title, with its pictures; the builds' before the name gone -add_shortcut() -{ - local id old_id config - id="$(shortcut_id "$EXE" "$NAME")" - old_id="$(shortcut_id "$OLD_EXE" "$OLD_NAME")" - for config in "$STEAM_DIR"/userdata/*/config; do - [ -d "$config" ] || continue - case "$config" in */userdata/0/*) continue ;; esac - python3 - "$config/shortcuts.vdf" "$id" "$NAME" "$EXE" "\"$GAME_DIR/\"" "$OLD_EXE" <<'PYTHON' || return 1 -import os, struct, sys - -path, appid, name, exe, start, old_exe = (sys.argv[1], int(sys.argv[2]), sys.argv[3], sys.argv[4], sys.argv[5], - sys.argv[6]) +path, exe = sys.argv[1], sys.argv[2].encode() # Steam's binary VDF: 0x00 a map, 0x01 a string, 0x02 an int32, 0x08 a map's end def read_map(data, at): @@ -158,7 +157,7 @@ def read_map(data, at): kind = data[at]; at += 1 if kind == 0x08: return items, at - end = data.index(b"\0", at); key = data[at:end]; at = end + 1 + end = data.index(b"\0", at); key = data[at:end].lower(); at = end + 1 if kind == 0x00: value, at = read_map(data, at) elif kind == 0x01: @@ -167,62 +166,45 @@ def read_map(data, at): value = struct.unpack_from(" "$desktop" && chmod 755 "$desktop" || return 1 + url="steam://addnonsteamgame/$(python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$desktop")" + log "asking Steam: $url" + # (Steam's own "Add to Steam" touches this first: steamos-add-to-steam) + touch /tmp/addnonsteamgamefile + steam "$url" >/dev/null 2>&1 & + for _ in $(seq 30); do have_shortcut && break; sleep 1; done + have_shortcut || return 1 + while read -r file; do + id="$(shortcut_id "$file" "$EXE")" || continue + log "shortcut $id in $file" + mkdir -p "$(dirname "$file")/grid" + cp "$BUNDLE/grid/library.png" "$(dirname "$file")/grid/${id}.png" + cp "$BUNDLE/grid/libraryp.png" "$(dirname "$file")/grid/${id}p.png" + cp "$BUNDLE/grid/library_hero.png" "$(dirname "$file")/grid/${id}_hero.png" + cp "$BUNDLE/grid/library_logo.png" "$(dirname "$file")/grid/${id}_logo.png" + done < <(shortcut_files) + return 0 } # --- the game @@ -283,36 +265,24 @@ fi # --- Steam -steam_closed=0 if have_shortcut; then log "the Steam shortcut is there" +elif unattended; then + echo "info: the Steam shortcut is missing (not added unattended)" +elif ! steam_running; then + info "Steam is not running, so $NAME could not be added to your library.\n\nStart Steam and run the installer again." else - if unattended; then - echo "info: the Steam shortcut is missing (not added unattended)" - else - info "$NAME is now added to your Steam library. Steam closes for a moment for that." - if steam_running; then - log "closing Steam" - steam -shutdown >/dev/null 2>&1 & - for _ in $(seq 90); do steam_running || break; sleep 1; done - steam_running && fail "Steam did not close. Close it (Steam menu > Exit) and run the installer again." - # (its last writes, after its processes end) - sleep 2 - fi - log "Steam closed" - steam_closed=1 - add_shortcut || fail "Could not add $NAME to the Steam library." - have_shortcut || fail "Could not add $NAME to the Steam library (its shortcut is missing after writing it)." - fi + add_shortcut || fail "Steam did not add $NAME to your library. Run the installer again; if it happens again, add\n$GAME_DIR/$NAME_FILE.desktop\nwith Steam's \"Add a Non-Steam Game\"." fi if unattended; then echo "info: installed in $GAME_DIR" exit 0 fi -if ask "$NAME is installed.${image_note:-}\n\nSwitch to Gaming Mode now? Start $NAME from your library there." yes; then +if have_shortcut_to "$OLD_DIR/halo-vr.sh"; then + info "The library still shows the old \"$OLD_NAME\" from before the game's new name. It no longer starts: remove it in Steam (its gear or Manage > Remove non-Steam game)." +fi +if ask "$NAME is installed.${image_note:-}\n\nSwitch to Gaming Mode now? Start $NAME from your library there (its pictures may show once Steam starts again)." yes; then steamos-session-select gamescope >/dev/null 2>&1 || info "Switch to Gaming Mode yourself (the \"Return to Gaming Mode\" icon or the power menu)." -elif [ "$steam_closed" = 1 ]; then - setsid steam >/dev/null 2>&1 < /dev/null & fi