mirror of
https://github.com/jwetzell/JakAudioTools.git
synced 2026-07-26 10:08:39 +00:00
Initial Commit
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
JAK1/
|
||||
JAK2/
|
||||
JAK3/
|
||||
OUT/
|
||||
@@ -0,0 +1,5 @@
|
||||
:: This works if all the files in the VAGp folder are mono compressed ADPCM
|
||||
mkdir "./OUT/WAV"
|
||||
for %%f in (./OUT/VAGp/*) do (
|
||||
ffmpeg -i "./OUT/VAGp/%%f" "./OUT/WAV/%%~nf.wav"
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
This is the start of an SBK file specifically BEACH.SBK from JAK1
|
||||
|
||||
|
||||
------------??????????????????------------------
|
||||
626561636800000000000000000000000000000028000000
|
||||
|
||||
------------NAME---------------- --????--
|
||||
776F726D2D69646C6500000000000000 32000F10
|
||||
776F726D2D7269736531000000000000 32000F10
|
||||
776F726D2D73696E6B00000000000000 32000F10
|
||||
7368656C6C2D75700000000000000000 05800710
|
||||
7368656C6C2D646F776E000000000000 05800710
|
||||
736E6170000000000000000000000000 05800710
|
||||
637261622D736C696465000000000000 05800710
|
||||
6C75726B6572637261622D6469657300 05800710
|
||||
70656C6963616E2D666C617000000000 64801B10
|
||||
70656C6963616E2D67756C7000000000 64801B10
|
||||
70757070792D6261726B000000000000 19C00810
|
||||
6C75726B6572646F672D69646C650000 19C00810
|
||||
6C75726B6572646F672D646965730000 19C00810
|
||||
73656167756C6C2D74616B656F666600 3C001910
|
||||
67656172732D72756D626C6500000000 0F000F10
|
||||
726F70652D7374726574636800000000 05800710
|
||||
6D6F6E6B657900000000000000000000 05800710
|
||||
62697264000000000000000000000000 05800710
|
||||
66757365000000000000000000000000 0A800C10
|
||||
7361636B2D6C616E6400000000000000 1E001910
|
||||
6C75726B6572646F672D626974650000 05800710
|
||||
7361636B2D696E636F6D696E67000000 1E001910
|
||||
63616E6E6F6E2D73686F740000000000 96006410
|
||||
646972742D6372756D626C6500000000 19800710
|
||||
67726F74746F2D706F6C652D68697400 19800710
|
||||
6567672D637261636B00000000000000 96003210
|
||||
76656E742D726F636B2D627265616B00 50001910
|
||||
6567672D686974000000000000000000 05800710
|
||||
63616E6E6F6E2D636861726765000000 05800710
|
||||
62656163682D616D6232000000000000 32001410
|
||||
746F7765722D77696E64730000000000 05800710
|
||||
746F7765722D77696E64320000000000 32001410
|
||||
746F7765722D77696E64330000000000 05800710
|
||||
77617465722D6C617000000000000000 32001410
|
||||
776F726D2D6269746500000000000000 1E000A10
|
||||
776F726D2D7461756E74000000000000 05800710
|
||||
74656C6573636F706500000000000000 05800710
|
||||
66616C6C696E672D6567670000000000 05800710
|
||||
64726970000000000000000000000000 05800710
|
||||
776F726D2D6469657300000000000000 05800710
|
||||
@@ -0,0 +1,48 @@
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def is_valid_file(parser, arg):
|
||||
if not os.path.exists(arg):
|
||||
parser.error("The file %s does not exist!" % arg)
|
||||
else:
|
||||
return arg
|
||||
|
||||
parser = argparse.ArgumentParser(description="Process JAK SBK files")
|
||||
|
||||
|
||||
parser.add_argument("-i", dest="filepath", required=True,
|
||||
help="Input path to JAK SBK file", metavar="FILE",
|
||||
type=lambda x: is_valid_file(parser, x))
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
filename = os.path.basename(args.filepath)
|
||||
|
||||
name_length = 20
|
||||
sounds_start = 24
|
||||
sounds_length = 20
|
||||
|
||||
with open(args.filepath, "rb") as f:
|
||||
soundbank_name = f.read(20).decode('utf-8').strip()
|
||||
f.seek(24)
|
||||
soundsFound = 0
|
||||
while 1:
|
||||
empty = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
sounds_chunk = f.read(sounds_length)
|
||||
if sounds_chunk == empty:
|
||||
break
|
||||
else:
|
||||
sound_name = sounds_chunk[:-4].decode('utf-8').strip()
|
||||
sound_data = sounds_chunk[-4:]
|
||||
soundsFound += 1
|
||||
print(f'Found {sound_name} with some data {sound_data[0:2].hex()} {sound_data[2:].hex()}')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def is_valid_file(parser, arg):
|
||||
if not os.path.exists(arg):
|
||||
parser.error("The file %s does not exist!" % arg)
|
||||
else:
|
||||
return arg
|
||||
|
||||
def load_name_from_dict(filepath, index, entrySize):
|
||||
with open(filepath,'rb') as dictFile:
|
||||
dictFile.seek(index*entrySize)
|
||||
dictFile.seek(4,1)
|
||||
return dictFile.read(8).decode('utf-8')
|
||||
|
||||
def check_game(parser,arg):
|
||||
valid_games = [1,2,3]
|
||||
if int(arg) not in valid_games:
|
||||
parser.error(f"Invalid game! Valid game numbers: {valid_games}")
|
||||
else:
|
||||
return int(arg)
|
||||
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description="Process JAK VAGWAD files")
|
||||
|
||||
|
||||
parser.add_argument("-i", dest="filepath", required=True,
|
||||
help="Input path to JAK VAGWAD file", metavar="FILE",
|
||||
type=lambda x: is_valid_file(parser, x))
|
||||
|
||||
parser.add_argument("-dict", dest="dictpath", required=False,
|
||||
help="Input path to JAK VAGDIR file to lookup names", metavar="FILE",
|
||||
type=lambda x: is_valid_file(parser, x))
|
||||
|
||||
parser.add_argument("-game", dest="game", required=True, default="VAGp",
|
||||
help="Some VAGWAD things are game specific please enter the game 1,2,3 so I can set these up",
|
||||
type=lambda x: check_game(parser,x))
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
separator = 'VAGp'
|
||||
dictionaryEntrySize = 12
|
||||
|
||||
# file "separator" and dictionary entry size change after Jak 1
|
||||
if(args.game != 1):
|
||||
separator = 'pGAV'
|
||||
dictionaryEntrySize = 16
|
||||
|
||||
#setup some byte versions of strings for finding
|
||||
magic = str.encode(separator)
|
||||
stereo = str.encode('Stereo')
|
||||
mono = str.encode('Mono')
|
||||
|
||||
#is this always 2000 bytes?
|
||||
stereoInterleaveSize = 8192
|
||||
|
||||
with open(args.filepath, "rb") as f:
|
||||
#setup directory for file output
|
||||
if not os.path.exists("./OUT/VAGp"):
|
||||
os.makedirs("./OUT/VAGp")
|
||||
|
||||
contents = f.read()
|
||||
fileStart = 0
|
||||
firstTime = True
|
||||
previousFileStart = 0
|
||||
fileCount = 0
|
||||
skipInterleave = False
|
||||
|
||||
while fileStart != -1:
|
||||
previousFileStart = fileStart
|
||||
if firstTime:
|
||||
fileStart = contents.find(magic,fileStart)
|
||||
firstTime = False
|
||||
else:
|
||||
#if last time the start of a stereo file was found we can start looking for the next file starting after the interleave
|
||||
if skipInterleave:
|
||||
fileStart = contents.find(magic,fileStart+len(magic)+stereoInterleaveSize)
|
||||
skipInterleave = False
|
||||
else:
|
||||
fileStart = contents.find(magic,fileStart+len(magic))
|
||||
|
||||
# I don't think there is a "mono" tag to be found but this will default to mono if none of this is found
|
||||
stereoLocation = contents.find(stereo)
|
||||
monoLocation = contents.find(mono)
|
||||
audioType = ('stereo','mono')[monoLocation<stereoLocation or (monoLocation==-1 and stereoLocation ==-1)]
|
||||
|
||||
if(audioType== 'stereo' and not skipInterleave):
|
||||
#this is the first start of a stereo file so skip interleave on the next go around
|
||||
skipInterleave = True
|
||||
|
||||
#FILE FOUND!!
|
||||
if(fileStart >= 0 and fileStart != previousFileStart):
|
||||
fileCount += 1
|
||||
outfilename = str(fileCount)
|
||||
# load name from dictionary for Jak 1 and 2, Jak 3 dictionary is obfuscated so skip it for now
|
||||
if(args.dictpath and args.game <= 2):
|
||||
outfilename = load_name_from_dict(args.dictpath,fileCount -1, dictionaryEntrySize)
|
||||
print(f'{audioType} file named {outfilename} found from {previousFileStart} : {fileStart - 1}')
|
||||
else:
|
||||
print(f'{audioType} file #{fileCount} found from {previousFileStart} : {fileStart - 1}')
|
||||
|
||||
with open(f'./OUT/VAGp/{outfilename.strip()}.VAGp','wb+') as out:
|
||||
f.seek(previousFileStart)
|
||||
out.write(f.read(fileStart-previousFileStart))
|
||||
out.close()
|
||||
|
||||
print(f'Found {fileCount} files')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user