72 lines
2.9 KiB
Python
72 lines
2.9 KiB
Python
#!/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 <a.jsonl> <b.jsonl> [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 <a.raw> <b.raw> <tick>
|
|
# 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 <a.jsonl> <b.jsonl> [maxReports] | --picture <a.raw> <b.raw> <tick>', 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())
|