Merge pull request #409 from outis1one/claude/wolf-pair-port-conflict-7nz8qg
Claude/wolf pair port conflict 7nz8qg
This commit is contained in:
+197
-36
@@ -205,6 +205,45 @@ fi
|
|||||||
|
|
||||||
register_service wolf gaming "Cloud gaming via Moonlight (Games-on-Whales Wolf)" 47989
|
register_service wolf gaming "Cloud gaming via Moonlight (Games-on-Whales Wolf)" 47989
|
||||||
|
|
||||||
|
# Downloads the latest GitHub-released AppImage for a standalone emulator into
|
||||||
|
# $EMU_DIR (skipped if a matching file is already there). AppImages dropped
|
||||||
|
# there are found automatically by ES-DE's app finder (it checks
|
||||||
|
# ~/Applications inside the container, mounted from emulators/) — this covers
|
||||||
|
# every system ES-DE hands off to a standalone frontend instead of a
|
||||||
|
# RetroArch libretro core (3DS, GameCube/Wii, PS2, ...). Same shape as the
|
||||||
|
# original Azahar-only download this was factored out of, just parameterized
|
||||||
|
# so PCSX2/Dolphin/anything else reuse the same fetch-latest-release logic
|
||||||
|
# instead of copy-pasting it per emulator.
|
||||||
|
_wolf_download_emulator_appimage() {
|
||||||
|
local _display_name="$1" _owner_repo="$2" _existing_glob="$3" _dir="$4"
|
||||||
|
if ls "$_dir"/$_existing_glob 2>/dev/null | grep -q .; then
|
||||||
|
log_info "$_display_name already present in $_dir/"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local _get=""
|
||||||
|
echo ""
|
||||||
|
log_info "$_display_name can be auto-downloaded."
|
||||||
|
prompt_yn "Download $_display_name AppImage now? (y/n):" "y" _get
|
||||||
|
[[ "$_get" =~ ^[Yy]$ ]] || return 0
|
||||||
|
|
||||||
|
log_info "Fetching latest $_display_name release from GitHub..."
|
||||||
|
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)
|
||||||
|
if [[ -z "$_url" ]]; then
|
||||||
|
log_warning "Could not resolve download URL — get it manually from https://github.com/${_owner_repo}/releases"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
local _file="$_dir/$(basename "$_url")"
|
||||||
|
curl -fL --progress-bar -o "$_file" "$_url" \
|
||||||
|
&& 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"
|
||||||
|
}
|
||||||
|
|
||||||
install_wolf() {
|
install_wolf() {
|
||||||
require_docker || return 1
|
require_docker || return 1
|
||||||
|
|
||||||
@@ -237,6 +276,11 @@ EOF
|
|||||||
echo " - Open Moonlight UFW ports: TCP ${WOLF_PORTS_TCP[*]} / UDP ${WOLF_PORTS_UDP[*]}"
|
echo " - Open Moonlight UFW ports: TCP ${WOLF_PORTS_TCP[*]} / UDP ${WOLF_PORTS_UDP[*]}"
|
||||||
echo " - Start Wolf and inject Steam + EmulationStation app profiles"
|
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 " - 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 " - 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)"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -771,37 +815,111 @@ UDEV
|
|||||||
log_success "Storage layout: $GAME_STORAGE_DIR/{roms/<system>/,steam,saves,media,emulators,...}"
|
log_success "Storage layout: $GAME_STORAGE_DIR/{roms/<system>/,steam,saves,media,emulators,...}"
|
||||||
log_info "ES-DE ROM directories pre-created. Drop ROMs in the matching subfolder."
|
log_info "ES-DE ROM directories pre-created. Drop ROMs in the matching subfolder."
|
||||||
|
|
||||||
# ── Optional: download Azahar (3DS emulator) ─────────────────────────────
|
# ── Optional: download standalone emulator AppImages ─────────────────────
|
||||||
# Azahar is an open-source Citra fork — the recommended legal 3DS emulator
|
# AppImages dropped in emulators/ are found automatically by ES-DE's app
|
||||||
# for ES-DE. AppImages dropped in emulators/ are found automatically by
|
# finder (checks ~/Applications inside the container). These are the
|
||||||
# ES-DE's app finder (checks ~/Applications inside the container).
|
# systems ES-DE hands off to a standalone frontend rather than a
|
||||||
local _AZAHAR_DIR="$GAME_STORAGE_DIR/emulators"
|
# RetroArch libretro core (Dolphin's libretro core in particular is
|
||||||
if ! ls "$_AZAHAR_DIR"/azahar*.AppImage 2>/dev/null | grep -q .; then
|
# unstable for Wii — confirmed live: "could not write to/read from Wii
|
||||||
local _get_az=""
|
# system memory" errors go away once a real standalone Dolphin build is
|
||||||
|
# present instead).
|
||||||
|
local _EMU_DIR="$GAME_STORAGE_DIR/emulators"
|
||||||
|
_wolf_download_emulator_appimage \
|
||||||
|
"Azahar (3DS — open-source Citra fork)" "azahar-emu/azahar" "azahar*.AppImage" "$_EMU_DIR"
|
||||||
|
_wolf_download_emulator_appimage \
|
||||||
|
"PCSX2 (PS2)" "PCSX2/pcsx2" "pcsx2*.AppImage" "$_EMU_DIR"
|
||||||
|
|
||||||
|
# Dolphin itself ships no official Linux AppImage — dolphin-emu.org's own
|
||||||
|
# Linux distribution is Flatpak-only. pkgforge-dev/Dolphin-emu-AppImage is
|
||||||
|
# a well-regarded THIRD-PARTY community build, not an official Dolphin
|
||||||
|
# release — flagged explicitly rather than silently offered as if it were
|
||||||
|
# one, so skip it and grab Dolphin's own Flatpak/build by hand instead if
|
||||||
|
# you'd rather not run an unofficial build.
|
||||||
|
if ! ls "$_EMU_DIR"/*[Dd]olphin*.AppImage 2>/dev/null | grep -q .; then
|
||||||
|
log_warning "Dolphin (GameCube/Wii) has no official Linux AppImage (dolphin-emu.org ships Flatpak only)."
|
||||||
|
log_warning "The option below is a well-regarded but THIRD-PARTY community build (pkgforge-dev), not"
|
||||||
|
log_warning "an official Dolphin release."
|
||||||
|
fi
|
||||||
|
_wolf_download_emulator_appimage \
|
||||||
|
"Dolphin (GameCube/Wii, community AppImage build)" "pkgforge-dev/Dolphin-emu-AppImage" "*[Dd]olphin*.AppImage" "$_EMU_DIR"
|
||||||
|
|
||||||
|
# ── 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
|
||||||
|
# standalone apps ES-DE launches directly and none of the three support
|
||||||
|
# gamepad-bound hotkeys natively (confirmed open feature requests:
|
||||||
|
# PCSX2/pcsx2#1082, azahar-emu/azahar#722; Dolphin's hotkeys are
|
||||||
|
# hardcoded to keyboard only). AntiMicroX bridges this by watching the
|
||||||
|
# real controller device (Wolf's virtual gamepad is a genuine uinput
|
||||||
|
# device — see games-on-whales/wolf's own docs on "inputtino" — so this
|
||||||
|
# is a real input device AntiMicroX can open, not a proprietary channel)
|
||||||
|
# and injecting whatever keyboard shortcut each app actually expects.
|
||||||
|
#
|
||||||
|
# GoW's own stock Sway config (/cfg/sway/config, baked into the esde and
|
||||||
|
# retroarch images — same one both apps' `launcher()` call copies) has a
|
||||||
|
# deliberate extension point at its very first line:
|
||||||
|
# include /home/retro/.config/sway/custom-cfg
|
||||||
|
# Since /home/retro/.config is already our own retro-home mount (see the
|
||||||
|
# esde/retroarch CATALOG mounts above), just writing a file to
|
||||||
|
# $GAME_STORAGE_DIR/retro-home/sway/custom-cfg on the host lands exactly
|
||||||
|
# there in the container, for both apps, with zero changes to GoW's own
|
||||||
|
# image or scripts needed.
|
||||||
|
#
|
||||||
|
# This only wires up the plumbing (download AntiMicroX, launch it
|
||||||
|
# visibly as a floating window every session). The actual button
|
||||||
|
# mapping — including AntiMicroX's own per-application "Auto Profile"
|
||||||
|
# switching (Options -> Settings -> Auto Profile in its GUI) needed to
|
||||||
|
# send a different key to each emulator from the same physical combo —
|
||||||
|
# has to be built once through AntiMicroX's own GUI while it's running;
|
||||||
|
# hand-authoring its .gamecontroller.amgp profile XML blind isn't
|
||||||
|
# something to guess at. Whatever gets saved there persists automatically
|
||||||
|
# (same retro-home mount), so it's a one-time setup.
|
||||||
|
local _AMX_DIR="$GAME_STORAGE_DIR/retro-home/antimicrox"
|
||||||
|
local _SWAY_CFG_DIR="$GAME_STORAGE_DIR/retro-home/sway"
|
||||||
|
mkdir -p "$_AMX_DIR" "$_SWAY_CFG_DIR"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
log_info "3DS emulation: Azahar (open-source Citra fork) can be auto-downloaded."
|
log_info "AntiMicroX lets you map one controller combo (e.g. Select+Start) to a"
|
||||||
prompt_yn "Download Azahar 3DS emulator AppImage now? (y/n):" "y" _get_az
|
log_info "different real keyboard shortcut per emulator — RetroArch's own hotkeys"
|
||||||
if [[ "$_get_az" =~ ^[Yy]$ ]]; then
|
log_info "already cover every RetroArch-driven system; this is for Dolphin/PCSX2/"
|
||||||
log_info "Fetching latest Azahar release from GitHub..."
|
log_info "Azahar, none of which support gamepad hotkeys natively. EXPERIMENTAL:"
|
||||||
local _AZ_URL
|
log_info "the actual button mapping has to be built once through its own GUI."
|
||||||
_AZ_URL=$(curl -fsSL "https://api.github.com/repos/azahar-emu/azahar/releases/latest" \
|
local _GET_AMX=""
|
||||||
| python3 -c "import sys,json; r=json.load(sys.stdin); \
|
prompt_yn "Set up AntiMicroX for a universal controller hotkey? (y/n):" "n" _GET_AMX
|
||||||
print(next((a['browser_download_url'] for a in r['assets'] \
|
if [[ "$_GET_AMX" =~ ^[Yy]$ ]]; then
|
||||||
if a['name'].endswith('.AppImage')), ''))" 2>/dev/null)
|
# Real release asset is "AntiMicroX-x86_64.AppImage" (capitalized) —
|
||||||
if [[ -n "$_AZ_URL" ]]; then
|
# confirmed against the actual GitHub release, not assumed. A plain
|
||||||
local _AZ_FILE="$_AZAHAR_DIR/$(basename "$_AZ_URL")"
|
# lowercase glob (like Azahar's/PCSX2's, which really are lowercase)
|
||||||
curl -fL --progress-bar -o "$_AZ_FILE" "$_AZ_URL" \
|
# would silently never match this one, on both the helper's own
|
||||||
&& chmod +x "$_AZ_FILE" \
|
# already-downloaded check and the lookup below.
|
||||||
&& chown "$ACTUAL_USER:$ACTUAL_USER" "$_AZ_FILE" \
|
_wolf_download_emulator_appimage \
|
||||||
&& log_success "Azahar downloaded: $_AZ_FILE" \
|
"AntiMicroX" "AntiMicroX/antimicrox" "[Aa]nti[Mm]icro[Xx]*.AppImage" "$_AMX_DIR"
|
||||||
|| log_warning "Download failed — get it manually from https://github.com/azahar-emu/azahar/releases"
|
local _AMX_APP
|
||||||
|
_AMX_APP=$(ls "$_AMX_DIR"/[Aa]nti[Mm]icro[Xx]*.AppImage 2>/dev/null | head -1)
|
||||||
|
if [[ -n "$_AMX_APP" ]]; then
|
||||||
|
backup_if_exists "$_SWAY_CFG_DIR/custom-cfg"
|
||||||
|
cat > "$_SWAY_CFG_DIR/custom-cfg" << CFGEOF
|
||||||
|
# Written by services/wolf.sh — AntiMicroX: universal controller-combo hotkey.
|
||||||
|
# Launched as a normal floating window (not hidden) so its own GUI is
|
||||||
|
# reachable through the Moonlight stream for one-time profile setup —
|
||||||
|
# see ~/docker/wolf/README.md for how to build the actual button mapping.
|
||||||
|
#
|
||||||
|
# AntiMicroX is a Qt5/X11 app running under XWayland here, same as ES-DE and
|
||||||
|
# Steam in this same stock config (see their own [class="..."] rules above) —
|
||||||
|
# app_id only matches native Wayland clients and would never match this one.
|
||||||
|
# Matched on both class and title as a fallback in case the exact WM_CLASS
|
||||||
|
# AntiMicroX registers turns out to differ from what's assumed here.
|
||||||
|
for_window [class="(?i)antimicrox"] floating enable, resize set 480 360, move position 20 20
|
||||||
|
for_window [title="(?i)antimicrox"] floating enable, resize set 480 360, move position 20 20
|
||||||
|
exec /home/retro/.config/antimicrox/$(basename "$_AMX_APP") --appimage-extract-and-run &
|
||||||
|
CFGEOF
|
||||||
|
chown -R 1000:1000 "$_AMX_DIR" "$_SWAY_CFG_DIR" 2>/dev/null || true
|
||||||
|
log_success "AntiMicroX will launch (as a small floating window) alongside ES-DE/RetroArch."
|
||||||
|
log_info "First session: open its window, map your combo, save — it persists from then on."
|
||||||
else
|
else
|
||||||
log_warning "Could not resolve download URL — get it manually from https://github.com/azahar-emu/azahar/releases"
|
log_warning "AntiMicroX download didn't produce a usable AppImage — skipping the Sway launch hook."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
log_info "Azahar already present in $GAME_STORAGE_DIR/emulators/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ── App selection ─────────────────────────────────────────────────────────
|
# ── App selection ─────────────────────────────────────────────────────────
|
||||||
echo ""
|
echo ""
|
||||||
@@ -3055,7 +3173,7 @@ Two things live on the game drive (\`$GAME_STORAGE_DIR\`):
|
|||||||
- \`retroarch/shaders/\` → ~/.config/retroarch/shaders (shaders/CRT filters — persist)
|
- \`retroarch/shaders/\` → ~/.config/retroarch/shaders (shaders/CRT filters — persist)
|
||||||
- \`retroarch/overlays/\` → ~/.config/retroarch/overlays (bezels/overlays — persist)
|
- \`retroarch/overlays/\` → ~/.config/retroarch/overlays (bezels/overlays — persist)
|
||||||
- \`saves/\` → /mnt/games/saves (RetroArch saves & states)
|
- \`saves/\` → /mnt/games/saves (RetroArch saves & states)
|
||||||
- \`emulators/\` → /mnt/games/emulators + ~/Applications (Azahar 3DS AppImage, etc.)
|
- \`emulators/\` → /mnt/games/emulators + ~/Applications (Azahar/PCSX2/Dolphin AppImages)
|
||||||
|
|
||||||
**2. \`wolf-state/\`** — Wolf's entire state folder (\`WOLF_STATE_DIR\` in
|
**2. \`wolf-state/\`** — Wolf's entire state folder (\`WOLF_STATE_DIR\` in
|
||||||
\`.env\`). This is the key to keeping games off the OS drive: it holds
|
\`.env\`). This is the key to keeping games off the OS drive: it holds
|
||||||
@@ -3096,14 +3214,57 @@ ES-DE is usable the moment you launch it; only ROMs and BIOS are yours to add.
|
|||||||
- **Exit a game** back to ES-DE: Start+Select opens the RetroArch menu → Quit,
|
- **Exit a game** back to ES-DE: Start+Select opens the RetroArch menu → Quit,
|
||||||
or use the Wolf hotkey START+UP+RB (Ctrl+Alt+Shift+W on a keyboard).
|
or use the Wolf hotkey START+UP+RB (Ctrl+Alt+Shift+W on a keyboard).
|
||||||
|
|
||||||
## 3DS emulation
|
## Standalone emulators (3DS / PS2 / GameCube+Wii)
|
||||||
Azahar (open-source Citra fork) AppImage lives in \`emulators/\` → mounted at
|
RetroArch's own libretro cores handle these systems poorly or not at all
|
||||||
\`/mnt/games/emulators\` and \`~/Applications\` (where ES-DE's app finder looks).
|
(Dolphin's libretro core in particular is unstable for Wii), so ES-DE hands
|
||||||
Point ES-DE's 3DS system at it via Alternative Emulators if it isn't
|
them off to standalone AppImages instead:
|
||||||
auto-detected. Re-download with:
|
|
||||||
\`\`\`bash
|
- **Azahar** (3DS, open-source Citra fork) — official releases
|
||||||
cd $WOLF_DIR && ./manage.sh apps
|
- **PCSX2** (PS2) — official releases
|
||||||
\`\`\`
|
- **Dolphin** (GameCube/Wii) — Dolphin itself ships no official Linux
|
||||||
|
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.
|
||||||
|
|
||||||
|
All three live in \`emulators/\` → mounted at \`/mnt/games/emulators\` and
|
||||||
|
\`~/Applications\` (where ES-DE's app finder looks). Point ES-DE's
|
||||||
|
3DS/PS2/GameCube/Wii systems at one via Alternative Emulators if it isn't
|
||||||
|
auto-detected. Missing ones get offered again on a fresh install
|
||||||
|
(\`sudo ./setup.sh wolf\`); to grab just one by hand, download its AppImage
|
||||||
|
into \`emulators/\`, \`chmod +x\` it.
|
||||||
|
|
||||||
|
## AntiMicroX — universal controller-combo hotkey (experimental)
|
||||||
|
RetroArch's own hotkeys (Settings -> Input -> Input Hotkey Binds) already
|
||||||
|
cover every RetroArch-driven system, but Dolphin/PCSX2/Azahar don't support
|
||||||
|
gamepad-bound hotkeys natively — AntiMicroX watches the controller directly
|
||||||
|
and injects whatever keyboard shortcut each app actually expects, so one
|
||||||
|
physical combo (e.g. hold Select, press Start) can mean "exit" — or save
|
||||||
|
state, or anything else — everywhere.
|
||||||
|
|
||||||
|
If you said yes to the AntiMicroX prompt during install, it launches
|
||||||
|
automatically as a small floating window every time ES-DE or RetroArch
|
||||||
|
starts. **Building the actual mapping is a one-time step, done through its
|
||||||
|
own GUI, not something this installer can pre-configure:**
|
||||||
|
|
||||||
|
1. Start ES-DE (or RetroArch) from Moonlight as normal — AntiMicroX's small
|
||||||
|
window appears floating in the corner alongside it.
|
||||||
|
2. In AntiMicroX: set up your controller under its device list, then create
|
||||||
|
a profile — click a button in its UI, press the real combo on your
|
||||||
|
gamepad, assign it the keyboard key the target emulator expects for that
|
||||||
|
action (see each emulator's own Settings -> Input/Hotkeys for its actual
|
||||||
|
bindings — Dolphin/PCSX2 defaults are commonly F1-F4-range keys).
|
||||||
|
3. For a **different translation per emulator** from the same physical
|
||||||
|
combo, use AntiMicroX's own **Options -> Settings -> Auto Profile** —
|
||||||
|
add a rule per application (matched by window class/title) so e.g.
|
||||||
|
Select+Start sends Esc when Dolphin has focus but F4 when RetroArch does.
|
||||||
|
4. Save. It's written under \`~/.config/antimicrox/\` inside the container,
|
||||||
|
which is the same \`retro-home/\` mount everything else here persists
|
||||||
|
through — it'll auto-load on every future session with no further setup.
|
||||||
|
|
||||||
|
To change the mapping later, just reopen AntiMicroX the same way. To remove
|
||||||
|
it entirely, delete \`retro-home/sway/custom-cfg\` and \`retro-home/antimicrox/\`
|
||||||
|
on the host and re-run \`sudo ./setup.sh wolf\`.
|
||||||
|
|
||||||
## Troubleshooting: app exits immediately ("Permission denied")
|
## Troubleshooting: app exits immediately ("Permission denied")
|
||||||
If a launcher (Steam, etc.) closes the moment it opens, its Wolf-managed home
|
If a launcher (Steam, etc.) closes the moment it opens, its Wolf-managed home
|
||||||
|
|||||||
Reference in New Issue
Block a user