Skip to content

Instantly share code, notes, and snippets.

@dextercd
Last active May 11, 2024 07:25
Show Gist options
  • Save dextercd/8604729b30ce893f4ed57d2902d6143a to your computer and use it in GitHub Desktop.
Save dextercd/8604729b30ce893f4ed57d2902d6143a to your computer and use it in GitHub Desktop.
import struct
import fastlz
file = open("/home/dexter/sc/snoita/save00/world/world_0_0.png_petri", "rb")
file_content = file.read()
# This uses little-endian, the rest of the file uses big-endian
compressed_size, uncompressed_size = struct.unpack("<ii", file_content[0:8])
# Noita includes the compressed size at the start, not counting it and the
# uncompressed sizes.
assert compressed_size == len(file_content) - 8
# pyfastlz expects the decompressed size at the start of the buffer, which
# we can match by taking a slice that discards the first 4 bytes
uncompressed_data = fastlz.decompress(file_content[4:])
assert uncompressed_size == len(uncompressed_data)
version, width, height = struct.unpack(">iii", uncompressed_data[0:12])
print(f"{version=}")
print(f"{width=}")
print(f"{height=}")
# After this comes:
# 512*512 bytes that are the materials in the world (these are indices into the materials list)
# Material list length followed by that many
# - mat name length
# - mat name bytes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment