Proton sandboxed keine Env-Vars aus dem Wrapper → direkt in LaunchOptions schreiben. steam-egpu: launcher checkt card0 vor Steam-Start und patcht localconfig.vdf steam-egpu-toggle.py: schaltet 120+ Spiele auf einmal um udev: automatisch bei eGPU-Connect/Disconnect
99 lines
3.4 KiB
Python
99 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Schaltet Steam-Launch-Options zwischen eGPU und iGPU um.
|
|
|
|
Wird per udev getriggert wenn die eGPU verbunden/getrennt wird.
|
|
Patched localconfig.vdf direkt — Steam muss danach neu gestartet werden.
|
|
|
|
Usage:
|
|
steam-egpu-toggle.py egpu # eGPU-Modus: DRI_PRIME=1 in alle Spiele
|
|
steam-egpu-toggle.py igpu # iGPU-Modus: DRI_PRIME entfernen
|
|
steam-egpu-toggle.py status # Aktuellen Modus anzeigen
|
|
"""
|
|
import sys, shutil
|
|
from pathlib import Path
|
|
import vdf
|
|
|
|
STEAM_USERDATA = Path.home() / ".local/share/Steam/userdata/19491507/config/localconfig.vdf"
|
|
|
|
EGPU_OPTS = "DRI_PRIME=1 VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/radeon_icd.json VKD3D_CONFIG=force_host_gpu DXVK_CONFIG=dxgi.allowUnsupportedDrivers=True %command%"
|
|
IGPU_OPTS = "%command%"
|
|
LAUNCH_KEY = "LaunchOptions"
|
|
|
|
# Spiele die NIEMALS angerührt werden (z.B. Proton, Steam Runtime, Tools)
|
|
SKIP_APPIDS = {
|
|
"1493710", # Proton Experimental
|
|
"4183110", # Steam Linux Runtime 4.0
|
|
"228980", # Steamworks Common Redistributables
|
|
}
|
|
|
|
|
|
def get_apps(config):
|
|
return config.get("UserLocalConfigStore", {}).get("Software", {}).get("Valve", {}).get("Steam", {}).get("apps", {})
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) < 2:
|
|
print("Usage: steam-egpu-toggle.py {egpu|igpu|status}")
|
|
sys.exit(1)
|
|
|
|
cmd = sys.argv[1]
|
|
|
|
if not STEAM_USERDATA.exists():
|
|
print(f"ERROR: {STEAM_USERDATA} nicht gefunden")
|
|
sys.exit(1)
|
|
|
|
# Backup
|
|
backup = STEAM_USERDATA.with_suffix(".vdf.togglebak")
|
|
shutil.copy2(STEAM_USERDATA, backup)
|
|
|
|
with open(STEAM_USERDATA) as f:
|
|
config = vdf.load(f)
|
|
|
|
apps = get_apps(config)
|
|
|
|
if cmd == "status":
|
|
e_count = sum(1 for a in apps.values() if a.get(LAUNCH_KEY, "").startswith("DRI_PRIME=1"))
|
|
w_count = sum(1 for a in apps.values() if "superx-game-wrapper" in a.get(LAUNCH_KEY, ""))
|
|
o_count = sum(1 for a in apps.values() if a.get(LAUNCH_KEY, "") and not a[LAUNCH_KEY].startswith("DRI_PRIME=1") and "superx-game-wrapper" not in a[LAUNCH_KEY])
|
|
print(f"eGPU-Modus: {e_count} Spiele")
|
|
print(f"Wrapper: {w_count} Spiele")
|
|
print(f"Individuell:{o_count} Spiele")
|
|
return
|
|
|
|
target_opts = EGPU_OPTS if cmd == "egpu" else IGPU_OPTS
|
|
changed = 0
|
|
cleaned_wrapper = 0
|
|
|
|
for appid, appcfg in apps.items():
|
|
if appid in SKIP_APPIDS:
|
|
continue
|
|
current = appcfg.get(LAUNCH_KEY, "")
|
|
|
|
# Cleanup: wrapper ersetzen
|
|
if "superx-game-wrapper" in current:
|
|
appcfg[LAUNCH_KEY] = target_opts
|
|
cleaned_wrapper += 1
|
|
changed += 1
|
|
# Cleanup: leere oder fehlende LaunchOptions
|
|
elif not current or current == "%command%":
|
|
appcfg[LAUNCH_KEY] = target_opts
|
|
changed += 1
|
|
elif cmd == "egpu" and not current.startswith("DRI_PRIME=1"):
|
|
appcfg[LAUNCH_KEY] = target_opts
|
|
changed += 1
|
|
elif cmd == "igpu" and current.startswith("DRI_PRIME=1"):
|
|
appcfg[LAUNCH_KEY] = target_opts
|
|
changed += 1
|
|
|
|
with open(STEAM_USERDATA, "w") as f:
|
|
vdf.dump(config, f, pretty=True)
|
|
|
|
mode = "eGPU (DRI_PRIME=1)" if cmd == "egpu" else "iGPU (Standard)"
|
|
print(f"Modus: {mode}")
|
|
print(f"Geändert: {changed} Spiele (davon {cleaned_wrapper} Wrapper ersetzt)")
|
|
print(f"Backup: {backup}")
|
|
print(f"\n⚠️ Steam muss NEU GESTARTET werden!")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|