mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-10-14 19:27:09 -04:00
x86-64 client: a Windows build on disk stays on Proton
Steam does not swap an installed build when a title's tool changes. A Linux game whose Windows build was installed (it ran on a Proton before) was put on DroidDeck direct, which was then handed Launcher.exe and ended in three seconds (device: Borderlands 2). Getting the Linux build back would mean downloading the game again, so such a game now stays a Windows game, on the client's default Proton; one with its Linux build installed, or none yet, goes to DroidDeck direct as before. The installed build is read from the appmanifest's InstalledDepots against appinfo's depot oslists.
This commit is contained in:
1 parent
d06468b802
commit
d9b86fe9b6
1 file changed
+41
-9
@@ -284,7 +284,8 @@ RUN
|
||||
# here, while no x86 client runs.
|
||||
if [ -f "$STEAM_X64/config/config.vdf" ] && ! pgrep -f 'steamrt64/steam( |$)' >/dev/null 2>&1; then
|
||||
python3 - "$STEAM_X64/config/config.vdf" "$STEAM_X64/appcache/appinfo.vdf" "$X64_HOME/direct-auto.json" \
|
||||
"$X64_HOME/direct-sniper" ${BL_X64_DIRECT_APPS:-550} <<'PY' || step "could not map titles to DroidDeck direct"
|
||||
"$X64_HOME/direct-sniper" "$STEAM_X64/steamapps" "$(x64_default_tool)" ${BL_X64_DIRECT_APPS:-550} \
|
||||
<<'PY' || step "could not map titles to DroidDeck direct"
|
||||
# Every game with a Linux build goes to DroidDeck direct: Steam would run it in its Linux runtime
|
||||
# container, which needs user namespaces no Android app has, and the game would not start. The
|
||||
# client's own appinfo cache says which games have a Linux build and which runtime Valve gives them
|
||||
@@ -292,8 +293,14 @@ RUN
|
||||
# direct-sniper for the tool's run script. A title on a tool chosen in Properties keeps it, except
|
||||
# BL_X64_DIRECT_APPS (Left 4 Dead 2 by default), which is always taken back.
|
||||
# direct-auto.json lists what this mapped.
|
||||
import json, re, struct, sys
|
||||
path, appinfo, auto_file, sniper_file, extra = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5:]
|
||||
# A game whose Windows build is the one installed (it ran on a Proton before) stays a Windows game, on
|
||||
# the client's default Proton: Steam does not swap an installed build when the tool changes, so
|
||||
# DroidDeck direct was handed Launcher.exe and the game ended at once (device: Borderlands 2), and
|
||||
# getting the Linux build back means downloading the game again.
|
||||
import json, os, re, struct, sys
|
||||
path, appinfo, auto_file, sniper_file, steamapps, proton = sys.argv[1:7]
|
||||
extra = sys.argv[7:]
|
||||
WINDOWS_DEPOTS = {}
|
||||
|
||||
|
||||
def read_kv(buf, pos, strings):
|
||||
@@ -362,9 +369,27 @@ def linux_games(file):
|
||||
tool = str(m.get("tool", "")).lower()
|
||||
runtime = "sniper" if "sniper" in tool else "soldier" if "soldier" in tool else runtime
|
||||
games[str(appid)] = runtime
|
||||
WINDOWS_DEPOTS[str(appid)] = {
|
||||
d for d, v in (info.get("depots") or {}).items()
|
||||
if isinstance(v, dict) and "windows" in str((v.get("config") or {}).get("oslist", ""))
|
||||
and "linux" not in str((v.get("config") or {}).get("oslist", ""))
|
||||
}
|
||||
return games
|
||||
|
||||
|
||||
def windows_installed(app):
|
||||
"""Whether the installed build of `app` is its Windows one (a Windows depot among those installed)."""
|
||||
try:
|
||||
text = open(os.path.join(steamapps, "appmanifest_%s.acf" % app), encoding="utf-8", errors="replace").read()
|
||||
except OSError:
|
||||
return False
|
||||
found = block(text, "InstalledDepots")
|
||||
if not found:
|
||||
return False
|
||||
installed = set(re.findall(r'"(\d+)"\s*\{', text[found[1]:found[2]]))
|
||||
return bool(installed & WINDOWS_DEPOTS.get(app, set()))
|
||||
|
||||
|
||||
def block(text, key):
|
||||
"""(start of the key, index after its opening brace, index of its closing brace) or None."""
|
||||
m = re.search(r'"%s"\s*\{' % re.escape(key), text)
|
||||
@@ -388,8 +413,9 @@ if not block(s, "CompatToolMapping"):
|
||||
if not st:
|
||||
sys.exit("no Steam section")
|
||||
s = s[:st[1]] + '\n\t\t\t\t"CompatToolMapping"\n\t\t\t\t{\n\t\t\t\t}' + s[st[1]:]
|
||||
mapped = []
|
||||
mapped, windows = [], []
|
||||
for app in sorted(games, key=int):
|
||||
on_windows = windows_installed(app)
|
||||
_, open_, close = block(s, "CompatToolMapping")
|
||||
inner = s[open_:close]
|
||||
old = block(inner, app)
|
||||
@@ -402,16 +428,22 @@ for app in sorted(games, key=int):
|
||||
automatic = name in ("", "droiddeck-direct", "droiddeck-proton-arm64") or name.startswith("proton_")
|
||||
if not automatic and app not in extra:
|
||||
continue
|
||||
if on_windows and (name == proton or not proton):
|
||||
continue
|
||||
inner = inner[:old[0]] + inner[old[2] + 1:]
|
||||
entry = ('\n\t\t\t\t\t"%s"\n\t\t\t\t\t{\n\t\t\t\t\t\t"name"\t\t"droiddeck-direct"\n'
|
||||
'\t\t\t\t\t\t"config"\t\t""\n\t\t\t\t\t\t"priority"\t\t"250"\n\t\t\t\t\t}' % app)
|
||||
elif on_windows and not proton:
|
||||
continue
|
||||
tool = proton if on_windows else "droiddeck-direct"
|
||||
entry = ('\n\t\t\t\t\t"%s"\n\t\t\t\t\t{\n\t\t\t\t\t\t"name"\t\t"%s"\n'
|
||||
'\t\t\t\t\t\t"config"\t\t""\n\t\t\t\t\t\t"priority"\t\t"250"\n\t\t\t\t\t}' % (app, tool))
|
||||
s = s[:open_] + entry + inner + s[close:]
|
||||
mapped.append(app)
|
||||
(windows if on_windows else mapped).append(app)
|
||||
open(path, "w", encoding="utf-8", errors="surrogateescape").write(s)
|
||||
json.dump(mapped, open(auto_file, "w"))
|
||||
open(sniper_file, "w").write("".join("%s\n" % a for a in mapped if games[a] != "scout"))
|
||||
print("droiddeck-steam-x64: %d Linux title(s) on DroidDeck direct (%d on the newer runtime)"
|
||||
% (len(mapped), sum(games[a] != "scout" for a in mapped)))
|
||||
print("droiddeck-steam-x64: %d Linux title(s) on DroidDeck direct (%d on the newer runtime)%s"
|
||||
% (len(mapped), sum(games[a] != "scout" for a in mapped),
|
||||
"; %d installed as Windows games kept on %s" % (len(windows), proton) if windows else ""))
|
||||
PY
|
||||
fi
|
||||
# The arm64 client's Proton tools (droiddeck-proton-arm64, GE-Proton, CachyOS): one wrapper per
|
||||
|
||||
Reference in new issue
Block a user