From 6dc74523c3f12fc0daccd807ebd8230b882b07fa Mon Sep 17 00:00:00 2001 From: MaxsTechReview Date: Sun, 4 Oct 2026 13:44:10 -0400 Subject: [PATCH] Start every title with a Valve pick on the Compatible Proton (#224) The client runs in Steam Deck mode, where a title's "Default" is not the "0" mapping but Valve's own pick for it: the Steam Deck compatibility recommended_runtime (proton-stable, a pinned Proton, or native for the Steam Linux Runtime) or an app_mappings entry in the SteamPlay manifests. A title the session had not mapped yet - not installed, or installed while the client was running on a build without the live helper - showed "Default (Proton Stable)" and launched with a Proton that cannot run here. Every playable Windows title in the appinfo cache with such a pick is now mapped to the default tool up front, before the client starts and in the live helper, the same way installed titles are. A runnable tool the user picks for one of them is kept, and they follow a change of the default. --- .../usr/local/bin/droiddeck-steam-compat | 5 +- .../overlay/usr/local/bin/steam-compatibility | 111 ++++++++++++------ tools/tests/test_droiddeck_fex.py | 40 ++++++- 3 files changed, 117 insertions(+), 39 deletions(-) diff --git a/tools/linuxfs/overlay/usr/local/bin/droiddeck-steam-compat b/tools/linuxfs/overlay/usr/local/bin/droiddeck-steam-compat index e3520f4d9..f2adc5581 100755 --- a/tools/linuxfs/overlay/usr/local/bin/droiddeck-steam-compat +++ b/tools/linuxfs/overlay/usr/local/bin/droiddeck-steam-compat @@ -397,11 +397,12 @@ class Helper: default, state = COMPAT["choose_default"](top["selected"], state, request, live, apply_request=not waiting) installed = COMPAT["installed_apps"](self.steam_root) self.installed = installed - apps = sorted(set(installed) | set(state.get("auto", {})), key=COMPAT["app_order"]) + picks = COMPAT["valve_picks"](self.steam_root) + apps = sorted(set(installed) | set(picks) | set(state.get("auto", {})), key=COMPAT["app_order"]) current = dict(page.compat("many(%s)" % json.dumps(apps)) or {}) current["0"] = top["selected"] native = COMPAT["native_targets"](self.steam_root, installed) - changes, auto = COMPAT["plan_mapping"](current, installed, [t["name"] for t in live], default, COMPAT["followers"](state, current), native) + changes, auto = COMPAT["plan_mapping"](current, installed, [t["name"] for t in live], default, COMPAT["followers"](state, current), native, picks) for app, tool in sorted(changes.items(), key=lambda item: COMPAT["app_order"](item[0])): page.compat("set(%d, %s)" % (int(app), json.dumps(tool))) say("%s -> %s" % ("default" if app == "0" else "app %s" % app, tool)) diff --git a/tools/linuxfs/overlay/usr/local/bin/steam-compatibility b/tools/linuxfs/overlay/usr/local/bin/steam-compatibility index f3600e557..ee1f1eea1 100755 --- a/tools/linuxfs/overlay/usr/local/bin/steam-compatibility +++ b/tools/linuxfs/overlay/usr/local/bin/steam-compatibility @@ -632,17 +632,18 @@ def installed_apps(steam_root): APPINFO_CACHE = {} +STEAM_PLAY_MANIFESTS = 891390 -def appinfo_platforms(path, wanted): +def appinfo_entries(path): import struct try: stamp = os.stat(path).st_mtime_ns except OSError: return {} cached = APPINFO_CACHE.get(path) - if cached and cached[0] == stamp and wanted <= cached[1].keys() | cached[2]: - return {app: cached[1][app] for app in wanted if app in cached[1]} + if cached and cached[0] == stamp: + return cached[1] try: with open(path, "rb") as f: data = f.read() @@ -655,16 +656,19 @@ def appinfo_platforms(path, wanted): return {} offset = 8 strings = None - if magic == 0x07564429: - table = struct.unpack_from("= 0x07564428 else 0) def section(position): @@ -697,23 +701,58 @@ def appinfo_platforms(path, wanted): raise ValueError("unknown appinfo field type %d" % kind) found = {} - try: - while offset + 8 <= len(data): + while offset + 8 <= len(data): + try: app, size = struct.unpack_from("= 0x07564428 else b"") body += struct.pack("