#!/usr/bin/env bash # Second Coat on a Steam Deck, or any Linux PC with Steam: the launcher in # ~/SecondCoat, and the launcher and each game in the Steam library with # their artwork, to start from Gaming Mode. # # The installer file on secondcoat.dev/steam-deck/ runs this in a terminal # from Desktop Mode: # # curl -fsSL https://secondcoat.dev/steam-deck/install.sh | bash # # It needs no password: everything goes in your home folder. Steam closes # while the launcher adds itself to the library (`--steam-setup`), and # starts again after. Running it again updates the launcher and puts the # tiles back. set -euo pipefail manifest="https://files.secondcoat.dev/launcher/latest.json" dir="$HOME/SecondCoat" app="$dir/Second-Coat.AppImage" say() { printf '\n\033[1;33m%s\033[0m\n' "$*"; } fail() { printf '\n\033[1;31m%s\033[0m\n' "$*" >&2 exit 1 } [ "$(uname -s)-$(uname -m)" = Linux-x86_64 ] || fail "Second Coat runs on x86-64 Linux here (a Steam Deck is one)." for tool in curl sha256sum python3; do command -v "$tool" >/dev/null || fail "This needs $tool, which is missing." done say "Looking up the latest launcher…" json="$(curl -fsSL "$manifest")" || fail "files.secondcoat.dev cannot be reached. Check the connection and try again." # The AppImage of the launcher's release manifest: version, file, SHA-256. read -r version file sha256 < <(python3 -c ' import json, sys m = json.loads(sys.argv[1]) b = m.get("builds", {}).get("linux", {}).get("appimage") if b: print(m["version"], b["file"], b["sha256"]) ' "$json") || fail "There is no launcher for Linux to download yet." mkdir -p "$dir" part="$dir/.Second-Coat.AppImage.part" say "Downloading the Second Coat launcher $version…" curl -fL --progress-bar -o "$part" "https://files.secondcoat.dev/launcher/$version/$file" \ || fail "The download stopped. Run the installer again to try once more." if ! echo "$sha256 $part" | sha256sum -c --status; then rm -f "$part" fail "The download is damaged (its SHA-256 does not match). Run the installer again." fi chmod +x "$part" mv -f "$part" "$app" echo "$app" # An AppImage mounts itself with FUSE 2; without it, it unpacks itself # to a temporary folder instead. if ! { [ -e /dev/fuse ] && /sbin/ldconfig -p 2>/dev/null | grep -q 'libfuse\.so\.2'; }; then export APPIMAGE_EXTRACT_AND_RUN=1 fi say "Adding Second Coat to Steam. Steam closes, and opens again after…" "$app" --steam-setup || fail "Second Coat could not be added to Steam (see above)." if grep -qs '^ID=steamos' /etc/os-release; then say "Done. Double-click Return to Gaming Mode on the desktop: Second Coat is in your library, under Non-Steam." else say "Done: Second Coat is in your Steam library." fi