def example():
    m = mem.Stackup((FILENAME,), nextto=__file__)
    cx = mcs48.mcs48()
    cx.m.map(m, 0)

    cx.vectors()

    for a in range(0x0a, 0x21):
        t = cx.m[a]
        data.Codeptr(cx.m, a, a + 1, t)
        cx.disass(t)
        cx.m.set_block_comment(t, "From PTR 0x%x" % a)


    for a in range(0x000, 0x800, 0x100):
        cx.disass(a + 0xfe)

    data.Txt(cx.m, 0x5ae, 0x5dc, label=False)
    data.Txt(cx.m, 0x5dc, 0x5f4, label=False)

    for a in (
            0x695,
            0x700,
            0x70d,
            0x720,
    ):
        cx.disass(a)
        cx.m.set_block_comment(a, "Manual")
    return NAME, (cx.m,)
def round_0(cx):
    ''' Things to do before the disassembler is let loose '''

    for a in (
        0x201ec,
        0x20212,
        0x20226,
    ):
        data.Txt(cx.m, a, a + 1);

    cx.m.set_label(0x20298, "board_id_list")
    data.Const(cx.m, 0x20298, 0x2029e)

    for a in (
        0x201b2,
        0x201ba,
        0x201c2,
        0x201ca,
        0x201d2,
    ):
        data.Txt(cx.m, a, a + 8)
    for a, b in (
        (0x20924, "Load_RegFile_Only()"),
        (0x20b7a, "Load_RegFile_Dispatch()"),
        (0x2102a, "Load_Control_Store()"),
    ):
        cx.m.set_label(a, b)
        cx.m.set_block_comment(a, b)
    
    cx.m.set_block_comment(0x2115a, "idx=0, adr=6, TYP")
    cx.m.set_block_comment(0x211a6, "idx=1, adr=7, VAL")
    cx.m.set_block_comment(0x211f4, "idx=2, adr=3, FIU")
    cx.m.set_block_comment(0x21242, "idx=4, adr=4, IOC")
    cx.m.set_block_comment(0x21300, "idx=3, adr=2, SEQ")
def round_0(cx):
    ''' Things to do before the disassembler is let loose '''
    for a in range(0x2012c, 0x20150, 4):
        data.Txt(cx.m, a, a + 4, label=True)
    data.Txt(cx.m, 0x20156, 0x2015a, label=True)

    cx.m.set_block_comment(0x20aa6, " does READ_NOVRAM_DATA.*")

    cx.m.set_label(0x206be, "GetBoardName(&String, Byte)")
    cx.m.set_label(0x214e6, "ReEnterBoard(?)")
    cx.m.set_label(0x22582, "TestRamBoard(?)")
def round_0(cx):
    ''' Things to do before the disassembler is let loose '''

    cx.m.set_label(0x116ca, 'months')
    for a in range(0x116ca, 0x116ee, 0x3):
        data.Txt(cx.m, a, a + 0x3, label=False)

    cx.m.set_label(0x12f12, 'error_messages')
    for a in range(0x12f12, 0x130f2, 0x1e):
        data.Txt(cx.m, a, a + 0x1e, label=False)

    cx.m.set_label(0x1312a, 'error_messages2')
    for a in range(0x1312a, 0x1330a, 0x1e):
        data.Txt(cx.m, a, a + 0x1e, label=False)

    cx.m.set_label(0x14824, 'push_error_messages')
    for a in range(0x14824, 0x149e6, 0x1e):
        data.Txt(cx.m, a, a + 0x1e, label=False)

    cx.m.set_label(0x149e6, 'exp_error_messages')
    for a in range(0x149e6, 0x14ba8, 0x1e):
        data.Txt(cx.m, a, a + 0x1e, label=False)

    cx.m.set_label(0x15ca8, 'tape_error_messages')
    for a in range(0x15ca8, 0x15e4c, 0x1e):
        data.Txt(cx.m, a, a + 0x1e, label=False)

    cx.m.set_label(0x15eb2, 'tape_error2_messages')
    for a in range(0x15eb2, 0x16056, 0x1e):
        data.Txt(cx.m, a, a + 0x1e, label=False)

    cx.m.set_label(0x1a2aa, 'config_strings')
    for a in range(0x1a2aa, 0x1a43a, 0x14):
        data.Txt(cx.m, a, a + 0x14, label=False)

    cx.m.set_label(0x18479, "ExpDestinations[16]")
    for a in range(0x18479, 0x18519, 10):
        data.Txt(cx.m, a, a + 10, label=False)

    cx.m.set_label(0x18519, "ExpStatus[10]")
    for a in range(0x18519, 0x1857d, 10):
        data.Txt(cx.m, a, a + 10, label=False)

    cx.m.set_label(0x11a36, "Str2Int(String, &LongInt, Long, Long, &Byte)")
    cx.m.set_label(0x11ab4, "Month(String, &LongInt, &Void)")
    cx.m.set_label(0x1330a, "ReportError(Byte error, Byte mode, String)")
    cx.m.set_label(0x1371a, "NameI(Char*, &void)")

    cx.m.set_label(0x1b0b8, "cur_push_level");
Exemple #5
0
	def __init__(self, pj, cpu, lo):
		super().__init__(pj, lo, lo + 10, "MenuPage")
		t = pj.m.bu16(lo)
		y1 = data.Txt(pj, t, t + 40, label=False)
		y1.compact = True
		y2 = data.Txt(pj, t + 40, t + 80, label=False)
		y2.compact = True
		self.t1 = y1.txt
		self.t2 = y2.txt
		self.ptr = []
		for i in range(1, 5):
			u = pj.m.bu16(lo + 2 * i)
			self.ptr.append(u)
			if u >= pj.m.lo and u < pj.m.hi:
				cpu.disass(u)
 def assy_str(self):
     a = self.lo
     m = self.lang.m
     for o, i in (
         (4, (0x70, 0x72,)),
         (6, (0x10,)),
         (7, (0xd9,)),
         (8, (0x51,)),
         (9, (0xc8, 0xc9,)),
         (10, (0xff,)),
         (11, (0xfc,)),
     ):
         if m[a + o] not in i:
             # print(self, "@%x" % o, i, "0x%x" % m[a + o])
             raise assy.Invalid()
     d = a + 2 + m.bs16(a + 2)
     i = m[a + 5] + 1
     a = self.lo
     m = self.lang.m
     for j in range(d, d + i):
         if not 0x20 <= m[j] <= 0x7e and m[j] not in (9, 10, 12, 13):
             raise assy.Invalid()
     y = data.Txt(m, d, d + i, label=False)
     m.set_line_comment(a, '"' + y.txt + '"')
     raise assy.Invalid()
Exemple #7
0
def str_len_args(pj, dst, args, argl):
	return
	for i in pj.m:
		if type(i) != decompile.Call or i.dst != dst:
			continue
		if i.args[args][:3] != "#0x":
			continue
		if argl >= 0 and i.args[argl][:3] != "#0x":
			continue
		s = int(i.args[args][1:],16)
		if s < pj.m.lo or s >= pj.m.hi:
			continue
		if argl < 0:
			l = -argl
		else:
			l = int(i.args[argl][1:],16)
		print("SL", "%04x" % s, l, i, i.args)
		j = pj.m.find_lo(s)
		if len(j) == 0:
			y = data.Txt(pj, s, s + l)
			y.compact = True
			j.append(y)
			print("SLN", y.txt)
			arg_strings.add(s)
		elif s not in arg_strings:
			print("SLX", pj.pg, "%04x" % j[0].lo, j[0].txt)
		i.lcmt += '"%s"\n' % j[0].txt
Exemple #8
0
def cmd_tbl(cx, start, end):
    x = cx.m.add_range(start, end, txt="CMD_TABLE")
    cx.m.set_label(start, "CMD_TABLE")
    l = list()
    for a in range(start, end, 2):
        x = data.Txt(cx.m, a, a + 2, label=False)
        l.append(x.txt)
    return l
Exemple #9
0
 def assy_inltxt(self):
     y = data.Txt(self.lang.m,
                  self.lo + 2,
                  label=False,
                  splitnl=True,
                  align=2)
     self.lang.disass(y.hi)
     raise assy.Invalid("Inline text hack")
def flow_check(asp, ins):
    ''' Flow-check to capture inline strings '''
    if ins.lo in (
        0x8000001c,
        0x80002010,
        0x80002028,
    ):
        return
    for f in ins.flow_out:
        if f.to in (
            0x80002010,
            0x80002028,
            0x80002aa8
        ):
            y = data.Txt(asp, ins.hi, label=False, align=2, splitnl=True)
            ins.dstadr = y.hi
            ins.flow_out.pop(-1)
            ins += code.Jump(cond=True, to=ins.dstadr)
        elif f.to in (
            0x80000018,
        ):
            if asp.bu16(ins.lo - 6) == 0x41f9:
                a = asp.bu32(ins.lo - 4)
                y = data.Txt(asp, a, splitnl=True)
        elif f.to in (
            0x80002034,
        ):
            if asp.bu16(ins.lo - 6) == 0x47f9:
                a = asp.bu32(ins.lo - 4)
                y = data.Txt(asp, a, splitnl=True)
        elif f.to in (
            0x8000001c,
            0x800000e2
        ):
            y = data.Txt(asp, ins.hi, label=False, align=2, splitnl=True)
            ins.dstadr = y.hi
            ins.flow_out.pop(-1)
            ins += code.Jump(cond=True, to=ins.dstadr)
        elif f.to in (
            0x80002068,
        ):
            if asp.bu16(ins.lo - 4) == 0x303c:
                a = asp.bu16(ins.lo - 2)
                t = RESHA_PROGRAMS.get(a)
                if t:
                    asp.set_line_comment(ins.lo - 4, t)
Exemple #11
0
def hack(cpu, lo):
    while lo:
        y = cpu.dataptr(lo)
        x = data.Pstruct(cpu.m, lo + 2, "B" * 1, fmt=", ".join(["0x%02x"] * 1))
        x = data.Txt(cpu.m, lo + 3, term=(0x85,), label=False)
        x.compact = True
        x = data.Pstruct(cpu.m, x.hi, "B" * 2, fmt=", ".join(["0x%02x"] * 2))
        x.compact = True
        lo = y.dst
Exemple #12
0
def round_0(cx):
    ''' Things to do before the disassembler is let loose '''
    for a, b, c in (
        (0x20418, 0x2047c, 4),
        (0x2048c, 0x204f8, 12),
        (0x204f8, 0x2055c, 10),
        (0x21784, 0x21946, 10),
        (0x21b8a, 0x21d48, 10),
    ):
        for d in range(a, b, c):
            y = data.Txt(cx.m, d, d + c, label=False)
Exemple #13
0
def cmd_table(cx):
    # CMD table
    x = cx.m.add_range(0x9b81, 0x9bff, txt="cmd-tbl")
    cx.m.set_label(x.lo, "CMDTBL")
    for a in range(x.lo, x.hi, 3):
        y = data.Txt(cx.m, a, a + 1, label=False)
        z = cx.codeptr(a + 1)
        if y.txt == " ":
            cx.m.set_label(z.dst, "CMD_SP")
        else:
            cx.m.set_label(z.dst, "CMD_%s" % y.txt)
def fc_outstr(asp, ins):
    ''' Spot string arguments to OutStr() and puts() '''
    for f in ins.flow_out:
        if f.to not in (0x3b28, 0x0900):
            continue
        if asp.bu16(ins.lo - 2) != 0x91e0:
            continue
        if asp.bu16(ins.lo - 8) != 0x1400:
            continue
        y = data.Txt(asp, asp.bu32(ins.lo - 6), align=1, label=False)
        asp.set_line_comment(ins.lo, '"' + y.txt + '"')
def round_0(cx):
    ''' Things to do before the disassembler is let loose '''

    # Look for SCCS-identifiers at the beginning
    for a, b in cx.m.gaps():
        for i in range(a, b - 3):
            if cx.m.bu32(i) == 0x40282329:
                for j in range(i, b):
                    if cx.m[j] in (0x00, 0x10, 0x22, 0x3e, 0x5c):
                        break
                y = data.Txt(cx.m, i, j, label=False)
 def __init__(self, cx, adr):
     self.adr = adr
     self.words = []
     print("CMD TABLE AT 0x%x" % adr)
     cx.m.set_label(adr, "COMMAND_TABLE_%x" % adr)
     cx.m.set_block_comment(adr, "COMMAND TABLE")
     while True:
         self.words.append(
             data.Txt(cx.m, adr, adr + 10, label=False).txt.rstrip())
         if cx.m.bu32(adr) == 0x41534349:
             break
         adr += 10
Exemple #17
0
	def t1(a):
		while True:
			data.Const(pj, a, a + 1)
			if pj.m.rd(a) == 0:
				return;
			a += 1
			y = data.Txt(pj, a)
			a = y.hi
			cpu.codeptr(pj, a)
			z = pj.m.bu16(a)
			pj.set_label(z, "func_" + y.txt)
			a += 2
Exemple #18
0
def task(pj, cx):
    pj.todo(0x0000, cx.disass)

    # 0x70e5
    pj.todo(0x0027, cx.disass)

    pj.todo(0x0066, cx.disass)

    x = data.Const(pj, 0x0068, 0x0800)
    x.typ = ".BYTE"
    x.fmt = "{Payload moved to 0x7000}"

    pj.todo(0x70d0, cx.disass)

    pj.todo(0x7322, cx.disass)
    pj.todo(0x7615, cx.disass)

    # Interrupt vector table
    for a in range(16):
        cx.codeptr(pj, 0x7300 + a * 2)

    data.Txt(pj, 0x707d, 0x707d + 0x14, label=False)
    data.Txt(pj, 0x70b0, 0x70b0 + 0xf, label=False)
    data.Txt(pj, 0x7092, 0x7092 + 0x1d, label=False)
    data.Txt(pj, 0x73f0, 0x73f0 + 0x12, label=False)
    data.Txt(pj, 0x7071, 0x7071 + 0x6, label=False)
    data.Txt(pj, 0x7077, 0x7077 + 0x6, label=False)

    discover.Discover(pj, cx)

    pj.set_label(0x7068, "memcpy(BC, DE,  L)")
def round_0(cx):
    ''' Things to do before the disassembler is let loose '''
    ioc_eeprom_exports.add_flow_check(cx)

    for a in range(BASE, BASE + SIZE, SEGMENT):
        cx.m.set_block_comment(a, "PROGRAM VECTORS")
        data.Const(cx.m, a, a + 2)

    for a, b in ((0x76084, 0x760c8), ):
        for i in range(a, b, 4):
            y = cx.dataptr(i)
            data.Txt(cx.m, y.dst)

    for a, b in (
        (0x7063e, 0x70708),
        (0x71025, 0x7105f),
        (0x712a6, 0x7130c),
        (0x719f2, 0x71a99),
        (0x74006, 0x7412e),
        (0x76248, 0x763b1),
    ):
        i = a
        while i < b:
            y = data.Txt(cx.m, i, splitnl=True)
            i = y.hi

    for a in range(0x765e4, 0x76650, 6):
        y = cx.dataptr(a + 2)
        data.Txt(cx.m, y.dst)

    for a in (
            0x7200a,
            0x769ce,
            0x769ec,
            0x76a0a,
            0x76a28,
    ):
        data.Txt(cx.m, a, splitnl=True)
Exemple #20
0
def collect_keys():
	keys = {}
	pj,m = setup(3)
	n = 0
	for a in range(0x4a3f, 0x4aad, 2):
		y = pj.m.bu16(a)
		assert pj.m[y] == 0xcc
		x = pj.m.bu16(y + 1)
		y = data.Txt(pj, x, x + 9)
		t = y.txt[:-4].strip().replace(" ","_")
		pj.m.set_label(a, "k_0x%02x" % n)
		pj.m.set_label(y, "test_key_" + t)
		keys[n] = t
		n += 1
	return keys
Exemple #21
0
def inline_text(asp, ins):
    if not ins.dstadr in (
            0x8000001c,
            0x800000e2,
            0x80002028,
            0x80002aa8,
    ):
        return
    if ins.lo in (
            0x8000001c,
            0x80002028,
    ):
        return
    y = data.Txt(asp, ins.hi, label=False, splitnl=True, align=2)
    ins.lang.disass(y.hi, asp=asp)
Exemple #22
0
def collect_errors():
	pj,m = setup(3)
	a = 0x7348
	n = m[a]
	a += 1
	e = {}
	for i in range(n):
		x = m[a]
		a += 1
		l = m[a]
		a += 1
		p = m.bu16(a)
		a += 2
		y1 = data.Txt(pj, p, p + l, label=False)
		e[x] = y1.txt
	return e
Exemple #23
0
 def t1(a, l):
     cx.m.set_label(a, l)
     while True:
         data.Const(cx.m, a, a + 1)
         if cx.m[a] == 0:
             return;
         a += 1
         y = data.Txt(cx.m, a, align=1, label=False)
         a = y.hi
         cx.codeptr(a)
         z = cx.m.bu16(a)
         if False:
             # XXX: doesn't work for ERROR
             print("XXX %04x" % (z-3), y.txt)
             cx.disass(z - 3)
         cx.m.set_label(z, "func_" + y.txt)
         a += 2
Exemple #24
0
 def t1(a, l):
     pj.set_label(a, l)
     while True:
         data.Const(pj, a, a + 1)
         if pj.m.rd(a) == 0:
             return
         a += 1
         y = data.Txt(pj, a, align=1, label=False)
         a = y.hi
         cpu.codeptr(pj, a)
         z = pj.m.bu16(a)
         if False:
             # XXX: doesn't work for ERROR
             print("XXX %04x" % (z - 3), y.txt)
             pj.todo(z - 3, cpu.disass)
         pj.set_label(z, "func_" + y.txt)
         a += 2
def round_0(cx):
    ''' Things to do before the disassembler is let loose '''

    for a in (
            0x80004afe,
            0x80004b42,
            0x80004b68,
            0x80004ece,
            0x80004eeb,
            0x80004f17,
            0x80004f2c,
            0x80004f40,
            0x80004f56,
            0x80004f74,
            0x80004f8a,
            0x80004f95,
            0x80004fac,
    ):
        data.Txt(cx.m, a, splitnl=True)
Exemple #26
0
 def assy_pushtxt(self):
     ''' XXX: Use PIL instead ? '''
     if len(self.lim) == 5 and self.lim[0].assy[0] == "+PTA":
         sreg = self.lim[0]['sreg']
         lim = self.lim[-4:]
         off = self.lo + 4
     elif len(self.lim) == 4:
         sreg = 7
         lim = self.lim
         off = self.lo + 2
     else:
         raise assy.Invalid()
     for i, j in zip(lim, ("+PTB", "+PTC", "+PTD", "PUSH")):
         if i.assy[0][:4] != j:
             raise assy.Invalid()
     if lim[0]['areg'] != lim[2]['areg']:
         raise assy.Invalid()
     if lim[1]['dreg'] != self['dreg']:
         raise assy.Invalid()
     if lim[2]['sreg'] != sreg:
         raise assy.Invalid()
     adr = off + lim[0]['x'] - (1 << 16)
     length = lim[1]['y'] + 1
     length *= {
         'B': 1,
         'W': 2,
         'L': 4,
     }[lim[2].assy[0][4]]
     if lim[2].assy[0][-1] == '-':
         adr -= length
     elif lim[2].assy[0][-1] != '+':
         raise assy.Invalid()
     for i in range(adr, adr + length):
         j = self.lang.m[i]
         if 32 <= j <= 126:
             pass
         elif j in (9, 10, 13):
             pass
         else:
             print("BAD char 0x%02x" % j)
             raise assy.Invalid()
     y = data.Txt(self.lang.m, adr, adr + length, label=False)
     return '"' + y.txt + '"'
 def flow_check(self, asp, ins):
     if hasattr(ins, "fixed_10568"):
         return
     ins.flow_out = []
     ins.flow_R()
     ptr = ins.hi
     exp_name_len = asp[ins.hi + 2]
     data.Const(asp, ptr, ptr + 3)
     ptr += 3
     y = data.Txt(asp, ptr, ptr + exp_name_len, label=False)
     ptr += exp_name_len
     narg = asp[ptr + 2] + asp[ptr + 3]
     z = data.Const(asp, ptr, ptr + 4 + narg)
     ptr = z.hi
     lbl = "exp_" + y.txt + "("
     asp.set_label(ins.lo, lbl + ")")
     # ins.compact = True
     if ptr & 1 and not asp[ptr]:
         z = data.Const(asp, ptr, ptr + 1)
         z.typ = ".PAD"
     ins.fixed_10568 = True
Exemple #28
0
def round_0(cx):
    ''' Things to do before the disassembler is let loose '''

    for a, b, n in (
        (0x201b4, 0x2022c, 10),
        (0x2025e, 0x202f4, 10),
        (0x202f8, 0x2036c, 10),
        (0x203ac, 0x20438, 10),
        (0x204f0, 0x20540, 10),
        (0x205de, 0x20638, 10),
        (0x2095c, 0x20c5e, 10),
    ):
        for i in range(a, b, n):
            data.Txt(cx.m, i, i + n, label=False)

    cx.m.set_label(0x20bb4, "TXTTBL_POWER_MARGINS")
    cx.m.set_label(0x20bdc, "TXTTBL_CLOCK_MARGINS")
    cx.m.set_label(0x20c04, "TXTTBL_CMDS")
    cx.m.set_label(0x20a74, "TXTTBL__ALL_COND_SYS_VAL...")

    cx.m.set_label(0x27982, "eval_buffer?")
    cx.m.set_label(0x225dc, "DISPATCH_CMDS(?)")
    cx.m.set_label(0x22472, "MATCH_CMDS(?)")
    cx.m.set_label(0x221f8, "MATCH_CLOCK_MARGINS(?)")
    cx.m.set_label(0x22168, "MATCH_POWER_MARGINS(?)")
    cx.m.set_label(0x25516, "TRY_SCRIPT_FILE(?)")

    for adr, cmd in (
        (0x21746, "TEST"),
        (0x21ae2, "RUN"),
        (0x21ea4, "ERRMESS"),
        (0x2150e, "INIT_STATE"),
        (0x22096, "ISOLATE"),
        (0x220dc, "TRACE"),
        (0x22122, "ULOAD"),
        (0x22288, "MARGIN"),
        (0x22518, "POWERDOWN"),
    ):
        cx.m.set_label(adr, "CMD_" + cmd + "(?)")
def example():
    cx = z80.z80()
    m = mem.Stackup(files=(FILENAME, ), nextto=__file__)
    cx.m.map(m, 0, 0x12)
    cx.m.map(m, lo=0xa000, hi=0xa59a, offset=0x12)

    data.Txt(cx.m, 0xa533, label=False)
    data.Txt(cx.m, 0xa546, label=False)
    data.Txt(cx.m, 0xa571, label=False)
    data.Txt(cx.m, 0xa574, label=False)
    data.Txt(cx.m, 0xa588, 0xa58c, label=False)
    data.Txt(cx.m, 0xa58c, 0xa590, label=False)
    data.Txt(cx.m, 0xa593, 0xa593 + 0x7, label=False)

    cx.disass(0x0000)

    # Interrupt vector table
    for a in range(12):
        cx.codeptr(0xa000 + a * 2)

    return NAME, (cx.m, )
Exemple #30
0
def task(pj, cpu):

    cpu.vectors(pj)

    token = {
        1: '?',
        2: 'end',
        3: 'sep',
        4: 'number',
        6: 'string',
    }

    err = {}

    #		6624		6626
    kbd_tbl = {
        0x01: ['9', '9'],
        0x02: ['.', '.'],
        0x03: ['enter', 'enter'],
        0x04: ['6', '6'],
        0x05: ['meter', 'range'],
        0x06: ['rcl', 'rcl'],
        0x07: ['unmask', 'ocp'],
        0x08: ['addr', 'addr'],
        0x09: ['7', '7'],
        0x0a: ['0', '0'],
        0x0b: ['2', '2'],
        0x0c: ['4', '4'],
        0x0d: ['output>', 'output>'],
        0x0e: ['on_off', 'on_off'],
        0x0f: ['1', '1'],
        0x10: ['vset', 'vset'],
        0x11: [None, None],
        0x12: ['sto', 'sto'],
        0x13: ['err', 'err'],
        0x14: ['lcl', 'lcl'],
        0x15: ['ovset', 'V_up'],
        0x16: ['fault', 'reset'],
        0x17: ['ocp', 'I_up'],
        0x18: ['dly', 'ovset'],
        0x19: ['<output', '<output'],
        0x1a: ['ocrst', 'I_dn'],
        0x1b: ['iset', 'iset'],
        0x1c: ['ovrst', 'V_dn'],
        0x1d: ['8', '8'],
        0x1e: ['backsp', 'backsp'],
        0x1f: ['3', '3'],
        0x20: ['5', '5'],
    }

    for i in range(1, 33):
        s = "%02x" % i
        a = pj.m.rd(0x87f0 + i - 1)
        b = pj.m.rd(0x87d0 + i - 1)
        s += "   "
        s += " %x" % a
        s += " %04x" % pj.m.bu16(0x87b2 + a * 2)
        s += " %-10s" % kbd_tbl[i][0]
        s += "   "
        s += " %x" % b
        s += " %04x" % pj.m.bu16(0x87b2 + b * 2)
        s += " %-10s" % kbd_tbl[i][1]
        print(s)

    def softlbl(a, n):
        if a not in pj.labels:
            pj.set_label(a, n)

    for a, n in (
        (0x002b, "display_chan"),
        (0x0085, "n_chan"),
        (0x0086, "model_desc_ptr"),
        (0x038f, "B_flag1"),
        (0x0390, "B_flag2"),
        (0x01bc, "cal_lock_flag"),
        (0x1000, "i8291_data"),
        (0x1001, "i8291_intrrupt1"),
        (0x1002, "i8291_intrrupt2"),
        (0x1003, "i8291_spoll"),
        (0x1004, "i8291_addressed"),
        (0x1005, "i8291_cmd_aux"),
        (0x1006, "i8291_addr1"),
        (0x1007, "i8291_addr2_eos"),
        (0x2000, "slv_force"),
        (0x3000, "slv_sense"),
        (0x4000, "dip_kbd_sense"),
        (0x5000, "kbd_dsply_scan"),
        (0x8100, "B=dsply_needs_update()"),
        (0x819b, "p4_p5()"),
        (0x81ac, "p4_p5(B)"),
        (0x81c0, "dsply_shift_bits(B,Y)"),
        (0x8236, "task__display"),
        (0x84e3, "i8291_init"),
        (0x8465, "MSG(X)"),
        (0x8775, "task__keyboard"),
        (0x87d0, "HP6626_keytbl"),
        (0x87f0, "HP6624_keytbl"),
        (0x88b6, "GETKEY"),
        (0x897f, "key_08_METER"),
        (0x89d5, "key_01_func"),
        (0x8992, "key_06_ENTER"),
        (0x89c0, "key_05_BS"),
        (0x8bb0, "key_09_output_control"),
        (0x8c1a, "key_04_LCL"),
        (0x8a2b, "key_03_OUTPUT_SELECT"),
        (0x8a81, "key_02_digit"),
        (0x8acd, "key_07_PERIOD"),
        (0x8bfa, "key_09_output_ONOFF"),
        (0x8c05, "key_09_output_OCP_UNMASK"),
        (0x8c40, "key_0e_RANGE"),
        (0x8cb3, "key_0a_V_UP"),
        (0x8d05, "key_0b_V_DOWN"),
        (0x8dce, "key_0c_I_UP"),
        (0x8e32, "key_0d_I_DOWN"),
        (0x91d7, "ERR=A"),
        (0x93f7, "err_NUMBER_RANGE"),
        (0x9463, "Get_Chan"),
        (0x9468, "Chan_Nr_Check"),
        (0x99d5, "cmd_A"),
        (0x99d9, "cmd_B"),
        (0x99dd, "cmd_S"),
        (0x9acb, "func_09_output_OCRST"),
        (0x9b4a, "func_09_output_OVRST"),
        (0x9b21, "get_chan"),
        (0x9ea6, "put_char"),
        (0x9ead, "put_CRNL"),
        (0x9ebc, "reset_outbuf"),
        (0x9ec4, "put_string"),
        (0x9ed2, "put_digits"),
        (0xa14b, "cmd_ID"),
        (0xaaf9, "Get_Nbr"),
        (0xb00b, "Output_40W20V_1"),
        (0xb032, "Output_40W50V_1"),
        (0xb059, "Output_80W20V_1"),
        (0xb080, "Output_80W50V_1"),
        (0xb0a7, "Output_25W_1"),
        (0xb0ce, "Output_50W_1"),
        (0xb0f5, "Output_100W20V_1"),
        (0xb11c, "Output_100W50V_1"),
        (0xb143, "Output_200W20V_1"),
        (0xb16a, "Output_200W50V_1"),
        (0xb191, "Output_10W10V_1"),
        (0xb1b8, "Output_40W20V_2"),
        (0xb1e4, "Output_40W50V_2"),
        (0xb210, "Output_80W20V_2"),
        (0xb23c, "Output_80W50V_2"),
        (0xb268, "Output_25W_2"),
        (0xb294, "Output_50W_2"),
        (0xb2c0, "Output_100W20V_2"),
        (0xb2ec, "Output_100W50V_2"),
        (0xb318, "Output_200W20V_2"),
        (0xb344, "Output_200W50V_2"),
        (0xb370, "Output_10W10V_2"),
        (0xb476, "Config_Model"),
        (0xb4c5, "ERR_NO_MODEL"),
        (0xb5ca, "special_model"),
        (0xb7c4, "tx_slave"),
        (0xb873, "rx_slave_byte"),
        (0xbacc, "yield"),
        (0xbade, "EE_Write_Word"),
        (0xbae9, "EE_Write_Byte"),
        (0xbb1e, "I2C_Ready"),
        (0xbb37, "EE_Read_Word"),
        (0xbb7f, "EE_Read_Byte"),
        (0xbbbf, "I2C_Error"),
        (0xbbcb, "I2C_Start_Byte"),
        (0xbbd2, "I2C_Poll_Ack"),
        (0xbbf5, "EE_SCL_LH"),
        (0xbc00, "EE_SCL_L"),
        (0xbc06, "I2C_Read_Byte"),
        (0xbc23, "I2C_Write_Byte"),
        (0xbc45, "I2C_Start"),
        (0xbc70, "I2C_Stop"),
        (0xbc8d, "I2C_Get_Ack"),
        (0xbc9f, "EE_Ack"),
        (0xbcd5, "cmd_OVCAL"),
        (0xc36a, "err_CAL_ERROR"),
        (0xc5cf, "cmd_CMODE"),
        (0xc62f, "err_CAL_LOCKED"),
        (0xc637, "err_STORE_LIMIT"),
        (0xcb22, "ROMSUM"),
        (0xce80, "task_setup"),
        (0xcea5, "task_switch"),
        (0xceb7, "task__vimes"),
        (0xd448, "init_slavetbl"),
    ):
        pj.set_label(a, n)

    data.Const(pj, 0x8000, 0x8002)

    pj.set_label(0xd472, "chan_ptr")
    for a in range(0xd472, 0xd47a, 2):
        data.Dataptr(pj, a, a + 2, pj.m.bu16(a))

    for a, b in ((0x8002, 0x802a), ):
        y = data.Txt(pj, a, b, align=1)

    for a in (
            0x827b,
            0x849b,
            0x84a7,
            0x84b3,
            0x84bf,
            0x84cb,
            0x84d7,
            0xbcb1,
            0xbcbd,
            0xbcc9,
            0xc255,
            0xcf01,
            0xd262,
    ):
        y = data.Txt(pj, a, a + 12, align=1)

    for a in (
            0xa183,
            0xa186,
            0xa18f,
            0xa198,
            0xaffe,
    ):
        y = data.Txt(pj, a, pfx=1, align=1)

    pj.set_label(0x8ec2, "ERROR_TEXTS")
    n = 0
    for a in range(0x8ec2, 0x9036, 12):
        y = data.Txt(pj, a, a + 12, align=1, label=False)
        err[n] = y.txt
        n += 1

    a = 0xa225
    nn = 7
    while a < 0xa370:
        b = pj.m.rd(a)
        if b == 0:
            break
        y = data.Txt(pj, a, pfx=1, align=1, label=False)
        token[nn] = y.txt
        a = y.hi
        nn += 1

    print("NN", nn)

    for a in range(0x87d0, 0x8810, 8):
        data.Const(pj, a, a + 8)

    def t1(a, l):
        pj.set_label(a, l)
        while True:
            data.Const(pj, a, a + 1)
            if pj.m.rd(a) == 0:
                return
            a += 1
            y = data.Txt(pj, a, align=1, label=False)
            a = y.hi
            cpu.codeptr(pj, a)
            z = pj.m.bu16(a)
            if False:
                # XXX: doesn't work for ERROR
                print("XXX %04x" % (z - 3), y.txt)
                pj.todo(z - 3, cpu.disass)
            pj.set_label(z, "func_" + y.txt)
            a += 2

    t1(0x8824, "HP6626_func_01_key")
    t1(0x8860, "HP6624_func_01_key")

    n = 1
    for a in range(0x87b4, 0x87d0, 2):
        x = pj.m.bu16(a)
        softlbl(x, "key_%02x_%04x" % (n, x))
        n += 1
        cpu.codeptr(pj, a)

    n = 1

    for a in range(0xa5d3, 0xa687, 2):
        x = pj.m.bu16(a)
        softlbl(x, "cmd_%02x_%04x" % (n, x))
        n += 1
        cpu.codeptr(pj, a)

    class tt_5(data.Data):
        def __init__(self, pj, lo):
            hi = lo + 4
            super(tt_5, self).__init__(pj, lo, hi, "tt_5")

        def render(self, pj):
            s = ".TT5\t"
            t = pj.m.rd(self.lo)
            if t in token:
                s += (token[t] + ", ").ljust(8)
            else:
                s += "T%02x, " % t
            s += "0x%02x, " % pj.m.rd(self.lo + 1)
            w = pj.m.bu16(self.lo + 2)
            s += pj.render_adr(w)
            return s

    def tt5(a, f, l=None, ex=0):
        if l == None:
            l = []
        pj.set_label(a, "tt5_%04x" % a)
        while True:
            ll = list(l)
            if pj.m.rd(a) == 0:
                data.Const(pj, a, a + 1)
                break
            t = pj.m.rd(a)
            if t in token:
                ll.append(token[t])
            else:
                ll.append("T%02x" % t)
            e = pj.m.rd(a + 1)
            if e != 0:
                ex = f + e * 2
                z = pj.m.bu16(ex)
                # print("%04x" % a, "%04x" % z, "A %02x" % e, ll)
                pj.set_label(z, "cmd_" + "_".join(ll))
            tt_5(pj, a)
            x = pj.m.bu16(a + 2)
            if x != 0:
                tt5(x, f, ll, ex)
            else:
                # print("%04x" % a, ll, "%04x" % ex)
                y = pj.t.find_lo(ex)
                y[0].lcmt += " ".join(ll) + "\n"
                # print(y)

            a += 4

    tt5(0xa3a2, 0xa5d1)

    for a in range(0xb7ac, 0xb7c4, 2):
        data.Const(pj, a, a + 2)

    # Task or coroutine table
    for a in range(0xce62, 0xce80, 6):
        data.Dataptr(pj, a, a + 2, pj.m.bu16(a))
        z = pj.m.bu16(a + 2)
        softlbl(z, "task_%04x" % z)
        cpu.codeptr(pj, a + 2)
        data.Dataptr(pj, a + 4, a + 6, pj.m.bu16(a + 4))

    if True:
        cpu.disass(pj, 0x8631)
        cpu.disass(pj, 0x8b64)
        cpu.disass(pj, 0x8d6d)
        cpu.disass(pj, 0x8d76)
        cpu.disass(pj, 0x8e84)
        cpu.disass(pj, 0x8e87)
        cpu.disass(pj, 0xab5c)
        cpu.disass(pj, 0xc7a2)
        cpu.disass(pj, 0xc7ad)
        cpu.disass(pj, 0xc7b8)
        cpu.disass(pj, 0xc7c5)
        cpu.disass(pj, 0xc7d9)
        cpu.disass(pj, 0xc7e6)
        cpu.disass(pj, 0xc7fc)
        cpu.disass(pj, 0xc809)
        cpu.disass(pj, 0xc814)
        cpu.disass(pj, 0xc821)
        cpu.disass(pj, 0xc835)
        cpu.disass(pj, 0xc842)
        cpu.disass(pj, 0xc84b)
        cpu.disass(pj, 0xcf0d)
        cpu.disass(pj, 0xc855)
        cpu.disass(pj, 0xd3b8)
        cpu.disass(pj, 0xd3f8)

    if True:
        # See above in t1
        cpu.disass(pj, 0x8b03)
        cpu.disass(pj, 0x8b14)
        cpu.disass(pj, 0x8b25)
        cpu.disass(pj, 0x8b36)
        cpu.disass(pj, 0x8b44)
        cpu.disass(pj, 0x8b65)
        cpu.disass(pj, 0x8b78)
        cpu.disass(pj, 0x8b86)
        cpu.disass(pj, 0x8b91)

    ##############

    def fp_val(pj, lo, hi):
        e = pj.m.s8(hi - 1)
        m = 0
        i = 0
        a = hi - 2
        while a >= lo:
            m |= pj.m.rd(a) << i
            i += 8
            a -= 1
        m *= 10**e
        return m

    class fp(data.Data):
        def __init__(self, pj, lo, hi):
            super(fp, self).__init__(pj, lo, hi, "fp")
            self.val = fp_val(pj, lo, hi)

        def render(self, pj):
            return ".FP\t%g" % self.val

    class tt_2(data.Data):
        def __init__(self, pj, lo):
            hi = lo + 5 + pj.m.rd(lo + 4) * 4
            super(tt_2, self).__init__(pj, lo, hi, "tt_2")

        def render(self, pj):
            s = ".TT2\t{\n"
            w = pj.m.bu16(self.lo + 0)
            s += "\t.next = " + pj.render_adr(w) + "\n"
            s += "\t.model = %4d\n" % pj.m.bu16(self.lo + 2)
            n = pj.m.rd(self.lo + 4)
            s += "\t.outputs = %d\n" % n
            a = self.lo + 5
            for i in range(n):
                w = pj.m.bu16(a)
                s += "\t.out1[%d] = " % i + pj.render_adr(w) + "\n"
                a += 2
                w = pj.m.bu16(a)
                s += "\t.out2[%d] = " % i + pj.render_adr(w) + "\n"
                a += 2
            return s + "\t}"

    class tt_output1(data.Data):
        def __init__(self, pj, lo):
            hi = lo + 39
            super(tt_output1, self).__init__(pj, lo, hi, "tt_output1")
            self.compact = True

        def render(self, pj):
            s = ".OUTPUT1\t"
            a = self.lo
            f = ["%4.1f", "%4.1f", "%6.3f", "%6.3f", "%4.1f"]
            for i in range(5):
                s += "0x%04x, " % pj.m.bu16(a)
                a += 2
                s += (f[i] + ", ") % fp_val(pj, a, a + 4)
                a += 4
            for i in range(3):
                s += "%5.2f, " % fp_val(pj, a, a + 3)
                a += 3
            return s[:-2]

    class tt_output2(data.Data):
        def __init__(self, pj, lo):
            hi = lo + 44
            super(tt_output2, self).__init__(pj, lo, hi, "tt_output2")
            self.compact = True

        def render(self, pj):
            s = ".OUTPUT2\t"
            a = self.lo
            f = ["%4.1f", "%4.1f", "%6.3f", "%6.3f", "%4.1f", "%5.3f", "%4.1f"]
            for i in range(7):
                s += "0x%04x, " % pj.m.bu16(a)
                a += 2
                s += (f[i] + ", ") % fp_val(pj, a, a + 4)
                a += 4
            s += "0x%04x" % pj.m.bu16(a)
            return s

    tt = {}

    def tt3_1(a):
        if a in tt:
            return
        tt[a] = True
        tt_output1(pj, a)

    def tt3_2(a):
        if a in tt:
            return
        tt[a] = True
        tt_output2(pj, a)
        return
        softlbl(a, "tt3_2_%04x" % a)
        while True:
            if pj.m.rd(a + 2) > 2:
                break
            data.Const(pj, a, a + 2, fmt="0x%02x")
            fp(pj, a + 2, a + 6)
            a += 6
        data.Const(pj, a, a + 2, fmt="0x%02x")

    a = 0xb39c
    while a:
        pj.set_label(a, "tt2_%04x" % a)
        x = pj.m.bu16(a)
        if x == 0:
            data.Dataptr(pj, a, a + 2, x)
            break
        y = tt_2(pj, a)
        a = x
        continue
        data.Const(pj, a + 2, a + 4, fmt="%d")
        data.Const(pj, a + 4, a + 5)
        y = pj.m.rd(a + 4)
        a += 5
        for i in range(y * 2):
            z = pj.m.bu16(a)
            tt3_1(z)
            data.Dataptr(pj, a, a + 2, z)
            a += 2
            z = pj.m.bu16(a)
            tt3_2(z)
            data.Dataptr(pj, a, a + 2, z)
            a += 2
        a = x

    ##############
    for a in range(0xb437, 0xb46e, 5):
        pj.set_label(a, "tt1_%04x" % a)
        data.Const(pj, a, a + 1)
        z = pj.m.bu16(a + 1)
        data.Dataptr(pj, a + 1, a + 3, z)
        tt3_1(z)
        z = pj.m.bu16(a + 3)
        data.Dataptr(pj, a + 3, a + 5, z)
        tt3_2(z)

    ##############

    while pj.run():
        pass

    #############
    # Add comment with error message

    for i in pj:
        if i.tag != "mc6809":
            continue
        if i.dstadr != 0x91d7:
            continue
        j = pj.t.find_hi(i.lo)
        if len(j) != 1:
            continue
        j = j[0]
        x = pj.m.rd(j.lo)
        if x != 0x86:
            continue
        y = pj.m.rd(j.lo + 1)
        j.lcmt += "Error: " + err[y] + "\n"