feat: add standalone SWBF2 2017 setup scripts for Wolf and native Linux Steam
Two self-contained scripts for getting SWBF2 (2017, AppID 1237950) working with GE-Proton on Linux — no dependency on the ubuntu-post-install framework. setup-swbf2-wolf.sh — for Wolf/Games-on-Whales + Moonlight streaming setup-swbf2-linux.sh — for native Linux Steam (no Docker) Both implement the same core fix: - msiextract bypass for JunoConfigureRegistry Wine incompatibility - EA Desktop files copied into Wine prefix from extracted MSI - link2ea_fix.reg + ea_services.reg written to drive_c - Launch wrapper that imports .reg files via Proton on every launch (direct system.reg edits are overwritten by wineserver on shutdown) Wolf version also handles Docker cp, container paths, STEAM_UNIX_SOCKET, and localconfig.vdf directory locking inside the Wolf state folder. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
This commit is contained in:
Executable
+255
@@ -0,0 +1,255 @@
|
||||
#!/bin/bash
|
||||
# setup-swbf2-linux.sh — Fix Star Wars Battlefront II (2017, AppID 1237950)
|
||||
# for native Linux Steam with GE-Proton (no Wolf / no Docker).
|
||||
#
|
||||
# What this does:
|
||||
# 1. Extracts EA Desktop from the bundled ea_app.msi using msiextract —
|
||||
# bypasses JunoConfigureRegistry, a .NET custom action Wine cannot run,
|
||||
# which causes the full MSI installer to roll back.
|
||||
# 2. Copies EA Desktop files (Link2EA.exe, EALocalHostSvc.exe, etc.) into the
|
||||
# game's Wine prefix.
|
||||
# 3. Writes link2ea_fix.reg and ea_services.reg into drive_c so they survive
|
||||
# Wine prefix operations.
|
||||
# 4. Installs a launch wrapper that imports the .reg files via Proton's own
|
||||
# wine binary on every launch — required because direct edits to system.reg
|
||||
# are overwritten when wineserver flushes to disk on shutdown.
|
||||
# 5. Sets Steam launch options for SWBF2.
|
||||
#
|
||||
# Prerequisites — do these BEFORE running this script:
|
||||
# a. GE-Proton10-34 (or later) installed via ProtonUp-Qt or manually.
|
||||
# In Steam: SWBF2 → Properties → Compatibility → Force GE-Proton.
|
||||
# b. msitools installed:
|
||||
# sudo apt-get install -y msitools # Debian/Ubuntu
|
||||
# sudo dnf install -y msitools # Fedora
|
||||
# c. Launch SWBF2 once — wait ~10 seconds for the "Origin is not installed"
|
||||
# error, then close it. This creates the Wine prefix and drops ea_app.msi.
|
||||
# d. Your EA account is linked to your Steam account at ea.com (one-time;
|
||||
# persists on EA's servers across reinstalls).
|
||||
#
|
||||
# After this script completes:
|
||||
# Launch SWBF2. Let Vulkan shaders compile on first run (several minutes,
|
||||
# only once). EA App authenticates via your linked Steam/EA account.
|
||||
#
|
||||
# Usage:
|
||||
# chmod +x setup-swbf2-linux.sh
|
||||
# ./setup-swbf2-linux.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
APPID="1237950"
|
||||
WRAPPER_PATH="$HOME/.local/bin/ea_install.sh"
|
||||
|
||||
echo "=== SWBF2 (2017) Linux Steam Setup ==="
|
||||
echo ""
|
||||
|
||||
# ── Locate Steam home ───────────────────────────────────────────────────────
|
||||
# Steam can live in either of two locations depending on install method.
|
||||
find_steam_home() {
|
||||
for candidate in \
|
||||
"$HOME/.steam/steam" \
|
||||
"$HOME/.local/share/Steam" \
|
||||
"$HOME/.var/app/com.valvesoftware.Steam/.steam/steam"; do
|
||||
if [ -d "$candidate/steamapps" ]; then
|
||||
echo "$candidate"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
STEAM_HOME=$(find_steam_home) || {
|
||||
echo "ERROR: Steam home not found. Is Steam installed and have you launched it at least once?"
|
||||
exit 1
|
||||
}
|
||||
echo "Steam home: $STEAM_HOME"
|
||||
|
||||
PFX_C="$STEAM_HOME/steamapps/compatdata/$APPID/pfx/drive_c"
|
||||
MSI="$PFX_C/ea_app.msi"
|
||||
|
||||
# ── Step 1: verify Wine prefix exists ──────────────────────────────────────
|
||||
echo ""
|
||||
if [ ! -d "$PFX_C" ]; then
|
||||
echo "ERROR: Wine prefix not found at $PFX_C"
|
||||
echo ""
|
||||
echo "Required before running this script:"
|
||||
echo " 1. In Steam: right-click SWBF2 → Properties → Compatibility"
|
||||
echo " → Force GE-Proton10-34 (or later)"
|
||||
echo " 2. Click Play on SWBF2 — wait ~10 seconds for 'Origin is not installed'"
|
||||
echo " 3. Close the error, then re-run this script"
|
||||
exit 1
|
||||
fi
|
||||
echo "[1/6] Wine prefix: OK"
|
||||
|
||||
# ── Step 2: verify ea_app.msi exists ───────────────────────────────────────
|
||||
if [ ! -f "$MSI" ]; then
|
||||
echo ""
|
||||
echo "ERROR: ea_app.msi not found at $MSI"
|
||||
echo ""
|
||||
echo "Launch SWBF2 once so Steam drops ea_app.msi into the Wine prefix."
|
||||
echo "You will see an 'Origin is not installed' error — that is expected."
|
||||
echo "Close it, then re-run this script."
|
||||
exit 1
|
||||
fi
|
||||
MSI_SIZE=$(stat -c%s "$MSI")
|
||||
if [ "$MSI_SIZE" -lt 50000000 ]; then
|
||||
echo "WARNING: ea_app.msi is only $MSI_SIZE bytes (expected ~227 MB)."
|
||||
echo "It may still be copying. Wait a moment and re-run."
|
||||
exit 1
|
||||
fi
|
||||
echo "[2/6] ea_app.msi ($(( MSI_SIZE / 1048576 )) MB): OK"
|
||||
|
||||
# ── Step 3: extract MSI on the host ────────────────────────────────────────
|
||||
echo "[3/6] Extracting EA Desktop files from MSI (~30s)..."
|
||||
if ! command -v msiextract >/dev/null 2>&1; then
|
||||
echo "ERROR: msitools not installed."
|
||||
echo " Debian/Ubuntu: sudo apt-get install -y msitools"
|
||||
echo " Fedora: sudo dnf install -y msitools"
|
||||
exit 1
|
||||
fi
|
||||
EXTRACT_DIR="/tmp/ea_app_extracted_$$"
|
||||
rm -rf "$EXTRACT_DIR"
|
||||
mkdir -p "$EXTRACT_DIR"
|
||||
if ! msiextract -C "$EXTRACT_DIR" "$MSI" >/dev/null 2>&1; then
|
||||
echo "ERROR: msiextract failed. Check that msitools is properly installed."
|
||||
rm -rf "$EXTRACT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
EA_SRC=$(find "$EXTRACT_DIR" -maxdepth 5 \
|
||||
-path "*/Electronic Arts/EA Desktop/EA Desktop" -type d 2>/dev/null | head -1)
|
||||
if [ -z "$EA_SRC" ] || [ ! -f "$EA_SRC/Link2EA.exe" ]; then
|
||||
echo "ERROR: Link2EA.exe not found after extraction. MSI structure may have changed."
|
||||
ls -la "$EXTRACT_DIR/Electronic Arts/EA Desktop/" 2>/dev/null || true
|
||||
rm -rf "$EXTRACT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
echo " $(ls "$EA_SRC" | wc -l) files extracted including Link2EA.exe"
|
||||
|
||||
# ── Step 4: copy EA Desktop files into Wine prefix ─────────────────────────
|
||||
echo "[4/6] Installing EA Desktop files into Wine prefix..."
|
||||
EA_DEST_BASE="$PFX_C/Program Files/Electronic Arts/EA Desktop"
|
||||
|
||||
# Use the version from a broken symlink left by a failed install, or default.
|
||||
EA_VERSION="14.2.0.3345"
|
||||
if [ -L "$EA_DEST_BASE/EA Desktop" ]; then
|
||||
_linked=$(readlink "$EA_DEST_BASE/EA Desktop" 2>/dev/null || true)
|
||||
[ -n "$_linked" ] && EA_VERSION="$_linked"
|
||||
fi
|
||||
|
||||
EA_DEST="$EA_DEST_BASE/$EA_VERSION"
|
||||
mkdir -p "$EA_DEST"
|
||||
cp -r "$EA_SRC/." "$EA_DEST/"
|
||||
|
||||
# Remove any stale symlink, then create a clean one
|
||||
rm -f "$EA_DEST_BASE/EA Desktop"
|
||||
ln -sf "$EA_VERSION" "$EA_DEST_BASE/EA Desktop"
|
||||
|
||||
if [ ! -f "$EA_DEST/Link2EA.exe" ]; then
|
||||
echo "ERROR: Copy failed — Link2EA.exe not found at $EA_DEST/Link2EA.exe"
|
||||
rm -rf "$EXTRACT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
echo " EA Desktop $EA_VERSION installed"
|
||||
rm -rf "$EXTRACT_DIR"
|
||||
|
||||
# ── Step 5: write .reg files and launch wrapper ─────────────────────────────
|
||||
echo "[5/6] Writing registry fix files and launch wrapper..."
|
||||
|
||||
# link2ea:// protocol handler — tells Wine how to find Link2EA.exe.
|
||||
# GE-Proton's steam.exe intercepts link2ea:// URLs and uses this handler
|
||||
# to launch Link2EA.exe, which hands off to EA Desktop for authentication.
|
||||
cat > "$PFX_C/link2ea_fix.reg" << 'REGEOF'
|
||||
Windows Registry Editor Version 5.00
|
||||
|
||||
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\link2ea]
|
||||
@="URL:link2ea Protocol"
|
||||
"URL Protocol"=""
|
||||
|
||||
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\link2ea\shell\open\command]
|
||||
@="\"C:\\Program Files\\Electronic Arts\\EA Desktop\\EA Desktop\\Link2EA.exe\" \"%1\""
|
||||
REGEOF
|
||||
|
||||
# EA Windows services — EALocalHostSvc provides local IPC that Link2EA.exe
|
||||
# needs. Without it launch fails with RPC_S_SERVER_UNAVAILABLE (0x800706ba).
|
||||
cat > "$PFX_C/ea_services.reg" << 'REGEOF'
|
||||
Windows Registry Editor Version 5.00
|
||||
|
||||
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EALocalHostSvc]
|
||||
"Type"=dword:00000010
|
||||
"Start"=dword:00000002
|
||||
"ErrorControl"=dword:00000001
|
||||
"ImagePath"="C:\\Program Files\\Electronic Arts\\EA Desktop\\EA Desktop\\EALocalHostSvc.exe"
|
||||
"DisplayName"="EA Local Host Service"
|
||||
"ObjectName"="LocalSystem"
|
||||
|
||||
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EABackgroundService]
|
||||
"Type"=dword:00000010
|
||||
"Start"=dword:00000002
|
||||
"ErrorControl"=dword:00000001
|
||||
"ImagePath"="C:\\Program Files\\Electronic Arts\\EA Desktop\\EA Desktop\\EABackgroundService.exe"
|
||||
"DisplayName"="EA Background Service"
|
||||
"ObjectName"="LocalSystem"
|
||||
REGEOF
|
||||
|
||||
# Launch wrapper. Runs regedit through Proton's launch chain on every launch
|
||||
# so registry entries survive wineserver restarts. Direct edits to system.reg
|
||||
# are overwritten when wineserver flushes to disk on shutdown.
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
cat > "$WRAPPER_PATH" << 'WRAPEOF'
|
||||
#!/bin/bash
|
||||
echo "=== launch $(date) ===" >> /tmp/ea_install.log
|
||||
"$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" "${10}" "${11}" regedit /S "C:\\link2ea_fix.reg"
|
||||
"$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" "${10}" "${11}" regedit /S "C:\\ea_services.reg"
|
||||
exec "$@"
|
||||
WRAPEOF
|
||||
chmod +x "$WRAPPER_PATH"
|
||||
echo " .reg files written, wrapper installed at $WRAPPER_PATH"
|
||||
|
||||
# ── Step 6: set launch options in localconfig.vdf ──────────────────────────
|
||||
echo "[6/6] Setting Steam launch options..."
|
||||
STEAM_UID=$(ls "$STEAM_HOME/userdata/" 2>/dev/null | head -1)
|
||||
if [ -z "$STEAM_UID" ]; then
|
||||
echo "WARNING: No Steam userdata found. Sign in to Steam first, then re-run."
|
||||
echo " Or set launch options manually — see below."
|
||||
else
|
||||
CFG_FILE="$STEAM_HOME/userdata/$STEAM_UID/config/localconfig.vdf"
|
||||
if [ ! -f "$CFG_FILE" ]; then
|
||||
echo "WARNING: localconfig.vdf not found. Launch Steam first, then re-run."
|
||||
else
|
||||
LAUNCH_OPT="$WRAPPER_PATH %command%"
|
||||
python3 - "$CFG_FILE" "$LAUNCH_OPT" << 'PYEOF'
|
||||
import sys, re
|
||||
path, opt = sys.argv[1], sys.argv[2]
|
||||
with open(path) as f:
|
||||
c = f.read()
|
||||
new = re.sub(r'("1237950".*?"LaunchOptions"\s*)"[^"]*"', rf'\1"{opt}"', c, flags=re.DOTALL)
|
||||
if new == c:
|
||||
new = re.sub(r'("1237950"\s*\n\s*\{)', rf'\1\n\t\t\t\t"LaunchOptions"\t\t"{opt}"', c)
|
||||
if new == c:
|
||||
print("WARNING: 1237950 block not found — set launch options manually (see below).")
|
||||
sys.exit(0)
|
||||
with open(path, 'w') as f:
|
||||
f.write(new)
|
||||
print(" LaunchOptions set.")
|
||||
PYEOF
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Setup complete ==="
|
||||
echo ""
|
||||
echo "Launch options set to: $WRAPPER_PATH %command%"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Launch SWBF2 from Steam"
|
||||
echo " 2. Let Vulkan shaders compile — do NOT skip (takes several minutes, once only)"
|
||||
echo " 3. EA App authenticates automatically if your Steam and EA accounts are linked"
|
||||
echo " 4. Game launches"
|
||||
echo ""
|
||||
echo "If launch options were not set automatically, set them in Steam:"
|
||||
echo " Right-click SWBF2 → Properties → Launch Options:"
|
||||
echo " $WRAPPER_PATH %command%"
|
||||
echo ""
|
||||
echo "Troubleshooting:"
|
||||
echo " Wrapper log: tail /tmp/ea_install.log"
|
||||
echo " Proton log: tail $STEAM_HOME/logs/steam_$APPID.log 2>/dev/null || \\"
|
||||
echo " tail \$(ls -t $STEAM_HOME/steamapps/compatdata/$APPID/../../../steam-$APPID.log 2>/dev/null | head -1)"
|
||||
Executable
+282
@@ -0,0 +1,282 @@
|
||||
#!/bin/bash
|
||||
# setup-swbf2-wolf.sh — Fix Star Wars Battlefront II (2017, AppID 1237950)
|
||||
# for Wolf / Games-on-Whales + Moonlight streaming.
|
||||
#
|
||||
# What this does:
|
||||
# 1. Extracts EA Desktop from the bundled ea_app.msi using msiextract on the
|
||||
# host — bypasses JunoConfigureRegistry, a .NET custom action that Wine
|
||||
# cannot run, which causes the full MSI installer to roll back.
|
||||
# 2. Copies EA Desktop files (Link2EA.exe, EALocalHostSvc.exe, etc.) into the
|
||||
# game's Wine prefix.
|
||||
# 3. Writes link2ea_fix.reg and ea_services.reg into drive_c so they survive
|
||||
# Wine prefix operations.
|
||||
# 4. Installs a launch wrapper that imports the .reg files via Proton's own
|
||||
# wine binary on every launch — required because direct edits to system.reg
|
||||
# are overwritten when wineserver flushes to disk on shutdown.
|
||||
# 5. Sets Steam launch options for SWBF2 and locks the config directory so
|
||||
# Steam cannot overwrite them via atomic rename on shutdown.
|
||||
#
|
||||
# Prerequisites — do these BEFORE running this script:
|
||||
# a. Wolf is running and Steam is open in Moonlight
|
||||
# b. GE-Proton10-34 (or later) is installed — in Steam go to
|
||||
# Settings → Compatibility → Enable Steam Play for all titles, then in
|
||||
# SWBF2 Properties → Compatibility force GE-Proton
|
||||
# c. msitools is installed on the Docker host:
|
||||
# sudo apt-get install -y msitools
|
||||
# d. Launch SWBF2 once from Moonlight — wait ~10 seconds for the
|
||||
# "Origin is not installed" error, then close it. This creates the Wine
|
||||
# prefix and drops ea_app.msi into drive_c.
|
||||
# e. Your EA account is linked to your Steam account at ea.com (one-time;
|
||||
# persists on EA's servers across reinstalls).
|
||||
#
|
||||
# After this script completes:
|
||||
# Launch SWBF2 from Moonlight. Let Vulkan shaders compile on first run
|
||||
# (several minutes, only happens once). EA App authenticates via your linked
|
||||
# Steam/EA account — no manual login needed if accounts are linked.
|
||||
#
|
||||
# Usage:
|
||||
# chmod +x setup-swbf2-wolf.sh
|
||||
# ./setup-swbf2-wolf.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
APPID="1237950"
|
||||
|
||||
echo "=== SWBF2 (2017) Wolf/Moonlight Setup ==="
|
||||
echo ""
|
||||
|
||||
# ── Locate the WolfSteam container ─────────────────────────────────────────
|
||||
WOLF_CONTAINER=$(docker ps --format '{{.Names}}' | grep -i WolfSteam | head -1)
|
||||
if [ -z "$WOLF_CONTAINER" ]; then
|
||||
echo "ERROR: WolfSteam container is not running."
|
||||
echo " Start Wolf and open Steam in Moonlight first."
|
||||
exit 1
|
||||
fi
|
||||
echo "Container: $WOLF_CONTAINER"
|
||||
|
||||
# ── Locate the Steam session home (Wolf mounts it as /home/retro) ──────────
|
||||
STEAM_HOME=$(find /etc/wolf /opt/wolf "$HOME" -maxdepth 6 \
|
||||
-type d -name Steam 2>/dev/null | grep -i 'wolf\|apps' | head -1)
|
||||
if [ -z "$STEAM_HOME" ]; then
|
||||
# Fallback: ask Docker where /home/retro actually lives on the host
|
||||
STEAM_HOME=$(docker inspect "$WOLF_CONTAINER" \
|
||||
--format '{{range .Mounts}}{{if eq .Destination "/home/retro"}}{{.Source}}{{end}}{{end}}' \
|
||||
2>/dev/null)
|
||||
fi
|
||||
if [ -z "$STEAM_HOME" ] || [ ! -d "$STEAM_HOME" ]; then
|
||||
echo "ERROR: Could not find Steam session home on the host."
|
||||
echo " Open Steam in Moonlight at least once so Wolf creates the session directory."
|
||||
exit 1
|
||||
fi
|
||||
echo "Steam home: $STEAM_HOME"
|
||||
|
||||
PFX_C="$STEAM_HOME/.steam/steam/steamapps/compatdata/$APPID/pfx/drive_c"
|
||||
MSI="$PFX_C/ea_app.msi"
|
||||
|
||||
# ── Step 1: verify Wine prefix exists ──────────────────────────────────────
|
||||
echo ""
|
||||
if [ ! -d "$PFX_C" ]; then
|
||||
echo "ERROR: Wine prefix not found at $PFX_C"
|
||||
echo ""
|
||||
echo "Required before running this script:"
|
||||
echo " 1. In Steam (via Moonlight): right-click SWBF2 → Properties → Compatibility"
|
||||
echo " → Force GE-Proton10-34 (or later)"
|
||||
echo " 2. Click Play on SWBF2 — wait ~10 seconds for 'Origin is not installed'"
|
||||
echo " 3. Close the error, then re-run this script"
|
||||
exit 1
|
||||
fi
|
||||
echo "[1/6] Wine prefix: OK"
|
||||
|
||||
# ── Step 2: verify ea_app.msi exists ───────────────────────────────────────
|
||||
if [ ! -f "$MSI" ]; then
|
||||
echo ""
|
||||
echo "ERROR: ea_app.msi not found at $MSI"
|
||||
echo ""
|
||||
echo "Launch SWBF2 once from Moonlight so Steam drops ea_app.msi into the"
|
||||
echo "Wine prefix. You will see an 'Origin is not installed' error — that is"
|
||||
echo "expected. Close it, then re-run this script."
|
||||
exit 1
|
||||
fi
|
||||
MSI_SIZE=$(stat -c%s "$MSI")
|
||||
if [ "$MSI_SIZE" -lt 50000000 ]; then
|
||||
echo "WARNING: ea_app.msi is only $MSI_SIZE bytes (expected ~227 MB)."
|
||||
echo "It may still be copying. Wait a moment and re-run."
|
||||
exit 1
|
||||
fi
|
||||
echo "[2/6] ea_app.msi ($(( MSI_SIZE / 1048576 )) MB): OK"
|
||||
|
||||
# ── Step 3: extract MSI on the host ────────────────────────────────────────
|
||||
echo "[3/6] Extracting EA Desktop files from MSI (~30s)..."
|
||||
if ! command -v msiextract >/dev/null 2>&1; then
|
||||
echo "ERROR: msitools not installed."
|
||||
echo " sudo apt-get install -y msitools"
|
||||
exit 1
|
||||
fi
|
||||
EXTRACT_DIR="/tmp/ea_app_extracted_$$"
|
||||
rm -rf "$EXTRACT_DIR"
|
||||
mkdir -p "$EXTRACT_DIR"
|
||||
if ! msiextract -C "$EXTRACT_DIR" "$MSI" >/dev/null 2>&1; then
|
||||
echo "ERROR: msiextract failed. Check msitools is properly installed."
|
||||
rm -rf "$EXTRACT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
EA_SRC=$(find "$EXTRACT_DIR" -maxdepth 5 \
|
||||
-path "*/Electronic Arts/EA Desktop/EA Desktop" -type d 2>/dev/null | head -1)
|
||||
if [ -z "$EA_SRC" ] || [ ! -f "$EA_SRC/Link2EA.exe" ]; then
|
||||
echo "ERROR: Link2EA.exe not found after extraction. MSI structure may have changed."
|
||||
ls -la "$EXTRACT_DIR/Electronic Arts/EA Desktop/" 2>/dev/null || true
|
||||
rm -rf "$EXTRACT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
echo " $(ls "$EA_SRC" | wc -l) files extracted including Link2EA.exe"
|
||||
|
||||
# ── Step 4: copy EA Desktop files into Wine prefix ─────────────────────────
|
||||
echo "[4/6] Installing EA Desktop files into Wine prefix..."
|
||||
EA_DEST_BASE="$PFX_C/Program Files/Electronic Arts/EA Desktop"
|
||||
|
||||
# Determine the versioned directory name. Use the broken symlink target from a
|
||||
# previous failed install attempt if present; otherwise default.
|
||||
EA_VERSION=$(docker exec "$WOLF_CONTAINER" \
|
||||
readlink "/home/retro/.steam/steam/steamapps/compatdata/$APPID/pfx/drive_c/Program Files/Electronic Arts/EA Desktop/EA Desktop" \
|
||||
2>/dev/null || echo "14.2.0.3345")
|
||||
|
||||
EA_DEST="$EA_DEST_BASE/$EA_VERSION"
|
||||
mkdir -p "$EA_DEST"
|
||||
cp -r "$EA_SRC/." "$EA_DEST/"
|
||||
chown -R 1000:1000 "$EA_DEST_BASE"
|
||||
|
||||
# Remove any stale symlink, then create a clean one
|
||||
rm -f "$EA_DEST_BASE/EA Desktop"
|
||||
ln -sf "$EA_VERSION" "$EA_DEST_BASE/EA Desktop"
|
||||
|
||||
if [ ! -f "$EA_DEST/Link2EA.exe" ]; then
|
||||
echo "ERROR: Copy failed — Link2EA.exe not found at $EA_DEST/Link2EA.exe"
|
||||
rm -rf "$EXTRACT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
echo " EA Desktop $EA_VERSION installed"
|
||||
rm -rf "$EXTRACT_DIR"
|
||||
|
||||
# ── Step 5: write .reg files and launch wrapper ─────────────────────────────
|
||||
echo "[5/6] Writing registry fix files and launch wrapper..."
|
||||
|
||||
# link2ea:// protocol handler — tells Wine how to find Link2EA.exe.
|
||||
# GE-Proton's steam.exe intercepts link2ea:// URLs and uses this handler
|
||||
# to launch Link2EA.exe, which hands off to EA Desktop for authentication.
|
||||
cat > "$PFX_C/link2ea_fix.reg" << 'REGEOF'
|
||||
Windows Registry Editor Version 5.00
|
||||
|
||||
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\link2ea]
|
||||
@="URL:link2ea Protocol"
|
||||
"URL Protocol"=""
|
||||
|
||||
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\link2ea\shell\open\command]
|
||||
@="\"C:\\Program Files\\Electronic Arts\\EA Desktop\\EA Desktop\\Link2EA.exe\" \"%1\""
|
||||
REGEOF
|
||||
|
||||
# EA Windows services — EALocalHostSvc provides local IPC that Link2EA.exe
|
||||
# needs. Without it launch fails with RPC_S_SERVER_UNAVAILABLE (0x800706ba).
|
||||
cat > "$PFX_C/ea_services.reg" << 'REGEOF'
|
||||
Windows Registry Editor Version 5.00
|
||||
|
||||
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EALocalHostSvc]
|
||||
"Type"=dword:00000010
|
||||
"Start"=dword:00000002
|
||||
"ErrorControl"=dword:00000001
|
||||
"ImagePath"="C:\\Program Files\\Electronic Arts\\EA Desktop\\EA Desktop\\EALocalHostSvc.exe"
|
||||
"DisplayName"="EA Local Host Service"
|
||||
"ObjectName"="LocalSystem"
|
||||
|
||||
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EABackgroundService]
|
||||
"Type"=dword:00000010
|
||||
"Start"=dword:00000002
|
||||
"ErrorControl"=dword:00000001
|
||||
"ImagePath"="C:\\Program Files\\Electronic Arts\\EA Desktop\\EA Desktop\\EABackgroundService.exe"
|
||||
"DisplayName"="EA Background Service"
|
||||
"ObjectName"="LocalSystem"
|
||||
REGEOF
|
||||
|
||||
chown 1000:1000 "$PFX_C/link2ea_fix.reg" "$PFX_C/ea_services.reg"
|
||||
|
||||
# Launch wrapper. Runs regedit through Steam's Proton/sniper launch chain on
|
||||
# every launch so registry entries survive wineserver restarts. Direct edits
|
||||
# to system.reg are overwritten when wineserver flushes to disk on shutdown —
|
||||
# going through the launch chain writes into wineserver's live memory instead.
|
||||
WRAPPER=$(mktemp)
|
||||
cat > "$WRAPPER" << 'WRAPEOF'
|
||||
#!/bin/bash
|
||||
echo "=== launch $(date) ===" >> /tmp/ea_install.log
|
||||
"$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" "${10}" "${11}" regedit /S "C:\\link2ea_fix.reg"
|
||||
"$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" "${10}" "${11}" regedit /S "C:\\ea_services.reg"
|
||||
exec "$@"
|
||||
WRAPEOF
|
||||
chmod +x "$WRAPPER"
|
||||
docker cp "$WRAPPER" "$WOLF_CONTAINER":/home/retro/ea_install.sh
|
||||
docker exec "$WOLF_CONTAINER" chmod +x /home/retro/ea_install.sh
|
||||
rm -f "$WRAPPER"
|
||||
echo " .reg files and wrapper installed"
|
||||
|
||||
# ── Step 6: set launch options and lock localconfig.vdf ────────────────────
|
||||
echo "[6/6] Setting Steam launch options..."
|
||||
STEAM_UID=$(ls "$STEAM_HOME/.steam/steam/userdata/" 2>/dev/null | head -1)
|
||||
if [ -z "$STEAM_UID" ]; then
|
||||
echo "WARNING: No Steam userdata found. Open Steam in Moonlight and sign in first."
|
||||
echo " Then re-run this script to set launch options, or set them manually:"
|
||||
echo " SWBF2 → Properties → Launch Options:"
|
||||
echo " STEAM_UNIX_SOCKET=/tmp/steam.sock /home/retro/ea_install.sh %command%"
|
||||
else
|
||||
CFG_DIR="$STEAM_HOME/.steam/steam/userdata/$STEAM_UID/config"
|
||||
CFG_FILE="$CFG_DIR/localconfig.vdf"
|
||||
if [ ! -f "$CFG_FILE" ]; then
|
||||
echo "WARNING: localconfig.vdf not found. Open Steam in Moonlight first, then re-run."
|
||||
else
|
||||
# Stop Steam so it flushes before we edit
|
||||
docker exec "$WOLF_CONTAINER" pkill -f steam.sh 2>/dev/null || true
|
||||
sleep 5
|
||||
chmod 755 "$CFG_DIR" 2>/dev/null || true
|
||||
|
||||
LAUNCH_OPT='STEAM_UNIX_SOCKET=/tmp/steam.sock /home/retro/ea_install.sh %command%'
|
||||
python3 - "$CFG_FILE" "$LAUNCH_OPT" << 'PYEOF'
|
||||
import sys, re
|
||||
path, opt = sys.argv[1], sys.argv[2]
|
||||
with open(path) as f:
|
||||
c = f.read()
|
||||
new = re.sub(r'("1237950".*?"LaunchOptions"\s*)"[^"]*"', rf'\1"{opt}"', c, flags=re.DOTALL)
|
||||
if new == c:
|
||||
new = re.sub(r'("1237950"\s*\n\s*\{)', rf'\1\n\t\t\t\t"LaunchOptions"\t\t"{opt}"', c)
|
||||
if new == c:
|
||||
print("WARNING: 1237950 block not found — set launch options manually in Steam:")
|
||||
print(" SWBF2 → Properties → Launch Options:")
|
||||
print(" STEAM_UNIX_SOCKET=/tmp/steam.sock /home/retro/ea_install.sh %command%")
|
||||
sys.exit(0)
|
||||
with open(path, 'w') as f:
|
||||
f.write(new)
|
||||
print(" LaunchOptions set.")
|
||||
PYEOF
|
||||
chown 1000:1000 "$CFG_FILE"
|
||||
|
||||
# Lock the config directory so Steam can't overwrite localconfig.vdf via
|
||||
# atomic rename (writes a temp file then renames into the directory).
|
||||
# chmod 444 on the file is bypassed by rename; locking the directory is not.
|
||||
chmod 555 "$CFG_DIR"
|
||||
echo " Config directory locked (chmod 555)"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Setup complete ==="
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Open Steam in Moonlight"
|
||||
echo " 2. Click Play on SWBF2"
|
||||
echo " 3. Let Vulkan shaders compile — do NOT skip (takes several minutes, once only)"
|
||||
echo " 4. EA App authenticates automatically if your Steam and EA accounts are linked"
|
||||
echo " 5. Game launches"
|
||||
echo ""
|
||||
echo "Troubleshooting:"
|
||||
echo " Check wrapper log: docker exec $WOLF_CONTAINER tail /tmp/ea_install.log"
|
||||
echo " Check Proton log: tail $STEAM_HOME/steam-$APPID.log"
|
||||
echo ""
|
||||
echo "If launch options were not set automatically, set them manually in Steam:"
|
||||
echo " Right-click SWBF2 → Properties → Launch Options:"
|
||||
echo " STEAM_UNIX_SOCKET=/tmp/steam.sock /home/retro/ea_install.sh %command%"
|
||||
Reference in New Issue
Block a user