def parse(self, reader: ByteIO, parent=None, in_array=False): name = None parent = parent if not in_array: string_id = reader.read_uint32() name = "ERROR" if string_id == -1 else self.strings[string_id] add = lambda v: parent.update({name: v} ) if not in_array else parent.append(v) data_type = reader.read_int8() flag_info = KVFlag.Nothing if data_type & 0x80: data_type &= 0x7F flag_info = KVFlag(reader.read_int8()) if data_type == KVType.NULL: add(None) return if data_type == KVType.BOOLEAN: add(reader.read_int8() > 0) return if data_type == KVType.INTEGER: add(reader.read_int64()) return if data_type == KVType.DOUBLE: add(reader.read_double()) return if data_type == KVType.STRING: string_id = reader.read_int32() if string_id == -1: add(None) return add(self.strings[string_id]) return if data_type == KVType.ARRAY: size = reader.read_uint32() arr = [] for _ in range(size): self.parse(reader, arr, True) add(arr) return if data_type == KVType.OBJECT: size = reader.read_uint32() tmp = {} for _ in range(size): self.parse(reader, tmp, False) add(tmp) if not parent: parent = tmp return parent
def read(self, reader: ByteIO): fourcc = reader.read_bytes(4) assert tuple(fourcc) == self.SIG, 'Invalid KV Signature' encoding = reader.read_bytes(16) assert tuple(encoding) == self.ENCODING, 'Unrecognized KV3 Encoding' format = reader.read_bytes(16) assert tuple(format) == self.FORMAT, 'Unrecognised KV3 Format' self.flags = reader.read_bytes(4) if self.flags[3] & 0x80: self.buffer.write_bytes( reader.read_bytes(self.info_block.block_size - (reader.tell() - self.info_block.absolute_offset))) working = True while reader.tell() != reader.size() and working: block_mask = reader.read_uint16() for i in range(16): if block_mask & (1 << i) > 0: offset_and_size = reader.read_uint16() offset = ((offset_and_size & 0xFFF0) >> 4) + 1 size = (offset_and_size & 0x000F) + 3 lookup_size = offset if offset < size else size entry = self.buffer.tell() self.buffer.seek(entry - offset) data = self.buffer.read_bytes(lookup_size) self.buffer.seek(entry) while size > 0: self.buffer.write_bytes( data[:lookup_size if lookup_size < size else size]) size -= lookup_size else: data = reader.read_int8() self.buffer.write_int8(data) if self.buffer.size() == (self.flags[2] << 16) + ( self.flags[1] << 8) + self.flags[0]: working = False break self.buffer.seek(0) string_count = self.buffer.read_uint32() for i in range(string_count): self.strings.append(self.buffer.read_ascii_string()) self.parse(self.buffer, self.kv, True) self.buffer.close() del self.buffer
def read(self, reader: ByteIO, block_info: InfoBlock = None): self.info_block = block_info entry = reader.tell() self.name_offset = reader.read_int32() self.name = reader.read_from_offset(entry + self.name_offset, reader.read_ascii_string) self.count = reader.read_int16() self.on_disc_size = reader.read_int16() entry = reader.tell() self.indirection_bytes_offset = reader.read_int32() self.indirection_level = reader.read_int32() with reader.save_current_pos(): reader.seek(entry + self.indirection_bytes_offset) indir_level = self.indirection_level if self.indirection_level < 10 else 10 for _ in range(indir_level): self.indirection_bytes.append(reader.read_int8()) self.data_type = reader.read_int32() self.type = KeyValueDataType(reader.read_int16()) reader.skip(2)
def read_from_buffer(self, reader: ByteIO): if self.format == DXGI_FORMAT.R32G32B32_FLOAT: return [ reader.read_float() for _ in range(self.format.name.count('32')) ] elif self.format == DXGI_FORMAT.R32G32B32_UINT: return [ reader.read_uint32() for _ in range(self.format.name.count('32')) ] elif self.format == DXGI_FORMAT.R32G32B32_SINT: return [ reader.read_int32() for _ in range(self.format.name.count('32')) ] elif self.format == DXGI_FORMAT.R32G32B32A32_FLOAT: return [ reader.read_float() for _ in range(self.format.name.count('32')) ] elif self.format == DXGI_FORMAT.R32G32B32A32_UINT: return [ reader.read_uint32() for _ in range(self.format.name.count('32')) ] elif self.format == DXGI_FORMAT.R32G32B32A32_SINT: return [ reader.read_int32() for _ in range(self.format.name.count('32')) ] elif self.format == DXGI_FORMAT.R16G16_FLOAT: return [ short_to_float(reader.read_int16()) for _ in range(self.format.name.count('16')) ] elif self.format == DXGI_FORMAT.R32G32_FLOAT: return [ short_to_float(reader.read_float()) for _ in range(self.format.name.count('32')) ] elif self.format == DXGI_FORMAT.R16G16_SINT: return [ reader.read_int16() for _ in range(self.format.name.count('16')) ] elif self.format == DXGI_FORMAT.R16G16_UINT: return [ reader.read_uint16() for _ in range(self.format.name.count('16')) ] elif self.format == DXGI_FORMAT.R8G8B8A8_SNORM: return [ reader.read_int8() for _ in range(self.format.name.count('8')) ] elif self.format == DXGI_FORMAT.R8G8B8A8_UNORM: return [ reader.read_uint8() for _ in range(self.format.name.count('8')) ] elif self.format == DXGI_FORMAT.R8G8B8A8_UINT: return [ reader.read_uint8() for _ in range(self.format.name.count('8')) ] else: raise NotImplementedError('Unknown buffer format {}'.format( self.format.name))