Script to create a gaming focused Distrobox with all emulators pre-configured
Shell
294
486 commits
updated Sep 18, 2026
Ansible playbooks for an Arch-based distrobox named gaming. Sets up ES-DE,
standalone emulators (shadPS4 for PS4, Dolphin for GC/Wii, PCSX2 for PS2,
DuckStation for PS1, Flycast for Dreamcast, xemu for Xbox, RPCS3 for PS3,
PPSSPP for PSP, Azahar for 3DS, Eden for Switch, Cemu for Wii U, RetroArch, and
Supermodel for Sega Model 3), RetroArch cores, host-side Walker desktop
launcher rendering/install scripts, DLC/patch batch installers for PS3 and
Switch, per-game RPCS3 optimization configs, optional Wine-managed Xenia
Manager for Xbox 360, Hedge Mod Manager for Sonic mods, optional native
Unleashed Recompiled for Sonic Unleashed, and a minimal zsh + starship shell
inside the box.
Beyond the core emulators, a large set of opt-in roles (all never-tagged,
or run via a standalone install-*.yml playbook) add: Sega arcade (Model 1/2/3
via Wine frontends + Supermodel), native recomp/decomp ports (Ship of Harkinian,
2Ship2Harkinian, Starship, Render96ex, SpaghettiKart, Sonic P-06, Unleashed
Recomp, PrBoom-Plus Doom II RT), Windows/Wine games (Colin McRae Rally, OutRun
2006, Sega Rally, GT5 Master Mod, Metal Gear Master Collection fixes, and more),
and reproducible NexusMods mod-set roles per game. See docs/nexusmods.md,
docs/external-installers.md, and docs/rebuild-runbook.md.
macos/ is a separate, native macOS baseline — ES-DE plus Dolphin, PCSX2 and
PPSSPP over Homebrew, with its own small Ansible playbook. It shares no code
with the Linux tree: no Distrobox, no Wine/Proton, no .so cores. Windows
software is permanently out of its scope. See macos/README.md
and macos/INSTALL.md.
Everything else in this file describes the Linux distrobox.
cd ansible
ansible-galaxy collection install -r collections/requirements.yml
cp host_vars/localhost.yml.example host_vars/localhost.yml
$EDITOR host_vars/localhost.yml
ansible-playbook site.yml
For a full run with optional Xbox 360/Xenia Manager:
ansible-playbook site.yml
ansible-playbook install-xenia.yml
All commands run from the ansible/ directory:
ansible-playbook site.yml # full setup from scratch
ansible-playbook reset-configs.yml # reset emulator configs without rebuilding
ansible-playbook backup.yml # backup before destructive testing
ansible-playbook restore.yml # restore from backup
ansible-playbook refresh-shadps4.yml # update shadPS4 builds
ansible-playbook install-xenia.yml # install/update Xenia Manager (optional)
ansible-playbook install-hedgemodmanager.yml # install/update Hedge Mod Manager
ansible-playbook install-pc-racing.yml # prepare/install optional Windows PC racing games
ansible-playbook install-outrun-2006.yml # install/update OutRun 2006
ansible-playbook install-sega-rally-revo.yml # install/update Sega Rally Revo
ansible-playbook install-sonic-p06.yml # install/update Sonic Project '06
ansible-playbook install-unleashed-recomp.yml # install/update Unleashed Recompiled
Tags allow running subsets:
ansible-playbook site.yml --tags check # host path and UID/GID validation
ansible-playbook site.yml --tags create # create the distrobox
ansible-playbook site.yml --tags bootstrap # install pacman + AUR packages
ansible-playbook site.yml --tags shadps4 # install/update shadPS4
ansible-playbook site.yml --tags hedgemodmanager # install/update Hedge Mod Manager
ansible-playbook site.yml --tags configure # configs, desktop entries, ES-DE
ansible-playbook site.yml --tags scripts # deploy box helper scripts
ansible-playbook site.yml --tags shell # deploy zsh + starship
ansible-playbook site.yml --tags verify # post-setup assertions
ansible-playbook reset-configs.yml --tags esde # reset only ES-DE
ansible-playbook reset-configs.yml --tags configs # reset only emulator INIs
ansible-playbook reset-configs.yml --tags desktop # reset only desktop entries
ansible-playbook reset-configs.yml --tags shell # reset only zsh/starship
These roles touch your specific ROM/NAS layout or perform large downloads, so they only run when the matching tag is explicitly passed:
ansible-playbook site.yml --tags dlcs # install PS3 DLCs + Switch NSPs
ansible-playbook site.yml --tags cheats # link Switch cheats to Eden
ansible-playbook site.yml --tags rpcs3_configs # per-game RPCS3 tuning
ansible-playbook site.yml --tags retroarch # download RA cores + assets
ansible-playbook site.yml --tags pcsx2_textures # PCSX2 HD texture packs + per-game settings + .pnach patches
ansible-playbook site.yml --tags pc_racing # prepare tested Windows PC racing games via Wine
ansible-playbook site.yml --tags sonic_p06 # install Sonic Project '06 via system Wine
ansible-playbook site.yml --tags unleashed_recomp # install native Unleashed Recompiled Flatpak
ansible-playbook site.yml --tags ogm # render the ogm (omarchy-games-menu) catalog fragment
All paths are configurable via Ansible variables. Defaults match the current machine's NAS layout:
dg_box_name: gaming
dg_host_uid: 1026 # NAS requires this UID
dg_host_gid: 1026
dg_data_root: /mnt/data
dg_box_home: /mnt/data/distrobox/gaming
dg_external_games_root: /mnt/terachad/Emulators
dg_roms_final_root: "{{ dg_external_games_root }}/ROMS_FINAL"
dg_emudeck_root: "{{ dg_external_games_root }}/EmuDeck"
dg_bios_root: "{{ dg_emudeck_root }}/Emulation/bios"
dg_rom_root: "{{ dg_emudeck_root }}/roms"
dg_rom_heavy_root: "{{ dg_emudeck_root }}/roms_heavy"
dg_ps3_dlc_source: "{{ dg_rom_heavy_root }}/ps3-DLC"
dg_switch_updates_source: "{{ dg_rom_heavy_root }}/switch_updates"
dg_switch_cheats_source: "{{ dg_rom_heavy_root }}/switch_cheats"
For another machine, create ansible/host_vars/localhost.yml and override any
variable. Or pass overrides on the command line:
ansible-playbook site.yml -e dg_data_root=/home/me/gaming -e dg_external_games_root=/media/games
On systems with both an NVIDIA dGPU and an AMD iGPU, emulators are forced to
use NVIDIA by injecting VK_ICD_FILENAMES into every desktop launcher and
ES-DE command. The distrobox is also created with --nvidia so NVIDIA drivers
are bind-mounted into the container. Controlled by dg_nvidia_enabled: true
in group_vars/all/gpu.yml. Set to false to disable.
For Steam/Proton, the launcher also exports LD_LIBRARY_PATH pointing only to
an Ansible-managed extraction of the matching lib32-nvidia-utils package.
Steam Runtime's entrypoint converts that into pressure-vessel app library paths
before launching Proton. This avoids a distrobox --nvidia edge case where
host 64-bit NVIDIA libraries can appear under /usr/lib32, breaking 32-bit
DXVK games such as Sonic Adventure DX and Castlevania Anniversary Collection.
Steam game compatibility research is tracked in
data/steam-proton-compat.json. Refresh it with
scripts/build-steam-proton-db.py and record source-backed local fixes in
data/steam-proton-overrides.json; see docs/steam-proton-compatibility.md.
If you screw up your emulator configs (ES-DE, DuckStation, PCSX2, etc.) and want to restore to Ansible-managed defaults without reinstalling the box:
ansible-playbook reset-configs.yml # reset everything
ansible-playbook reset-configs.yml --tags esde # reset only ES-DE
ansible-playbook reset-configs.yml --tags configs # reset only emulator INIs
ansible-playbook reset-configs.yml --tags shell # reset only zsh/starship
This re-applies seed_configs, desktop_apps, configure_esde, and
shell_config roles. Existing files are backed up automatically before
overwriting.
Before destructive testing (e.g. rebuilding from scratch):
ansible-playbook backup.yml # commits container image + archives configs
ansible-playbook restore.yml # prompts for timestamp, restores both
Backups are stored under $DG_BOX_HOME/backups/.
The NAS requires UID/GID 1026 for file access. The check_host role asserts
the host user matches dg_host_uid before proceeding. The container user
inherits the host UID/GID through distrobox.
Override for another machine:
# ansible/host_vars/localhost.yml
dg_host_uid: 1000
dg_host_gid: 1000
gaming with --nvidia drivers bind-mountedgroup_vars/all/packages.yml)dg_atari_enabled, off by default) on cores the list already carried
(docs/atari.md)$DG_BOX_HOME/bin/flycast-hiresSelect+Start shutdown hotkey$DG_BIOS_ROOTCUSA00003.toml config with v1.28 patch XML, PS4 11.00 sys_module symlinksPS3 DLCs and patches: install_dlcs role batch-extracts every .pkg
from $DG_PS3_DLC_SOURCE into RPCS3's dev_hdd0/game/ — bypasses the
GUI-only installer limitation
Switch updates and DLC: same role extracts NSPs from
$DG_SWITCH_UPDATES_SOURCE into Eden's NAND at
~/.local/share/eden/nand/user/Contents/registered/
Switch cheats: switch_cheats role symlinks Atmosphere-format cheats
from $DG_SWITCH_CHEATS_SOURCE into Eden's load path
Per-game RPCS3 configs: rpcs3_per_game_configs role scans installed
PS3 games, queries the RPCS3 compatibility API, and writes tuned
custom_configs/<TITLE_ID>_config.yml for games with "Ingame" or "Loadable"
status. Hand-curated overrides for known-problematic titles (Gran Turismo 6,
Gran Turismo 5, Metal Gear Solid 4).
PCSX2 HD texture packs + per-game settings + .pnach patches:
pcsx2_textures role symlinks per-game texture replacement directories
into ~/.config/PCSX2/textures/<SERIAL>/replacements/<link_as>/ (no
copy — textures live on NAS, PCSX2 caches in RAM after first load),
symlinks .pnach patch files into ~/.config/PCSX2/patches/, mass-symlinks
~/.config/PCSX2/cheats/ from a NAS cheats source, downloads a curated
list of public .pnach URLs (e.g. Silent's GT4 USA patches from his
GitHub), and writes per-game override INIs to
~/.config/PCSX2/gamesettings/<SERIAL>.ini. Initial configs cover Gran
Turismo 4 (SCUS-97328) with Silentwarior112's HD HUD/UI pack + update 2.1
dg_pcsx2_texture_packs, dg_pcsx2_per_game_settings,
dg_pcsx2_extra_patches, and dg_pcsx2_patch_urls in
group_vars/all/pcsx2.yml.Texture pack updates are a manual process — the source forums (GTPlanet, Nexus Mods, Silent's Blog) are Cloudflare-walled and Drive/MEGA links throttle scripted downloads. Check periodically:
When a new version drops, download manually and drop into the existing pack directory in your NAS — the role re-symlinks on next run.
group_vars/all/launchers.yml and rendered via a single Jinja2 template.
Each Exec line is wrapped with the NVIDIA-preference env vars.config/desktop/rendered/; it does not write
into the host applications directory from inside the distrobox. Install or
refresh host menu entries from the host with:scripts/install-host-launchers.sh
The script validates every rendered .desktop file, skips optional apps that
are not installed in the box, removes stale installed entries for missing
optional apps, and restarts Walker if it is running.
The install_dlcs role also deploys standalone scripts into the box that you
can run manually for advanced tasks:
# List / download missing PS3 patches from PSN's public update server
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \
"$DG_ROM_HEAVY_ROOT/ps3" \
--dlc-dir "$DG_PS3_DLC_SOURCE" --list
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \
"$DG_ROM_HEAVY_ROOT/ps3" \
--dlc-dir "$DG_PS3_DLC_SOURCE" \
--download-dir "$DG_BOX_HOME/dlc-temp" --download
# List outdated Switch games (Nintendo's CDN needs console auth, so no download)
python3 $DG_BOX_HOME/scripts/check_switch_updates.py \
"$DG_ROM_HEAVY_ROOT/switch" \
--updates-dir "$DG_SWITCH_UPDATES_SOURCE"
# Reorganize a messy switch_updates dump into per-title-ID folders
# (handles .nsp/.nsz/.xci/.xcz; mods and non-patch files are left alone)
python3 $DG_BOX_HOME/scripts/reorganize_switch_nsps.py \
"$DG_SWITCH_UPDATES_SOURCE" --dry-run
Note on Switch updates: Nintendo's update CDN requires device-specific
certificates from a hacked Switch. check_switch_updates.py only reports
what's outdated (using the public blawar/titledb version database) — you
source the NSPs yourself.
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \
$DG_ROM_HEAVY_ROOT/ps3 --dlc-dir $DG_ROM_HEAVY_ROOT/ps3-DLC --list
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \
$DG_ROM_HEAVY_ROOT/ps3 --dlc-dir $DG_ROM_HEAVY_ROOT/ps3-DLC \
--download-dir $DG_BOX_HOME/dlc-temp --download
$DG_BOX_HOME/dlc-temp, then copy into the canonical cache:
rsync -av $DG_BOX_HOME/dlc-temp/ $DG_ROM_HEAVY_ROOT/ps3-DLC/
cd ansible && ansible-playbook site.yml --tags dlcs
The extract_ps3_dlc.py extractor uses the PKG's filename version
(e.g. -A0122-V0100-) and compares against the destination's
PARAM.SFO VERSION to decide whether to re-extract. Re-running after
all patches are applied is a no-op.
Some PS3 games regress on current RPCS3 when patched to the latest version (GT6 is notorious — older RPCS3 builds broke above 1.12 or so). To cap a game at a specific patch level:
# Wipe the current patch content dir so the version check doesn't block
rm -rf $DG_BOX_HOME/.config/rpcs3/dev_hdd0/game/<CONTENT_ID>
# Re-extract only patches up to the target version
python3 $DG_BOX_HOME/scripts/extract_ps3_dlc.py \
$DG_ROM_HEAVY_ROOT/ps3-DLC/<TITLE_ID> \
--max-version 01.12
--max-version skips any patch PKG whose filename-encoded version
exceeds the limit. Without the rm -rf first, the version-aware
idempotency check would refuse to downgrade.
The expected layout is clean extracted title directories, not raw .pkg files:
$DG_PS4_ROM_ROOT/
CUSA00003/
eboot.bin
...
Xbox 360 support uses Xenia Manager inside a dedicated Wine prefix.
ansible-playbook install-xenia.yml will:
multilib inside the boxwine and winetricksAfter that, launch Xenia Manager and use its Manage page to install Canary.
Sonic mod support uses Hedge Mod Manager 8 built natively inside the distrobox,
not host Flatpak. The default site.yml run installs it; rerun only that role
with:
ansible-playbook install-hedgemodmanager.yml
The wrapper is written to {{ dg_box_home }}/bin/hedge-mod-manager.
It sees the same Steam install and external library paths as Steam inside the
box, including the Proton prefixes under steamapps/compatdata.
Windows PC racing games are optional and live outside the normal rebuild path. They use system Wine inside the distrobox:
ansible-playbook install-pc-racing.yml
The install root is {{ dg_pc_racing_install_root }}; per-game prefixes stay
under {{ dg_pc_racing_prefix_root }}.
Installer GUIs are only launched when explicitly requested with
-e dg_pc_racing_run_installers=true.
Sonic P-06 is an optional Windows Unity fangame install managed outside Steam with system Wine, DXVK, core fonts, GStreamer codecs, and a dedicated prefix:
ansible-playbook install-sonic-p06.yml
The source is the already extracted Silver Release under
{{ dg_sonic_p06_source_dir }}. The managed copy lives at
{{ dg_sonic_p06_install_root }}.
ansible/ # Ansible playbooks and roles (primary)
site.yml # full setup playbook
reset-configs.yml # config-only reset playbook
backup.yml / restore.yml # backup and restore
refresh-shadps4.yml # standalone shadPS4 update
install-xenia.yml # standalone Xenia Manager install
install-hedgemodmanager.yml # standalone Hedge Mod Manager install
install-pc-racing.yml # optional Windows PC racing setup
install-outrun-2006.yml # focused OutRun 2006 install
install-sega-rally-revo.yml # focused Sega Rally Revo install
install-sonic-p06.yml # optional Sonic Project '06 setup
install-unleashed-recomp.yml # optional Unleashed Recompiled install
group_vars/all/ # all dg_* variable defaults
main.yml # paths, UID/GID, box identity
packages.yml # pacman + AUR package lists
emulators.yml # per-emulator INI settings
esde.yml # ES-DE system definitions
launchers.yml # rendered host desktop launcher definitions
ogm.yml # ogm (omarchy-games-menu) catalog metadata
gpu.yml # NVIDIA preference config
shadps4.yml # shadPS4 release / path config
xenia.yml # Xenia Manager config
hedgemodmanager.yml # Hedge Mod Manager source-build config
pc_racing.yml # Windows PC racing source/install metadata
sonic_p06.yml # Sonic Project '06 Wine config
unleashed_recomp.yml # Unleashed Recompiled source staging config
pcsx2.yml # PCSX2 texture packs and per-game overrides
host_vars/localhost.yml.example # machine-specific overrides template
roles/ # one role per setup phase
check_host/ # host validation
create_box/ # distrobox creation (--nvidia)
bootstrap_packages/ # pacman + AUR packages
link_storage/ # BIOS/firmware symlinks
seed_configs/ # emulator INI settings, wrappers
scripts_in_box/ # deploy Python helpers into box
install_dlcs/ # PS3 PKG + Switch NSP batch install
switch_cheats/ # symlink cheats into Eden load path
rpcs3_per_game_configs/ # per-title RPCS3 tuning from API
retroarch_extras/ # 21 buildbot cores + 8 asset packs
pcsx2_textures/ # PCSX2 HD textures + per-game settings + .pnach patches
desktop_apps/ # .desktop entry rendering
configure_esde/ # ES-DE custom systems XML
shell_config/ # minimal zsh + starship
verify/ # post-setup assertions
refresh_shadps4/ # shadPS4 GitHub release management
install_xenia/ # Wine prefix and Xenia Manager
install_hedgemodmanager/ # native HMM 8 source build
install_pc_racing/ # Wine wrappers for tested Windows racing games
install_sonic_p06/ # Wine wrapper for Sonic Project '06
install_unleashed_recomp/ # native Unleashed Recompiled Flatpak install
ogm_catalog/ # host-side ogm (omarchy-games-menu) catalog fragment
scripts/ # helper scripts invoked by the Ansible roles
config/ # live config source trees (emulator INIs, ES-DE, desktop templates)
docs/ # historical notes and focused docs
Core setup & rebuild:
Sources & downloads — upstream repos/pages for every native port, recomp, decomp, fan game and ROM-hack tool, if you want to grab a build yourself
Save backups — mirror emulator/PC-port saves to the NAS (backup-saves) and restore them on a fresh remount (restore-saves)
Rebuild Runbook — from-scratch rebuild, opt-in tags, standalone playbooks
External Installers — download inventory for the opt-in Windows/Wine games and tools
ogm launcher integration — omarchy-games-menu catalog fragment, ogm scan hooks
Unsupported / parked games — games/mods we couldn't get working; the detailed trail lives in GitHub issues
Forza database editing — edit FM4/FM2 car prices & economy in gamedb.slt; swap PFP career/easy (Sandbox) modes; revert
Atari ST / Hatari — focused installation, BIOS setup and mandatory validation
Mods, patches & HD textures:
install_<game>_mods roles, shared loaders, GUI-tool/deferred items, and Proton gotchasWindows / Wine games:
Arcade & ray-traced ports:
Xbox 360 & per-game tuning:
Historical notes:
This repo does not provide ROMs, BIOS files, firmware, keys, or game packages.
Playbooks only detect, link, and configure files that already exist on your machine. They should not delete ROMs, BIOS, saves, firmware, or game data.
Generated emulator state, shader caches, saves, logs, firmware modules, and ROMs must not be committed.
480 commits
6 commits
Shell
43.8%
Python
41.6%
Jinja
11.5%
C
2.2%
Script to create a gaming focused Distrobox with all emulators pre-configured
Shell
294
486 commits
updated Sep 18, 2026
Ansible playbooks for an Arch-based distrobox named gaming. Sets up ES-DE,
standalone emulators (shadPS4 for PS4, Dolphin for GC/Wii, PCSX2 for PS2,
DuckStation for PS1, Flycast for Dreamcast, xemu for Xbox, RPCS3 for PS3,
PPSSPP for PSP, Azahar for 3DS, Eden for Switch, Cemu for Wii U, RetroArch, and
Supermodel for Sega Model 3), RetroArch cores, host-side Walker desktop
launcher rendering/install scripts, DLC/patch batch installers for PS3 and
Switch, per-game RPCS3 optimization configs, optional Wine-managed Xenia
Manager for Xbox 360, Hedge Mod Manager for Sonic mods, optional native
Unleashed Recompiled for Sonic Unleashed, and a minimal zsh + starship shell
inside the box.
Beyond the core emulators, a large set of opt-in roles (all never-tagged,
or run via a standalone install-*.yml playbook) add: Sega arcade (Model 1/2/3
via Wine frontends + Supermodel), native recomp/decomp ports (Ship of Harkinian,
2Ship2Harkinian, Starship, Render96ex, SpaghettiKart, Sonic P-06, Unleashed
Recomp, PrBoom-Plus Doom II RT), Windows/Wine games (Colin McRae Rally, OutRun
2006, Sega Rally, GT5 Master Mod, Metal Gear Master Collection fixes, and more),
and reproducible NexusMods mod-set roles per game. See docs/nexusmods.md,
docs/external-installers.md, and docs/rebuild-runbook.md.
macos/ is a separate, native macOS baseline — ES-DE plus Dolphin, PCSX2 and
PPSSPP over Homebrew, with its own small Ansible playbook. It shares no code
with the Linux tree: no Distrobox, no Wine/Proton, no .so cores. Windows
software is permanently out of its scope. See macos/README.md
and macos/INSTALL.md.
Everything else in this file describes the Linux distrobox.
cd ansible
ansible-galaxy collection install -r collections/requirements.yml
cp host_vars/localhost.yml.example host_vars/localhost.yml
$EDITOR host_vars/localhost.yml
ansible-playbook site.yml
For a full run with optional Xbox 360/Xenia Manager:
ansible-playbook site.yml
ansible-playbook install-xenia.yml
All commands run from the ansible/ directory:
ansible-playbook site.yml # full setup from scratch
ansible-playbook reset-configs.yml # reset emulator configs without rebuilding
ansible-playbook backup.yml # backup before destructive testing
ansible-playbook restore.yml # restore from backup
ansible-playbook refresh-shadps4.yml # update shadPS4 builds
ansible-playbook install-xenia.yml # install/update Xenia Manager (optional)
ansible-playbook install-hedgemodmanager.yml # install/update Hedge Mod Manager
ansible-playbook install-pc-racing.yml # prepare/install optional Windows PC racing games
ansible-playbook install-outrun-2006.yml # install/update OutRun 2006
ansible-playbook install-sega-rally-revo.yml # install/update Sega Rally Revo
ansible-playbook install-sonic-p06.yml # install/update Sonic Project '06
ansible-playbook install-unleashed-recomp.yml # install/update Unleashed Recompiled
Tags allow running subsets:
ansible-playbook site.yml --tags check # host path and UID/GID validation
ansible-playbook site.yml --tags create # create the distrobox
ansible-playbook site.yml --tags bootstrap # install pacman + AUR packages
ansible-playbook site.yml --tags shadps4 # install/update shadPS4
ansible-playbook site.yml --tags hedgemodmanager # install/update Hedge Mod Manager
ansible-playbook site.yml --tags configure # configs, desktop entries, ES-DE
ansible-playbook site.yml --tags scripts # deploy box helper scripts
ansible-playbook site.yml --tags shell # deploy zsh + starship
ansible-playbook site.yml --tags verify # post-setup assertions
ansible-playbook reset-configs.yml --tags esde # reset only ES-DE
ansible-playbook reset-configs.yml --tags configs # reset only emulator INIs
ansible-playbook reset-configs.yml --tags desktop # reset only desktop entries
ansible-playbook reset-configs.yml --tags shell # reset only zsh/starship
These roles touch your specific ROM/NAS layout or perform large downloads, so they only run when the matching tag is explicitly passed:
ansible-playbook site.yml --tags dlcs # install PS3 DLCs + Switch NSPs
ansible-playbook site.yml --tags cheats # link Switch cheats to Eden
ansible-playbook site.yml --tags rpcs3_configs # per-game RPCS3 tuning
ansible-playbook site.yml --tags retroarch # download RA cores + assets
ansible-playbook site.yml --tags pcsx2_textures # PCSX2 HD texture packs + per-game settings + .pnach patches
ansible-playbook site.yml --tags pc_racing # prepare tested Windows PC racing games via Wine
ansible-playbook site.yml --tags sonic_p06 # install Sonic Project '06 via system Wine
ansible-playbook site.yml --tags unleashed_recomp # install native Unleashed Recompiled Flatpak
ansible-playbook site.yml --tags ogm # render the ogm (omarchy-games-menu) catalog fragment
All paths are configurable via Ansible variables. Defaults match the current machine's NAS layout:
dg_box_name: gaming
dg_host_uid: 1026 # NAS requires this UID
dg_host_gid: 1026
dg_data_root: /mnt/data
dg_box_home: /mnt/data/distrobox/gaming
dg_external_games_root: /mnt/terachad/Emulators
dg_roms_final_root: "{{ dg_external_games_root }}/ROMS_FINAL"
dg_emudeck_root: "{{ dg_external_games_root }}/EmuDeck"
dg_bios_root: "{{ dg_emudeck_root }}/Emulation/bios"
dg_rom_root: "{{ dg_emudeck_root }}/roms"
dg_rom_heavy_root: "{{ dg_emudeck_root }}/roms_heavy"
dg_ps3_dlc_source: "{{ dg_rom_heavy_root }}/ps3-DLC"
dg_switch_updates_source: "{{ dg_rom_heavy_root }}/switch_updates"
dg_switch_cheats_source: "{{ dg_rom_heavy_root }}/switch_cheats"
For another machine, create ansible/host_vars/localhost.yml and override any
variable. Or pass overrides on the command line:
ansible-playbook site.yml -e dg_data_root=/home/me/gaming -e dg_external_games_root=/media/games
On systems with both an NVIDIA dGPU and an AMD iGPU, emulators are forced to
use NVIDIA by injecting VK_ICD_FILENAMES into every desktop launcher and
ES-DE command. The distrobox is also created with --nvidia so NVIDIA drivers
are bind-mounted into the container. Controlled by dg_nvidia_enabled: true
in group_vars/all/gpu.yml. Set to false to disable.
For Steam/Proton, the launcher also exports LD_LIBRARY_PATH pointing only to
an Ansible-managed extraction of the matching lib32-nvidia-utils package.
Steam Runtime's entrypoint converts that into pressure-vessel app library paths
before launching Proton. This avoids a distrobox --nvidia edge case where
host 64-bit NVIDIA libraries can appear under /usr/lib32, breaking 32-bit
DXVK games such as Sonic Adventure DX and Castlevania Anniversary Collection.
Steam game compatibility research is tracked in
data/steam-proton-compat.json. Refresh it with
scripts/build-steam-proton-db.py and record source-backed local fixes in
data/steam-proton-overrides.json; see docs/steam-proton-compatibility.md.
If you screw up your emulator configs (ES-DE, DuckStation, PCSX2, etc.) and want to restore to Ansible-managed defaults without reinstalling the box:
ansible-playbook reset-configs.yml # reset everything
ansible-playbook reset-configs.yml --tags esde # reset only ES-DE
ansible-playbook reset-configs.yml --tags configs # reset only emulator INIs
ansible-playbook reset-configs.yml --tags shell # reset only zsh/starship
This re-applies seed_configs, desktop_apps, configure_esde, and
shell_config roles. Existing files are backed up automatically before
overwriting.
Before destructive testing (e.g. rebuilding from scratch):
ansible-playbook backup.yml # commits container image + archives configs
ansible-playbook restore.yml # prompts for timestamp, restores both
Backups are stored under $DG_BOX_HOME/backups/.
The NAS requires UID/GID 1026 for file access. The check_host role asserts
the host user matches dg_host_uid before proceeding. The container user
inherits the host UID/GID through distrobox.
Override for another machine:
# ansible/host_vars/localhost.yml
dg_host_uid: 1000
dg_host_gid: 1000
gaming with --nvidia drivers bind-mountedgroup_vars/all/packages.yml)dg_atari_enabled, off by default) on cores the list already carried
(docs/atari.md)$DG_BOX_HOME/bin/flycast-hiresSelect+Start shutdown hotkey$DG_BIOS_ROOTCUSA00003.toml config with v1.28 patch XML, PS4 11.00 sys_module symlinksPS3 DLCs and patches: install_dlcs role batch-extracts every .pkg
from $DG_PS3_DLC_SOURCE into RPCS3's dev_hdd0/game/ — bypasses the
GUI-only installer limitation
Switch updates and DLC: same role extracts NSPs from
$DG_SWITCH_UPDATES_SOURCE into Eden's NAND at
~/.local/share/eden/nand/user/Contents/registered/
Switch cheats: switch_cheats role symlinks Atmosphere-format cheats
from $DG_SWITCH_CHEATS_SOURCE into Eden's load path
Per-game RPCS3 configs: rpcs3_per_game_configs role scans installed
PS3 games, queries the RPCS3 compatibility API, and writes tuned
custom_configs/<TITLE_ID>_config.yml for games with "Ingame" or "Loadable"
status. Hand-curated overrides for known-problematic titles (Gran Turismo 6,
Gran Turismo 5, Metal Gear Solid 4).
PCSX2 HD texture packs + per-game settings + .pnach patches:
pcsx2_textures role symlinks per-game texture replacement directories
into ~/.config/PCSX2/textures/<SERIAL>/replacements/<link_as>/ (no
copy — textures live on NAS, PCSX2 caches in RAM after first load),
symlinks .pnach patch files into ~/.config/PCSX2/patches/, mass-symlinks
~/.config/PCSX2/cheats/ from a NAS cheats source, downloads a curated
list of public .pnach URLs (e.g. Silent's GT4 USA patches from his
GitHub), and writes per-game override INIs to
~/.config/PCSX2/gamesettings/<SERIAL>.ini. Initial configs cover Gran
Turismo 4 (SCUS-97328) with Silentwarior112's HD HUD/UI pack + update 2.1
dg_pcsx2_texture_packs, dg_pcsx2_per_game_settings,
dg_pcsx2_extra_patches, and dg_pcsx2_patch_urls in
group_vars/all/pcsx2.yml.Texture pack updates are a manual process — the source forums (GTPlanet, Nexus Mods, Silent's Blog) are Cloudflare-walled and Drive/MEGA links throttle scripted downloads. Check periodically:
When a new version drops, download manually and drop into the existing pack directory in your NAS — the role re-symlinks on next run.
group_vars/all/launchers.yml and rendered via a single Jinja2 template.
Each Exec line is wrapped with the NVIDIA-preference env vars.config/desktop/rendered/; it does not write
into the host applications directory from inside the distrobox. Install or
refresh host menu entries from the host with:scripts/install-host-launchers.sh
The script validates every rendered .desktop file, skips optional apps that
are not installed in the box, removes stale installed entries for missing
optional apps, and restarts Walker if it is running.
The install_dlcs role also deploys standalone scripts into the box that you
can run manually for advanced tasks:
# List / download missing PS3 patches from PSN's public update server
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \
"$DG_ROM_HEAVY_ROOT/ps3" \
--dlc-dir "$DG_PS3_DLC_SOURCE" --list
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \
"$DG_ROM_HEAVY_ROOT/ps3" \
--dlc-dir "$DG_PS3_DLC_SOURCE" \
--download-dir "$DG_BOX_HOME/dlc-temp" --download
# List outdated Switch games (Nintendo's CDN needs console auth, so no download)
python3 $DG_BOX_HOME/scripts/check_switch_updates.py \
"$DG_ROM_HEAVY_ROOT/switch" \
--updates-dir "$DG_SWITCH_UPDATES_SOURCE"
# Reorganize a messy switch_updates dump into per-title-ID folders
# (handles .nsp/.nsz/.xci/.xcz; mods and non-patch files are left alone)
python3 $DG_BOX_HOME/scripts/reorganize_switch_nsps.py \
"$DG_SWITCH_UPDATES_SOURCE" --dry-run
Note on Switch updates: Nintendo's update CDN requires device-specific
certificates from a hacked Switch. check_switch_updates.py only reports
what's outdated (using the public blawar/titledb version database) — you
source the NSPs yourself.
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \
$DG_ROM_HEAVY_ROOT/ps3 --dlc-dir $DG_ROM_HEAVY_ROOT/ps3-DLC --list
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \
$DG_ROM_HEAVY_ROOT/ps3 --dlc-dir $DG_ROM_HEAVY_ROOT/ps3-DLC \
--download-dir $DG_BOX_HOME/dlc-temp --download
$DG_BOX_HOME/dlc-temp, then copy into the canonical cache:
rsync -av $DG_BOX_HOME/dlc-temp/ $DG_ROM_HEAVY_ROOT/ps3-DLC/
cd ansible && ansible-playbook site.yml --tags dlcs
The extract_ps3_dlc.py extractor uses the PKG's filename version
(e.g. -A0122-V0100-) and compares against the destination's
PARAM.SFO VERSION to decide whether to re-extract. Re-running after
all patches are applied is a no-op.
Some PS3 games regress on current RPCS3 when patched to the latest version (GT6 is notorious — older RPCS3 builds broke above 1.12 or so). To cap a game at a specific patch level:
# Wipe the current patch content dir so the version check doesn't block
rm -rf $DG_BOX_HOME/.config/rpcs3/dev_hdd0/game/<CONTENT_ID>
# Re-extract only patches up to the target version
python3 $DG_BOX_HOME/scripts/extract_ps3_dlc.py \
$DG_ROM_HEAVY_ROOT/ps3-DLC/<TITLE_ID> \
--max-version 01.12
--max-version skips any patch PKG whose filename-encoded version
exceeds the limit. Without the rm -rf first, the version-aware
idempotency check would refuse to downgrade.
The expected layout is clean extracted title directories, not raw .pkg files:
$DG_PS4_ROM_ROOT/
CUSA00003/
eboot.bin
...
Xbox 360 support uses Xenia Manager inside a dedicated Wine prefix.
ansible-playbook install-xenia.yml will:
multilib inside the boxwine and winetricksAfter that, launch Xenia Manager and use its Manage page to install Canary.
Sonic mod support uses Hedge Mod Manager 8 built natively inside the distrobox,
not host Flatpak. The default site.yml run installs it; rerun only that role
with:
ansible-playbook install-hedgemodmanager.yml
The wrapper is written to {{ dg_box_home }}/bin/hedge-mod-manager.
It sees the same Steam install and external library paths as Steam inside the
box, including the Proton prefixes under steamapps/compatdata.
Windows PC racing games are optional and live outside the normal rebuild path. They use system Wine inside the distrobox:
ansible-playbook install-pc-racing.yml
The install root is {{ dg_pc_racing_install_root }}; per-game prefixes stay
under {{ dg_pc_racing_prefix_root }}.
Installer GUIs are only launched when explicitly requested with
-e dg_pc_racing_run_installers=true.
Sonic P-06 is an optional Windows Unity fangame install managed outside Steam with system Wine, DXVK, core fonts, GStreamer codecs, and a dedicated prefix:
ansible-playbook install-sonic-p06.yml
The source is the already extracted Silver Release under
{{ dg_sonic_p06_source_dir }}. The managed copy lives at
{{ dg_sonic_p06_install_root }}.
ansible/ # Ansible playbooks and roles (primary)
site.yml # full setup playbook
reset-configs.yml # config-only reset playbook
backup.yml / restore.yml # backup and restore
refresh-shadps4.yml # standalone shadPS4 update
install-xenia.yml # standalone Xenia Manager install
install-hedgemodmanager.yml # standalone Hedge Mod Manager install
install-pc-racing.yml # optional Windows PC racing setup
install-outrun-2006.yml # focused OutRun 2006 install
install-sega-rally-revo.yml # focused Sega Rally Revo install
install-sonic-p06.yml # optional Sonic Project '06 setup
install-unleashed-recomp.yml # optional Unleashed Recompiled install
group_vars/all/ # all dg_* variable defaults
main.yml # paths, UID/GID, box identity
packages.yml # pacman + AUR package lists
emulators.yml # per-emulator INI settings
esde.yml # ES-DE system definitions
launchers.yml # rendered host desktop launcher definitions
ogm.yml # ogm (omarchy-games-menu) catalog metadata
gpu.yml # NVIDIA preference config
shadps4.yml # shadPS4 release / path config
xenia.yml # Xenia Manager config
hedgemodmanager.yml # Hedge Mod Manager source-build config
pc_racing.yml # Windows PC racing source/install metadata
sonic_p06.yml # Sonic Project '06 Wine config
unleashed_recomp.yml # Unleashed Recompiled source staging config
pcsx2.yml # PCSX2 texture packs and per-game overrides
host_vars/localhost.yml.example # machine-specific overrides template
roles/ # one role per setup phase
check_host/ # host validation
create_box/ # distrobox creation (--nvidia)
bootstrap_packages/ # pacman + AUR packages
link_storage/ # BIOS/firmware symlinks
seed_configs/ # emulator INI settings, wrappers
scripts_in_box/ # deploy Python helpers into box
install_dlcs/ # PS3 PKG + Switch NSP batch install
switch_cheats/ # symlink cheats into Eden load path
rpcs3_per_game_configs/ # per-title RPCS3 tuning from API
retroarch_extras/ # 21 buildbot cores + 8 asset packs
pcsx2_textures/ # PCSX2 HD textures + per-game settings + .pnach patches
desktop_apps/ # .desktop entry rendering
configure_esde/ # ES-DE custom systems XML
shell_config/ # minimal zsh + starship
verify/ # post-setup assertions
refresh_shadps4/ # shadPS4 GitHub release management
install_xenia/ # Wine prefix and Xenia Manager
install_hedgemodmanager/ # native HMM 8 source build
install_pc_racing/ # Wine wrappers for tested Windows racing games
install_sonic_p06/ # Wine wrapper for Sonic Project '06
install_unleashed_recomp/ # native Unleashed Recompiled Flatpak install
ogm_catalog/ # host-side ogm (omarchy-games-menu) catalog fragment
scripts/ # helper scripts invoked by the Ansible roles
config/ # live config source trees (emulator INIs, ES-DE, desktop templates)
docs/ # historical notes and focused docs
Core setup & rebuild:
Sources & downloads — upstream repos/pages for every native port, recomp, decomp, fan game and ROM-hack tool, if you want to grab a build yourself
Save backups — mirror emulator/PC-port saves to the NAS (backup-saves) and restore them on a fresh remount (restore-saves)
Rebuild Runbook — from-scratch rebuild, opt-in tags, standalone playbooks
External Installers — download inventory for the opt-in Windows/Wine games and tools
ogm launcher integration — omarchy-games-menu catalog fragment, ogm scan hooks
Unsupported / parked games — games/mods we couldn't get working; the detailed trail lives in GitHub issues
Forza database editing — edit FM4/FM2 car prices & economy in gamedb.slt; swap PFP career/easy (Sandbox) modes; revert
Atari ST / Hatari — focused installation, BIOS setup and mandatory validation
Mods, patches & HD textures:
install_<game>_mods roles, shared loaders, GUI-tool/deferred items, and Proton gotchasWindows / Wine games:
Arcade & ray-traced ports:
Xbox 360 & per-game tuning:
Historical notes:
This repo does not provide ROMs, BIOS files, firmware, keys, or game packages.
Playbooks only detect, link, and configure files that already exist on your machine. They should not delete ROMs, BIOS, saves, firmware, or game data.
Generated emulator state, shader caches, saves, logs, firmware modules, and ROMs must not be committed.
480 commits
6 commits
Shell
43.8%
Python
41.6%
Jinja
11.5%
C
2.2%