Skip to content

Instantly share code, notes, and snippets.

@apocalyptech
Last active May 16, 2024 15:06
Show Gist options
  • Save apocalyptech/8f8815c06bde9cd46d5170e1548c1e66 to your computer and use it in GitHub Desktop.
Save apocalyptech/8f8815c06bde9cd46d5170e1548c1e66 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
# vim: set expandtab tabstop=4 shiftwidth=4:
import struct
import argparse
def main():
parser = argparse.ArgumentParser(
description='Fix Animal Well savefile verification after edits',
)
parser.add_argument('filename',
nargs=1,
type=str,
help='Save file to edit',
)
args = parser.parse_args()
args.filename = args.filename[0]
with open(args.filename, 'r+b') as df:
# Read the data and at least check the first uint32 to see if
# it's 9, which we believe is a version number for the savefile.
data = df.read()
df.seek(0)
version = struct.unpack('<I', df.read(4))[0]
if version != 9:
raise RuntimeError(f'{args.filename} does not look like an Animal Well savefile that we understand')
# Compute the XOR'd checksum (which lives at byte 0xD). Be sure
# to omit whatever checksum is currently living there. (We could
# substitute 0x00 but that wouldn't change the XOR, so we're just
# skipping the byte entirely.)
total = 0
for byte in data[:13] + data[14:]:
total ^= byte
# Check to see if we even need to write it
if total == data[0xD]:
print(f'{args.filename}: No need to write checksum -- 0x{total:02X} is already correct')
else:
packed = struct.pack('<B', total)
df.seek(0xD)
df.write(packed)
print(f'{args.filename}: Wrote new checksum 0x{total:02X} (previous: 0x{data[0xD]:02X})')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment