#!/usr/bin/env python3 from sys import argv from itertools import cycle, islice from subprocess import run run(['sh', '-c', 'rm -f dcm*']) def roundrobin(*iterables): "roundrobin('ABC', 'D', 'EF') --> A D E B F C" # Recipe credited to George Sakkis num_active = len(iterables) nexts = cycle(iter(it).__next__ for it in iterables) while num_active: try: for next in nexts: yield next() except StopIteration: # Remove the iterator we just exhausted from the cycle. num_active -= 1 nexts = cycle(islice(nexts, num_active)) filenames = argv[1:] roms = [None] * len(filenames) for i, f in enumerate(filenames): with open(f, 'rb') as fd: roms[i] = fd.read() path_offset_stop_tuples = [] with open(filenames[0] + '-info.txt') as f: for l in f: if '\t' not in l: continue label, directive, *misc = l.split() if directive.lower() != 'file': continue file_offset = int(label, 16) file_path, _, _ = misc[0].partition(',') for l in f: if '\t' not in l: continue label, directive, *_ = l.split() if directive.lower() != 'endf': continue file_len = int(label, 16) path_offset_stop_tuples.append((file_path, file_offset, file_len)) break # for p, o, l in path_offset_stop_tuples: # print(p, hex(o), hex(l)) path_offset_bin_tuples = [] for p, o, s in path_offset_stop_tuples: b = roms[0][o:s] path_offset_bin_tuples.append((p,o,b)) skippery = 128 single_letters = iter('bcdefg') for n, r in zip(filenames[1:], roms[1:]): print('Comparing %s against original %s' % (n, filenames[0])) sl = next(single_letters) for objpath, objoffset, objbin in path_offset_bin_tuples: _, _, objname = objpath.rpartition('/') earlier = reversed(range(0, objoffset, 16)) later = range(objoffset, len(r)-len(objbin)+16, 16) bothways = roundrobin(later, earlier) for tryoffset in bothways: # print(hex(tryoffset), end='=', flush=True) objbincmp = r[tryoffset:tryoffset+len(objbin)] a = objbin[0:len(objbin):skippery] b = objbincmp[0:len(objbin):skippery] maxmatches = len(a) matches = sum(ax == bx for (ax, bx) in zip(a, b)) # print(str(int(matches*100/len(objbin))) + '%', end= ' ', flush=True) if matches * 3 >= maxmatches: print('Found %s at %X (moved from %X)' % (objname, tryoffset, objoffset)) with open('dcm-a-%05X-%s' % (objoffset, objname), 'wb') as f: f.write(objbin) with open('dcm-%s-%05X-%s-%05X' % (sl, objoffset, objname, tryoffset), 'wb') as f: f.write(objbincmp) print('\tvbindiff dcm*%s*' % objname) break else: print('Did not find %s' % objname)