diff options
author | Háčky <hatschky@gmail.com> | 2014-11-27 07:15:45 +0000 |
---|---|---|
committer | Háčky <hatschky@gmail.com> | 2014-11-27 07:15:45 +0000 |
commit | 319ed6d0e0266f5f6174a5acd929914db8cfae1d (patch) | |
tree | 76408d9cadcbed1e702efa8c44f4cf5e364b0a4d /scripts/checksum.py | |
parent | 17853b802692237d98f96d1a80caf2019f71753e (diff) |
Diffstat (limited to 'scripts/checksum.py')
-rw-r--r-- | scripts/checksum.py | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/scripts/checksum.py b/scripts/checksum.py new file mode 100644 index 0000000..8b5f63c --- /dev/null +++ b/scripts/checksum.py @@ -0,0 +1,89 @@ +import struct +import sys + +chunk_lengths = [0,0,0,6,2,5,12,5,3,1,2,5,5,5,1,13,13] + +bytewises = [] +bytewise_results = [] +wordwises = [] +wordwise_results = [] +crcs = [] +crc_results = [] + +data = "" +with open(sys.argv[1], 'rb') as f: + data = f.read() +f.closed + +base_address = struct.unpack('<I', data[1:5])[0] +i = 0x11 # first chunk location +while i < len(data): + chunk_type = ord(data[i]) + if chunk_type == 0x02: # END_OF_CHUNKS + break + elif chunk_type == 0x07: # CUSTOM_BERRY + start_address = struct.unpack('<I', data[i+1:i+5])[0] - base_address + bytewises.append([start_address + 0x52C, start_address, start_address + 0x52C]) + elif chunk_type == 0x0D: # BATTLE_TRAINER + start_address = struct.unpack('<I', data[i+1:i+5])[0] - base_address + wordwises.append([start_address + 0xB8, start_address, start_address + 0xB8]) + elif chunk_type == 0x0F: # CHECKSUM_BYTES + start_address = struct.unpack('<I', data[i+5:i+9])[0] - base_address + end_address = struct.unpack('<I', data[i+9:i+13])[0] - base_address + bytewise.append([i + 1, start_address, end_address]) + elif chunk_type == 0x10: # CHECKSUM_CRC + start_address = struct.unpack('<I', data[i+5:i+9])[0] - base_address + end_address = struct.unpack('<I', data[i+9:i+13])[0] - base_address + crcs.append([i + 1, start_address, end_address]) + elif chunk_type < 0x02 or chunk_type > 0x10: + print "Unknown chunk {0:X}".format(chunk_type) + raise TypeError + i += chunk_lengths[chunk_type] + + +# calculate and insert all wordwise checksums +for wordwise in wordwises: + sum = 0 + for i in range(wordwise[1], wordwise[2], 4): + sum = (sum + struct.unpack('<I', data[i:i+4])[0]) & 0xFFFFFFFF + wordwise_results.append(sum) +i = 0 +for wordwise in wordwises: + data = data[0:wordwise[0]] + struct.pack('<I', wordwise_results[i]) + data[(wordwise[0] + 4):] + i += 1 + + +# calculate and insert all bytewise checksums +for bytewise in bytewises: + sum = 0 + for i in range(bytewise[1], bytewise[2]): + sum = (sum + ord(data[i])) & 0xFFFFFFFF + bytewise_results.append(sum) +i = 0 +for bytewise in bytewises: + data = data[0:bytewise[0]] + struct.pack('<I', bytewise_results[i]) + data[(bytewise[0] + 4):] + i += 1 + + +# calculate and insert all CRC checksums +for crc in crcs: + sum = 0x1121 + for i in range(crc[1], crc[2]): + sum ^= ord(data[i]) + for j in range(8): + if(sum & 1): + sum = (sum >> 1) ^ 0x8408 + else: + sum >>= 1 + sum = ~sum & 0xFFFF + crc_results.append(sum) + +i = 0 +for crc in crcs: + data = data[0:crc[0]] + struct.pack('<I', crc_results[i]) + data[(crc[0] + 4):] + i += 1 + + +# write the updated file +out = open(sys.argv[2], 'w') +out.write(data)
\ No newline at end of file |