[core/utils] Add save path resolution on Linux

If a wine prefix is specified in the config, attempt to
find savegames in there.
This commit is contained in:
derrod 2020-12-16 11:18:58 +01:00
parent 3e2a6011ff
commit 5e061d6946
2 changed files with 49 additions and 7 deletions

View file

@ -32,6 +32,7 @@ from legendary.models.chunk import Chunk
from legendary.utils.game_workarounds import is_opt_enabled from legendary.utils.game_workarounds import is_opt_enabled
from legendary.utils.savegame_helper import SaveGameHelper from legendary.utils.savegame_helper import SaveGameHelper
from legendary.utils.manifests import combine_manifests from legendary.utils.manifests import combine_manifests
from legendary.utils.wine_helpers import read_registry, get_shell_folders
# ToDo: instead of true/false return values for success/failure actually raise an exception that the CLI/GUI # ToDo: instead of true/false return values for success/failure actually raise an exception that the CLI/GUI
@ -412,19 +413,43 @@ class LegendaryCore:
# the following variables are known: # the following variables are known:
path_vars = { path_vars = {
'{appdata}': os.path.expandvars('%APPDATA%'),
'{installdir}': igame.install_path, '{installdir}': igame.install_path,
'{userdir}': os.path.expandvars('%userprofile%/documents'),
'{epicid}': self.lgd.userdata['account_id'] '{epicid}': self.lgd.userdata['account_id']
} }
# the following variables are in the EGL binary but are not used by any of
# my games and I'm not sure where they actually point at: if os.name == 'nt':
# {UserProfile} (Probably %USERPROFILE%) path_vars.update({
# {UserSavedGames} '{appdata}': os.path.expandvars('%APPDATA%'),
'{userdir}': os.path.expandvars('%userprofile%/documents'),
# '{userprofile}': os.path.expandvars('%userprofile%'), # possibly wrong
'{usersavedgames}': os.path.expandvars('%userprofile%/Saved Games')
})
else:
# attempt to get WINE prefix from config
wine_pfx = self.lgd.config.get(app_name, 'wine_prefix', fallback=None)
if not wine_pfx:
wine_pfx = self.lgd.config.get(f'{app_name}.env', 'WINEPREFIX', fallback=None)
if not wine_pfx:
proton_pfx = self.lgd.config.get(f'{app_name}.env', 'STEAM_COMPAT_DATA_PATH', fallback=None)
if proton_pfx:
wine_pfx = f'{proton_pfx}/pfx'
# if we have a prefix, read the `user.reg` file and get the proper paths.
if wine_pfx:
wine_reg = read_registry(wine_pfx)
wine_folders = get_shell_folders(wine_reg, wine_pfx)
# path_vars['{userprofile}'] = user_path
path_vars['{appdata}'] = wine_folders['AppData']
# this maps to ~/Documents, but the name is locale-dependent so just resolve the symlink from WINE
path_vars['{userdir}'] = os.path.realpath(wine_folders['Personal'])
path_vars['{usersavedgames}'] = wine_folders['4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4']
# replace backslashes
save_path = save_path.replace('\\', '/')
# these paths should always use a forward slash # these paths should always use a forward slash
new_save_path = [path_vars.get(p.lower(), p) for p in save_path.split('/')] new_save_path = [path_vars.get(p.lower(), p) for p in save_path.split('/')]
return os.path.join(*new_save_path) return os.path.realpath(os.path.join(*new_save_path))
def check_savegame_state(self, path: str, save: SaveGameFile) -> (SaveGameStatus, (datetime, datetime)): def check_savegame_state(self, path: str, save: SaveGameFile) -> (SaveGameStatus, (datetime, datetime)):
latest = 0 latest = 0

View file

@ -0,0 +1,17 @@
import os
import configparser
def read_registry(wine_pfx):
reg = configparser.ConfigParser(comment_prefixes=(';', '#', '/', 'WINE'), allow_no_value=True)
reg.optionxform = str
reg.read(os.path.join(wine_pfx, 'user.reg'))
return reg
def get_shell_folders(registry, wine_pfx):
folders = dict()
for k, v in registry['Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\Shell Folders'].items():
path_cleaned = v.strip('"').strip().replace('\\\\', '/').replace('C:/', '')
folders[k.strip('"').strip()] = os.path.join(wine_pfx, 'drive_c', path_cleaned)
return folders