diff --git a/services/wolf.sh b/services/wolf.sh index ce21bac..e9a4c3b 100644 --- a/services/wolf.sh +++ b/services/wolf.sh @@ -798,7 +798,8 @@ UDEV "$GAME_STORAGE_DIR/steam-cache" \ "$GAME_STORAGE_DIR/bios" "$GAME_STORAGE_DIR/retroarch/cores" \ "$GAME_STORAGE_DIR/retroarch/shaders" "$GAME_STORAGE_DIR/retroarch/overlays" \ - "$GAME_STORAGE_DIR/retro-home" "$GAME_STORAGE_DIR/retro-home-data" + "$GAME_STORAGE_DIR/retro-home" "$GAME_STORAGE_DIR/retro-home-data" \ + "$GAME_STORAGE_DIR/esde-custom-systems" # ── Wolf state folder on the game drive ─────────────────────────────────── # This is the clean way to keep Steam (and everything else) off the OS @@ -860,7 +861,7 @@ UDEV # confirmed live: "data is corrupted" / "could not write to/read from Wii # system memory" was this directory not existing at all, since only # .config had a persistent mount before this). - chown -R 1000:1000 "$GAME_STORAGE_DIR/retro-home" "$GAME_STORAGE_DIR/retro-home-data" "$GAME_STORAGE_DIR/retroarch" 2>/dev/null || true + chown -R 1000:1000 "$GAME_STORAGE_DIR/retro-home" "$GAME_STORAGE_DIR/retro-home-data" "$GAME_STORAGE_DIR/retroarch" "$GAME_STORAGE_DIR/esde-custom-systems" 2>/dev/null || true log_success "Storage layout: $GAME_STORAGE_DIR/{roms//,steam,saves,media,emulators,...}" log_info "ES-DE ROM directories pre-created. Drop ROMs in the matching subfolder." @@ -910,6 +911,93 @@ UDEV log_success "Linked $_EMU_DIR/Dolphin_Emulator.AppImage -> $(basename "$_DOLPHIN_REAL") (the filename ES-DE's own find-rules require)" fi + # Cemu (Wii U) — no libretro core exists (checked live: a third-party + # attempt exists but was never merged into RetroArch and there are no + # plans to; standalone is the only real path). Cemu's own official + # release asset is already named Cemu--x86_64.AppImage, which + # matches ES-DE's own find-rule (Cemu*.AppImage) directly — no + # Dolphin-style rename/symlink needed here. + # + # SECURITY NOTE: Cemu's official Linux release assets were compromised + # (supply-chain attack) for a period around v2.6 in 2026-05, later + # restored — confirmed via Datadog Security Labs' public writeup. Always + # download from cemu-project/Cemu's own GitHub releases (which this + # does) rather than a mirror, and check the project's own release notes + # if you want to verify checksums before running it. + log_warning "Cemu (Wii U) downloads from cemu-project's official releases. Its Linux release assets" + log_warning "were briefly compromised in a supply-chain attack around v2.6 (since restored) — worth" + log_warning "knowing given Wii U games are otherwise unverifiable executables running with your GPU." + _wolf_download_emulator_appimage \ + "Cemu (Wii U)" "cemu-project/Cemu" "Cemu*.AppImage" "$_EMU_DIR" + log_info "Cemu needs its own Wii U common key (keys.txt) for most encrypted retail games — that's" + log_info "not something this installer can supply. Cemu's own First-Time Setup Wizard covers where" + log_info "to put it once you have one." + + # ── Optional: TI-99/4A as its own ES-DE system ──────────────────────────── + # TI-99/4A has no libretro core and isn't one of ES-DE's built-in systems, + # so getting it real ES-DE treatment (artwork scraping, gameplay-time + # tracking) needs a custom system definition — confirmed against ES-DE's + # own USERGUIDE.md: a custom_systems/es_systems.xml, living outside the + # bundled config specifically so it complements rather than replaces it, + # at ~/ES-DE/custom_systems/ inside the container (its own mount, added + # above — that path isn't covered by any of the existing .config/ + # .local/share mounts). js99er (this repo's existing browser-based + # TI-99/4A emulator, a separate non-Wolf service) is deliberately not + # used here — it's not something ES-DE can launch as a system. + # + # ti99sim-sdl (billzajac/ti99sim) is the real target — genuine SDL2 + # joystick/gamepad support, confirmed against its own README — but it's + # source-only with no AppImage, so unlike Azahar/PCSX2/Dolphin/Cemu this + # installer can't just download a working binary: building it here would + # mean compiling against the HOST's glibc/SDL2 while the binary actually + # needs to run inside the ES-DE container's own (different) runtime, and + # that mismatch isn't something to guess at blind. The custom system + # definition below always gets written — cheap and correct regardless — + # pointing at emulators/ti99sim-sdl (the same ~/Applications convention + # every other standalone emulator here uses), so dropping a working + # binary there is the only remaining step. + echo "" + local _GET_TI99="" + prompt_yn "Set up TI-99/4A as its own ES-DE system (artwork scraping, gameplay-time tracking)? (y/n):" "n" _GET_TI99 + if [[ "$_GET_TI99" =~ ^[Yy]$ ]]; then + mkdir -p "$GAME_STORAGE_DIR/esde-custom-systems" "$GAME_STORAGE_DIR/roms/ti994a" + local _TI99_XML="$GAME_STORAGE_DIR/esde-custom-systems/es_systems.xml" + if [ ! -f "$_TI99_XML" ] || ! grep -q 'ti994a' "$_TI99_XML" 2>/dev/null; then + backup_if_exists "$_TI99_XML" + [ -f "$_TI99_XML" ] || echo '' > "$_TI99_XML" + sed -i 's###' "$_TI99_XML" 2>/dev/null + cat >> "$_TI99_XML" << 'XMLEOF' + + ti994a + Texas Instruments TI-99/4A + %ROMPATH%/ti994a + .ctg .rpk .bin + %INJECT%=%BASENAME%.esprefix /home/retro/Applications/ti99sim-sdl --joystick1=1 %ROM% + ti99 + ti99 + + +XMLEOF + chown "$ACTUAL_USER:$ACTUAL_USER" "$_TI99_XML" + log_success "TI-99/4A added as an ES-DE system (roms/ti994a/, custom_systems/es_systems.xml)" + else + log_info "TI-99/4A system definition already present — left as-is." + fi + echo "" + log_warning "ti99sim-sdl itself still needs to be built and placed by hand — this installer can't" + log_warning "safely cross-compile a binary that's guaranteed to run inside the ES-DE container:" + log_info " 1. git clone https://github.com/billzajac/ti99sim.git && cd ti99sim && make" + log_info " (needs libsdl2-dev — same build machine/container the ES-DE image itself runs on" + log_info " gives the best chance the result actually runs; a plain host build may hit a" + log_info " glibc/SDL2 mismatch inside the container)" + log_info " 2. Copy the resulting ti99sim-sdl binary to:" + log_info " $GAME_STORAGE_DIR/emulators/ti99sim-sdl" + log_info " 3. You'll also need your own TI-99/4A console ROM + GROM dump (real console" + log_info " firmware, same legal situation as any other console BIOS) — ti99sim's own" + log_info " README covers where it expects that once you have it." + log_info " 4. Drop .ctg/.rpk/.bin cartridge files into roms/ti994a/" + fi + # ── App selection ───────────────────────────────────────────────────────── echo "" echo "═══════════════════════════════════════════════════════" @@ -1436,7 +1524,8 @@ CATALOG = { f'{games}/retro-home-data:/home/retro/.local/share:rw', f'{games}/retroarch:/home/retro/.config/retroarch:rw', f'{games}/emulators:/mnt/games/emulators:rw', - f'{games}/emulators:/home/retro/Applications:rw'], + f'{games}/emulators:/home/retro/Applications:rw', + f'{games}/esde-custom-systems:/home/retro/ES-DE/custom_systems:rw'], env=STD_ENV, cap_add=STD_CAP, security_opt=[], ipc_mode='host', ulimits=[], privileged=False, ), @@ -2817,7 +2906,8 @@ CATALOG = { f'{games}/retro-home-data:/home/retro/.local/share:rw', f'{games}/retroarch:/home/retro/.config/retroarch:rw', f'{games}/emulators:/mnt/games/emulators:rw', - f'{games}/emulators:/home/retro/Applications:rw'], + f'{games}/emulators:/home/retro/Applications:rw', + f'{games}/esde-custom-systems:/home/retro/ES-DE/custom_systems:rw'], env=STD_ENV, cap_add=STD_CAP, security_opt=[], ipc_mode='host', ulimits=[], privileged=False, ), @@ -3092,7 +3182,9 @@ PYEOF echo "── EMULATION (ES-DE) FIRST RUN ───────────────────────" echo "" echo " • Drop ROMs in roms// (e.g. roms/snes/, roms/genesis/)" - echo " • Drop BIOS files in bios/ (PSX/Saturn/Dreamcast/Neo-Geo need them)" + echo " • Drop BIOS files in bios/ (PSX/Saturn/Dreamcast/Neo-Geo need them; PS2/PCSX2 and" + echo " TI-99/4A need their own BIOS/console ROM too, but PS2 is configured inside PCSX2's own" + echo " settings rather than auto-detected from bios/, and TI-99/4A's setup is manual — see below)" echo " • RetroArch cores are pre-downloaded — retro games launch immediately" echo " • Shaders, overlays, cheats, and the game database are pre-downloaded too —" echo " all persist on the game drive and survive new sessions and reinstalls" @@ -3268,7 +3360,11 @@ ES-DE is usable the moment you launch it; only ROMs and BIOS are yours to add. - **ROMs**: drop files into \`roms//\` (e.g. \`roms/snes/\`, \`roms/genesis/\`). Every standard system folder is pre-created. - **BIOS**: drop firmware into \`bios/\` (mounted at \`~/bioses\`). Required for - PSX, Saturn, Dreamcast, Neo-Geo, PC Engine CD, etc. + PSX, Saturn, Dreamcast, Neo-Geo, PC Engine CD, etc. **PS2/PCSX2 also needs + its own BIOS**, but it's configured inside PCSX2's own settings UI (BIOS + directory) rather than auto-detected from this shared folder — point it at + \`bios/\` there, or its own default location. **TI-99/4A** needs a real + console ROM + GROM dump too — see the TI-99/4A section below. - **RetroArch cores**: pre-downloaded into \`retroarch/cores/\` and mounted at \`~/.config/retroarch/cores\`, so libretro games launch right away. Refresh or expand the set with \`./manage.sh cores\` (\`all\` = full buildbot set + the @@ -3359,6 +3455,53 @@ 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. +## Wii U (Cemu) +No libretro core exists for Wii U — Cemu is standalone-only, same download +pattern as the three above (\`emulators/\`, official cemu-project/Cemu +releases, auto-offered on install). Two things worth knowing: +- Cemu's own Linux release assets were briefly compromised in a + supply-chain attack around v2.6 (2026-05, since restored) — this + installer downloads straight from cemu-project's own GitHub releases, + but it's worth being aware of if you want to check checksums yourself. +- Most retail Wii U games are encrypted and need your own Wii U common key + (\`keys.txt\`) — Cemu's own First-Time Setup Wizard covers where that goes. + +## TI-99/4A +If you said yes to the TI-99/4A prompt during install, it's set up as a +real ES-DE system (\`roms/ti994a/\`, artwork scraping, gameplay-time +tracking) via a custom system definition at +\`esde-custom-systems/es_systems.xml\` — **not** this repo's \`js99er\` +service, which is browser-based and isn't something ES-DE can launch as a +system. + +The emulator itself, \`ti99sim-sdl\` (real SDL2 gamepad support), isn't +auto-downloaded — it has no AppImage, and building it on the host risks a +glibc/SDL2 mismatch against the ES-DE container's own runtime that isn't +safe to guess at blind. Build it yourself and drop the binary at +\`emulators/ti99sim-sdl\`: +\`\`\`bash +git clone https://github.com/billzajac/ti99sim.git && cd ti99sim && make +\`\`\` +(needs \`libsdl2-dev\`). You'll also need your own TI-99/4A console ROM + +GROM dump — same legal situation as any other console BIOS, and not +something this installer supplies — ti99sim's own README covers where it +expects that. Then drop \`.ctg\`/\`.rpk\`/\`.bin\` cartridge files into +\`roms/ti994a/\`. + +## MAME: sample packs showing up as games +MAME sample packs (audio for a handful of older analog-sound games) use the +exact same \`.zip\`-per-game naming as real ROMs, so if they're sitting in +\`roms/mame/\` alongside your actual ROM set, ES-DE/RetroArch's MAME core +lists them as if they were games too — there's no reliable filename-only +way to tell them apart (a samples zip and a ROM zip for the same game can +share the identical name). They belong in RetroArch's system directory +instead, under a MAME-core-specific \`samples/\` subfolder (e.g. +\`retroarch/system/mame2003-plus/samples/\` for MAME2003-Plus — the exact +subfolder name depends on which MAME core variant you're using), never in +\`roms/mame/\` itself. A samples zip's contents are almost entirely \`.wav\` +files where a real ROM zip's aren't, which is the practical way to tell +them apart if you're not sure which of your files are which. + ## Troubleshooting: app exits immediately ("Permission denied") If a launcher (Steam, etc.) closes the moment it opens, its Wolf-managed home dir has root-owned files the in-container user (uid 1000) can't write. Fix: