Пример #1
0
    def __init__(self, memory, address):
        super().__init__(memory, address)
        
        while True:
            if address >= 0x8000 or memory[address]:
                break

            try:
                instr = Instruction(self.memory, address)
            except InstructionDecodeError:
                print("Encountered invalid instruction [%02x] in code at: %02x:%04x" % (memory.byte(address), memory.bankNumber, address))
                break
            if not self.resize(len(self) + instr.size, allow_fail=True):
                print("Odd instruction overlap at: %02x:%04x" % (memory.bankNumber, address))
                break

            for n in range(1, instr.size):
                memory.ensureNoLabel(address + n)
            address += instr.size
            
            target = instr.jumpTarget()
            if target != None and target < 0x8000:
                if memory.bankNumber > 0:
                    active_bank = memory
                else:
                    active_bank = memory.activeRomBankAt(address - instr.size)
                    if active_bank is not None:
                        active_bank = RomInfo.romBank(active_bank)
                other_memory = RomInfo.memoryAt(target, active_bank)
                if other_memory:
                    other_block = other_memory[target]
                    if other_block == None:
                        other_block = CodeBlock(other_memory, target)
                    elif isinstance(other_block, CodeBlock):
                        if instr.type in (CALL, RST):
                            other_block.onCall(self.memory, address - instr.size, address)
                        else:
                            other_block.onJump(self.memory, address - instr.size, address)
                    other_block.addAutoLabel(target, address, instr.type)
            elif isinstance(instr.p0, Ref) and isinstance(instr.p0.target, int) and instr.p0.target >= 0x8000:
                mem = RomInfo.memoryAt(instr.p0.target, memory)
                if mem:
                    mem.addAutoLabel(instr.p0.target, address, "data")
            elif isinstance(instr.p1, Ref) and isinstance(instr.p1.target, int):
                mem = RomInfo.memoryAt(instr.p1.target, memory)
                if mem:
                    mem.addAutoLabel(instr.p1.target, address, "data")
            elif instr.p0 in (BC, DE, HL) and isinstance(instr.p1, int):
                if 0x4000 <= instr.p1 < 0x8000 and memory.bankNumber > 0: # Banked ROM
                    RomInfo.memoryAt(instr.p1, memory).addAutoLabel(instr.p1, address, "data")
                elif 0xC000 <= instr.p1 < 0xE000: # WRAM
                    RomInfo.memoryAt(instr.p1).addAutoLabel(instr.p1, address, "data")
                elif 0xFF80 <= instr.p1 < 0xFFFF: # HRAM
                    RomInfo.memoryAt(instr.p1).addAutoLabel(instr.p1, address, "data")
            if not instr.hasNext():
                break
Пример #2
0
 def export(self, file):
     try:
         target_memory = RomInfo.memoryAt(self.__target_address, RomInfo.romBank(self.__bank))
     except IndexError:
         file.dataLine(4)
         return
     label = target_memory.getLabel(self.__target_address)
     if not label:
         file.dataLine(4)
         return
     file.asmLine(4, "dw", str(label), "BANK(%s)" % (label), is_data=True)
Пример #3
0
    def __init__(self, memory, address):
        super().__init__(memory, address, size=4)
        
        self.__target_address = memory.word(address)
        self.__bank = memory.byte(address + 2)
        unknown = memory.byte(address + 3)
        
        print("SDCC farcall to: %02x:%04x" % (self.__bank, self.__target_address))

        try:
            target_memory = RomInfo.memoryAt(self.__target_address, RomInfo.romBank(self.__bank))
        except IndexError:
            return
        target_block = target_memory[self.__target_address]
        if target_block is None:
            target_block = CodeBlock(target_memory, self.__target_address)
        target_block.addAutoLabel(self.__target_address, address, "call")
Пример #4
0
    def export(self, path):
        for bank in RomInfo.getRomBanks():
            AutoLabelLocalizer(bank)

        if not os.path.exists(path):
            shutil.copytree(
                os.path.join(os.path.dirname(__file__), "template"), path)
        open(os.path.join(path, "rom.gb.md5"),
             "wt").write("%s rom.gb\n" % (self.__rom.md5sum()))

        objfiles = []
        for bank in RomInfo.getRomBanks():
            print("Processing bank: %d" % (bank.bankNumber))
            self.__exportRomBank(
                AssemblyFile(
                    os.path.join(path, "src",
                                 "bank%02X.asm" % (bank.bankNumber)), bank),
                bank)

        f = AssemblyFile(os.path.join(path, "src", "memory.asm"))
        self.__exportRam(f, RomInfo.getWRam())
        self.__exportRam(f, RomInfo.getHRam())

        macro_file = open(os.path.join(path, "src", "include", "macros.inc"),
                          "wt")
        for macro, contents in sorted(RomInfo.macros.items()):
            macro_file.write("%s: MACRO\n" % (macro))
            for line in contents.rstrip().split("\n"):
                macro_file.write("    %s\n" % (line.rstrip()))
            macro_file.write("ENDM\n")

        charmap_file = open(
            os.path.join(path, "src", "include", "charmaps.inc"), "wt")
        for name, data in sorted(RomInfo.charmap.items()):
            if name == "main":
                charmap_file.write("SETCHARMAP %s\n" % (name))
            else:
                charmap_file.write("NEWCHARMAP %s\n" % (name))
            for key, value in sorted(data.items()):
                charmap_file.write("CHARMAP \"%s\", %d\n" % (value, key))
Пример #5
0
    def processRom(self):
        # First process all the annotations
        for bank in RomInfo.getRomBanks():
            for addr, comments in bank.getAllComments():
                for comment in comments:
                    if comment.startswith("@"):
                        callAnnotation(bank, addr, comment[1:])
            for addr, comment in bank.getAllInlineComments():
                if comment.startswith("@"):
                    callAnnotation(bank, addr, comment[1:])

        # Next process our normal entry point, header info and interrupts.
        ROMHeader(RomInfo.romBank(0))
        if RomInfo.romBank(0)[0x0100] is None:
            CodeBlock(RomInfo.romBank(0), 0x0100).addLabel(0x0100, "entry")

        for addr, name in [(0x0040, "isrVBlank"), (0x0048, "isrLCDC"),
                           (0x0050, "isrTimer"), (0x0058, "isrSerial"),
                           (0x0060, "isrJoypad")]:
            if RomInfo.memoryAt(addr).byte(addr) not in (
                    0x00, 0xff) and RomInfo.memoryAt(addr)[addr] == None:
                CodeBlock(RomInfo.romBank(0), addr).addLabel(addr, name)

        # Finally, for any data that has no blocks on it, see if we have marks from instrumentation that can decode it
        for bank in RomInfo.getRomBanks():
            for addr in range(bank.base_address,
                              bank.base_address + len(bank)):
                if not bank[addr]:
                    if bank.hasMark(addr, "CODE"):
                        CodeBlock(bank, addr)
                    elif bank.hasMark(addr, "GFX_LOW") and bank.hasMark(
                            addr + 1, "GFX_HIGH"):
                        size = 2
                        while size < 16 and bank.hasMark(
                                addr + size, "GFX_LOW") and bank.hasMark(
                                    addr + size + 1, "GFX_HIGH"):
                            size += 2
                        GfxBlock(bank, addr, bpp=2, size=size // 2)
                    elif bank.hasMark(addr, "GFX_HIGH"):
                        size = 1
                        while size < 8 and bank.hasMark(
                                addr + size, "GFX_HIGH"):
                            size += 1
                        GfxBlock(bank, addr, bpp=1, size=size)
                    elif bank.hasMark(addr, "PTR_LOW") and bank.hasMark(
                            addr + 1, "PTR_HIGH"):
                        DataBlock(bank, addr, format="p", amount=1)
                    elif bank.hasMark(addr, "WORD_LOW") and bank.hasMark(
                            addr + 1, "WORD_HIGH"):
                        DataBlock(bank, addr, format="w", amount=1)
Пример #6
0
def processInstrumentation(filename):
    f = open(filename, "rb")
    while True:
        data = f.read(16)
        if not data:
            break
        source, used_as = struct.unpack("<QQ", data)
        if (source & ID_MASK) == ID_ROM:
            addr = source & 0x3FFF
            bank = (source >> 14) & 0x3FF
            if bank > 0:
                addr |= 0x4000
            
            memory = RomInfo.romBank(bank)
            if used_as & MARK_INSTR:
                memory.mark(addr, "CODE")
            if used_as & MARK_DATA:
                memory.mark(addr, "DATA")
                used_as_id = (used_as & ID_MASK)
                used_as_addr = (used_as & 0xFFFF)
                if used_as_id == ID_VRAM:
                    if used_as_addr < 0x1800:
                        if (used_as_addr & 1) == 0:
                            memory.mark(addr, "GFX_LOW")
                        else:
                            memory.mark(addr, "GFX_HIGH")
                    else:
                        memory.mark(addr, "TILE")
                elif used_as_id == ID_OAM:
                    pass
                elif used_as_id == ID_IO:
                    pass
                elif used_as_id == ID_ROM:
                    if used_as_addr & 0xF000 == 0x2000:
                        memory.mark(addr, "BANK")
            if used_as & MARK_PTR_LOW:
                memory.mark(addr, "PTR_LOW")
            if used_as & MARK_PTR_HIGH:
                memory.mark(addr, "PTR_HIGH")
            if used_as & MARK_WORD_LOW:
                memory.mark(addr, "WORD_LOW")
            if used_as & MARK_WORD_HIGH:
                memory.mark(addr, "WORD_HIGH")

            if bank == 0 and (used_as & MARK_BANK_MASK) != 0 and (used_as & MARK_BANK_MASK) >> MARK_BANK_SHIFT:
                memory.setActiveRomBankAt(addr, (used_as & MARK_BANK_MASK) >> MARK_BANK_SHIFT)
Пример #7
0
 def __init__(self, rom):
     self.__rom = rom
     RomInfo.init(rom)
Пример #8
0
 def formatAsAddressOrLabel(self, target, source_addr):
     label = RomInfo.getLabelAt(target, RomInfo.romBank(self.memory.activeRomBankAt(source_addr)))
     if label:
         return label
     return "$%04x" % (target)