actaeon/scripts/extracters/chuni.py

74 lines
3.3 KiB
Python

from pathlib import Path
from itertools import chain
from PyCriCodecs import AWB, ACB, HCA
from .extracter import Extracter, add_extracter
class Chuni(Extracter):
def __init__(self, *, data_dir, opt_dir, **kwargs):
super().__init__(**kwargs)
self.data_dir = Path(data_dir)
self.opt_dir = Path(opt_dir)
self.out_dir /= 'chuni'
def process_image(self, file: Path, out: Path, media_type):
out.parent.mkdir(parents=True, exist_ok=True)
self.ffmpeg(['-i', file], media_type, out)
print(file)
def process_music(self, file: Path, out: Path):
out.parent.mkdir(parents=True, exist_ok=True)
awb = AWB(str(file))
# omnimix hca's cannot be decoded by PyCriCodecs
self.ffmpeg(['-i', self.vgmstream(next(awb.getfiles()))], 'music', out)
print(file)
def process_audio(self, hca: bytes, out: Path):
out.parent.mkdir(parents=True, exist_ok=True)
self.ffmpeg(['-i', self.vgmstream(hca)], 'audio', out)
print(out)
def extract_images(self):
for folder_name, output_folder in (
('avatarAccessory', 'avatar'),
('ddsImage', 'character'),
('mapIcon', 'map-icon'),
('namePlate', 'name-plate'),
('systemVoice', 'system-voice-icon')
):
for file in chain(self.data_dir.glob(f'A000/{folder_name}/*/*.dds'),
self.opt_dir.glob(f'*/{folder_name}/*/*.dds')):
yield self.process_image, file, self.out_dir / output_folder / file.name, 'images'
texture = self.data_dir / 'surfboard' / 'texture'
yield self.process_image, texture / 'CHU_UI_Common_Avatar_body_00.dds', self.out_dir / 'avatar' / 'CHU_UI_Common_Avatar_body_00.dds', 'images'
yield self.process_image, texture / 'CHU_UI_Common_Avatar_face_00.dds', self.out_dir / 'avatar' / 'CHU_UI_Common_Avatar_face_00.dds', 'images'
yield self.process_image, texture / 'CHU_UI_title_rank_00_v10.dds', self.out_dir / 'trophy' / 'CHU_UI_title_rank_00_v10.dds', 'images'
def extract_jacket(self):
for file in chain(self.data_dir.glob('A000/music/*/*.dds'),
self.opt_dir.glob('*/music/*/*.dds')):
yield self.process_image, file, self.out_dir / 'jacket' / file.name, 'jackets'
def extract_music(self):
for file in chain(self.data_dir.glob('A000/cueFile/*/music*.awb'),
self.opt_dir.glob('*/cueFile/*/music*.awb')):
yield self.process_music, file, self.out_dir / 'music' / file.name
def extract_audio(self):
for file in chain(self.data_dir.glob('A000/cueFile/*/systemvoice*.acb'),
self.opt_dir.glob('*/cueFile/*/systemvoice*.acb')):
acb = ACB(str(file))
names = self.acb_filenames(acb)
for i, data in enumerate(acb.awb.getfiles()):
yield self.process_audio, data, self.out_dir / 'system-voice' / f'{file.stem}_{names[0][i][1]}'
@staticmethod
def register(parser):
parser.add_argument('--data-dir', help='data directory (containing A000)', required=True)
parser.add_argument('--opt-dir', help='opt directory (containing A001, etc.)', required=True)
add_extracter(Chuni)