Пример #1
0
 def __init__(self, data):
   self.data = data
   
   if try_read_str(self.data, 0, 4) == "Yaz0":
     self.data = Yaz0Decompressor.decompress(self.data)
   
   data = self.data
   
   self.size = read_u32(data, 4)
   self.file_data_list_offset = read_u32(data, 0xC) + 0x20
   self.file_data_total_size = read_u32(data, 0x10)
   self.file_data_total_size_2 = read_u32(data, 0x14)
   self.file_data_total_size_3 = read_u32(data, 0x18)
   num_nodes = read_u32(data, 0x20)
   node_list_offset = 0x40
   self.total_num_file_entries = read_u32(data, 0x28)
   file_entries_list_offset = read_u32(data, 0x2C) + 0x20
   self.string_list_offset = read_u32(data, 0x34) + 0x20
   
   self.nodes = []
   for node_index in range(0, num_nodes):
     offset = node_list_offset + node_index*0x10
     node = Node(data, offset)
     self.nodes.append(node)
   
   self.file_entries = []
   for node in self.nodes:
     for file_index in range(node.first_file_index, node.first_file_index+node.num_files):
       file_entry_offset = file_entries_list_offset + file_index*0x14
       
       file_entry = FileEntry(data, file_entry_offset, self)
       self.file_entries.append(file_entry)
       node.files.append(file_entry)
   
   self.instantiated_object_files = {}
Пример #2
0
def disassemble_all_code(self):
    if not os.path.isfile(
            r"C:\devkitPro\devkitPPC\bin\powerpc-eabi-objdump.exe"):
        raise Exception(
            r"Failed to disassemble code: Could not find devkitPPC. devkitPPC should be installed to: C:\devkitPro\devkitPPC"
        )

    rels_arc = self.get_arc("files/RELS.arc")
    out_dir = os.path.join(self.randomized_output_folder, "disassemble")
    if not os.path.isdir(out_dir):
        os.mkdir(out_dir)
    main_symbols = get_main_symbols(self)

    files_to_disassemble = get_list_of_all_rels(self)
    files_to_disassemble.append("sys/main.dol")

    for file_path in files_to_disassemble:
        basename_with_ext = os.path.basename(file_path)
        print(basename_with_ext)

        rel_file_entry = rels_arc.get_file_entry(basename_with_ext)
        if rel_file_entry:
            rel_file_entry.decompress_data_if_necessary()
            data = rel_file_entry.data
        else:
            data = self.gcm.read_file_data(file_path)
            if try_read_str(data, 0, 4) == "Yaz0":
                data = Yaz0Decompressor.decompress(data)

        basename, file_ext = os.path.splitext(basename_with_ext)

        is_rel = (file_ext == ".rel")

        bin_path = os.path.join(out_dir, basename_with_ext)
        with open(bin_path, "wb") as f:
            data.seek(0)
            f.write(data.read())

        asm_path = os.path.join(out_dir, basename + ".asm")

        disassemble_file(bin_path, asm_path)

        if is_rel:
            rel_map_data = self.gcm.read_file_data("files/maps/" + basename +
                                                   ".map")
            rel_map_data.seek(0)
            rel_map_data = rel_map_data.read()

            # Copy the map file to the output directory
            rel_map_path = os.path.join(out_dir, basename + ".map")
            with open(rel_map_path, "wb") as f:
                f.write(rel_map_data)

            rel_map_data = rel_map_data.decode("ascii")
            add_relocations_and_symbols_to_rel(asm_path, bin_path,
                                               main_symbols, rel_map_data)
        else:
            add_symbols_to_main(asm_path, main_symbols)
Пример #3
0
    def __init__(self, file_path):
        self.file_path = file_path
        with open(self.file_path, "rb") as file:
            self.data = BytesIO(file.read())

        if try_read_str(self.data, 0, 4) == "Yaz0":
            self.data = Yaz0Decompressor.decompress(self.data)

        data = self.data

        self.id = read_u32(data, 0)

        self.sections = []
        self.num_sections = read_u32(data, 0xC)
        self.section_info_table_offset = read_u32(data, 0x10)
        for section_index in range(0, self.num_sections):
            section_info_offset = self.section_info_table_offset + section_index * 8
            section = Section(data, section_info_offset)
            self.sections.append(section)

        self.relocation_data_offset_for_module = {}
        self.imp_table_offset = read_u32(data, 0x28)
        self.imp_table_length = read_u32(data, 0x2C)
        offset = self.imp_table_offset
        while offset < self.imp_table_offset + self.imp_table_length:
            module_num = read_u32(data, offset)
            relocation_data_offset = read_u32(data, offset + 4)
            self.relocation_data_offset_for_module[
                module_num] = relocation_data_offset
            offset += 8

        self.relocation_entries_for_module = {}
        curr_section_num = None
        for module_num, relocation_data_offset in self.relocation_data_offset_for_module.items(
        ):
            self.relocation_entries_for_module[module_num] = []

            offset = relocation_data_offset
            prev_relocation_offset = 0
            while True:
                relocation_type = read_u8(data, offset + 2)
                if relocation_type == 0xCB:  # R_RVL_STOP
                    break

                relocation_data_entry = RelocationDataEntry(
                    data, offset, prev_relocation_offset, curr_section_num)
                prev_relocation_offset = relocation_data_entry.relocation_offset

                if relocation_data_entry.relocation_type == 0xCA:  # R_RVL_SECT
                    curr_section_num = relocation_data_entry.section_num_to_relocate_against
                    prev_relocation_offset = 0
                else:
                    self.relocation_entries_for_module[module_num].append(
                        relocation_data_entry)

                offset += 8
Пример #4
0
def disassemble_all_code(self):
    rels_arc = self.get_arc("files/RELS.arc")
    out_dir = os.path.join(self.randomized_output_folder, "disassemble")
    if not os.path.isdir(out_dir):
        os.mkdir(out_dir)
    main_symbols = get_main_symbols(self)

    files_to_disassemble = get_list_of_all_rels(self)
    files_to_disassemble.append("sys/main.dol")

    for file_path in files_to_disassemble:
        basename_with_ext = os.path.basename(file_path)
        print(basename_with_ext)

        rel_file_entry = rels_arc.get_file_entry(basename_with_ext)
        if rel_file_entry:
            rel_file_entry.decompress_data_if_necessary()
            data = rel_file_entry.data
        else:
            data = self.gcm.read_file_data(file_path)
            if try_read_str(data, 0, 4) == "Yaz0":
                data = Yaz0Decompressor.decompress(data)

        basename, file_ext = os.path.splitext(basename_with_ext)

        is_rel = (file_ext == ".rel")

        bin_path = os.path.join(out_dir, basename_with_ext)
        with open(bin_path, "wb") as f:
            data.seek(0)
            f.write(data.read())

        asm_path = os.path.join(out_dir, basename + ".asm")

        disassemble_file(bin_path, asm_path)

        if is_rel:
            rel_map_data = self.gcm.read_file_data("files/maps/" + basename +
                                                   ".map")
            rel_map_data.seek(0)
            rel_map_data = rel_map_data.read().decode("ascii")

            add_relocations_and_symbols_to_rel(asm_path, bin_path,
                                               main_symbols, rel_map_data)
        else:
            add_symbols_to_main(asm_path, main_symbols)
Пример #5
0
 def get_raw_file(self, file_path):
   file_path = file_path.replace("\\", "/")
   
   if file_path in self.raw_files_by_path:
     return self.raw_files_by_path[file_path]
   else:
     if file_path.startswith("files/rels/"):
       rel_name = os.path.basename(file_path)
       rels_arc = self.get_arc("files/RELS.arc")
       rel_file_entry = rels_arc.get_file_entry(rel_name)
     else:
       rel_file_entry = None
     
     if rel_file_entry:
       rel_file_entry.decompress_data_if_necessary()
       data = rel_file_entry.data
     else:
       data = self.gcm.read_file_data(file_path)
     
     if try_read_str(data, 0, 4) == "Yaz0":
       data = Yaz0Decompressor.decompress(data)
     
     self.raw_files_by_path[file_path] = data
     return data
Пример #6
0
 def decompress_data_if_necessary(self):
   if try_read_str(self.data, 0, 4) == "Yaz0":
     self.data = Yaz0Decompressor.decompress(self.data)
     self.type &= ~0x84 # Clear compressed type bits
Пример #7
0
 def __init__(self, data):
   self.data = data
   
   if try_read_str(self.data, 0, 4) == "Yaz0":
     self.data = Yaz0Decompressor.decompress(self.data)
   
   data = self.data
   
   self.size = read_u32(data, 4)
   self.file_data_list_offset = read_u32(data, 0xC) + 0x20
   self.file_data_total_size = read_u32(data, 0x10)
   self.file_data_total_size_2 = read_u32(data, 0x14)
   self.file_data_total_size_3 = read_u32(data, 0x18)
   num_nodes = read_u32(data, 0x20)
   node_list_offset = 0x40
   self.total_num_file_entries = read_u32(data, 0x28)
   file_entries_list_offset = read_u32(data, 0x2C) + 0x20
   self.string_list_offset = read_u32(data, 0x34) + 0x20
   
   self.nodes = []
   for node_index in range(0, num_nodes):
     offset = node_list_offset + node_index*0x10
     node = Node(data, offset)
     self.nodes.append(node)
   
   self.file_entries = []
   self.dzx_files = []
   self.event_list_files = []
   self.bmg_files = []
   self.bdl_files = []
   self.bti_files = []
   self.chart_lists = []
   for node in self.nodes:
     for file_index in range(node.first_file_index, node.first_file_index+node.num_files):
       file_entry_offset = file_entries_list_offset + file_index*0x14
       
       file_entry = FileEntry(data, file_entry_offset, self)
       self.file_entries.append(file_entry)
       node.files.append(file_entry)
       
       if file_entry.is_dir:
         continue
       
       if file_entry.name.endswith(".dzs"):
         dzx = DZx(file_entry)
         self.dzx_files.append(dzx)
       elif file_entry.name.endswith(".dzr"):
         dzx = DZx(file_entry)
         self.dzx_files.append(dzx)
       elif file_entry.name == "event_list.dat":
         event_list = EventList(file_entry)
         self.event_list_files.append(event_list)
       elif file_entry.name.endswith(".bmg"):
         bmg = BMG(file_entry)
         self.bmg_files.append(bmg)
       elif file_entry.name.endswith(".bdl"):
         bdl = BDL(file_entry)
         self.bdl_files.append(bdl)
       elif file_entry.name.endswith(".bti"):
         bti = BTIFile(file_entry)
         self.bti_files.append(bti)
       elif file_entry.name == "cmapdat.bin":
         chart_list = ChartList(file_entry)
         self.chart_lists.append(chart_list)
Пример #8
0
    def __init__(self, file_path):
        self.file_path = file_path
        with open(self.file_path, "rb") as file:
            self.data = BytesIO(file.read())

        if try_read_str(self.data, 0, 4) == "Yaz0":
            self.data = Yaz0Decompressor.decompress(self.data)

        data = self.data

        self.id = read_u32(data, 0)

        self.sections = []
        self.num_sections = read_u32(data, 0xC)
        self.section_info_table_offset = read_u32(data, 0x10)
        for section_index in range(0, self.num_sections):
            section_info_offset = self.section_info_table_offset + section_index * 8
            section = Section(data, section_info_offset)
            self.sections.append(section)

        self.relocation_data_offset_for_module = {}
        self.imp_table_offset = read_u32(data, 0x28)
        self.imp_table_length = read_u32(data, 0x2C)
        offset = self.imp_table_offset
        while offset < self.imp_table_offset + self.imp_table_length:
            module_num = read_u32(data, offset)
            relocation_data_offset = read_u32(data, offset + 4)
            self.relocation_data_offset_for_module[
                module_num] = relocation_data_offset
            offset += 8

        self.relocation_entries_for_module = {}
        curr_section_num = None
        for module_num, relocation_data_offset in self.relocation_data_offset_for_module.items(
        ):
            self.relocation_entries_for_module[module_num] = []

            offset = relocation_data_offset
            prev_relocation_offset = 0
            while True:
                relocation_type = read_u8(data, offset + 2)
                if relocation_type == 0xCB:  # R_RVL_STOP
                    break

                relocation_data_entry = RelocationDataEntry(
                    data, offset, prev_relocation_offset, curr_section_num)
                prev_relocation_offset = relocation_data_entry.relocation_offset

                if relocation_data_entry.relocation_type == 0xCA:  # R_RVL_SECT
                    curr_section_num = relocation_data_entry.section_num_to_relocate_against
                    prev_relocation_offset = 0
                else:
                    self.relocation_entries_for_module[module_num].append(
                        relocation_data_entry)

                offset += 8

        # Space after this fix_size offset can be reused for other purposes.
        # Such as using the space that originally had the relocations list for .bss static variables instead.
        self.fix_size = read_u32(data, 0x48)
        self.fix_size = (self.fix_size +
                         0x1F) & ~(0x1F)  # Round up to nearest 0x20

        self.bss_section_index = None  # The byte at offset 0x33 in the REL is reserved for this value at runtime.
        for section_index, section in enumerate(self.sections):
            if section.is_bss:
                self.bss_section_index = section_index
                section.offset = self.fix_size
                break