Skip to content

Commit

Permalink
Version 0.3.6
Browse files Browse the repository at this point in the history
rla2json: add `--dump-audio` option
rla2json: add `--no_parallel` option
  • Loading branch information
mos9527 committed Sep 8, 2024
1 parent 5b818d5 commit fde8937
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 17 deletions.
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,9 @@
"module": "sssekai",
"args": [
"rla2json",
"--dump-audio",
"D:\\proseka_reverse\\assets\\streaming_live\\archive\\1st_live_vbs-1",
"D:\\proseka_reverse\\assets\\streaming_live\\archive\\1st_live_vbs-1_src"
"D:\\proseka_reverse\\assets\\streaming_live\\archive\\1st_live_vbs-1_hca"
],
"justMyCode": true
},
Expand Down
2 changes: 1 addition & 1 deletion sssekai/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__VERSION_MAJOR__ = 0
__VERSION_MINOR__ = 3
__VERSION_PATCH__ = 5
__VERSION_PATCH__ = 6

__version__ = '%s.%s.%s' % (__VERSION_MAJOR__,__VERSION_MINOR__,__VERSION_PATCH__)
6 changes: 4 additions & 2 deletions sssekai/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,10 @@ def write(__s):
spineextract_parser.set_defaults(func=main_spineextract)
# rla2json
rla2json_parser = subparsers.add_parser('rla2json', help='''Read streaming_live/archive files and dump their information to JSON''')
rla2json_parser.add_argument('infile', type=str, help='input file')
rla2json_parser.add_argument('outdir', type=str, help='output directory. multiple json files may be produced')
rla2json_parser.add_argument('infile', type=str, help='input file. either a streaming_live bundle or a zip file with the same file hierarchy (i.e. containing sekai.rlh, sekai_xx_xxxxxx.rla files)')
rla2json_parser.add_argument('outdir', type=str, help='output directory. RLA files in JSON format will be saved, unless otherwise specified.')
rla2json_parser.add_argument('--dump-audio', action='store_true', help='dump raw HCA audio data instead of the JSON data. Use https://github.com/mos9527/sssekai_streaming_hca_decoder to decode them.')
rla2json_parser.add_argument('--no-parallel', action='store_true', help='disable parallel processing')
rla2json_parser.set_defaults(func=main_rla2json)
# apphash
apphash_parser = subparsers.add_parser('apphash', help='''Download/extract game AppHash values''')
Expand Down
56 changes: 43 additions & 13 deletions sssekai/entrypoint/rla2json.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,67 @@
from UnityPy.enums import ClassIDType
from sssekai.fmt.rla import read_rla
from tqdm import tqdm
import zipfile, base64
logger = getLogger(__name__)


def worker_job(sname, version, script):
def dump_json_job(sname, version, script):
rla = read_rla(BytesIO(script), version)
dump(rla, open(sname + '.json', 'w', encoding='utf-8'), indent=4, ensure_ascii=False)

def dump_audio_job(sname, version, script):
rla = read_rla(BytesIO(script), version)
for tick, data in rla.items():
data = data.get('SoundData', None)
if data:
for i, b64data in enumerate(data):
fname = sname + '_%d_%d.hca' % (i, tick)
raw_data = base64.b64decode(b64data['data'])
with open(fname, 'wb') as f: f.write(raw_data)

def main_rla2json(args):
with open(args.infile,'rb') as f:
env = load_assetbundle(f)
with open(args.infile,'rb') as f:
datas = dict()
for obj in env.objects:
if obj.type in {ClassIDType.TextAsset}:
data = obj.read()
datas[data.name] = data
if f.read(2) == b'PK':
f.seek(0)
with zipfile.ZipFile(f, 'r') as z:
for name in z.namelist():
with z.open(name) as zf:
datas[name] = zf.read()
else:
f.seek(0)
rla_env = load_assetbundle(f)
for obj in rla_env.objects:
if obj.type in {ClassIDType.TextAsset}:
data = obj.read()
datas[data.name] = data.script.tobytes()
header = datas.get('sekai.rlh', None)
assert header, "RLH Header file not found!"
makedirs(args.outdir, exist_ok=True)
header = loads(header.text)
header = loads(header.decode('utf-8'))
splitSeconds = header['splitSeconds']

dump(header, open(path.join(args.outdir, 'sekai.rlh.json'), 'w', encoding='utf-8'), indent=4, ensure_ascii=False)
version = tuple(map(int, header['version'].split('.')))
splitSeconds = header['splitSeconds']
logger.info('Version: %d.%d' % version)
logger.info('Count: %d' % len(header['splitFileIds']))

worker_job = dump_json_job
if args.dump_audio:
worker_job = dump_audio_job
logger.info('Dumping RLA raw HCA audio data')
else:
logger.info('Dumping RLA data to JSON')
with ProcessPoolExecutor() as executor:
logger.info('Dumping RLA data with %d processors' % executor._max_workers)
if not args.no_parallel:
logger.info('Dumping RLA data with %d processors' % executor._max_workers)
futures = []
for sid in header['splitFileIds']:
sname = 'sekai_%2d_%08d' % (splitSeconds, sid)
script = datas[sname + '.rla'].script.tobytes()
futures.append(executor.submit(worker_job, path.join(args.outdir,sname), version, script))
script = datas[sname + '.rla']
if args.no_parallel:
worker_job(path.join(args.outdir,sname), version, script)
else:
futures.append(executor.submit(worker_job, path.join(args.outdir,sname), version, script))
finsihed_futures = set()
with tqdm(total=len(futures)) as pbar:
while len(finsihed_futures) < len(futures):
Expand Down

0 comments on commit fde8937

Please sign in to comment.