From 2c51ab5faa0b5c8c189389a25dec5086f6c631d4 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 1 Sep 2026 14:37:01 +0000 Subject: [PATCH 1/2] wolf: symlink downloaded Dolphin AppImage to the name ES-DE actually looks for MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ES-DE's es_find_rules.xml DOLPHIN entry only auto-detects a file literally named Dolphin_Emulator*.AppImage under ~/Applications. pkgforge-dev's own community-build release asset isn't named that, so the AppImage downloaded by install_wolf() sat in emulators/ unnoticed and ES-DE reported "Couldn't launch game, emulator not found" (%EMULATOR_DOLPHIN% unresolved) even though the file was right there — confirmed live on a real box. Drop a same-directory Dolphin_Emulator.AppImage symlink pointing at whatever the real download is named, without renaming/losing the vendor filename. Runs unconditionally (not just after a fresh download) so it also repairs installs that grabbed the file before this fix existed. --- services/wolf.sh | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/services/wolf.sh b/services/wolf.sh index 74ca723..33018bd 100644 --- a/services/wolf.sh +++ b/services/wolf.sh @@ -277,7 +277,8 @@ EOF echo " - Start Wolf and inject Steam + EmulationStation app profiles" echo " - Create bios/ + retroarch/{cores,shaders,overlays}/ on the game drive and pre-download RetroArch cores (~1.5 GB)" echo " - Offer to auto-download standalone emulator AppImages into emulators/:" - echo " Azahar (3DS), PCSX2 (PS2), Dolphin (GameCube/Wii — unofficial community build)" + echo " Azahar (3DS), PCSX2 (PS2), Dolphin (GameCube/Wii — unofficial community build," + echo " symlinked to Dolphin_Emulator.AppImage so ES-DE's own find-rules can see it)" echo " - Offer to set up AntiMicroX (universal controller-combo hotkey, experimental —" echo " downloads it and wires a Sway launch hook; the button mapping itself is" echo " built later through AntiMicroX's own GUI)" @@ -847,6 +848,24 @@ UDEV _wolf_download_emulator_appimage \ "Dolphin (GameCube/Wii, community AppImage build)" "pkgforge-dev/Dolphin-emu-AppImage" "*[Dd]olphin*.AppImage" "$_EMU_DIR" + # ES-DE's own find-rules (es_find_rules.xml, DOLPHIN entry's ) + # only match a file literally named Dolphin_Emulator*.AppImage under + # ~/Applications — confirmed live: ES-DE reported "Couldn't launch game, + # emulator not found" / unresolved %EMULATOR_DOLPHIN% even with the + # AppImage sitting right there in emulators/, because pkgforge-dev's own + # release asset isn't named that. Point ES-DE at it with a same-directory + # symlink under the exact name it looks for, without renaming/losing the + # real vendor filename. Re-run unconditionally (not just right after a + # fresh download) so this also repairs an existing install that grabbed + # the file before this fix existed. + local _DOLPHIN_REAL + _DOLPHIN_REAL=$(ls "$_EMU_DIR"/*[Dd]olphin*.AppImage 2>/dev/null | grep -vi '/Dolphin_Emulator.*\.AppImage$' | head -1) + if [[ -n "$_DOLPHIN_REAL" ]]; then + ln -sf "$(basename "$_DOLPHIN_REAL")" "$_EMU_DIR/Dolphin_Emulator.AppImage" + chown -h "$ACTUAL_USER:$ACTUAL_USER" "$_EMU_DIR/Dolphin_Emulator.AppImage" 2>/dev/null || true + log_success "Linked $_EMU_DIR/Dolphin_Emulator.AppImage -> $(basename "$_DOLPHIN_REAL") (the filename ES-DE's own find-rules require)" + fi + # ── Optional: AntiMicroX for a universal controller-combo hotkey ───────── # RetroArch's own hotkeys (Settings -> Input -> Input Hotkey Binds) are # global across every libretro core, but Dolphin/PCSX2/Azahar each run as @@ -3233,7 +3252,14 @@ them off to standalone AppImages instead: AppImage (dolphin-emu.org's own Linux distribution is Flatpak-only); this uses a well-regarded but **third-party** community AppImage build (pkgforge-dev) instead. Skip it and install Dolphin's own Flatpak by hand - if you'd rather not run an unofficial build. + if you'd rather not run an unofficial build. ES-DE only auto-detects a + file literally named \`Dolphin_Emulator*.AppImage\` — since pkgforge-dev's + own release asset isn't named that, this installer also drops a + \`Dolphin_Emulator.AppImage\` symlink next to the real download pointing at + it, so ES-DE actually finds it. If you ever grab a different Dolphin + AppImage by hand instead, re-point (or recreate) that symlink at it, or + ES-DE will report "emulator not found" even with the file sitting right + there. All three live in \`emulators/\` → mounted at \`/mnt/games/emulators\` and \`~/Applications\` (where ES-DE's app finder looks). Point ES-DE's From 4199f42f7094a86f0b24c3a5c073e16127ae82c2 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 1 Sep 2026 15:03:57 +0000 Subject: [PATCH 2/2] wolf: fix wrong-architecture AppImage downloads (aarch64 picked on x86_64 hosts) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _wolf_download_emulator_appimage picked whatever release asset happened to be first in the GitHub API's asset list among files ending in .AppImage, with no architecture filtering. Confirmed live: pkgforge-dev's Dolphin AppImage release lists an aarch64 build ahead of the x86_64 one, so the downloaded file silently failed at launch with a bare "exec format error" and no indication why — the earlier "emulator not found" symlink fix (previous commit) got ES-DE to find the file at all, which is what surfaced this as the next failure. Now prefers whichever release asset's filename actually tags the host's own architecture, falls back to an untagged asset (Azahar/PCSX2's releases carry no arch tag and are unaffected either way), and only then falls back to "take the first one". Also verifies the downloaded file's real ELF architecture against the host post-download and warns loudly if it still doesn't match, since filename tagging isn't something every release can be trusted to get right. --- services/wolf.sh | 49 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/services/wolf.sh b/services/wolf.sh index 33018bd..c47f559 100644 --- a/services/wolf.sh +++ b/services/wolf.sh @@ -227,11 +227,33 @@ _wolf_download_emulator_appimage() { [[ "$_get" =~ ^[Yy]$ ]] || return 0 log_info "Fetching latest $_display_name release from GitHub..." + # A release can publish AppImages for more than one CPU architecture + # (x86_64 and aarch64 both showing up as plain "*.AppImage" assets) with + # no guarantee the one this host needs sorts first in the GitHub API's + # asset list. Prefer whichever asset's filename actually tags the host's + # own architecture; fall back to an asset with no arch tag at all before + # ever falling back to "just take the first one". local _url _url=$(curl -fsSL "https://api.github.com/repos/${_owner_repo}/releases/latest" \ - | python3 -c "import sys,json; r=json.load(sys.stdin); \ - print(next((a['browser_download_url'] for a in r['assets'] \ - if a['name'].endswith('.AppImage')), ''))" 2>/dev/null) + | HOST_ARCH="$(uname -m)" python3 -c ' +import sys, json, os +host = os.environ.get("HOST_ARCH", "") +arch_tags = { + "x86_64": ["x86_64", "amd64", "x64"], + "aarch64": ["aarch64", "arm64"], + "arm64": ["aarch64", "arm64"], +}.get(host, [host] if host else []) +all_arch_tags = ["x86_64", "amd64", "x64", "aarch64", "arm64", "armv7", "armhf", "i386", "i686"] +def has(name, tags): + n = name.lower() + return any(t in n for t in tags) +r = json.load(sys.stdin) +assets = [a for a in r["assets"] if a["name"].endswith(".AppImage")] +matching = [a for a in assets if arch_tags and has(a["name"], arch_tags)] +untagged = [a for a in assets if not has(a["name"], all_arch_tags)] +pick = matching or untagged or assets +print(pick[0]["browser_download_url"] if pick else "") +' 2>/dev/null) if [[ -z "$_url" ]]; then log_warning "Could not resolve download URL — get it manually from https://github.com/${_owner_repo}/releases" return 1 @@ -241,7 +263,26 @@ _wolf_download_emulator_appimage() { && chmod +x "$_file" \ && chown "$ACTUAL_USER:$ACTUAL_USER" "$_file" \ && log_success "$_display_name downloaded: $_file" \ - || log_warning "Download failed — get it manually from https://github.com/${_owner_repo}/releases" + || { log_warning "Download failed — get it manually from https://github.com/${_owner_repo}/releases"; return 1; } + + # Belt-and-suspenders: the filename-based preference above can't help + # when a release tags no architecture in the name at all, so verify the + # actual ELF header matches this host post-download. Confirmed live: a + # wrong-arch AppImage downloads with no error and no visible symptom + # until launch time, where it fails as a bare "exec format error" with + # nothing pointing back at the cause. + local _got_arch + _got_arch=$(file -b "$_file" 2>/dev/null) + case "$(uname -m)" in + x86_64) + echo "$_got_arch" | grep -qi 'x86-64\|x86_64' || \ + log_warning "$_file doesn't look like an x86_64 build ($_got_arch) — it will fail with 'exec format error'. Grab the x86_64 asset by hand from https://github.com/${_owner_repo}/releases" + ;; + aarch64|arm64) + echo "$_got_arch" | grep -qi 'aarch64\|arm64' || \ + log_warning "$_file doesn't look like an aarch64 build ($_got_arch) — it may fail to run. Grab the aarch64 asset by hand from https://github.com/${_owner_repo}/releases" + ;; + esac } install_wolf() {