Merge pull request #435 from outis1one/claude/wolf-pair-port-conflict-7nz8qg
Claude/wolf pair port conflict 7nz8qg
This commit is contained in:
+249
-8
@@ -325,6 +325,7 @@ EOF
|
|||||||
echo " and Wii U (Cemu) in ES-DE via a second, opt-in 'Alternative emulators' command"
|
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 " - 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 " 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)"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1391,6 +1392,49 @@ PS2XMLPY
|
|||||||
log_success "PS2: added PCEE2 as the default RetroArch core (custom_systems/es_systems.xml) — ES-DE's"
|
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)"
|
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_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.
|
||||||
|
mkdir -p "$GAME_STORAGE_DIR/esde-settings"
|
||||||
|
_ESDE_SETTINGS="$GAME_STORAGE_DIR/esde-settings/es_settings.xml"
|
||||||
|
backup_if_exists "$_ESDE_SETTINGS"
|
||||||
|
python3 - "$_ESDE_SETTINGS" << 'ESDESETTINGSPY'
|
||||||
|
import re, sys
|
||||||
|
path = sys.argv[1]
|
||||||
|
try:
|
||||||
|
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
|
||||||
|
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)"
|
||||||
|
|
||||||
# ── App selection ─────────────────────────────────────────────────────────
|
# ── App selection ─────────────────────────────────────────────────────────
|
||||||
echo ""
|
echo ""
|
||||||
echo "═══════════════════════════════════════════════════════"
|
echo "═══════════════════════════════════════════════════════"
|
||||||
@@ -1941,7 +1985,23 @@ CATALOG = {
|
|||||||
f'{games}/retroarch:/home/retro/.config/retroarch:rw',
|
f'{games}/retroarch:/home/retro/.config/retroarch:rw',
|
||||||
f'{games}/emulators:/mnt/games/emulators: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'],
|
f'{games}/esde-custom-systems:/home/retro/ES-DE/custom_systems:rw',
|
||||||
|
# ~/ES-DE (settings, gamelists, downloaded_media, logs) has
|
||||||
|
# NO mount at all otherwise (confirmed against ES-DE's own
|
||||||
|
# source and GOW's es-de startup.sh: getAppDataDirectory()
|
||||||
|
# is a plain $HOME/ES-DE, no XDG redirect) — Wolf normally
|
||||||
|
# reuses the same app container across sessions rather than
|
||||||
|
# recreating it each time (confirmed against Wolf's own
|
||||||
|
# docker.cpp: it only removes the container on session end
|
||||||
|
# if WOLF_STOP_CONTAINER_ON_EXIT=TRUE, which this repo never
|
||||||
|
# sets), so this doesn't get wiped every reconnect — but it
|
||||||
|
# IS lost on any real reinstall/container recreate, unlike
|
||||||
|
# everything else here which lives on the game drive. Only
|
||||||
|
# mounting settings/ specifically (not the whole ~/ES-DE
|
||||||
|
# tree) keeps this additive and non-breaking alongside the
|
||||||
|
# existing custom_systems mount above — gamelists/scraped
|
||||||
|
# media durability is a separate, not-yet-done improvement.
|
||||||
|
f'{games}/esde-settings:/home/retro/ES-DE/settings:rw'],
|
||||||
env=ESDE_ENV, cap_add=STD_CAP, security_opt=[], ipc_mode='host',
|
env=ESDE_ENV, cap_add=STD_CAP, security_opt=[], ipc_mode='host',
|
||||||
ulimits=[], privileged=False,
|
ulimits=[], privileged=False,
|
||||||
devices=['/dev/uinput:/dev/uinput'],
|
devices=['/dev/uinput:/dev/uinput'],
|
||||||
@@ -3415,14 +3475,17 @@ print(next(iter(ids)) if len(ids) == 1 else '')
|
|||||||
if [ -n "$ACTIVE_CLIENT_ID" ]; then
|
if [ -n "$ACTIVE_CLIENT_ID" ]; then
|
||||||
CLIENT_ID="$ACTIVE_CLIENT_ID"
|
CLIENT_ID="$ACTIVE_CLIENT_ID"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Exactly one client is actively streaming right now — using that one."
|
echo "Exactly one Moonlight session (device/TV) is actively streaming right"
|
||||||
|
echo "now — using that one. (This is about which SCREEN/DEVICE you're"
|
||||||
|
echo "configuring, not how many controllers are plugged into it — that's"
|
||||||
|
echo "the next question.)"
|
||||||
elif [ "${#CLIENT_IDS[@]}" -eq 1 ]; then
|
elif [ "${#CLIENT_IDS[@]}" -eq 1 ]; then
|
||||||
CLIENT_ID="${CLIENT_IDS[0]}"
|
CLIENT_ID="${CLIENT_IDS[0]}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Only one paired client — using it."
|
echo "Only one paired Moonlight device — using it."
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
read -r -p "Which client [1-${#CLIENT_IDS[@]}]: " PICK
|
read -r -p "Which Moonlight session/device [1-${#CLIENT_IDS[@]}]: " PICK
|
||||||
if ! [[ "$PICK" =~ ^[0-9]+$ ]] || [ "$PICK" -lt 1 ] || [ "$PICK" -gt "${#CLIENT_IDS[@]}" ]; then
|
if ! [[ "$PICK" =~ ^[0-9]+$ ]] || [ "$PICK" -lt 1 ] || [ "$PICK" -gt "${#CLIENT_IDS[@]}" ]; then
|
||||||
echo "Invalid selection."
|
echo "Invalid selection."
|
||||||
exit 1
|
exit 1
|
||||||
@@ -3430,8 +3493,64 @@ print(next(iter(ids)) if len(ids) == 1 else '')
|
|||||||
CLIENT_ID="${CLIENT_IDS[$((PICK-1))]}"
|
CLIENT_ID="${CLIENT_IDS[$((PICK-1))]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Wolf's own logs record "Creating <TYPE> joypad for controller <N>"
|
||||||
|
# every time it creates a virtual pad (confirmed live against real
|
||||||
|
# log output) — polling this gives real, human-readable context per
|
||||||
|
# slot instead of asking the user to guess or watch logs by hand
|
||||||
|
# themselves. Wolf's own wording is 0-indexed ("controller 0",
|
||||||
|
# "controller 1"); every prompt in this tool is deliberately
|
||||||
|
# 1-indexed instead ("1st controller", "2nd controller"...) —
|
||||||
|
# confirmed live that mixing the two ("exactly one CLIENT is
|
||||||
|
# active" read as "exactly one CONTROLLER" right above a
|
||||||
|
# 0-indexed-sounding prompt) is a real, easy misread. "1st
|
||||||
|
# controller" here always means Wolf's "controller 0", "2nd" means
|
||||||
|
# "controller 1", and so on — stated explicitly at every prompt so
|
||||||
|
# the two numbering schemes never have to be reconciled in your head.
|
||||||
|
#
|
||||||
|
# NOTE: this only tells you what TYPE Wolf most recently created
|
||||||
|
# for a given slot NUMBER — it can't tell you which PHYSICAL
|
||||||
|
# controller that was, and it can't let you reassign a physical
|
||||||
|
# controller to a different slot number. Which controller becomes
|
||||||
|
# slot 0 vs. slot 1 is decided entirely by Moonlight (the client),
|
||||||
|
# upstream of Wolf, based on connection order — not something this
|
||||||
|
# override (or Wolf's API at all) can control.
|
||||||
|
_ordsuffix() {
|
||||||
|
case "$1" in
|
||||||
|
1) echo "st" ;;
|
||||||
|
2) echo "nd" ;;
|
||||||
|
3) echo "rd" ;;
|
||||||
|
*) echo "th" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
echo ""
|
echo ""
|
||||||
read -r -p "How many controller slots to force a type for [2]: " NSLOTS
|
echo "Checking Wolf's logs for controllers it has already created a pad for..."
|
||||||
|
declare -A LAST_SEEN_TYPE
|
||||||
|
while IFS=$'\t' read -r cnum ctype; do
|
||||||
|
[ -n "$cnum" ] && LAST_SEEN_TYPE["$cnum"]="$ctype"
|
||||||
|
done < <(docker compose logs wolf 2>/dev/null | python3 -c "
|
||||||
|
import re, sys
|
||||||
|
for line in sys.stdin:
|
||||||
|
m = re.search(r'Creating (\w+) joypad for controller (\d+)', line)
|
||||||
|
if m:
|
||||||
|
print(f'{m.group(2)}\t{m.group(1).upper()}')
|
||||||
|
")
|
||||||
|
if [ "${#LAST_SEEN_TYPE[@]}" -gt 0 ]; then
|
||||||
|
echo "Last type Wolf created, per controller (most recent reconnect wins):"
|
||||||
|
for cnum in $(printf '%s\n' "${!LAST_SEEN_TYPE[@]}" | sort -n); do
|
||||||
|
_n=$((cnum + 1))
|
||||||
|
echo " Your ${_n}$(_ordsuffix "$_n") controller (Wolf calls it \"controller $cnum\"): last seen as ${LAST_SEEN_TYPE[$cnum]}"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "No controllers found in Wolf's logs yet — connect them and start a"
|
||||||
|
echo "stream first if you want this list populated (not required, you can"
|
||||||
|
echo "still answer blind below)."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Now, separately: how many physical GAMEPADS/CONTROLLERS do you have"
|
||||||
|
echo "connected to that device right now (this tool can't detect that —"
|
||||||
|
echo "count your own controllers)?"
|
||||||
|
read -r -p "Number of controllers [2]: " NSLOTS
|
||||||
NSLOTS="${NSLOTS:-2}"
|
NSLOTS="${NSLOTS:-2}"
|
||||||
if ! [[ "$NSLOTS" =~ ^[0-9]+$ ]] || [ "$NSLOTS" -lt 1 ]; then
|
if ! [[ "$NSLOTS" =~ ^[0-9]+$ ]] || [ "$NSLOTS" -lt 1 ]; then
|
||||||
echo "Invalid number."
|
echo "Invalid number."
|
||||||
@@ -3440,8 +3559,16 @@ print(next(iter(ids)) if len(ids) == 1 else '')
|
|||||||
|
|
||||||
OVERRIDE_TYPES=()
|
OVERRIDE_TYPES=()
|
||||||
for i in $(seq 1 "$NSLOTS"); do
|
for i in $(seq 1 "$NSLOTS"); do
|
||||||
read -r -p " Slot $i type (AUTO/XBOX/PS/NINTENDO) [AUTO]: " T
|
cnum=$((i - 1))
|
||||||
T="${T:-AUTO}"
|
SEEN="${LAST_SEEN_TYPE[$cnum]:-}"
|
||||||
|
DEFAULT="${SEEN:-AUTO}"
|
||||||
|
SUF="$(_ordsuffix "$i")"
|
||||||
|
if [ -n "$SEEN" ]; then
|
||||||
|
read -r -p " Your ${i}${SUF} controller (controller $cnum, last seen as $SEEN) — force to which type? (AUTO/XBOX/PS/NINTENDO) [$DEFAULT]: " T
|
||||||
|
else
|
||||||
|
read -r -p " Your ${i}${SUF} controller (controller $cnum, not seen yet) — force to which type? (AUTO/XBOX/PS/NINTENDO) [AUTO]: " T
|
||||||
|
fi
|
||||||
|
T="${T:-$DEFAULT}"
|
||||||
T="$(echo "$T" | tr '[:lower:]' '[:upper:]')"
|
T="$(echo "$T" | tr '[:lower:]' '[:upper:]')"
|
||||||
case "$T" in
|
case "$T" in
|
||||||
AUTO|XBOX|PS|NINTENDO) ;;
|
AUTO|XBOX|PS|NINTENDO) ;;
|
||||||
@@ -3603,7 +3730,23 @@ CATALOG = {
|
|||||||
f'{games}/retroarch:/home/retro/.config/retroarch:rw',
|
f'{games}/retroarch:/home/retro/.config/retroarch:rw',
|
||||||
f'{games}/emulators:/mnt/games/emulators: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'],
|
f'{games}/esde-custom-systems:/home/retro/ES-DE/custom_systems:rw',
|
||||||
|
# ~/ES-DE (settings, gamelists, downloaded_media, logs) has
|
||||||
|
# NO mount at all otherwise (confirmed against ES-DE's own
|
||||||
|
# source and GOW's es-de startup.sh: getAppDataDirectory()
|
||||||
|
# is a plain $HOME/ES-DE, no XDG redirect) — Wolf normally
|
||||||
|
# reuses the same app container across sessions rather than
|
||||||
|
# recreating it each time (confirmed against Wolf's own
|
||||||
|
# docker.cpp: it only removes the container on session end
|
||||||
|
# if WOLF_STOP_CONTAINER_ON_EXIT=TRUE, which this repo never
|
||||||
|
# sets), so this doesn't get wiped every reconnect — but it
|
||||||
|
# IS lost on any real reinstall/container recreate, unlike
|
||||||
|
# everything else here which lives on the game drive. Only
|
||||||
|
# mounting settings/ specifically (not the whole ~/ES-DE
|
||||||
|
# tree) keeps this additive and non-breaking alongside the
|
||||||
|
# existing custom_systems mount above — gamelists/scraped
|
||||||
|
# media durability is a separate, not-yet-done improvement.
|
||||||
|
f'{games}/esde-settings:/home/retro/ES-DE/settings:rw'],
|
||||||
env=ESDE_ENV, cap_add=STD_CAP, security_opt=[], ipc_mode='host',
|
env=ESDE_ENV, cap_add=STD_CAP, security_opt=[], ipc_mode='host',
|
||||||
ulimits=[], privileged=False,
|
ulimits=[], privileged=False,
|
||||||
devices=['/dev/uinput:/dev/uinput'],
|
devices=['/dev/uinput:/dev/uinput'],
|
||||||
@@ -4108,6 +4251,31 @@ once (Wolf doesn't dedupe repeated pairings of the same device) — every
|
|||||||
duplicate of an active ID is tagged ACTIVE together, so it doesn't matter
|
duplicate of an active ID is tagged ACTIVE together, so it doesn't matter
|
||||||
which one you'd have picked by hand.
|
which one you'd have picked by hand.
|
||||||
|
|
||||||
|
**It labels controllers "1st"/"2nd"/"3rd"/"4th" — always meaning Wolf's own
|
||||||
|
"controller 0"/"controller 1"/"controller 2"/"controller 3".** Wolf's own
|
||||||
|
log wording is 0-indexed; this tool is deliberately 1-indexed throughout
|
||||||
|
so the two numbering schemes never have to be reconciled in your head
|
||||||
|
(confirmed live that mixing them — reading "exactly one client is
|
||||||
|
active" as "exactly one controller" right above a 0-indexed-sounding
|
||||||
|
prompt — is a real, easy misread).
|
||||||
|
|
||||||
|
Before asking anything, it polls \`docker compose logs wolf\` for every
|
||||||
|
\`Creating <TYPE> joypad for controller <N>\` line Wolf has ever logged
|
||||||
|
(most recent per slot wins) and shows you what it last saw, e.g.:
|
||||||
|
\`\`\`
|
||||||
|
Your 1st controller (Wolf calls it "controller 0"): last seen as NINTENDO
|
||||||
|
Your 2nd controller (Wolf calls it "controller 1"): last seen as XBOX
|
||||||
|
\`\`\`
|
||||||
|
— then uses that as the suggested default at each prompt, so if nothing's
|
||||||
|
changed you can just hit Enter through them. **This can't tell you which
|
||||||
|
physical controller became which slot, and it can't let you reassign
|
||||||
|
one** — which controller becomes slot 0 vs. slot 1 is decided entirely by
|
||||||
|
Moonlight (the client), based on connection order, upstream of Wolf and
|
||||||
|
this tool alike. If you need to know that for certain, connect your
|
||||||
|
controllers one at a time while following the log live
|
||||||
|
(\`docker compose logs -f wolf | grep -i controller\`) — you'll see
|
||||||
|
exactly which slot number each one becomes as it connects.
|
||||||
|
|
||||||
Then it asks how many controllers to configure and what type to force
|
Then it asks how many controllers to configure and what type to force
|
||||||
each one to. There are only **3 concrete types** (confirmed against Wolf's own
|
each one to. There are only **3 concrete types** (confirmed against Wolf's own
|
||||||
virtual-pad source, \`inputtino\`) — not one per real controller brand:
|
virtual-pad source, \`inputtino\`) — not one per real controller brand:
|
||||||
@@ -4163,6 +4331,41 @@ regardless of which type it's sharing a GUID with. This is a reasoned
|
|||||||
workaround, not one confirmed working live — if it doesn't pan out,
|
workaround, not one confirmed working live — if it doesn't pan out,
|
||||||
that's useful to know.
|
that's useful to know.
|
||||||
|
|
||||||
|
## ES-DE launches a second game while one is already running
|
||||||
|
**Symptom** (confirmed live, not Cemu-specific — happens on any system):
|
||||||
|
a second controller's input reaches ES-DE's own menu in the background
|
||||||
|
and launches an entirely different game — you'll hear/see it start
|
||||||
|
playing underneath whatever already has focus.
|
||||||
|
|
||||||
|
**Cause:** ES-DE's own **"Run in background (while game is launched)"**
|
||||||
|
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.
|
||||||
|
|
||||||
|
**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**.
|
||||||
|
|
||||||
|
**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
|
||||||
|
game drive at all before this — confirmed against ES-DE's own source
|
||||||
|
(\`getAppDataDirectory()\` is a plain \`$HOME/ES-DE\`, no XDG redirect) and
|
||||||
|
GOW's own \`es-de\` startup script. In normal day-to-day use this mostly
|
||||||
|
didn't matter, since Wolf reuses the same app container across sessions
|
||||||
|
rather than recreating it each time (confirmed against Wolf's own
|
||||||
|
\`docker.cpp\`: the container is only removed on session end if
|
||||||
|
\`WOLF_STOP_CONTAINER_ON_EXIT=TRUE\`, which this repo never sets) — but it
|
||||||
|
meant this setting, and everything else under \`~/ES-DE\`, wasn't safe
|
||||||
|
across an actual reinstall or container recreate the way roms/saves/BIOS
|
||||||
|
already are. Only \`settings/\` is mounted now (\`esde-settings/\`, additive,
|
||||||
|
doesn't touch the existing \`custom_systems\` mount) — gamelists and
|
||||||
|
scraped media durability is a related gap, not yet fixed.
|
||||||
|
|
||||||
## EA games (Battlefront II 2017, etc.)
|
## EA games (Battlefront II 2017, etc.)
|
||||||
EA titles require GE-Proton and the EA App to be installed inside the Wine
|
EA titles require GE-Proton and the EA App to be installed inside the Wine
|
||||||
prefix. The EA App handles authentication — without it, the game launches
|
prefix. The EA App handles authentication — without it, the game launches
|
||||||
@@ -4391,6 +4594,44 @@ time Cemu launches from ES-DE too.
|
|||||||
characters?** That's not a Cemu-specific bug — see
|
characters?** That's not a Cemu-specific bug — see
|
||||||
"Multiple controllers" above (\`./manage.sh controllers\`).
|
"Multiple controllers" above (\`./manage.sh controllers\`).
|
||||||
|
|
||||||
|
**If Input Settings' Save button is cut off the bottom of the screen**
|
||||||
|
(confirmed live: happens even maximized, at higher resolutions, and
|
||||||
|
closing the window doesn't save — Cemu's Input Settings dialog is a
|
||||||
|
fixed size, not resizable, and can genuinely be taller than the session's
|
||||||
|
viewport) — try moving the dialog first: hold **Alt** and **left-click-drag
|
||||||
|
anywhere inside it** (not just the titlebar) to reposition it upward, or
|
||||||
|
use xfwm4's own **Alt+F7** (grab-to-move, drop with click or Enter) if
|
||||||
|
that doesn't work. Either is a plain X11/XFCE window-manager trick, not
|
||||||
|
Cemu-specific, and usually the fastest fix.
|
||||||
|
|
||||||
|
**If that still doesn't work, or you'd rather skip the GUI entirely: edit
|
||||||
|
the controller profile file directly.** Cemu's per-slot controller config
|
||||||
|
isn't inside the Docker container at all — it's plain XML on the game
|
||||||
|
drive (Desktop and ES-DE both mount \`~/.config\` from the same place):
|
||||||
|
\`\`\`bash
|
||||||
|
GAME_DIR=\$(grep '^GAME_STORAGE_DIR=' $WOLF_DIR/.env | cut -d= -f2-)
|
||||||
|
ls "\$GAME_DIR/retro-home/Cemu/controllerProfiles/"
|
||||||
|
\`\`\`
|
||||||
|
File naming is 0-indexed the same way Wolf's own controller numbering is
|
||||||
|
(yet another place this comes up) — \`controller0.xml\` is Cemu's
|
||||||
|
**Controller 1**, \`controller1.xml\` is **Controller 2**, and so on.
|
||||||
|
Each holds one or more \`<controller>\` blocks (one per SDL device that's
|
||||||
|
ever been assigned to that slot, identified by its own \`<uuid>\`/
|
||||||
|
\`<display_name>\`) with a \`<mappings>\` list of \`<mapping>\`/\`<button>\`
|
||||||
|
pairs. **Confirmed against real captured profiles from different
|
||||||
|
controller brands: these values are universal SDL_CONTROLLER_BUTTON_*
|
||||||
|
semantics, not raw per-device button indices** — so a complete, working
|
||||||
|
\`<mappings>\` block can be copied verbatim from one \`<controller>\` entry
|
||||||
|
into a different device's empty one in the same file (e.g. a
|
||||||
|
newly-selected device whose Save got cut off, leaving it with
|
||||||
|
\`<mappings />\` and nothing bound) without touching Cemu's GUI at all. If
|
||||||
|
a slot ends up with more than one \`<controller>\` block and only one
|
||||||
|
device is actually in use, deleting the stale block(s) removes any
|
||||||
|
ambiguity about which one Cemu picks. Back up the file first
|
||||||
|
(\`cp controllerN.xml controllerN.xml.bak\`) before hand-editing; no
|
||||||
|
\`sudo\` needed, these files are written world-writable by Cemu itself.
|
||||||
|
Close Cemu completely and relaunch for a hand-edited profile to take effect.
|
||||||
|
|
||||||
ROMs are mounted at \`/ROMs\` inside Desktop too, so Cemu's own File → Load
|
ROMs are mounted at \`/ROMs\` inside Desktop too, so Cemu's own File → Load
|
||||||
can browse straight to \`/ROMs/wiiu/\` without needing ES-DE at all.
|
can browse straight to \`/ROMs/wiiu/\` without needing ES-DE at all.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user