Skip to content

Instantly share code, notes, and snippets.

@faried
Created April 4, 2012 14:29
Show Gist options
  • Save faried/2301766 to your computer and use it in GitHub Desktop.
Save faried/2301766 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
"""DCPU-16 disassembler.
Run as parse.py /path/to/dcpufile.
http://0x10c.com/doc/dcpu-16.txt
"""
import sys
MASK_B = 0b1111110000000000
MASK_A = 0b0000001111110000
MASK_O = 0b0000000000001111
REGS = ['A', 'B', 'C', 'X', 'Y', 'Z', 'I', 'J']
OPCODES = ["", "SET", "ADD", "SUB", "MUL", "DIV", "MOD", "SHL", "SHR",
"AND", "BOR", "XOR", "IFE", "IFN", "IFG", "IFB"]
SPECIALS = ["POP", "PEEK", "PUSH", "SP", "PC", "O"]
def wrs(thing):
"""Write something with a space after it."""
sys.stdout.write(thing + ' ')
def nextword(idx, data):
"""Return the next word to operate on."""
return (ord(data[idx]) << 8) + ord(data[idx+1])
def parsearg(i, val, data):
"""An argument to an opcode can be of several types.
Returns an integer to advance the index in the data array.
"""
newi = 0
# register
if val >= 0x00 and val <= 0x07:
wrs(REGS[val])
# [register]
elif val >= 0x08 and val <= 0x0f:
wrs('[%s]' % REGS[val - 0x08])
# [nextword + register]
elif val >= 0x10 and val <= 0x17:
i += 2
word = nextword(i, data)
wrs('[%s + %s]' % (hex(word), REGS[val - 0x10]))
newi = 2
elif val >= 0x18 and val <= 0x1d:
wrs(SPECIALS[val - 0x18])
# [nextword]
elif val == 0x1e:
i += 2
word = nextword(i, data)
wrs('[%s]' % hex(word))
newi = 2
# literal nextword
elif val == 0x1f:
i += 2
word = nextword(i, data)
wrs(hex(word))
newi = 2
# literal between 0 and 16
elif val >= 0x20 and val <= 0x3f:
val -= 0x20
wrs(hex(val))
# something else
else:
wrs(hex(val))
return newi
def main(args):
"""Main branching logic."""
if len(args) != 1:
sys.stderr.write('usage: %s datafile\n')
sys.exit(1)
data = file(args[0], 'rb').read()
ldata = len(data)
idx = 0
while idx < ldata:
# print the PC
wrs('0x%02x' % (idx / 2))
word = nextword(idx, data)
opcode = word & MASK_O
if opcode == 0:
opcode = (word & MASK_A) >> 4
arg = (word & MASK_B) >> 10
if opcode == 0:
if arg != 0:
wrs('SPECIAL')
else:
wrs('0000')
elif opcode == 1:
wrs('JSR')
idx += parsearg(idx, arg, data)
else:
wrs('RESERVED')
else:
wrs(OPCODES[opcode])
arg1 = (word & MASK_A) >> 4
arg2 = (word & MASK_B) >> 10
idx += parsearg(idx, arg1, data)
idx += parsearg(idx, arg2, data)
sys.stdout.write('\n')
idx += 2
if __name__ == '__main__':
main(sys.argv[1:])
# eof
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment