diff --git a/proton b/proton index ed7534bf..eee0d12b 100755 --- a/proton +++ b/proton @@ -72,7 +72,7 @@ def upgrade_pfx(old_ver): if old_ver == CURRENT_PREFIX_VERSION: return - log("Upgrading prefix from " + str(old_ver) + " to " + CURRENT_PREFIX_VERSION + " (" + os.environ["STEAM_COMPAT_DATA_PATH"] + ")") + log("Upgrading prefix from " + str(old_ver) + " to " + CURRENT_PREFIX_VERSION + " (" + g_compatdata.base_dir + ")") if old_ver is None: return @@ -93,25 +93,25 @@ def upgrade_pfx(old_ver): (int(new_proton_maj) == int(old_proton_maj) and \ int(new_proton_min) < int(old_proton_min)): log("Removing newer prefix") - if old_proton_ver == "3.7" and not os.path.exists(os.environ["STEAM_COMPAT_DATA_PATH"] + "/tracked_files"): + if old_proton_ver == "3.7" and not os.path.exists(g_compatdata.tracked_files_file): #proton 3.7 did not generate tracked_files, so copy it into place first - try_copy(g_proton.path("proton_3.7_tracked_files"), os.environ["STEAM_COMPAT_DATA_PATH"] + "/tracked_files") - remove_tracked_files(os.environ["STEAM_COMPAT_DATA_PATH"]) + try_copy(g_proton.path("proton_3.7_tracked_files"), g_compatdata.tracked_files_file) + remove_tracked_files(g_compatdata.base_dir) return if old_proton_ver == "3.7" and old_prefix_ver == "1": - if not os.path.exists(prefix + "/drive_c/windows/syswow64/kernel32.dll"): + if not os.path.exists(g_compatdata.prefix_dir + "/drive_c/windows/syswow64/kernel32.dll"): #shipped a busted 64-bit-only installation on 20180822. detect and wipe clean log("Detected broken 64-bit-only installation, re-creating prefix.") - shutil.rmtree(prefix) + shutil.rmtree(g_compatdata.prefix_dir) return #replace broken .NET installations with wine-mono support - if os.path.exists(prefix + "/drive_c/windows/Microsoft.NET/NETFXRepair.exe") and \ - file_is_wine_fake_dll(prefix + "/drive_c/windows/system32/mscoree.dll"): + if os.path.exists(g_compatdata.prefix_dir + "/drive_c/windows/Microsoft.NET/NETFXRepair.exe") and \ + file_is_wine_fake_dll(g_compatdata.prefix_dir + "/drive_c/windows/system32/mscoree.dll"): log("Broken .NET installation detected, switching to wine-mono.") #deleting this directory allows wine-mono to work - shutil.rmtree(prefix + "/drive_c/windows/Microsoft.NET") + shutil.rmtree(g_compatdata.prefix_dir + "/drive_c/windows/Microsoft.NET") except ValueError: log("Prefix has an invalid version?! You may want to back up user files and delete this prefix.") @@ -189,11 +189,23 @@ class Proton: def path(self, d): return self.base_dir + d +class CompatData: + def __init__(self, compatdata): + self.base_dir = compatdata + "/" + self.prefix_dir = self.path("pfx/") + self.version_file = self.path("version") + self.tracked_files_file = self.path("tracked_files") + self.prefix_lock = FileLock(self.path("pfx.lock"), timeout=-1) + + def path(self, d): + return self.base_dir + d + if not "STEAM_COMPAT_DATA_PATH" in os.environ: log("No compat data path?") sys.exit(1) g_proton = Proton(os.path.dirname(sys.argv[0])) +g_compatdata = CompatData(os.environ["STEAM_COMPAT_DATA_PATH"]) #extract if needed with g_proton.dist_lock: @@ -245,8 +257,7 @@ with g_proton.dist_lock: run_wine([g_proton.wine_bin, "wineboot"]) run_wine([g_proton.wineserver_bin, "-w"]) -prefix = os.environ["STEAM_COMPAT_DATA_PATH"] + "/pfx/" -env["WINEPREFIX"] = prefix +env["WINEPREFIX"] = g_compatdata.prefix_dir if "PROTON_LOG" in env and nonzero(env["PROTON_LOG"]): env["WINEDEBUG"] = "+timestamp,+pid,+tid,+seh,+debugstr,+loaddll,+mscoree" @@ -369,29 +380,27 @@ def set_dir_casefold_bit(dir_path): pass os.close(dr) -prefix_lock = FileLock(os.environ["STEAM_COMPAT_DATA_PATH"] + "/pfx.lock", timeout=-1) -with prefix_lock: - version_file = os.environ["STEAM_COMPAT_DATA_PATH"] + "/version" - if os.path.exists(version_file): - with open(version_file, "r") as f: +with g_compatdata.prefix_lock: + if os.path.exists(g_compatdata.version_file): + with open(g_compatdata.version_file, "r") as f: upgrade_pfx(f.readline().strip()) else: upgrade_pfx(None) - if not os.path.exists(prefix): - makedirs(prefix + "/drive_c") - set_dir_casefold_bit(prefix + "/drive_c") + if not os.path.exists(g_compatdata.prefix_dir): + makedirs(g_compatdata.prefix_dir + "/drive_c") + set_dir_casefold_bit(g_compatdata.prefix_dir + "/drive_c") - if not os.path.exists(prefix + "/user.reg"): + if not os.path.exists(g_compatdata.prefix_dir + "/user.reg"): #copy default prefix into place - with open(os.environ["STEAM_COMPAT_DATA_PATH"] + "/tracked_files", "w") as tfiles: - mergedirs(g_proton.default_pfx_dir, prefix, tfiles) + with open(g_compatdata.tracked_files_file, "w") as tfiles: + mergedirs(g_proton.default_pfx_dir, g_compatdata.prefix_dir, tfiles) - with open(version_file, "w") as f: + with open(g_compatdata.version_file, "w") as f: f.write(CURRENT_PREFIX_VERSION + "\n") #create font files symlinks - create_fonts_symlinks(prefix) + create_fonts_symlinks(g_compatdata.prefix_dir) #copy steam files into place if "STEAM_COMPAT_CLIENT_INSTALL_PATH" in os.environ: @@ -400,7 +409,7 @@ with prefix_lock: else: #linux-only fallback, really shouldn't get here steamdir = os.environ["HOME"] + ".steam/root/" - dst = prefix + "/drive_c/Program Files (x86)/" + dst = g_compatdata.prefix_dir + "/drive_c/Program Files (x86)/" makedirs(dst + "Steam") filestocopy = ["steamclient.dll", "steamclient64.dll", @@ -413,13 +422,13 @@ with prefix_lock: try_copy(steamdir + "/legacycompat/" + f, dstfile) #copy openvr files into place - dst = prefix + "/drive_c/vrclient/bin/" + dst = g_compatdata.prefix_dir + "/drive_c/vrclient/bin/" makedirs(dst) try_copy(g_proton.lib_dir + "wine/fakedlls/vrclient.dll", dst) try_copy(g_proton.lib64_dir + "wine/fakedlls/vrclient_x64.dll", dst) - try_copy(g_proton.lib_dir + "wine/dxvk/openvr_api_dxvk.dll", prefix + "/drive_c/windows/syswow64/") - try_copy(g_proton.lib64_dir + "wine/dxvk/openvr_api_dxvk.dll", prefix + "/drive_c/windows/system32/") + try_copy(g_proton.lib_dir + "wine/dxvk/openvr_api_dxvk.dll", g_compatdata.prefix_dir + "/drive_c/windows/syswow64/") + try_copy(g_proton.lib64_dir + "wine/dxvk/openvr_api_dxvk.dll", g_compatdata.prefix_dir + "/drive_c/windows/system32/") #parse linux openvr config and present it in win32 format to the app. #logic from openvr's CVRPathRegistry_Public::GetPaths @@ -462,10 +471,10 @@ with prefix_lock: except (TypeError, ValueError, OSError): log("Missing or invalid openvrpaths.vrpath file! " + str(sys.exc_info()[1])) - makedirs(prefix + "/drive_c/users/steamuser/Local Settings/Application Data/openvr") + makedirs(g_compatdata.prefix_dir + "/drive_c/users/steamuser/Local Settings/Application Data/openvr") #remove existing file - vrpaths_name = prefix + "/drive_c/users/steamuser/Local Settings/Application Data/openvr/openvrpaths.vrpath" + vrpaths_name = g_compatdata.prefix_dir + "/drive_c/users/steamuser/Local Settings/Application Data/openvr/openvrpaths.vrpath" if os.path.exists(vrpaths_name): os.remove(vrpaths_name) @@ -505,15 +514,15 @@ with prefix_lock: for f in wined3dfiles: try_copy(g_proton.default_pfx_dir + "drive_c/windows/system32/" + f + ".dll", - prefix + "drive_c/windows/system32/" + f + ".dll") + g_compatdata.prefix_dir + "drive_c/windows/system32/" + f + ".dll") try_copy(g_proton.default_pfx_dir + "drive_c/windows/syswow64/" + f + ".dll", - prefix + "drive_c/windows/syswow64/" + f + ".dll") + g_compatdata.prefix_dir + "drive_c/windows/syswow64/" + f + ".dll") for f in dxvkfiles: try_copy(g_proton.lib64_dir + "wine/dxvk/" + f + ".dll", - prefix + "drive_c/windows/system32/" + f + ".dll") + g_compatdata.prefix_dir + "drive_c/windows/system32/" + f + ".dll") try_copy(g_proton.lib_dir + "wine/dxvk/" + f + ".dll", - prefix + "drive_c/windows/syswow64/" + f + ".dll") + g_compatdata.prefix_dir + "drive_c/windows/syswow64/" + f + ".dll") dlloverrides[f] = "n" if "nod3d11" in config_opts: