#!/usr/bin/env python3 import struct OP = [ # Mnemonic, mask, value, xmask, ymask, kmask, klabel ('CLS', '', 0xffff, 0x00e0, 0x0000, 0x0000, 0x0000, False), ('RET', '', 0xffff, 0x00ee, 0x0000, 0x0000, 0x0000, False), ('SYS', '{k}', 0xf000, 0x0000, 0x0000, 0x0000, 0x0fff, True), ('JP', '{k}', 0xf000, 0x1000, 0x0000, 0x0000, 0x0fff, True), ('CALL', '{k}', 0xf000, 0x2000, 0x0000, 0x0000, 0x0fff, True), ('SE', 'V{x:01x}, {k:02x}', 0xf000, 0x3000, 0x0f00, 0x0000, 0x00ff, False), ('SNE', 'V{x:01x}, {k:02x}', 0xf000, 0x4000, 0x0f00, 0x0000, 0x00ff, False), ('SE', 'V{x:01x}, V{y:01x}', 0xf00f, 0x5000, 0x0f00, 0x00f0, 0x0000, False), ('LD', 'V{x:01x}, {k:02x}', 0xf000, 0x6000, 0x0f00, 0x0000, 0x00ff, False), ('ADD', 'V{x:01x}, {k:02x}', 0xf000, 0x7000, 0x0f00, 0x0000, 0x00ff, False), ('LD', 'V{x:01x}, V{y:01x}', 0xf00f, 0x8000, 0x0f00, 0x00f0, 0x0000, False), ('OR', 'V{x:01x}, V{y:01x}', 0xf00f, 0x8001, 0x0f00, 0x00f0, 0x0000, False), ('AND', 'V{x:01x}, V{y:01x}', 0xf00f, 0x8002, 0x0f00, 0x00f0, 0x0000, False), ('XOR', 'V{x:01x}, V{y:01x}', 0xf00f, 0x8003, 0x0f00, 0x00f0, 0x0000, False), ('ADD', 'V{x:01x}, V{y:01x}', 0xf00f, 0x8004, 0x0f00, 0x00f0, 0x0000, False), ('SUB', 'V{x:01x}, V{y:01x}', 0xf00f, 0x8005, 0x0f00, 0x00f0, 0x0000, False), ('SHR', 'V{x:01x}, V{y:01x}', 0xf00f, 0x8006, 0x0f00, 0x00f0, 0x0000, False), ('SHL', 'V{x:01x}, V{y:01x}', 0xf00f, 0x800e, 0x0f00, 0x00f0, 0x0000, False), ('SNE', 'V{x:01x}, V{y:01x}', 0xf00f, 0x9000, 0x0f00, 0x00f0, 0x0000, False), ('LD', 'I, {k}', 0xf000, 0xa000, 0x0000, 0x0000, 0x0fff, True), ('JP', 'V0, {k}', 0xf000, 0xb000, 0x0000, 0x0000, 0x0fff, True), ('RND', 'V{x:01x}, {k:02x}', 0xf000, 0xc000, 0x0f00, 0x0000, 0x00ff, False), ('DRW', 'V{x:01x}, V{y:01x}, {k:02x}', 0xf000, 0xd000, 0x0f00, 0x00f0, 0x000f, False), ('SKP', 'V{x:01x}', 0xf0ff, 0xe09e, 0x0f00, 0x0000, 0x0000, False), ('SKNP', 'V{x:01x}', 0xf0ff, 0xe0a1, 0x0f00, 0x0000, 0x0000, False), ('LD', 'V{x:01x}, DT', 0xf0ff, 0xf007, 0x0f00, 0x0000, 0x0000, False), ('LD', 'V{x:01x}, K', 0xf0ff, 0xf00a, 0x0f00, 0x0000, 0x0000, False), ('LD', 'DT, V{x:01x}', 0xf0ff, 0xf015, 0x0f00, 0x0000, 0x0000, False), ('LD', 'ST, V{x:01x}', 0xf0ff, 0xf018, 0x0f00, 0x0000, 0x0000, False), ('ADD', 'I, V{x:01x}', 0xf0ff, 0xf01e, 0x0f00, 0x0000, 0x0000, False), ('LD', 'F, V{x:01x}', 0xf0ff, 0xf029, 0x0f00, 0x0000, 0x0000, False), ('LD', 'B, V{x:01x}', 0xf0ff, 0xf033, 0x0f00, 0x0000, 0x0000, False), ('LD', '[I], V{x:01x}', 0xf0ff, 0xf055, 0x0f00, 0x0000, 0x0000, False), ('LD', 'V{x:01x}, [I]', 0xf0ff, 0xf065, 0x0f00, 0x0000, 0x0000, False), ('DATA', '{k:04x}', 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, False) ] def c8decode(ins): def _unmask(v, m): if m == 0: return None r = v & m while (m & 1) == 0: m >>= 1 r >>= 1 return r for mn, fmt, mask, value, xmask, ymask, kmask, klabel in OP: if (ins & mask) == value: xo = _unmask(ins, xmask) yo = _unmask(ins, ymask) ko = _unmask(ins, kmask) return (mn, fmt, xo, yo, ko, klabel) def disasm(filename, org=0x200): pc = org targets = set() listing = [] with open(filename, 'rb') as f: while True: w = f.read(2) if len(w) != 2: break instr = struct.unpack('>H', w)[0] mn, fmt, xo, yo, ko, klabel = c8decode(instr) if klabel: targets.add(ko) listing.append((pc, instr, mn, fmt, xo, yo, ko, klabel)) pc += 2 end = pc print(f"""; ; {filename} ; start={org:03x} end={end:03x} size={end-org}(dec) ; """) for pc, instr, mn, fmt, xo, yo, ko, klabel in listing: if pc in targets: label = "l%03x" % (pc,) else: label = "" if klabel: if org <= ko <= end: ko = f"l{ko:03x}" else: ko = f"{ko:03x}" o = fmt.format(x=xo, y=yo, k=ko) print(f"{label:8s} {mn:5s} {o:12s} ; {pc:03x}: {instr:04x}") if __name__ == '__main__': import sys for fn in sys.argv[1:]: disasm(fn)