Skip to content

Instantly share code, notes, and snippets.

Created June 29, 2021 17:20
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save monodop/f74ee058c173d526713317e1aa2870aa to your computer and use it in GitHub Desktop.
Convert Snowrunner UWP Saves to Steam
import os
import struct
import sys
import uuid
import zipfile
import json
# Snowrunner save "converter" (Xbox Game Pass for PC -> Steam)
# Might work for other games available with the Game Pass if the app name is changed.
# Running: Just run the script with Python 3 to create a ZIP file that contains the save files
# Thanks to @Z1ni for building the original Yakuza save converted that this was modified from:
# Thanks to @snoozbuster for figuring out the container format at
xgp_app = "FocusHomeInteractiveSA.SnowRunnerWindows10_4hny5m903y3g0"
save_zip_path = ""
def read_utf16_str(f):
str_len = struct.unpack("<i",[0]
return * 2).decode("utf-16")
def read_utf16_strc(f, c):
def get_file_paths():
# Find gamepass save dir
wgs_dir = os.path.expandvars(f"%LOCALAPPDATA%\\Packages\\{xgp_app}\\SystemAppData\\wgs")
# Get the correct user directory
dirs = [d for d in os.listdir(wgs_dir) if d != "t"]
dir_count = len(dirs)
if dir_count != 1:
raise Exception(f"Expected one user directory in wgs directory, found {dir_count}")
containers_dir = os.path.join(wgs_dir, dirs[0])
containers_idx_path = os.path.join(containers_dir, "containers.index")
save_files = []
# Read the index file
with open(containers_idx_path, "rb") as f:
# Unknown
file_count = struct.unpack("<i",[0]
# Unknown
store_pkg_name = read_utf16_str(f)
# Unknown
# Unknown
for _ in range(file_count):
# File name
fname = read_utf16_str(f)
# Duplicate of the file name
# Unknown quoted hex number
# Container number
container_num = struct.unpack("B",[0]
# Unknown
# Read container (folder) GUID
container_guid = uuid.UUID(
# Unknown
print(fname, container_num, container_guid)
# Read the container file in the file directory
with open(os.path.join(containers_dir, container_guid.hex.upper(), f"container.{container_num}"), "rb") as cf:
# Unknown
while, 1)
# Output filename (steam format)
output_filename = read_utf16_strc(cf, 128).strip('\0') + '.cfg'
# File guid (uwp format)
file_guid = uuid.UUID(
print(" - ", output_filename, file_guid)
# Unknown
save_files.append((output_filename, os.path.join(containers_dir, container_guid.hex.upper(), file_guid.hex.upper())))
return save_files
def main():
# Get save file paths with correct names
save_files = get_file_paths()
# Store the save files into a zip
with zipfile.ZipFile(save_zip_path, "x") as save_zip:
for info in save_files:
orig_fname, container_fname = info
save_zip.write(container_fname, arcname=orig_fname)
except FileExistsError:
print(f"Save file container ZIP \"{save_zip_path}\" already exists.")
print(f"Save files stored to \"{save_zip_path}\"")
if __name__ == "__main__":
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment