#!/usr/bin/env python3 # Boktai 1 checksum fixer # Usage: python3 boktai1_checksum_fix.py SAVEGAME.SaveRAM import struct import sys # Memory blocks that are checksummed, array of (start, length) pairs, in bytes BLOCKS = [ (0x0000, 0x18), (0x00c0, 0x28), (0x0200, 0x28), (0x0340, 0x400), (0x0780, 0x418), (0x0dc0, 0x400), (0x1200, 0x418), (0x1840, 0x168), (0x1a40, 0x168), ] # Calculates checksum of xs, an array of uint16_t's. Returns 4 uint16_t's. def checksum(xs): ck_add = 0 ck_xor = 0 for x in xs: ck_add = (ck_add + x) & 0xffff ck_xor ^= x return [ # Constant 0xffff, # Number of bytes in this block len(xs)*2, # All halfwords folded with addition ck_add, # All halfwords folded with XOR ck_xor, ] if len(sys.argv) < 2: print("Usage: python3 " + sys.argv[0] + " SAVEGAME.SaveRAM") sys.exit(1) with open(sys.argv[1], "r+b") as f: for start, length in BLOCKS: f.seek(start) block = f.read(length) # The save is an array of big-endian halfwords, so we use > to convert # to native endianess when reading and writing halfwords = struct.iter_unpack(">H", block) check = checksum([x[0] for x in halfwords]) for c in check: f.write(struct.pack(">H", c)) print("OK")