Exemple #1
0
    def write(self) -> bytes:
        toc_buffer = bytearray(8 * (len(self.model) + 1))
        toc_cursor = 0
        image_buffer = bytearray()
        # File list
        for w16 in self.model:
            # TOC entry
            # Pointer
            write_u32(toc_buffer,
                      u32_checked(len(toc_buffer) + len(image_buffer)),
                      toc_cursor)
            # entry data
            write_u8(toc_buffer, w16.entry_data.width, toc_cursor + 4)
            write_u8(toc_buffer, w16.entry_data.height, toc_cursor + 5)
            write_u8(toc_buffer, w16.entry_data.index, toc_cursor + 6)
            write_u8(toc_buffer, w16.entry_data.null, toc_cursor + 7)
            toc_cursor += 8
            # Palettes
            pal = bytes(w16.pal)
            assert len(pal) == 3 * 16
            image_buffer += pal
            # Data
            image_buffer += w16.compressed_img_data

        # Null toc entry
        write_u32(toc_buffer, u32_checked(len(toc_buffer) + len(image_buffer)),
                  toc_cursor)

        return toc_buffer + image_buffer
Exemple #2
0
    def write(self) -> Tuple[bytes, List[int], Optional[int]]:
        buffer = bytearray()

        # Sprites
        spr_pointer = len(buffer)
        for tiles in self.model.sprites:
            for tile in tiles:
                buffer += tile

        # Palettes
        pal_pointer = len(buffer)
        data = bytearray(len(self.model.palettes) * PAL_LEN * PAL_ENTRY_LEN)
        cursor = 0
        for pal in self.model.palettes:
            for i, col in enumerate(pal):
                write_u8(data, u8(col), cursor)
                cursor += 1
                if i % 3 == 2:
                    write_u8(data, u8(0xAA), cursor)
                    cursor += 1
        buffer += data

        # Header
        header = bytearray(4 * 4)
        write_u32(header, u32_checked(spr_pointer), 0x00)
        write_u32(header, u32_checked(len(self.model.sprites)), 0x04)
        write_u32(header, u32_checked(pal_pointer), 0x08)
        write_u32(header, u32_checked(len(self.model.palettes) * PAL_LEN),
                  0x0C)
        pointer_offsets = [len(buffer), len(buffer) + 8]
        header_pointer = len(buffer)
        buffer += header

        return buffer, pointer_offsets, header_pointer
Exemple #3
0
    def to_bytes(self):
        """Convert the string list back to bytes"""
        length_of_index = 4 * (len(self.strings) + 1)
        length_of_str_bytes = 0
        offset_list = []
        strings_bytes = []
        for s in self.strings:
            b = bytes(s, self.string_encoding) + bytes([0])
            offset_list.append(
                u32_checked(length_of_index + length_of_str_bytes))
            length_of_str_bytes += len(b)
            strings_bytes.append(b)

        result = bytearray(length_of_index + length_of_str_bytes)
        cursor = 0
        for pnt in offset_list:
            write_u32(result, pnt, cursor)
            cursor += 4
        # End of pointers markers
        write_u32(result, u32_checked(length_of_index + length_of_str_bytes),
                  cursor)
        cursor += 4

        # Write string bytes
        offset_list.append(u32_checked(length_of_index + length_of_str_bytes))
        for i, s in enumerate(strings_bytes):
            length = offset_list[i + 1] - offset_list[i]
            result[cursor:cursor + length] = s
            cursor += length

        return result
Exemple #4
0
    def write(self) -> Tuple[bytes, List[int], Optional[int]]:
        pointer_offsets = []
        buffer = bytearray()

        # Insert the tiles with their masks
        tile_table = []
        for i in range(len(self.model.tiles)):
            tile_table.append(u32_checked(len(buffer)))
            current_mask = self.model.masks[i]
            current_tile = self.model.tiles[i]
            for x in range(ZMAPPAT_TILE_SIZE // 8):
                buffer += current_mask[x * 4:x * 4 +
                                       4] + current_tile[x * 4:x * 4 + 4]

        # Insert the tile pointers table
        table = bytearray(len(tile_table) * 4)
        table_pointer = u32_checked(len(buffer))
        for i, x in enumerate(tile_table):
            pointer_offsets.append(len(buffer) + i * 4)
            write_u32(table, x, i * 4)
        buffer += table

        # The palette
        palette_pointer = u32_checked(len(buffer))
        palette_buffer = bytearray(len(self.model.palette) * 4 // 3)
        j = 0
        for i, p in enumerate(self.model.palette):
            write_u8(palette_buffer, u8(p), j)
            j += 1
            if i % 3 == 2:
                # Insert the fourth color
                write_u8(palette_buffer, u8(0), j)
                j += 1
        assert j == len(palette_buffer)
        buffer += palette_buffer

        # The header
        header_pointer = len(buffer)
        header = bytearray(0x8)
        pointer_offsets.append(len(buffer))
        pointer_offsets.append(len(buffer) + 4)
        write_u32(header, table_pointer, 0)
        write_u32(header, palette_pointer, 4)

        buffer += header
        return buffer, pointer_offsets, header_pointer
Exemple #5
0
    def write(self) -> Tuple[bytes, List[int], Optional[int]]:
        pointer_offsets = []
        buffer = bytearray()

        # Image data
        image_pointer = len(buffer)
        buffer += self.model.image_data
        # Padding
        if len(buffer) % 16 != 0:
            buffer += bytes(0 for _ in range(0, 16 - (len(buffer) % 16)))

        # Palette
        palette_pointer = len(buffer)
        palette_buffer = bytearray(len(self.model.palette) + int(len(self.model.palette) / 3))
        j = 0
        for i, p in enumerate(self.model.palette):
            write_u8(palette_buffer, u8(p), j)
            j += 1
            if i % 3 == 2:
                # Insert the fourth color
                write_u8(palette_buffer, u8(0x80), j)
                j += 1
        assert j == len(palette_buffer)
        buffer += palette_buffer

        # Header
        # We don't really know how many 0s the game wants but better to many than too few...
        header = bytearray(0x34)
        header[0:4] = MAGIC_NUMBER
        pointer_offsets.append(len(buffer) + 0x04)
        write_u32(header, u32_checked(image_pointer), 0x04)
        write_u32(header, u32_checked(len(self.model.image_data)), 0x08)
        write_u8(header, self.model.actual_dim, 0x0C)
        write_u8(header, self.model.image_type.value, 0x0D)
        write_u32(header, self.model.unk10, 0x10)
        write_u16(header, self.model.width, 0x14)
        write_u16(header, self.model.height, 0x16)
        pointer_offsets.append(len(buffer) + 0x18)
        write_u32(header, u32_checked(palette_pointer), 0x18)
        write_u32(header, u32_checked(len(self.model.palette) // 3), 0x1C)

        header_pointer = len(buffer)
        buffer += header

        return buffer, pointer_offsets, header_pointer
Exemple #6
0
    def write(self) -> Tuple[bytes, List[int], Optional[int]]:
        from skytemple_files.common.types.file_types import FileType

        pointer_offsets = []

        char_offsets = []
        sorted_entries = sorted(self.model.entries,
                                key=lambda x: (x.table, x.char))
        buffer = bytearray()
        # Image data
        for i, e in enumerate(sorted_entries):
            char_offsets.append(u32_checked(len(buffer)))
            buffer += FileType.RLE_NIBBLE.compress(e.data)

        if len(buffer) % 16 != 0:
            buffer += bytearray([0xAA] * (16 - len(buffer) % 16))
        # Character pointers
        char_pointer = bytearray(
            len(self.model.entries) * BANNER_FONT_ENTRY_LEN)
        char_pointer_offset = u32_checked(len(buffer))
        last: Tuple[Optional[int], Optional[int]] = (None, None)
        for i, e in enumerate(sorted_entries):
            if last == (e.char, e.table):
                raise ValueError(
                    "Character {e.char} in table {e.table} is be defined multiple times in a font file!"
                )
            last = (e.char, e.table)
            pointer_offsets.append(len(buffer) + i * BANNER_FONT_ENTRY_LEN)
            write_u32(char_pointer, char_offsets[i], i * BANNER_FONT_ENTRY_LEN)
            write_u8(char_pointer, e.char, i * BANNER_FONT_ENTRY_LEN + 0x4)
            write_u8(char_pointer, e.table, i * BANNER_FONT_ENTRY_LEN + 0x5)
            write_i16(char_pointer, e.width, i * BANNER_FONT_ENTRY_LEN + 0x6)
        buffer += char_pointer

        # Header
        header = bytearray(0xC)
        pointer_offsets.append(len(buffer))
        write_u32(header, char_pointer_offset, 0)
        write_u32(header, u32_checked(len(self.model.entries)), 0x4)
        write_u32(header, self.model.unknown, 0x8)

        header_pointer = len(buffer)
        buffer += header

        return buffer, pointer_offsets, header_pointer
Exemple #7
0
    def write(self) -> bytes:
        bytelen_single_tile = int(BGP_TILE_DIM * BGP_TILE_DIM / 2)

        palette_length = u32_checked(len(self.model.palettes) * BGP_PAL_NUMBER_COLORS * BGP_PAL_ENTRY_LEN)
        tiles_length = u32_checked(len(self.model.tiles) * bytelen_single_tile)
        tilemapping_length = u32_checked(len(self.model.tilemap) * BGP_TILEMAP_ENTRY_BYTELEN)
        palette_begin = BGP_HEADER_LENGTH
        tilemapping_begin = u32_checked(palette_begin + palette_length)
        tiles_begin = u32_checked(tilemapping_begin + tilemapping_length)
        # 32 byte header + palette, tiles and tilemapping data
        self.data = bytearray(BGP_HEADER_LENGTH + palette_length + tiles_length + tilemapping_length)

        # Header
        write_u32(self.data, u32(palette_begin), 0)
        write_u32(self.data, palette_length, 4)
        write_u32(self.data, tiles_begin, 8)
        write_u32(self.data, tiles_length, 12)
        write_u32(self.data, tilemapping_begin, 16)
        write_u32(self.data, tilemapping_length, 20)
        write_u32(self.data, self.model.header.unknown3, 24)
        write_u32(self.data, self.model.header.unknown4, 28)
        self.bytes_written = BGP_HEADER_LENGTH

        assert self.bytes_written == palette_begin
        # Palettes
        for palette in self.model.palettes:
            for i, color in enumerate(palette):
                self._write_byte(u8(color))
                if i % 3 == 2:
                    # Insert the fourth color
                    self._write_byte(u8(BGP_PAL_UNKNOWN4_COLOR_VAL))

        assert self.bytes_written == tilemapping_begin
        # Tile Mappings
        for entry in self.model.tilemap:
            write_u16(self.data, entry.to_int(), self.bytes_written)
            self.bytes_written += BGP_TILEMAP_ENTRY_BYTELEN

        assert self.bytes_written == tiles_begin
        # Tiles
        for tile in self.model.tiles:
            self.data[self.bytes_written:self.bytes_written+bytelen_single_tile] = tile
            self.bytes_written += bytelen_single_tile

        return self.data
Exemple #8
0
 def write(self) -> bytes:
     file_data = bytearray(4)
     write_u32(file_data, u32_checked(len(self.model.evo_entries)*MEVO_ENTRY_LENGTH+4), 0)
     
     for x in self.model.evo_entries:
         file_data += x.to_bytes()
     for y in self.model.evo_stats:
         file_data += y.to_bytes()
     return bytes(file_data)
Exemple #9
0
 def _push_string(self, full_binary: bytes, out_data: bytearray,
                  pointer: u32) -> u32:
     """Add the string that's being pointed to to in full_binary to out_data and return a new relative pointer"""
     str_len, string = read_var_length_string(full_binary, pointer)
     new_pointer = u32_checked(len(out_data))
     out_data += bytes(string, string_codec.PMD2_STR_ENCODER)
     number_of_nulls = self._read_nulls(full_binary, pointer + str_len) + 1
     out_data += (b'\0' * number_of_nulls)
     return new_pointer
Exemple #10
0
 def write(self) -> bytes:
     data = bytearray(HEADER_SIZE)
     write_u32(data, u32_checked(len(data)), 0)
     for e in self.model.trap_table:
         data += e.to_bytes()
     write_u32(data, u32_checked(len(data)), 4)
     for e in self.model.item_table:
         data += e.to_bytes()
     write_u32(data, u32_checked(len(data)), 8)
     for e in self.model.move_table:
         data += e.to_bytes()
     write_u32(data, u32_checked(len(data)), 12)
     for e in self.model.general_table:
         data += e.to_bytes()
     write_u32(data, u32_checked(len(data)), 16)
     for e in self.model.special_move_table:
         data += e.to_bytes()
     return bytes(data)
Exemple #11
0
    def write(self) -> bytes:
        nb_items = len(self.model.items_effects)

        header = bytearray(4 + 2 * nb_items + len(self.model.effects_code) * 8)
        write_u32(header, u32_checked(4 + 2 * nb_items), 0)
        code_data = bytearray(0)
        current_ptr = len(header)
        for i, c in enumerate(self.model.effects_code):
            write_u32(header, u32_checked(current_ptr),
                      4 + 2 * nb_items + i * 8)
            write_u32(header, u32_checked(len(c)),
                      4 + 2 * nb_items + i * 8 + 4)
            code_data += bytearray(c)
            current_ptr += len(c)

        for i, x in enumerate(self.model.items_effects):
            write_u16(header, u16_checked(x), 4 + 2 * i)
        file_data = header + code_data
        return bytes(file_data)
 def to_bytes(self) -> bytes:
     buffer = bytearray(12)
     write_u32(
         buffer,
         u32_checked(
             self.item_id * 8 +
             self._overlay29bin.symbols['ItemSpawnTable'].begin_absolute),
         0)
     write_u32(
         buffer,
         u32_checked(self.monster_id * 4 + self._overlay29bin.
                     symbols['MonsterSpawnTable'].begin_absolute), 4)
     write_u32(
         buffer,
         u32_checked(
             self.tile_id * 4 +
             self._overlay29bin.symbols['TileSpawnTable'].begin_absolute),
         8)
     return buffer
Exemple #13
0
    def write(self) -> Tuple[bytes, List[int], Optional[int]]:
        pointer_offsets = []

        sorted_entries = sorted(self.model.entries,
                                key=lambda x: (x.table, x.char))
        buffer = bytearray()
        # Image data
        for i, e in enumerate(sorted_entries):
            buffer += e.data

        if len(buffer) % 16 != 0:
            buffer += bytearray([0xAA] * (16 - len(buffer) % 16))
        # Character pointers
        char_pointer = bytearray(len(self.model.entries) * FONT_SIR0_ENTRY_LEN)
        char_pointer_offset = len(buffer)
        last: Tuple[Optional[int], Optional[int]] = (None, None)
        for i, e in enumerate(sorted_entries):
            if last == (e.char, e.table):
                raise ValueError(
                    f(
                        _("Character {e.char} in table {e.table} is be defined multiple times in a font file!"
                          )))
            last = (e.char, e.table)
            pointer_offsets.append(len(buffer) + i * FONT_SIR0_ENTRY_LEN)
            write_u32(char_pointer, u32_checked(i * FONT_SIR0_DATA_LEN),
                      i * FONT_SIR0_ENTRY_LEN)
            write_u8(char_pointer, e.char, i * FONT_SIR0_ENTRY_LEN + 0x4)
            write_u8(char_pointer, e.table, i * FONT_SIR0_ENTRY_LEN + 0x5)
            write_u32(char_pointer, e.width, i * FONT_SIR0_ENTRY_LEN + 0x6)
            write_u8(char_pointer, e.cat, i * FONT_SIR0_ENTRY_LEN + 0xA)
            write_u8(char_pointer, e.padding, i * FONT_SIR0_ENTRY_LEN + 0xB)
        buffer += char_pointer

        # Header
        header = bytearray(0x8)
        write_u32(header, u32_checked(len(self.model.entries)), 0)
        pointer_offsets.append(len(buffer) + 4)
        write_u32(header, u32_checked(char_pointer_offset), 0x4)

        header_pointer = len(buffer)
        buffer += header

        return buffer, pointer_offsets, header_pointer
Exemple #14
0
    def write(self) -> bytes:
        # Correct all pointers in content by HEADER_LEN
        if not isinstance(self.model.content, bytearray):
            self.model.content = bytearray(self.model.content)
        for i, pnt_off in enumerate(self.model.content_pointer_offsets):
            self.model.content_pointer_offsets[i] = pnt_off + HEADER_LEN
            write_u32(self.model.content,
                      u32(read_u32(self.model.content, pnt_off) + HEADER_LEN),
                      pnt_off)

        # Also add the two header pointers
        pointer_offsets = [4, 8] + self.model.content_pointer_offsets

        # Pointer offsets list
        pol = bytearray(4 * len(pointer_offsets))
        pol_cursor = self._encode_pointer_offsets(pol, pointer_offsets)
        pol = pol[:pol_cursor]

        len_content_padding = self._len_pad(len(self.model.content))
        len_eof_padding = self._len_pad(len(pol))

        pointer_pol = HEADER_LEN + len(
            self.model.content) + len_content_padding
        self.bytes_written = 0
        self.data = bytearray(pointer_pol + len(pol) + len_eof_padding)

        # Header
        self._append(b'SIR0')
        self._write_u32(u32_checked(self.model.data_pointer + HEADER_LEN))
        self._write_u32(u32_checked(pointer_pol))
        self._write_u32(u32(0))

        assert self.bytes_written == HEADER_LEN
        self._append(self.model.content)
        self._pad(len_content_padding)

        assert self.bytes_written == pointer_pol
        self._append(pol)
        self._pad(len_eof_padding)

        assert self.bytes_written == len(self.data)
        return self.data
Exemple #15
0
    def write(self) -> bytes:
        nb_items = len(self.model.struct_ids)

        header = bytearray(4 + 2 * nb_items)
        write_u32(header, u32_checked(4 + 2 * nb_items), 0)

        for i, x in enumerate(self.model.struct_ids):
            write_i16(header, i16_checked(x), 4 + 2 * i)

        file_data = header + self.model.struct_data
        return bytes(file_data)
Exemple #16
0
 def write(self) -> bytes:
     header = bytearray(len(self.model.attrs) * 4)
     data = bytearray(0)
     for i, g_list in enumerate(self.model.attrs):
         current_ptr = u32_checked(len(header) + len(data))
         d_list = bytearray(g_list)
         if len(d_list) % 4 != 0:
             d_list += bytearray(4 - (len(d_list) % 4))
         write_u32(header, current_ptr, i * 4)
         data += d_list
     data = header + data
     return bytes(data)
Exemple #17
0
    def compress(cls, data: bytes) -> 'Pkdpx':
        """Create a new PKDPX container from originally uncompressed data."""
        from skytemple_files.common.types.file_types import FileType

        new_container = cls()
        flags, px_data = FileType.PX.compress(data)

        new_container.compression_flags = flags
        new_container.length_decompressed = u32_checked(len(data))
        new_container.compressed_data = px_data
        new_container.length_compressed = u16_checked(len(px_data) + 0x14)
        return new_container
Exemple #18
0
 def write(self) -> bytes:
     header = bytearray(6 + 2 * len(self.model.list_dungeons))
     write_u32(header, u32_checked(len(header)), 0)
     code_data = bytearray(0)
     current = 0
     for i, x in enumerate(self.model.list_dungeons):
         for y in sorted(x, key=lambda v: v.floor):
             code_data += bytearray(y.to_bytes())
             current += 1
         write_u16(header, u16_checked(current), 6 + 2 * i)
     file_data = header + code_data
     return bytes(file_data)
Exemple #19
0
    def compress(cls, data: bytes) -> 'Atupx':
        """Create a new ATUPX container from originally uncompressed data."""
        from skytemple_files.common.types.file_types import FileType

        new_container = cls()
        compressed_data = FileType.CUSTOM_999.compress(data)

        new_container.compressed_data = compressed_data
        new_container.length_decompressed = u32_checked(len(data))
        new_container.length_compressed = u16_checked(
            len(compressed_data) + 0xb)
        return new_container
Exemple #20
0
    def write(self) -> Tuple[bytes, List[int], Optional[int]]:
        """Returns the content and the offsets to the pointers and the sub-header pointer, for Sir0 serialization."""
        pointer_offsets = []

        floor_lists, floor_layouts = self.model.minimize()
        # Floor list data
        data = bytearray(
            sum((len(floor_list) + 1) * 4 for floor_list in floor_lists))
        cursor = 0
        for floor_list in floor_lists:
            cursor += 4  # null floor
            for floor in floor_list:
                data[cursor:cursor + 4] = floor.to_mappa()
                cursor += 4
        # Floor list LUT
        start_floor_list_lut = u32_checked(len(data))
        floor_list_lut = bytearray(4 * len(floor_lists))
        cursor_floor_data = u32(0)
        for i, floor_list in enumerate(floor_lists):
            pointer_offsets.append(start_floor_list_lut + i * 4)
            write_u32(floor_list_lut, cursor_floor_data, i * 4)
            cursor_floor_data = u32_checked(cursor_floor_data +
                                            (len(floor_list) + 1) * 4)
        data += floor_list_lut
        # Floor layout data
        start_floor_layout_data = u32_checked(len(data))
        layout_data = bytearray(4 * len(floor_layouts))
        for i, layout in enumerate(floor_layouts):
            layout_data[i * 4:(i + 1) * 4] = layout.to_mappa()
        data += layout_data
        # Sub-header
        data_pointer = len(data)
        subheader = bytearray(8)
        pointer_offsets.append(data_pointer + 0x00)
        write_u32(subheader, start_floor_list_lut, 0x00)
        pointer_offsets.append(data_pointer + 0x04)
        write_u32(subheader, start_floor_layout_data, 0x04)
        data += subheader

        return data, pointer_offsets, data_pointer
Exemple #21
0
    def on_cr_item_awarded_edited(self, widget, path, text):
        match = PATTERN_ITEM_ENTRY.match(text)
        if match is None:
            return
        try:
            item_id = u32_checked(int(match.group(1)))
        except ValueError:
            return

        # item_id:
        self._list_store[path][4] = item_id
        # item_name:
        self._list_store[path][5] = self._item_names[item_id]
Exemple #22
0
    def write(self) -> bytes:
        files = self.model.get_files_bytes()
        len_header = (len(self.model.get_files_bytes()) +
                      1) * 8 + 16  # 16 is a row of padding
        if len_header % 16 != 0:
            len_header += 16 - (len_header % 16)
        out_buffer = bytearray(b'\xff' * (
            # Header len:
            max(self.fixed_header_len, len_header) +
            # File data:
            self._get_file_sizes(files)))

        write_u32(out_buffer, u32(0), 0x00)
        write_u32(out_buffer, u32_checked(len(files)), 0x04)

        data_cursor = len_header
        toc_curosr = 8
        for file in files:
            # toc pointer
            write_u32(out_buffer, u32_checked(data_cursor), toc_curosr)
            # toc length
            write_u32(out_buffer, u32_checked(len(file)), toc_curosr + 0x04)
            # file
            out_buffer[data_cursor:data_cursor + len(file)] = file

            data_cursor += len(file)
            # If the cursor is not aligned with 16 bytes, we pad.
            if data_cursor % 16 != 0:
                data_cursor += 16 - (data_cursor % 16)

            toc_curosr += 8

        # If the toc cursor is not aligned with 16 bytes, we will with zeros
        if toc_curosr % 16 != 0:
            pad = 16 - (toc_curosr % 16)
            out_buffer[toc_curosr:toc_curosr + pad] = b'\x00' * pad

        return out_buffer
Exemple #23
0
    def _wrap_sir0(self, full_binary: bytes, table_data: bytes, entry_len: int,
                   string_offs_per_entry: List[int], write_subheader) -> bytes:
        table_data = bytearray(table_data)
        out_data = bytearray()
        pointer_offsets = []

        # 1. Write strings
        number_entries = 0
        for i in range(0, len(table_data), entry_len):
            for string_off in string_offs_per_entry:
                new_pointer = self._push_string(
                    full_binary, out_data,
                    u32_checked(
                        read_u32(table_data, i + string_off) -
                        self._binary.loadaddress))
                pointer_offsets.append(i + string_off)
                write_u32(table_data, new_pointer, i + string_off)
            number_entries += 1
        # Padding
        self._pad(out_data)

        # 2. Correct string pointer offsets
        pointer_offsets = [off + len(out_data) for off in pointer_offsets]

        # 3. Append table
        pointer_data_block = len(out_data)
        out_data += table_data
        # Padding
        self._pad(out_data)

        # 4. Write sub-header
        if write_subheader:
            data_pointer = len(out_data)
            pointer_offsets.append(len(out_data))
            out_data += pointer_data_block.to_bytes(4,
                                                    byteorder='little',
                                                    signed=False)
            out_data += number_entries.to_bytes(4,
                                                byteorder='little',
                                                signed=False)
        else:
            data_pointer = pointer_data_block

        # 5. Convert into SIR0
        return FileType.SIR0.serialize(
            FileType.SIR0.wrap(out_data, pointer_offsets, data_pointer))
Exemple #24
0
    def write(self) -> bytes:
        buffer = bytearray(self.model.header_size +
                           WTU_ENTRY_LEN * len(self.model.entries))
        buffer[0:4] = MAGIC_NUMBER
        write_u32(buffer, u32_checked(len(self.model.entries)), 0x4)
        write_u32(buffer, self.model.image_mode, 0x8)
        write_u32(buffer, self.model.header_size, 0xC)

        for i, e in enumerate(self.model.entries):
            write_u16(buffer, e.x,
                      self.model.header_size + (i * WTU_ENTRY_LEN) + 0x00)
            write_u16(buffer, e.y,
                      self.model.header_size + (i * WTU_ENTRY_LEN) + 0x02)
            write_u16(buffer, e.width,
                      self.model.header_size + (i * WTU_ENTRY_LEN) + 0x04)
            write_u16(buffer, e.height,
                      self.model.header_size + (i * WTU_ENTRY_LEN) + 0x06)

        return buffer
Exemple #25
0
    def sir0_serialize_parts(self) -> Tuple[bytes, List[int], Optional[int]]:
        string_codec.init()

        out_data = bytearray()
        # 1. Write strings
        pointer_offsets: List[u32] = []
        for entry in self.list:
            pointer_offsets.append(u32_checked(len(out_data)))
            out_data += bytes(entry.name,
                              string_codec.PMD2_STR_ENCODER) + b'\0'

        # Padding
        self._pad(out_data)

        # Write table
        sir0_pointer_offsets = []
        pointer_data_block = len(out_data)
        for i, entry in enumerate(self.list):
            entry_buffer = bytearray(LEN_ACTOR_ENTRY)
            write_u16(entry_buffer, entry.type, 0)
            write_u16(entry_buffer, entry.entid, 2)
            sir0_pointer_offsets.append(len(out_data) + 4)
            write_u32(entry_buffer, pointer_offsets[i], 4)
            write_u16(entry_buffer, entry.unk3, 8)
            write_u16(entry_buffer, entry.unk4, 10)
            out_data += entry_buffer

        # Padding
        self._pad(out_data)

        # 4. Write sub-header
        data_pointer = len(out_data)
        sir0_pointer_offsets.append(len(out_data))
        out_data += pointer_data_block.to_bytes(4,
                                                byteorder='little',
                                                signed=False)
        out_data += len(self.list).to_bytes(4,
                                            byteorder='little',
                                            signed=False)

        return out_data, sir0_pointer_offsets, data_pointer
Exemple #26
0
    def write(self) -> bytes:
        buffer = bytearray(FONT_DAT_ENTRY_LEN * len(self.model.entries))
        write_u32(buffer, u32_checked(len(self.model.entries)), 0x00)

        # Font Data
        last: Tuple[Optional[int], Optional[int]] = (None, None)
        for i, e in enumerate(
                sorted(self.model.entries, key=lambda x: (x.table, x.char))):
            if last == (e.char, e.table):
                raise ValueError(
                    _("Character {e.char} in table {e.table} is defined multiple times in a font file!"
                      ))
            last = (e.char, e.table)
            off_start = 0x4 + (i * FONT_DAT_ENTRY_LEN)
            write_u8(buffer, e.char, off_start + 0x00)
            write_u8(buffer, e.table, off_start + 0x01)
            write_u8(buffer, e.width, off_start + 0x02)
            write_u8(buffer, e.bprow, off_start + 0x03)
            buffer[off_start + 0x04:off_start + FONT_DAT_ENTRY_LEN] = e.data

        return buffer
Exemple #27
0
    def write(self) -> Tuple[bytes, List[int], Optional[int]]:
        """Returns the content and the offsets to the pointers and the sub-header pointer, for Sir0 serialization."""
        fixed_floors = bytearray()
        pointers = []
        for floor in self.model.fixed_floors:
            pointers.append(u32_checked(len(fixed_floors)))
            fixed_floors += floor.to_bytes()

        # Padding
        if len(fixed_floors) % 4 != 0:
            fixed_floors += bytes(
                0xAA for _ in range(0, 4 - (len(fixed_floors) % 4)))

        header_buffer = bytearray((len(self.model.fixed_floors) + 1) * 4)
        pointer_offsets = []
        i = 0
        for i, pointer in enumerate(pointers):
            pointer_offsets.append(len(fixed_floors) + i * 4)
            write_u32(header_buffer, pointer, i * 4)
        write_u32(header_buffer, u32(0xAAAAAAAA), (i + 1) * 4)

        return fixed_floors + header_buffer, pointer_offsets, len(fixed_floors)
Exemple #28
0
    def from_bin(cls, data: bytes):
        data = memoryview(bytearray(data))
        data_pointer = read_u32(data, 0x04)
        pointer_offset_list_pointer = read_u32(data, 0x08)

        pointer_offsets = cls._decode_pointer_offsets(data, pointer_offset_list_pointer)

        # Correct pointers by subtracting the header
        for pnt_off in pointer_offsets:
            write_u32(
                data,  # type: ignore
                u32_checked(read_u32(data, pnt_off) - HEADER_LEN),
                pnt_off
            )

        # The first two are for the pointers in the header, we remove them now, they are not
        # part of the content pointers
        content_pointer_offsets = [pnt - HEADER_LEN for pnt in pointer_offsets][2:]

        return cls(
            bytes(data[HEADER_LEN:pointer_offset_list_pointer]),
            content_pointer_offsets,
            data_pointer - HEADER_LEN
        )
Exemple #29
0
    def sir0_serialize_parts(self) -> Tuple[bytes, List[int], Optional[int]]:
        string_codec.init()

        out_data = bytearray()
        # 1. Write strings
        pointer_offsets = []
        for entry in self.list:
            pointer_offsets.append(u32_checked(len(out_data)))
            out_data += bytes(entry.name, string_codec.PMD2_STR_ENCODER) + b'\0'

        # Padding
        self._pad(out_data)

        # Write table
        sir0_pointer_offsets = []
        pointer_data_block = len(out_data)
        for i, entry in enumerate(self.list):
            entry_buffer = bytearray(LEN_LEVEL_ENTRY)
            write_u16(entry_buffer, entry.mapty, 0)
            write_u16(entry_buffer, entry.nameid, 2)
            write_u16(entry_buffer, entry.mapid, 4)
            write_i16(entry_buffer, entry.weather, 6)
            sir0_pointer_offsets.append(len(out_data) + 8)
            write_u32(entry_buffer, pointer_offsets[i], 8)
            out_data += entry_buffer
        out_data += PADDING_END

        # Padding
        self._pad(out_data)

        # 4. Write sub-header
        # sir0_pointer_offsets.append(len(out_data))
        # out_data += pointer_data_block.to_bytes(4, byteorder='little', signed=False)
        # out_data += len(self.list).to_bytes(4, byteorder='little', signed=False)

        return out_data, sir0_pointer_offsets, pointer_data_block
Exemple #30
0
    def sir0_serialize_parts(self) -> Tuple[bytes, List[int], Optional[int]]:
        data = bytearray()
        pointers = []
        pointer_offsets = []
        for i, color_frames in enumerate(self.colors):
            pointers.append(u32_checked(len(data)))
            number_colors = len(color_frames) // 3
            buffer_entry = bytearray(((number_colors + 1) * 4))
            # Number colors
            write_u8(buffer_entry, u8_checked(number_colors), 0)
            # Unk
            write_u8(buffer_entry,
                     u8_checked(self.durations_per_frame_for_colors[i]), 2)
            # Always one null color
            null_color = False
            if len(color_frames) == 0:
                null_color = True
                color_frames = [0, 0, 0]
            cursor = 4
            for j, (r, g, b) in enumerate(chunk(color_frames, 3)):
                write_u8(buffer_entry, r, cursor)
                write_u8(buffer_entry, g, cursor + 1)
                write_u8(buffer_entry, b, cursor + 2)
                write_u8(buffer_entry, u8(128 if not null_color else 0),
                         cursor + 3)
                cursor += 4

            data += buffer_entry
        data_offset = cursor = len(data)
        data += bytes(4 * len(pointers))
        for pnt in pointers:
            write_u32(data, pnt, cursor)
            pointer_offsets.append(cursor)
            cursor += 4

        return data, pointer_offsets, data_offset