def unpack_header(self, reader: BinaryReader) -> int: self.big_endian = reader.unpack_value("?", offset=0xD) reader.byte_order = ">" if self.big_endian else "<" self.bit_big_endian = reader.unpack_value("?", offset=0xE) reader.unpack_value("4s", asserted=b"BND3") self.signature = reader.unpack_value("8s").decode("ascii").rstrip("\0") self.flags = BinderFlags.read(reader, self.bit_big_endian) reader.byte_order = ">" if self.big_endian or self.flags.is_big_endian else "<" reader.seek(2, 1) # skip peeked endian bytes reader.assert_pad(1) entry_count = reader.unpack_value("i") reader.seek(12, 1) # skip file size return entry_count
def unpack(self, reader: BinaryReader, **kwargs): reader.unpack_value("4s", asserted=b"TPF\0") self.platform = TPFPlatform(reader.unpack_value("B", offset=0xC)) reader.byte_order = ">" if self.platform in { TPFPlatform.Xbox360, TPFPlatform.PS3 } else "<" reader.unpack_value("i") # data length file_count = reader.unpack_value("i") reader.unpack_value("B") # platform self.tpf_flags = reader.unpack_value("B") if self.tpf_flags not in {0, 1, 2, 3}: raise ValueError( f"`TPF.tpf_flags` was {self.tpf_flags}, but expected 0, 1, 2, or 3." ) self.encoding = reader.unpack_value("B") if self.encoding not in {0, 1, 2}: raise ValueError( f"`TPF.encoding` was {self.encoding}, but expected 0, 1, or 2." ) reader.assert_pad(1) encoding = reader.get_utf_16_encoding( ) if self.encoding == 1 else "shift_jis_2004" self.textures = [ TPFTexture.unpack_from(reader, self.platform, self.tpf_flags, encoding) for _ in range(file_count) ]
def unpack_header(self, reader: BinaryReader): reader.unpack_value("4s", asserted=b"BND4") self.unknown1 = reader.unpack_value("?") self.unknown2 = reader.unpack_value("?") reader.assert_pad(3) self.big_endian = reader.unpack_value("?") self.bit_big_endian = not reader.unpack_value("?") # note reversal reader.assert_pad(1) reader.byte_order = ">" if self.big_endian else "<" # no need to check flags for an override in BND4 entry_count = reader.unpack_value("i") reader.unpack_value("q", asserted=0x40) # header size self.signature = reader.unpack_value("8s").decode("ascii").rstrip("\0") entry_header_size = reader.unpack_value("q") data_offset = reader.unpack_value( "q") # end of all headers, including hash table self.unicode = reader.unpack_value("?") self.flags = BinderFlags.read(reader, self.bit_big_endian) self.hash_table_type = reader.unpack_value("B") reader.assert_pad(5) hash_table_offset = reader.unpack_value("q") flags_header_size = self.flags.get_bnd_entry_header_size() if entry_header_size != flags_header_size: raise ValueError( f"Expected BND entry header size {flags_header_size} based on flags\n" f"{self.flags:08b}, but BND header says {entry_header_size}.") if self.hash_table_type != 4 and hash_table_offset != 0: _LOGGER.warning( f"Found non-zero hash table offset {hash_table_offset}, but header says this BHD has no hash " f"table.") entry_headers = [ BinderEntryHeader.from_bnd4_reader(reader, self.flags, self.bit_big_endian, self.unicode) for _ in range(entry_count) ] if self.hash_table_type == 4: # Save the initial hash table. reader.seek(hash_table_offset) self._most_recent_hash_table = reader.read(data_offset - hash_table_offset) return entry_headers
def unpack_header(self, reader: BinaryReader): reader.unpack_value("4s", asserted=b"BND4") self.unknown1 = reader.unpack_value("?") self.unknown2 = reader.unpack_value("?") reader.assert_pad(3) self.big_endian = reader.unpack_value("?") self.bit_big_endian = not reader.unpack_value("?") # note reversal reader.assert_pad(1) reader.byte_order = ">" if self.big_endian else "<" # no need to check flags for an override in BND4 entry_count = reader.unpack_value("i") reader.unpack_value("q", asserted=0x40) # header size self.signature = reader.unpack_value("8s").decode("ascii").rstrip("\0") entry_header_size = reader.unpack_value("q") data_offset = reader.unpack_value( "q") # end of all headers, including hash table self.unicode = reader.unpack_value("?") self.flags = BinderFlags.read(reader, self.bit_big_endian) self.hash_table_type = reader.unpack_value("B") reader.assert_pad(5) hash_table_offset = reader.unpack_value("q") return entry_count, entry_header_size, hash_table_offset, data_offset