def get_msbt_hashes(lang: str = 'USen') -> {}: """ Gets the MSBT hash table for the given language, or US English by default :param lang: The game language to use, defaults to USen. :type lang: str, optional :returns: A dictionary of MSBT files and their vanilla hashes. :rtype: dict of str: str """ if not hasattr(get_msbt_hashes, 'texthashes'): get_msbt_hashes.texthashes = {} if lang not in get_msbt_hashes.texthashes: hash_table = util.get_exec_dir() / 'data' / 'msyt' / \ f'Msg_{lang}_hashes.csv' if hash_table.exists(): get_msbt_hashes.texthashes[lang] = {} with hash_table.open('r') as h_file: csv_loop = csv.reader(h_file) for row in csv_loop: get_msbt_hashes.texthashes[lang][row[0]] = row[1] elif util.get_game_file(f'Pack/Bootup_{lang}.pack').exists(): get_msbt_hashes.texthashes[lang] = {} with util.get_game_file(f'Pack/Bootup_{lang}.pack').open( 'rb') as b_file: bootup_pack = sarc.read_file_and_make_sarc(b_file) msg_bytes = util.decompress( bootup_pack.get_file_data( f'Message/Msg_{lang}.product.ssarc').tobytes()) msg_pack = sarc.SARC(msg_bytes) for msbt in msg_pack.list_files(): get_msbt_hashes.texthashes[lang][msbt] = xxhash.xxh32( msg_pack.get_file_data(msbt)).hexdigest() return get_msbt_hashes.texthashes[lang]
def msbt_to_msyt(tmp_dir: Path = util.get_work_dir() / 'tmp_text'): """ Converts MSBTs in given temp dir to MSYTs """ subprocess.run([ str(util.get_exec_dir() / 'helpers' / 'msyt.exe'), 'export', '-d', str(tmp_dir) ], creationflags=util.CREATE_NO_WINDOW) fix_msbts = [ msbt for msbt in tmp_dir.rglob('**/*.msbt') if not msbt.with_suffix('.msyt').exists() ] if fix_msbts: print('Some MSBTs failed to convert. Trying again individually...') pool = multiprocessing.Pool( processes=min(multiprocessing.cpu_count(), len(fix_msbts))) pool.map(_msyt_file, fix_msbts) pool.close() pool.join() fix_msbts = [ msbt for msbt in tmp_dir.rglob('**/*.msbt') if not msbt.with_suffix('.msyt').exists() ] if fix_msbts: print( f'{len(fix_msbts)} MSBT files failed to convert. They will not be merged.' ) for msbt_file in tmp_dir.rglob('**/*.msbt'): Path(msbt_file).unlink() return fix_msbts
def get_msyt_hashes() -> dict: if not hasattr(get_msyt_hashes, 'hashes'): import json get_msyt_hashes.hashes = json.loads( (util.get_exec_dir() / 'data' / 'msyt' / 'msyt_hashes.json')\ .read_text(encoding='utf-8'), encoding='utf-8' ) return get_msyt_hashes.hashes
def msyt_to_msbt(tmp_dir: Path = util.get_work_dir() / 'tmp_text'): """ Converts merged MSYTs in given temp dir to MSBTs """ msyt_bin = util.get_exec_dir() / 'helpers' / 'msyt.exe' merge_dir = tmp_dir / 'merged' m_args = [str(msyt_bin), 'create', '-d', str(merge_dir), '-p', 'wiiu', '-o', str(merge_dir)] subprocess.run(m_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=util.CREATE_NO_WINDOW) for merged_msyt in merge_dir.rglob('**/*.msyt'): merged_msyt.unlink()
def get_entry_hashes() -> dict: """ Gets the text entry hash table :return: A dict containing the hashes of every text entry in every game language :rtype: dict """ if not hasattr(get_entry_hashes, 'hashes'): from json import loads get_entry_hashes.hashes = loads( (util.get_exec_dir() / 'data' / 'msyt' / 'lang_hashes.json').read_text(encoding='utf-8')) return get_entry_hashes.hashes
def _msyt_file(file): subprocess.call([ str(util.get_exec_dir() / "helpers" / "msyt.exe"), 'export', str(file) ], creationflags=util.CREATE_NO_WINDOW)