Fix real regression: ES-DE Run-in-background patch broke ROM discovery

Confirmed live on a real install: after the previous commit, ES-DE found
zero games on every system. Root-caused by walking GOW's own
apps/es-de/build/scripts/startup.sh line by line: GOW's image bakes a
FULL es_settings.xml template (100+ settings, including
ROMDirectory=/ROMs, confirmed against the real template file in the
games-on-whales/gow repo) and its own startup script copies that
template into place exactly once, the very first time the container
starts, gated on the settings file not already existing.

The previous fix pre-created a minimal stub file (containing only
RunInBackground) before the container had ever started - GOW's startup
script saw that file "already there", skipped writing its own template
entirely, and ES-DE fell back to vanilla upstream defaults for
everything else in that file, including ROMDirectory, which is not
/ROMs by default. Every system's games vanished as a result.

Also corrects an earlier wrong claim in both the code comment and
README: ES-DE's own *compiled* default for RunInBackground is false, but
GOW's own template deliberately sets it to true - that's the real,
confirmed source of the original background-launch bug, not an
accidental toggle as previously assumed.

Fix: only ever patch an es_settings.xml that already exists with real
content (`[ -s "$_ESDE_SETTINGS" ]`) - never create one. On a genuinely
fresh install, before EmulationStation has ever launched once, the
installer now says so explicitly and defers rather than guessing, with
clear instructions to connect once and re-run. Verified against GOW's
actual real template: the patch flips just RunInBackground (line count
unchanged, ROMDirectory and everything else untouched), is idempotent on
re-run, and the skip-when-absent gate was verified directly against both
the missing-file and populated-file cases.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLX1yYKJExGSXmgUhxKQG6
This commit is contained in:
Claude
2026-09-03 18:15:50 +00:00
parent c57f760fdc
commit 52207598b9
+62 -37
View File
@@ -325,7 +325,8 @@ EOF
echo " and Wii U (Cemu) in ES-DE via a second, opt-in 'Alternative emulators' command"
echo " - Expose Wolf's REST API socket to the host (WOLF_SOCKET_PATH + /var/run/wolf mount)"
echo " so './manage.sh controllers' can force distinct pad types per controller slot"
echo " - Force ES-DE's 'Run in background' off durably (mounts + writes esde-settings/es_settings.xml)"
echo " - Mount ~/ES-DE/settings durably + force 'Run in background' off (only once"
echo " GOW's own es_settings.xml template already exists — never pre-created)"
return 0
fi
@@ -1392,48 +1393,56 @@ PS2XMLPY
log_success "PS2: added PCEE2 as the default RetroArch core (custom_systems/es_systems.xml) — ES-DE's"
log_info "own build doesn't ship it yet (added upstream in the not-yet-released 3.5.0)"
# ── ES-DE: force "Run in background" off ────────────────────────────────
# ES-DE's own compiled default for this IS already off (confirmed against
# its real Settings.cpp: mBoolMap["RunInBackground"] = {false, false}) —
# this write exists purely so that default stays durable and explicit
# rather than relying on it never having been toggled. Real, confirmed
# cause of a genuine bug otherwise: with it on, ES-DE keeps running and
# listening to every controller even after a game/emulator has launched
# and taken visual focus a second controller's input can still reach
# ES-DE's own menu in the background and launch (and start playing audio
# for) a completely different game while the first one is still up
# front. ES-DE's own USERGUIDE.md explicitly names this failure mode
# ("make sure that the setting Run in background... is disabled").
# Confirmed live: this affects any system, not just Cemu.
# ── ES-DE: force "Run in background" off (once GOW's own template exists) ──
# GOW's own image bakes a FULL es_settings.xml template (100+ settings —
# confirmed against apps/es-de/build/configs/es/es_settings.xml in the
# games-on-whales/gow repo) that deliberately sets RunInBackground=true
# (NOT ES-DE's own compiled default, which is false — GOW's template is
# what actually causes the real, confirmed cross-system bug this exists
# to fix: with it on, ES-DE keeps listening to every controller even
# after a game/emulator has focus, so a second controller's input can
# reach ES-DE's own menu and launch a different game underneath whatever
# is already running). GOW's own startup.sh copies that template exactly
# ONCE, the very first time the container starts, gated on
# `test -f $ES_CFG_DIR/settings/es_settings.xml` — if a file is already
# sitting there, GOW's own copy is skipped entirely and ES-DE falls back
# to its own vanilla defaults for EVERYTHING ELSE in that file, including
# ROMDirectory (GOW's template sets it to the /ROMs this whole repo
# mounts games at; ES-DE's own default is not that).
#
# es_settings.xml is the user's OWN full settings state (theme, scraper
# prefs, everything) — unlike es_systems.xml this is never a full
# rewrite, only a surgical strip-and-reappend of this one <bool> entry,
# same idempotent pattern as everywhere else in this file. Written as a
# plain top-level element with no <settings> wrapper, matching what
# ES-DE's own Settings::saveFile() actually produces today (confirmed
# against its source — the "wrap everything in <settings>" format is
# loader-side forward-compatibility for a future ES-DE release, not
# what gets written now); either format loads fine either way.
# CONFIRMED LIVE, THE HARD WAY: an earlier version of this exact step
# pre-created a MINIMAL stub file (containing only the RunInBackground
# line) before the container had ever started — GOW's startup.sh saw
# that file "already existing", skipped its own copy, and ES-DE's
# ROMDirectory silently fell back to a default that isn't /ROMs, finding
# zero games on every single system. Root-caused by walking GOW's own
# startup.sh line by line against a real "ES-DE finds no game files"
# report. Never pre-create this file — only ever patch an ALREADY
# existing one (i.e. one GOW's own bootstrap has already populated in
# full, meaning ES-DE has been launched via Moonlight at least once).
mkdir -p "$GAME_STORAGE_DIR/esde-settings"
_ESDE_SETTINGS="$GAME_STORAGE_DIR/esde-settings/es_settings.xml"
if [ -s "$_ESDE_SETTINGS" ]; then
backup_if_exists "$_ESDE_SETTINGS"
python3 - "$_ESDE_SETTINGS" << 'ESDESETTINGSPY'
import re, sys
path = sys.argv[1]
try:
with open(path) as f:
with open(path) as f:
content = f.read()
except FileNotFoundError:
content = ''
content = re.sub(r'[ \t]*<bool name="RunInBackground" value="[^"]*"[ \t]*/>[ \t]*\n?', '', content)
line = ' <bool name="RunInBackground" value="false" />\n'
content = (content.rstrip('\n') + '\n' + line) if content.strip() else line
line = '<bool name="RunInBackground" value="false" />\n'
content = content.rstrip('\n') + '\n' + line
with open(path, 'w') as f:
f.write(content)
ESDESETTINGSPY
chown "$ACTUAL_USER:$ACTUAL_USER" "$_ESDE_SETTINGS"
log_success "ES-DE: 'Run in background (while game is launched)' forced off (esde-settings/es_settings.xml)"
else
log_info "ES-DE: 'Run in background' fix deferred — esde-settings/es_settings.xml doesn't"
log_info "exist yet (GOW writes its real, full template the first time EmulationStation"
log_info "actually launches). Connect to it via Moonlight once, then re-run"
log_info "'sudo ./setup.sh wolf' to apply this fix without touching anything else."
fi
# ── App selection ─────────────────────────────────────────────────────────
echo ""
@@ -4359,15 +4368,31 @@ playing underneath whatever already has focus.
setting. When it's on, ES-DE keeps running and listening to every
controller even after something else has launched and taken visual
focus — ES-DE's own USERGUIDE.md names this exact failure mode directly.
ES-DE's compiled default for this is already off, but nothing durably
enforced that in this setup before now, so it's easy for it to have
gotten toggled on at some point and stick that way.
ES-DE's own *compiled* default for this is off but GOW's own bundled
\`es_settings.xml\` template (baked into \`ghcr.io/games-on-whales/es-de\`)
deliberately sets it **on**, which is the actual, confirmed source of the
default behavior here.
**This installer now forces it off automatically** (\`esde-settings/es_settings.xml\`,
written fresh on every install/reinstall) — no menu digging required. If
you're on an install from before this existed, re-run \`sudo ./setup.sh wolf\`
to pick it up, or set it by hand: **Main Menu → Other Settings → Run in
background (while game is launched) → off**.
**This installer forces it back off** by patching \`esde-settings/es_settings.xml\`
— but only an *already-populated* copy of that file, never by creating one
itself. That distinction matters: GOW's own container startup script only
writes its real template (100+ settings, including where ES-DE looks for
your ROMs) the very first time EmulationStation actually launches, gated
on that file not already existing — pre-creating even a minimal version of
it ourselves, before that first launch, would make GOW skip writing its
own template entirely and leave ES-DE on vanilla upstream defaults for
everything else in that file. **Confirmed live, the hard way:** an earlier
version of this exact fix did precisely that, and ROM discovery broke
completely (every system, not just one) because ES-DE's ROM path fell
back to something other than \`/ROMs\`.
So in practice: if you've already launched EmulationStation via Moonlight
at least once, re-running \`sudo ./setup.sh wolf\` applies this immediately.
**If you haven't yet** (a genuinely fresh install), the installer says so
and skips the patch rather than guessing — connect to EmulationStation
once first, then re-run \`sudo ./setup.sh wolf\`. Setting it by hand works
too, any time: **Main Menu → Other Settings → Run in background (while
game is launched) → off**.
**Why this needed its own mount, not just a one-time write:** \`~/ES-DE\`
(settings, gamelists, scraped artwork, logs) had no bind mount onto the