Created
September 5, 2021 21:25
-
-
Save Chase-san/704284e4acd841471d9836e6bc296f2f to your computer and use it in GitHub Desktop.
A python script to decode the hello games no man's sky save files. (The newer compressed kind)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import io | |
import os | |
import lz4.block | |
from glob import glob | |
FILE_PATH = os.path.dirname(os.path.realpath(__file__)) | |
def uint32(data): | |
"""Convert 4 bytes to a little endian unsigned integer.""" | |
return int.from_bytes(data, byteorder='little', signed=False) | |
def decompress(data): | |
"""Decompresses the given save bytes. If your groking this file for the important bit, this is it.""" | |
size = len(data) | |
din = io.BytesIO(data) | |
out = bytearray() | |
while din.tell() < size: | |
magic = uint32(din.read(4)) | |
if magic != 0xfeeda1e5: | |
print("Invalid Block, bad file") | |
return bytes() # some unsupported format | |
compressedSize = uint32(din.read(4)) | |
uncompressedSize = uint32(din.read(4)) | |
din.seek(4, 1) # skip 4 bytes | |
out += lz4.block.decompress(din.read(compressedSize), uncompressed_size=uncompressedSize) | |
return out | |
def findSaveGames(): | |
"""Finds all saves on windows.""" | |
return glob("C:\\Users\\*\\AppData\\Roaming\\HelloGames\\NMS\\*\\save*.hg") | |
def decodeSave(src, dst): | |
print("Decoding save: %s" % os.path.basename(src)) | |
fin = open(src, "rb") | |
data = fin.read(2) | |
if data[0] != 0x7B and data[1] != 0x22: | |
print("Decompressing file.") | |
fin.seek(0,0) # seek to start | |
data = decompress(fin.read()) | |
else: | |
fin.seek(0,0) | |
data = fin.read() | |
fin.close() | |
print("Saving to: %s" % os.path.basename(dst)) | |
fout = open(dst, "wb") | |
fout.write(data) | |
fout.close() | |
for file in findSaveGames(): | |
dst = os.path.join(FILE_PATH, "d_" + os.path.basename(file)) | |
decodeSave(file, dst) |
This was a bit ago I didn't really remember the details.
Hi, thanks for responding! I'm just wondering what your approach was to finding the format of the files? I want to do that same in python for the latest versions of the game files. Do you recall how you determined the file formats? I mean...if you did that just by looking at the binary you have more skill than I do. I would assume there was some source defining the format used? Thanks again!
There is a lot you can tell just looking at the binary files. But I think I got the information off from a discord chat.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Interested to ask a question or two. Just a fellow coder and mod developer for NMS. I'm BigBuffaloBill on discord if you have a minute sometime.