Example #1
0
    def parse_subsegments(self, yaml) -> List[Segment]:
        ret: List[Segment] = []

        if not yaml or "subsegments" not in yaml:
            return ret

        prev_start: RomAddr = -1

        for i, subsection_yaml in enumerate(yaml["subsegments"]):
            # End of previous segment
            if isinstance(subsection_yaml, list) and len(subsection_yaml) == 1:
                continue

            typ = Segment.parse_segment_type(subsection_yaml)
            start = Segment.parse_segment_start(subsection_yaml)

            segment_class = Segment.get_class_for_type(typ)

            end = self.get_next_seg_start(i, yaml["subsegments"])

            if (
                isinstance(start, int)
                and isinstance(prev_start, int)
                and start < prev_start
            ):
                log.error(
                    f"Error: Group segment {self.name} contains subsegments which are out of ascending rom order (0x{prev_start:X} followed by 0x{start:X})"
                )

            vram = None
            if start != "auto":
                assert isinstance(start, int)
                vram = self.get_most_parent().rom_to_ram(start)

            segment: Segment = Segment.from_yaml(
                segment_class, subsection_yaml, start, end, vram
            )
            segment.parent = self

            ret.append(segment)
            prev_start = start

        return ret
Example #2
0
    def parse_subsegments(self, segment_yaml) -> List[Segment]:
        base_segments: OrderedDict[str, Segment] = OrderedDict()
        ret = []
        prev_start: RomAddr = -1
        inserts: OrderedDict[str, int] = (
            OrderedDict()
        )  # Used to manually add "all_" types for sections not otherwise defined in the yaml

        found_sections = OrderedDict(
            (s_name, Range()) for s_name in self.section_boundaries
        )  # Stores yaml index where a section was first found

        if "subsegments" not in segment_yaml:
            return []

        # Mark any manually added dot types
        if options.auto_all_sections():
            cur_section = None

            for i, subsection_yaml in enumerate(segment_yaml["subsegments"]):
                # rompos marker
                if isinstance(subsection_yaml,
                              list) and len(subsection_yaml) == 1:
                    if cur_section is not None:
                        # End the current section
                        found_sections[cur_section].end = i
                        cur_section = None
                    continue

                typ = Segment.parse_segment_type(subsection_yaml)
                if typ.startswith("all_"):
                    typ = typ[4:]
                if not typ.startswith("."):
                    typ = f".{typ}"

                if typ in found_sections:
                    if cur_section is None:
                        # Starting point
                        found_sections[typ].start = i
                        cur_section = typ
                    else:
                        if cur_section != typ:
                            # We're changing sections
                            if found_sections[cur_section].has_end():
                                log.error(
                                    f"Section {cur_section} end encountered but was already ended earlier!"
                                )
                            if found_sections[typ].has_start():
                                log.error(
                                    f"Section {typ} start encounted but has already started earlier!"
                                )

                            # End the current section
                            found_sections[cur_section].end = i

                            # Start the next section
                            found_sections[typ].start = i
                            cur_section = typ

            if cur_section is not None:
                found_sections[cur_section].end = len(
                    segment_yaml["subsegments"])

            inserts = self.find_inserts(found_sections)

        for i, subsection_yaml in enumerate(segment_yaml["subsegments"]):
            # rompos marker
            if isinstance(subsection_yaml, list) and len(subsection_yaml) == 1:
                continue

            typ = Segment.parse_segment_type(subsection_yaml)
            start = Segment.parse_segment_start(subsection_yaml)

            # Add dummy segments to be expanded later
            if typ.startswith("all_"):
                ret.append(Segment(start, "auto", typ, "", "auto"))
                continue

            segment_class = Segment.get_class_for_type(typ)

            end = self.get_next_seg_start(i, segment_yaml["subsegments"])

            if (isinstance(start, int) and isinstance(prev_start, int)
                    and start < prev_start):
                log.error(
                    f"Error: Group segment {self.name} contains subsegments which are out of ascending rom order (0x{prev_start:X} followed by 0x{start:X})"
                )

            vram = None
            if start != "auto":
                assert isinstance(start, int)
                vram = self.get_most_parent().rom_to_ram(start)

            segment: Segment = Segment.from_yaml(segment_class,
                                                 subsection_yaml, start, end,
                                                 vram)
            segment.sibling = base_segments.get(segment.name, None)
            segment.parent = self

            for i, section in enumerate(self.section_order):
                if not self.section_boundaries[section].has_start(
                ) and dotless_type(section) == dotless_type(segment.type):
                    if i > 0:
                        prev_section = self.section_order[i - 1]
                        self.section_boundaries[
                            prev_section].end = segment.vram_start
                    self.section_boundaries[section].start = segment.vram_start

            ret.append(segment)

            # todo change
            if typ in CODE_TYPES:
                base_segments[segment.name] = segment

            prev_start = start

        # Add the automatic all_ sections
        orig_len = len(ret)
        for section in reversed(inserts):
            idx = inserts[section]

            if idx == -1:
                idx = orig_len

            # bss hack TODO maybe rethink
            if section == "bss" and self.vram_start is not None:
                rom_start = self.rom_end
                vram_start = self.vram_start + self.rom_end - self.rom_start
            else:
                rom_start = "auto"
                vram_start = "auto"

            ret.insert(
                idx,
                (Segment(rom_start, "auto", "all_" + section, "", vram_start)))

        check = True
        while check:
            check = self.handle_alls(ret, base_segments)

        # TODO why is this necessary?
        if (self.section_boundaries[".rodata"].has_start()
                and not self.section_boundaries[".rodata"].has_end()):
            assert self.vram_end is not None
            self.section_boundaries[".rodata"].end = self.vram_end

        return ret
Example #3
0
    def parse_subsegments(self, segment_yaml) -> List[Segment]:
        base_segments: OrderedDict[str, Segment] = OrderedDict()
        ret = []
        prev_start: RomAddr = -1

        if "subsegments" not in segment_yaml:
            print(f"Error: Group segment {self.name} is missing a 'subsegments' field")
            sys.exit(2)

        for i, subsection_yaml in enumerate(segment_yaml["subsegments"]):
            # rompos marker
            if isinstance(subsection_yaml, list) and len(subsection_yaml) == 1:
                continue

            typ = Segment.parse_segment_type(subsection_yaml)

            if typ.startswith("all_"):
                ret.append(Segment("auto", "auto", typ, "", "auto"))
                continue

            segment_class = Segment.get_class_for_type(typ)

            start = Segment.parse_segment_start(subsection_yaml)
            end = self.rom_end if i == len(segment_yaml["subsegments"]) - 1 else Segment.parse_segment_start(segment_yaml["subsegments"][i + 1])

            if isinstance(start, int) and isinstance(prev_start, int) and start < prev_start:
                print(f"Error: Code segment {self.name} contains subsegments which are out of ascending rom order (0x{prev_start:X} followed by 0x{start:X})")
                sys.exit(1)

            segment: Segment = Segment.from_yaml(segment_class, subsection_yaml, start, end)
            segment.sibling = base_segments.get(segment.name, None)
            segment.parent = self

            if segment.rom_start != "auto":
                assert isinstance(segment.rom_start, int)
                segment.vram_start = self.rom_to_ram(segment.rom_start)

            # TODO: assumes section order - generalize and stuff
            if self.data_vram_start == None and "data" in segment.type:
                self.data_vram_start = segment.vram_start
            if self.rodata_vram_start == None and "rodata" in segment.type:
                self.data_vram_end = segment.vram_start
                self.rodata_vram_start = segment.vram_start
            if self.rodata_vram_end == None and "bss" in segment.type:
                self.rodata_vram_end = segment.vram_start
                self.bss_vram_start = segment.vram_start

            ret.append(segment)

            # todo change
            if typ in ["c", "asm", "hasm"]:
                base_segments[segment.name] = segment

            prev_start = start

        check = True

        while check:
            check = self.handle_alls(ret, base_segments)

        if self.rodata_vram_start != None and self.rodata_vram_end == None:
            assert self.vram_end is not None
            self.rodata_vram_end = self.vram_end

        return ret