#!/usr/bin/env python3 import os, struct, sys, ast, argparse def read_uint32_be(data, offset): return struct.unpack('>I', data[offset:offset+4])[0] def generate_checksum(data): seed = 0xDF26F436 t1 = t2 = t3 = t4 = t5 = t6 = seed for i in range(0x1000, 0x1000 + 0x100000, 4): d = read_uint32_be(data, i) shift = d & 0x1F r = ((d << shift) & 0xFFFFFFFF) | ((d >> (32 - shift)) & 0xFFFFFFFF) if t6 + d > 0xFFFFFFFF: t4 += 1 t6 = (t6 + d) & 0xFFFFFFFF t3 ^= d t5 = (t5 + r) & 0xFFFFFFFF if t2 > d: t2 ^= r else: t2 ^= t6 ^ d t1 = (t1 + (read_uint32_be(data, 0x0750 + (i & 0xFF)) ^ d)) & 0xFFFFFFFF chksum0 = t6 ^ t4 ^ t3 chksum1 = t5 ^ t2 ^ t1 return chksum0, chksum1 if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('files', help='file list') parser.add_argument('out', help='output file') parser.add_argument('-c', '--compress', help='decompress file, otherwise compress it', action='store_true', default=False) args = parser.parse_args() outputBuffer = bytearray() with open(args.out, 'wb') as w, open(args.files, 'rt') as f: total_size = 0 dmadata_table = ast.literal_eval(f.read()) for base_file, comp_file, _, _ in dmadata_table: if args.compress: if comp_file.endswith('dmadata'): dma_file_name = comp_file break else: if base_file.endswith('dmadata'): dma_file_name = base_file break else: print('Could not find dmadata') sys.exit(1) for base_file, comp_file, _, _ in dmadata_table: file_name = comp_file if args.compress and comp_file != '' else base_file if file_name != '': try: with open(file_name, 'rb') as current_file: file_data = current_file.read() outputBuffer += file_data total_size += len(file_data) except: print('Could not open file ' + file_name) sys.exit(1) required_rom_size = 1 << (len(outputBuffer) - 1).bit_length() while total_size < required_rom_size: outputBuffer.append(total_size % 256) total_size += 1 chksum0, chksum1 = generate_checksum(outputBuffer) outputBuffer[0x10:0x18] = chksum0.to_bytes(4, byteorder='big') + chksum1.to_bytes(4, byteorder='big') w.write(outputBuffer)