#!/usr/bin/env python3 """Dump PARTOUT(4.0) pinball .DAT structure: groups, component type ids, float attribute ids.""" import struct, sys, collections FIXED = {0: 2, 2: 2, 13: 0} # partman::_field_size; everything else has a uint32 length prefix def parse(path): d = open(path, 'rb').read() sig = d[0:21].split(b'\0')[0].decode() app = d[21:71].split(b'\0')[0].decode() desc = d[71:171].split(b'\0')[0].decode() filesize, ngroups, sizeofbody, unknown = struct.unpack_from('= 4: g['attrs'].append(int(struct.unpack_from(' 1: base = 'CADET.DAT' if 'CADET.DAT' in results else list(results)[0] bf, bsv, battr = results[base] for name, (f, svs, attrs) in results.items(): if name == base: continue print(f"--- {name} vs {base}") print(f" component types only in {name}: {sorted(set(svs) - set(bsv))}") print(f" component types missing from {name}: {sorted(set(bsv) - set(svs))}") print(f" attrs only in {name}: {sorted(set(attrs) - set(battr))}") print(f" attrs missing from {name}: {sorted(set(battr) - set(attrs))}") bn = {g['name'] for g in bf['groups'] if g['name']} fn = {g['name'] for g in f['groups'] if g['name']} print(f" shared component names: {len(bn & fn)} / {len(fn)} in {name}") print(f" sample names only in {name}: {sorted(fn - bn)[:25]}") print()