import sys, array # # constants # state_assign = 1 state_compare = 2 state_done = 3 # # functions # def prettyip(ip): return ("ROMC:%04X" % (ip + 0x4000 - 0x30000)) def arg_standard(mode): global ip if mode in (0, 1, 2): sys.stdout.write("@CF%02X.%c " % (data[ip], "bwl"[mode])) ip += 1 elif mode in (3, 4): sys.stdout.write("@(CF%02X).%c " % (data[ip], "bw"[mode - 3])) ip += 1 elif mode == 5: sys.stdout.write("RANDOM(0x%02X) " % data[ip]) ip += 1 elif mode == 6: sys.stdout.write("0x%02X " % data[ip]) ip += 1 else: sys.stdout.write("0x%04X " % (data[ip] + 0x100 * data[ip+1])) ip += 2 def arg_random(mode): global ip, state, state_compare sys.stdout.write("RANDOM(@CF%02X.b) " % data[ip]) if mode: sys.stderr.write("%s: Modeless token has mode bits set; wtf?!\n" % prettyip(ip - 1)) if state == state_compare: sys.stderr.write("%s: RANDOM(address) used in an IF statement; this doesn't work!\n" % prettyip(ip - 1)) ip += 1 def arg_16bit(mode): global ip if mode in (0, 1, 2): sys.stdout.write("@%04X.%c " % ((data[ip] + 0x100 * data[ip+1]), "bwl"[mode])) elif mode in (3, 4): sys.stdout.write("@(%04X).%c " % ((data[ip] + 0x100 * data[ip+1]), "bw"[mode - 3])) else: sys.stdout.write("@(%04X).l " % (data[ip] + 0x100 * data[ip+1])) sys.stderr.write("%s: 16-bit address token has weird mode bits set; wtf?!\n" % prettyip(ip - 1)) ip += 2 def arg_let(mode): global ip if mode in (0, 1, 2): sys.stdout.write("@CF%02X.%c " % (data[ip], "bwl"[mode])) ip += 1 elif mode in (3, 4): sys.stdout.write("@(CF%02X).%c " % (data[ip], "bw"[mode - 3])) ip += 1 else: sys.stdout.write("@%04X.%c " % ((data[ip] + 0x100 * data[ip+1]), "bwl"[mode - 5])) ip += 2 def arg_jump(mode): global ip sys.stdout.write("%04X " % (data[ip] + 0x100 * data[ip+1])) if mode: sys.stderr.write("%s: Modeless token has mode bits set; wtf?!\n" % prettyip(ip - 1)) ip += 2 def arg_incdec(mode): global ip if mode in (0, 1, 2): sys.stdout.write("@CF%02X.%c " % (data[ip], "bwl"[mode])) else: sys.stdout.write("@CF%02X.l " % data[ip]) sys.stderr.write("%s: INC/DEC token has weird mode bits set; wtf?!\n" % prettyip(ip - 1)) ip += 1 def arg_indirect(mode): global ip sys.stdout.write("@CF%02X " % data[ip]) if mode: sys.stderr.write("%s: Modeless token has mode bits set; wtf?!\n" % prettyip(ip - 1)) ip += 1 def arg_unknown(mode): global ip sys.stdout.write("%02X " % data[ip]) if mode: sys.stderr.write("%s: Modeless token has mode bits set; wtf?!\n" % prettyip(ip - 1)) ip += 1 def arg_none(mode): if mode: sys.stderr.write("%s: Argumentless token has mode bits set; wtf?!\n" % prettyip(ip - 1)) def arg_illegal(mode): sys.stderr.write("%s: Illegal token; looks like we hit data!\n" % prettyip(ip - 1)) # # token definitions # statement_tokens = ( ("LET ", arg_let, state_assign), ("IF ", arg_standard, state_compare), ("GOTO ", arg_jump, state_done), ("SYS ", arg_jump, state_done), ("SET ", arg_unknown, state_done), ("GOSUB ", arg_jump, state_done), ("RETURN ", arg_none, state_done), ("INC ", arg_incdec, state_done), ("DEC ", arg_incdec, state_done), ("GOSUB ", arg_indirect, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("??? ", arg_illegal, state_done), ("END ", arg_none, state_done)) expression_tokens = ( ("", arg_standard, 0), ("* ", arg_standard, 0), ("/ ", arg_standard, 0), ("+ ", arg_standard, 0), ("- ", arg_standard, 0), ("AND ", arg_standard, 0), ("OR ", arg_standard, 0), ("NAND ", arg_standard, 0), ("XOR ", arg_standard, 0), ("NOT ", arg_standard, 0), (">> ", arg_standard, 0), ("<< ", arg_standard, 0), ("= ", arg_standard, 0), ("< ", arg_standard, 0), ("> ", arg_standard, 0), ("<= ", arg_standard, 0), (">= ", arg_standard, 0), ("-- ", arg_standard, 0), ("= ", arg_random, 0), ("= ", arg_16bit, 0), ("", arg_standard, 0), ("", arg_standard, 0), ("", arg_standard, 0), ("", arg_standard, 0), ("", arg_standard, 0), ("", arg_standard, 0), ("", arg_standard, 0), ("", arg_standard, 0), ("", arg_standard, 0), ("", arg_standard, 0), ("", arg_standard, 0), ("", arg_none, state_done)) # # main program # try: fn = sys.argv[1] startip = int(sys.argv[2],0) endip = int(sys.argv[3],0) except (IndexError, ValueError): sys.exit("Usage: debasic filename start end\n") f = open(fn, "rb") data = array.array('B') data.fromstring(f.read()) f.close() ip = startip state = state_done while ip <= endip: sys.stdout.write("%s " % prettyip(ip)) token = data[ip] & 0x1F mode = data[ip] >> 5 ip += 1 sys.stdout.write(statement_tokens[token][0]) statement_tokens[token][1](mode) state = statement_tokens[token][2] while state != state_done: token = data[ip] & 0x1F mode = data[ip] >> 5 ip += 1 sys.stdout.write(expression_tokens[token][0]) expression_tokens[token][1](mode) if expression_tokens[token][2]: state = expression_tokens[token][2] sys.stdout.write("\n")