mirror of
https://github.com/Escartem/AnimeWwise.git
synced 2026-06-04 23:40:25 +08:00
upload new files
This commit is contained in:
57
filereader.py
Normal file
57
filereader.py
Normal file
@@ -0,0 +1,57 @@
|
||||
import struct
|
||||
|
||||
|
||||
class FileReader:
|
||||
"""
|
||||
Simplified byte file reader with buffer
|
||||
Not particularly optimised, contains repetitive functions
|
||||
In the scope of this project, not everything will be used either
|
||||
|
||||
"""
|
||||
def __init__(self, file, endianness: str):
|
||||
self.stream = file
|
||||
self.endianness = endianness
|
||||
|
||||
def _read(self, mode:str, bufferLength:int, endianness=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]
|
||||
|
||||
# read methods
|
||||
def ReadInt16(self, endianness=None) -> int:
|
||||
return self._read("h", 2, endianness)
|
||||
|
||||
def ReadUInt16(self, endianness=None) -> int:
|
||||
return self._read("H", 2, endianness)
|
||||
|
||||
def ReadInt32(self, endianness=None) -> int:
|
||||
return self._read("i", 4, endianness)
|
||||
|
||||
def ReadUInt32(self, endianness=None) -> int:
|
||||
return self._read("I", 4, endianness)
|
||||
|
||||
def ReadLong(self, endianness=None) -> int:
|
||||
return self._read("l", 4, endianness)
|
||||
|
||||
def ReadULong(self, endianness=None) -> int:
|
||||
return self._read("L", 4, endianness)
|
||||
|
||||
def ReadLongLong(self, endianness=None) -> int:
|
||||
return self._read("q", 8, endianness)
|
||||
|
||||
def ReadULongLong(self, endianness=None) -> int:
|
||||
return self._read("Q", 8, endianness)
|
||||
|
||||
def ReadBytes(self, length:int, endianness=None) -> bytes:
|
||||
return self._read(f"{str(length)}s", int(length), endianness)
|
||||
|
||||
# buffer utils
|
||||
def GetBufferPos(self) -> int:
|
||||
return self.stream.tell()
|
||||
|
||||
def SetBufferPos(self, pos:int):
|
||||
self.stream.seek(pos)
|
||||
212
wavescan.py
Normal file
212
wavescan.py
Normal file
@@ -0,0 +1,212 @@
|
||||
# Custom rewrite of the Wwise AKPK packages extractor, original by Nicknine and bnnm
|
||||
# TODO: use extracted files id with the mapping table to restore file names
|
||||
# TODO: make the mapping table :(
|
||||
from filereader import FileReader
|
||||
import os
|
||||
|
||||
filename = "External0.pck"
|
||||
cwd = os.getcwd()
|
||||
reader = FileReader(open(filename, "rb"), "little") # defaults to little endian
|
||||
bank_version = 0
|
||||
|
||||
def main():
|
||||
global bank_version
|
||||
|
||||
# check file
|
||||
if reader.ReadBytes(4) != b"AKPK":
|
||||
print("Not a valid file")
|
||||
return
|
||||
|
||||
# check endianness
|
||||
reader.SetBufferPos(0x08)
|
||||
endian_check = reader.ReadLong() # this is the same bytes as the flag sector, which seems to be always 1
|
||||
|
||||
if endian_check == 1:
|
||||
endianness = 0 # little
|
||||
elif endian_check == 0x1000000:
|
||||
endianness = 1 # big
|
||||
else:
|
||||
print("uknown endianness, aborting")
|
||||
return
|
||||
|
||||
# retrieve sectors in header
|
||||
reader.SetBufferPos(0x04)
|
||||
|
||||
header_size = reader.ReadLong()
|
||||
flag = reader.ReadLong()
|
||||
|
||||
languages_sector_size = reader.ReadLong()
|
||||
banks_sector_size = reader.ReadLong()
|
||||
sounds_sector_size = reader.ReadLong()
|
||||
externals_sector_size = 0
|
||||
|
||||
if languages_sector_size + banks_sector_size + sounds_sector_size + 0x10 < header_size:
|
||||
externals_sector_size = reader.ReadLong()
|
||||
|
||||
sectors = [[True, banks_sector_size, 0, 0, "bnk"], [False, sounds_sector_size, 1, 0, "wem"], [False, externals_sector_size, 1, 1, "wem"]]
|
||||
|
||||
# get langs in the file
|
||||
lang_array = get_langs(languages_sector_size)
|
||||
|
||||
# extract each sector
|
||||
for sector in sectors:
|
||||
extract_sector(*sector[1:], endianness, lang_array, bank_version)
|
||||
|
||||
if sector[0] and bank_version == 0:
|
||||
if externals_sector_size == 0:
|
||||
print("can't detect bank version")
|
||||
bank_version = 62
|
||||
|
||||
def get_langs(langs_sector_size):
|
||||
string_offset = reader.GetBufferPos()
|
||||
lang_array = {}
|
||||
langs = reader.ReadLong()
|
||||
|
||||
for i in range(langs):
|
||||
lang_offset = reader.ReadLong()
|
||||
lang_id = reader.ReadLong()
|
||||
|
||||
lang_offset += string_offset
|
||||
|
||||
current = reader.GetBufferPos()
|
||||
|
||||
reader.SetBufferPos(lang_offset)
|
||||
|
||||
# get dummy bytes to detect encoding
|
||||
test_byte_1 = reader.ReadBytes(1)
|
||||
test_byte_2 = reader.ReadBytes(1)
|
||||
|
||||
reader.SetBufferPos(lang_offset)
|
||||
|
||||
if test_byte_1 == 0 or test_byte_2 == 0:
|
||||
lang_name = reader.ReadBytes(0x20).decode("utf-16le").replace("\x00", "")
|
||||
else:
|
||||
lang_name = reader.ReadBytes(0x10).decode("utf-8").replace("\x00", "")
|
||||
|
||||
lang_array[lang_id] = lang_name
|
||||
|
||||
reader.SetBufferPos(current)
|
||||
|
||||
reader.SetBufferPos(string_offset + langs_sector_size)
|
||||
|
||||
return lang_array
|
||||
|
||||
def detect_bank_version(offset):
|
||||
global bank_version
|
||||
|
||||
current = reader.GetBufferPos()
|
||||
reader.SetBufferPos(offset)
|
||||
|
||||
# maybe update buffer pos instead
|
||||
dummy = reader.ReadLong()
|
||||
dummy = reader.ReadLong()
|
||||
|
||||
bank_version = reader.ReadLong()
|
||||
|
||||
if bank_version > 0x1000:
|
||||
print("wrong bank version")
|
||||
bank_version = 62
|
||||
|
||||
reader.SetBufferPos(current)
|
||||
|
||||
def extract_sector(section_size, is_sounds, is_externals, ext, endianness, lang_array, bank_version, filter_bnk_only=0, filter_wem_only=0):
|
||||
# check sector validity
|
||||
if section_size == 0:
|
||||
return
|
||||
files = reader.ReadLong()
|
||||
if files == 0:
|
||||
return
|
||||
|
||||
entry_size = (section_size - 0x04) / files
|
||||
|
||||
if entry_size == 0x18:
|
||||
alt_mode = 1
|
||||
else:
|
||||
alt_mode = 0
|
||||
|
||||
for i in range(files):
|
||||
# ids must be unsigned here, if signed you need to do id += 2**32 afterwards
|
||||
if alt_mode == 1 and is_externals == 1:
|
||||
if endianness == 0:
|
||||
file_id_2 = reader.ReadULong()
|
||||
file_id_1 = reader.ReadULong()
|
||||
else:
|
||||
file_id_1 = reader.ReadULong()
|
||||
file_id_2 = reader.ReadULong()
|
||||
else:
|
||||
file_id = reader.ReadULong()
|
||||
|
||||
block_size = reader.ReadLong()
|
||||
|
||||
# get file size
|
||||
if alt_mode == 1 and is_externals == 1:
|
||||
size = reader.ReadLong()
|
||||
elif alt_mode == 1:
|
||||
size = reader.ReadLongLong()
|
||||
else:
|
||||
size = reader.ReadLong()
|
||||
|
||||
offset = reader.ReadLong()
|
||||
lang_id = reader.ReadLong()
|
||||
|
||||
if block_size != 0:
|
||||
offset *= block_size
|
||||
|
||||
# bank version must be detected at this offset
|
||||
if is_sounds == 0 and bank_version == 0:
|
||||
detect_bank_version(offset)
|
||||
|
||||
# update extension for olders banks using differents codecs
|
||||
if is_sounds == 1 and bank_version < 62:
|
||||
current = reader.GetBufferPos()
|
||||
|
||||
codec_offset = offset + 0x14
|
||||
reader.SetBufferPos(codec_offset)
|
||||
|
||||
codec = reader.ReadInt16()
|
||||
|
||||
if codec == 0x0401 or codec == 0x0166:
|
||||
ext = "xma"
|
||||
elif codec == 0xFFFF:
|
||||
ext = "ogg"
|
||||
else:
|
||||
ext = "wav"
|
||||
|
||||
reader.SetBufferPos(current)
|
||||
|
||||
# set file path
|
||||
if lang_id == 0:
|
||||
path = ""
|
||||
else:
|
||||
path = "".join([f"{e}/" for e in list(lang_array.values())])
|
||||
|
||||
# se file name
|
||||
if alt_mode == 1 and is_externals == 1:
|
||||
name = f"externals/{path}{ID1:08x}{ID2:08x}.{ext}"
|
||||
else:
|
||||
name = f"{path}{ID}.{ext}"
|
||||
|
||||
# filtering utilities
|
||||
if filter_bnk_only == 1 and ext != "bnk":
|
||||
continue
|
||||
|
||||
if filter_wem_only == 1 and ext != "wem":
|
||||
continue
|
||||
|
||||
print(f"NAME - {name} | OFFSET - {offset} | SIZE - {size}")
|
||||
|
||||
# save file into disk
|
||||
current = reader.GetBufferPos()
|
||||
reader.SetBufferPos(offset)
|
||||
file_data = reader.ReadBytes(size)
|
||||
|
||||
os.makedirs(os.path.join(cwd, os.path.dirname(name)), exist_ok=True)
|
||||
|
||||
with open(os.path.join(cwd, name), "wb+") as f:
|
||||
f.write(file_data)
|
||||
f.close()
|
||||
|
||||
reader.SetBufferPos(current)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user