#!/usr/bin/env python3 # Compare two ride traces in stsim's line format -- stsim's against the # real C64's (c64trace.py), or a golden against the current tree -- field # by field. # # compare.py [maxReports] # the first maxReports ticks that differ (default 12), with the # fields that differ, then how often and from when each field does # compare.py --picture # the screen cells, colour cells and glyphs that differ on one tick, # from the two machines' picture dumps (STSIM_RAW / c64trace's rawOut) import json import sys SCREEN_CELLS = 1000 SCREEN_COLS = 40 CHARSET = 2048 GLYPH_BYTES = 8 RAW_BYTES = SCREEN_CELLS * 2 + CHARSET def traces(pathA, pathB, maxReports): a = [json.loads(line) for line in open(pathA)] b = [json.loads(line) for line in open(pathB)] counts = {} first = {} reports = 0 for i in range(min(len(a), len(b))): x, y = a[i], b[i] fields = [k for k in x if x.get(k) != y.get(k)] + [k for k in y if k not in x] for k in fields: counts[k] = counts.get(k, 0) + 1 first.setdefault(k, i) if fields and reports < maxReports: print('line %d: ' % i + ' '.join('%s: %s vs %s' % (k, x.get(k), y.get(k)) for k in fields)) reports += 1 if len(a) != len(b): print('lengths differ: %d vs %d lines' % (len(a), len(b))) if not counts: print('every common line matches' if len(a) != len(b) else 'identical') return print('fields that differ (lines, first line): ' + ', '.join('%s %d @%d' % (k, counts[k], first[k]) for k in sorted(counts, key=first.get))) def picture(pathA, pathB, tick): a = open(pathA, 'rb').read()[tick * RAW_BYTES:(tick + 1) * RAW_BYTES] b = open(pathB, 'rb').read()[tick * RAW_BYTES:(tick + 1) * RAW_BYTES] for i in range(SCREEN_CELLS): if a[i] != b[i]: print('screen row %d col %d: %02X vs %02X' % (i // SCREEN_COLS, i % SCREEN_COLS, a[i], b[i])) for i in range(SCREEN_CELLS): if a[SCREEN_CELLS + i] != b[SCREEN_CELLS + i]: print('colour row %d col %d: %X vs %X' % (i // SCREEN_COLS, i % SCREEN_COLS, a[SCREEN_CELLS + i], b[SCREEN_CELLS + i])) for ch in range(CHARSET // GLYPH_BYTES): o = SCREEN_CELLS * 2 + ch * GLYPH_BYTES if a[o:o + GLYPH_BYTES] != b[o:o + GLYPH_BYTES]: print('glyph %02X: %s vs %s' % (ch, a[o:o + GLYPH_BYTES].hex(), b[o:o + GLYPH_BYTES].hex())) def main(): if len(sys.argv) == 5 and sys.argv[1] == '--picture': picture(sys.argv[2], sys.argv[3], int(sys.argv[4])) return 0 if len(sys.argv) not in (3, 4): print('usage: compare.py [maxReports] | --picture ', file=sys.stderr) return 2 traces(sys.argv[1], sys.argv[2], int(sys.argv[3]) if len(sys.argv) == 4 else 12) return 0 if __name__ == '__main__': sys.exit(main())