예제 #1
0
def main(fn):
    cartridge = Cartridge(fn)

    try:
        os.mkdir("dump")
    except:
        pass

    print "============== Audio data ======================"
    addr = 5
    n = 1
    while 1:
        a = cartridge.read_int32(addr)
        a = a & 0xffffff

        l = cartridge.read_int32(a)
        if l == 0:
            break

        format = cartridge.read_int16(a+4)

        print "Audio%05d: %06X %d %s" % (n, a, l, format)
        f = open("dump/%05d.aud" % n,"wb")
        f.write(cartridge.data[a+4:a+l+4])
        f.close()
        addr += 3
        n += 1

    index_base = cartridge.read_int16(2)
    mover_scripts_end = cartridge.read_int16(index_base+2)
    mover_scripts = cartridge.read_int16(index_base+4)
    mover_scripts_spi = mover_scripts * 2 + index_base
    mover_scripts_num = cartridge.read_int16(mover_scripts_spi - 2)
    cx_offset = cartridge.read_int16(index_base+6)
    addrs = {}
    aliases = {}
    for i in range(mover_scripts_num):
        addr = cartridge.read_int16(mover_scripts_spi + i*2)
        if addr in addrs:
            if not addr in aliases:
                aliases[addr] = []
            aliases[addr].append(i)
        else:
            addrs[addr] = i

    addrs_keys = addrs.keys()
    addrs_keys.sort()
    if 0:
        for addr in addrs_keys:
            if addr in aliases:
                aliases_str = " aliases: " +",".join([ "%d" % a for a in aliases[addr]])
            else:
                aliases_str = ""

            print "Script%05d: %04X (%06X)%s" % (addrs[addr], addr, index_base + addr*2, aliases_str)

    print "============== Mover Scripts ======================"
    addr = addrs_keys[0]
    while addr<mover_scripts_end:
        if addr in addrs:
            print "scr%d:" % addrs[addr]
            if addr in aliases:
                for a in aliases[addr]:
                    print "scr%d:" % a

        spi_addr = addr*2+index_base
        cmd = cartridge.read_int16(spi_addr)
        if (cmd & 0xF000) == 0xF000:
            if cmd == 0xF000:
                cmd_txt = "done"
            elif cmd == 0xF001:
                cmd_txt = "ctrl_F001"
            elif cmd == 0xF002:
                cmd_txt = "wait_completion"
            elif cmd == 0xF003:
                arg = cartridge.read_int16(spi_addr+2)
                cmd_txt = "wait_completion_max %d" % arg
                addr += 1
            elif cmd == 0xF004:
                cmd_txt = "wait_04"
            elif cmd == 0xF005:
                arg = cartridge.read_int16(spi_addr+2)
                cmd_txt = "wait_completion_max %d" % arg
                addr += 1
            elif cmd == 0xF006:
                arg = cartridge.read_int16(spi_addr+2)
                if arg in addrs:
                    label = "scr%d" % addrs[arg]
                else:
                    label = "%04X" % arg

                cmd_txt = "call %s" % label
                addr += 1
            elif cmd == 0xF007:
                cmd_txt = "ctrl_F007"
            elif cmd == 0xF008:
                cmd_txt = "ctrl_F008"
            elif cmd == 0xF009:
                cmd_txt = "ctrl_F009"
            elif cmd == 0xF00A:
                cmd_txt = "return"
            elif cmd == 0xF00B:
                cmd_txt = "ctrl_F00B"
            elif cmd == 0xF00C:
                cmd_txt = "ctrl_F00C"
            elif cmd == 0xF00D:
                cmd_txt = "wait_0D"
            elif cmd == 0xF00E:
                cmd_txt = "ctrl_F00E"
            elif cmd == 0xF00F:
                cmd_txt = "ctrl_F00F"
            else:
                cmd_txt = "ctrl_%04X" % cmd
        else:
                cmd_txt = "cmd_%04X" % cmd

        print "\t%04X: %s" % (addr, cmd_txt)
        addr += 1

    xrefs_code_local = {}
    xrefs_code_global = {}
    xrefs_data = {}
    xrefs_globals = {}
    barriers = {}
    labels = {}

    def add_xref(addr, typ, ref):
        #print "add xref %s %04X -> %04X" % (typ, addr, ref)
        if typ == "code_local":
            xrefs = xrefs_code_local
        elif typ == "code_global":
            xrefs = xrefs_code_global
        elif typ == "data":
            xrefs = xrefs_data
        elif typ == "globals":
            xrefs = xrefs_globals
        else:
            return

        if not ref in xrefs:
            xrefs[ref] = {}

        xrefs[ref][addr] = 1

    barriers_list = []

    print "=================== Code ======================="
    for pass_num in (1,2):
        addr = 0x20
        cpu = CPU(cartridge, index_base, cx_offset, addr, None, None)
        cpu.labels = labels
        barriers[addr] = 1
        while addr < mover_scripts-1:
            spi_addr = addr * 2 + index_base
            decoded = cpu.decode(addr)
            if decoded.barrier:
                barriers[addr+1] = 1
            for typ, ref in decoded.xrefs:
                add_xref(addr,typ, ref)

            hex = []
            for i in range(decoded.cmd_len):
                hex.append("%04X" % cartridge.read_int16(spi_addr + i * 2))
            hex = " ".join(hex)

            if pass_num == 2:
                if addr in barriers_list:
                    print "//------------------------------------------------------------------"
                if addr in xrefs_code_global:
                    print "// global entry, xrefs: ",",".join(["%04X"%d for d in xrefs_code_global[addr]])
                if addr in xrefs_data:
                    print "// data entry, xrefs: ",",".join(["%04X"%d for d in xrefs_data[addr]])
                if addr in labels:
                    print "     %20s:                                // xrefs: %s" % (labels[addr],",".join(["%04X"%d for d in xrefs_code_local[addr]]))
                print "%04X: %-20s %-9s %-20s // %s" % (addr, hex, 
                        decoded.cmd, decoded.args or "", decoded.descr or "")

            addr += decoded.cmd_len

        barriers[addr] = 1

        if pass_num == 1:
            barriers_list = barriers.keys()
            barriers_list.sort()
            #print "barriers", barriers_list[:10]
            for ref in xrefs_code_local:
                ref_idx = bisect.bisect(barriers_list,ref) - 1
                #print "barrs", ref_idx, ref, barriers_list[ref_idx]
                for addr in xrefs_code_local[ref]:
                    addr_idx = bisect.bisect(barriers_list,addr) - 1
                    if ref_idx != addr_idx:
                        #print "cross area jump: %04X %04X %d %d" % (addr, ref, addr_idx, ref_idx)
                        if ref_idx<addr_idx:
                            start_idx = ref_idx
                            end_idx = addr_idx
                        else:
                            start_idx = addr_idx
                            end_idx = ref_idx
                        if end_idx - start_idx<10:
                            for idx in range(start_idx,end_idx):
                                try:
                                    #print "delete barrier", barriers_list[start_idx+1]
                                    del barriers_list[start_idx+1]
                                except IndexError:
                                    pass
                        else:
                            print "%04X: too long cross area jump %d -> %d, ignoring" % (addr, addr_idx, ref_idx)
                    else:
                        #print "intra area jump: %04X %04X %d %d" % (addr, ref, addr_idx, ref_idx)
                        pass

            labels = {}
            refs = xrefs_code_local.keys()
            refs.sort()
            last_area = -1
            label_cnt = 0
            for ref in refs:
                ref_idx = bisect.bisect(barriers_list,ref) - 1
                if ref_idx != last_area:
                    label_cnt = 1
                    last_area = ref_idx
                labels[ref] = "L%d_%d" % (ref_idx, label_cnt)
                label_cnt += 1
    print "=================== Globals ======================="
    refs = xrefs_globals.keys()
    refs.sort()
    for ref in refs:
        print "%04X %s" % (ref,",".join(["%04X"%d for d in xrefs_globals[ref].keys()]))