diff --git a/filereader.py b/filereader.py index ec31744..507a8ff 100644 --- a/filereader.py +++ b/filereader.py @@ -14,48 +14,57 @@ class FileReader: if name: self.name = name - def _read(self, mode:str, bufferLength:int, endianness:str=None) -> bytes: + def _read(self, mode:str, bufferLength:int, endianness:str=None, pos:int=None) -> bytes: # endianness override if endianness is None: endianness = self.endianness endianness = "<" if endianness == "little" else ">" - return struct.unpack(f"{endianness}{mode}", bytearray(self.stream.read(bufferLength)))[0] + if pos: + pos_backup = self.GetBufferPos() + self.SetBufferPos(pos) + + data = struct.unpack(f"{endianness}{mode}", bytearray(self.stream.read(bufferLength)))[0] + + if pos: + self.SetBufferPos(pos_backup) + + return data # read methods - def ReadInt8(self, endianness:str=None) -> int: - return self._read("b", 1, endianness) + def ReadInt8(self, endianness:str=None, pos:int=None) -> int: + return self._read("b", 1, endianness, pos) - def ReadUInt8(self, endianness:str=None) -> int: - return self._read("B", 1, endianness) + def ReadUInt8(self, endianness:str=None, pos:int=None) -> int: + return self._read("B", 1, endianness, pos) - def ReadInt16(self, endianness:str=None) -> int: - return self._read("h", 2, endianness) + def ReadInt16(self, endianness:str=None, pos:int=None) -> int: + return self._read("h", 2, endianness, pos) - def ReadUInt16(self, endianness:str=None) -> int: - return self._read("H", 2, endianness) + def ReadUInt16(self, endianness:str=None, pos:int=None) -> int: + return self._read("H", 2, endianness, pos) - def ReadInt32(self, endianness:str=None) -> int: - return self._read("i", 4, endianness) + def ReadInt32(self, endianness:str=None, pos:int=None) -> int: + return self._read("i", 4, endianness, pos) - def ReadUInt32(self, endianness:str=None) -> int: - return self._read("I", 4, endianness) + def ReadUInt32(self, endianness:str=None, pos:int=None) -> int: + return self._read("I", 4, endianness, pos) - def ReadLong(self, endianness:str=None) -> int: - return self._read("l", 4, endianness) + def ReadLong(self, endianness:str=None, pos:int=None) -> int: + return self._read("l", 4, endianness, pos) - def ReadULong(self, endianness:str=None) -> int: - return self._read("L", 4, endianness) + def ReadULong(self, endianness:str=None, pos:int=None) -> int: + return self._read("L", 4, endianness, pos) - def ReadLongLong(self, endianness:str=None) -> int: - return self._read("q", 8, endianness) + def ReadLongLong(self, endianness:str=None, pos:int=None) -> int: + return self._read("q", 8, endianness, pos) - def ReadULongLong(self, endianness:str=None) -> int: - return self._read("Q", 8, endianness) + def ReadULongLong(self, endianness:str=None, pos:int=None) -> int: + return self._read("Q", 8, endianness, pos) - def ReadBytes(self, length:int, endianness:str=None) -> bytes: - return self._read(f"{str(length)}s", int(length), endianness) + def ReadBytes(self, length:int, endianness:str=None, pos:int=None) -> bytes: + return self._read(f"{str(length)}s", int(length), endianness, pos) # buffer utils def GetBufferPos(self) -> int: diff --git a/wwise.py b/wwise.py index 3ab83b6..b887ed1 100644 --- a/wwise.py +++ b/wwise.py @@ -142,14 +142,50 @@ def parse_wwise(reader): else: metadata["codecDisplay"] = codec - # parse more infos + # parse duration if metadata["codec"] == "PTADPCM": metadata["layoutType"] = "interleave" metadata["interleaveBlockSize"] = metadata["blockSize"] // metadata["channels"] metadata["numSamples"] = int((chunks["data"]["length"] / (metadata["channels"] * metadata["interleaveBlockSize"])) * (2 + (metadata["interleaveBlockSize"] - 0x05) * 2)) metadata["duration"] = metadata["numSamples"] / metadata["sampleRate"] + + elif metadata["codec"] == "VORBIS": + if (metadata["blockSize"] != 0 or metadata["bitsPerSample"] != 0): + print(f"[WARNING] worbis type at {reader.GetName()}, skipping") + return metadata + + if "vorb" in chunks: + # vorb chunk only in wwise earlier to 2012, therefore impossible for mihoyo games + print(f"[WARNING] found vorb chunk at {reader.GetName()}, is this the correct game ?") + return metadata + + extra_offset = chunks["fmt"]["offset"] + 0x18 + + if metadata["extraSize"] != 0x30: + print(f"[WARNING] unknown extra wwise size at {reader.GetName()}, skipping") + return metadata + + data_offset = 0x10 + blocks_offset = 0x28 + # define header to type 2, packet to modified and codebook to aoTuV603, required ? + + metadata["numSamples"] = reader.ReadInt32(extra_offset) + setup_offset = reader.ReadUInt32(extra_offset + data_offset) + audio_offset = reader.ReadUInt32(extra_offset + data_offset + 0x04) + + print(metadata["numSamples"]) + print(setup_offset) + print(audio_offset) + + block_size_1_exp = reader.ReadUInt8(extra_offset + blocks_offset) + block_size_0_exp = reader.ReadUInt8(extra_offset + blocks_offset + 0x01) + + chunks["data"]["offset"] -= audio_offset + + # ignore packets update and codebooks parse attempts, not implemented + + metadata["layoutType"] = "none" + metadata["duration"] = metadata["numSamples"] / metadata["sampleRate"] return metadata - - # TODO: parse VORBIS