57 lines
2.1 KiB
Python
57 lines
2.1 KiB
Python
import zlib
|
|
|
|
MAGIC_BYTES = b"PlZ"
|
|
|
|
|
|
def decompress_sav_to_gvas(data: bytes) -> tuple[bytes, int]:
|
|
uncompressed_len = int.from_bytes(data[0:4], byteorder="little")
|
|
compressed_len = int.from_bytes(data[4:8], byteorder="little")
|
|
magic_bytes = data[8:11]
|
|
save_type = data[11]
|
|
# Check for magic bytes
|
|
if magic_bytes != MAGIC_BYTES:
|
|
raise Exception(
|
|
f"not a compressed Palworld save, found {magic_bytes} instead of {MAGIC_BYTES}"
|
|
)
|
|
# Valid save types
|
|
if save_type not in [0x30, 0x31, 0x32]:
|
|
raise Exception(f"unknown save type: {save_type}")
|
|
# We only have 0x31 (single zlib) and 0x32 (double zlib) saves
|
|
if save_type not in [0x31, 0x32]:
|
|
raise Exception(f"unhandled compression type: {save_type}")
|
|
if save_type == 0x31:
|
|
# Check if the compressed length is correct
|
|
if compressed_len != len(data) - 12:
|
|
raise Exception(f"incorrect compressed length: {compressed_len}")
|
|
# Decompress file
|
|
uncompressed_data = zlib.decompress(data[12:])
|
|
if save_type == 0x32:
|
|
# Check if the compressed length is correct
|
|
if compressed_len != len(uncompressed_data):
|
|
raise Exception(f"incorrect compressed length: {compressed_len}")
|
|
# Decompress file
|
|
uncompressed_data = zlib.decompress(uncompressed_data)
|
|
# Check if the uncompressed length is correct
|
|
if uncompressed_len != len(uncompressed_data):
|
|
raise Exception(f"incorrect uncompressed length: {uncompressed_len}")
|
|
|
|
return uncompressed_data, save_type
|
|
|
|
|
|
def compress_gvas_to_sav(data: bytes, save_type: int) -> bytes:
|
|
uncompressed_len = len(data)
|
|
compressed_data = zlib.compress(data)
|
|
compressed_len = len(compressed_data)
|
|
if save_type == 0x32:
|
|
compressed_data = zlib.compress(compressed_data)
|
|
|
|
# Create a byte array and append the necessary information
|
|
result = bytearray()
|
|
result.extend(uncompressed_len.to_bytes(4, byteorder="little"))
|
|
result.extend(compressed_len.to_bytes(4, byteorder="little"))
|
|
result.extend(MAGIC_BYTES)
|
|
result.extend(bytes([save_type]))
|
|
result.extend(compressed_data)
|
|
|
|
return bytes(result)
|