该引擎的游戏主要为Apricot及其分社大概2010年之后的游戏。2010年之前的游戏虽然压缩方式一样,但是文件头我看不懂,留待大佬解决。
文件格式为:
arc.a01
arc.a02
arc.a03
...
arc.dat一、解包
工具:GARbro
https://github.com/morkt/GARbro双击arc.dat,解包script文件夹得到脚本文件。二、文本
工具:SExtractor
https://github.com/satan53x/SExtractor/tree/main
1、导出
填入正则表达式:09_search=^\s<MenuAdd \d (?P<msg>.+)>$10_search=^<Name (?P<name>.+)>$11_search=^<Text \d{9} (?P<unfinish>.+)>$12_search=^<Text \d{9} (?P<unfinish>.+)13_search=^<Text (?P<unfinish>.+)>$14_search=^<Text (?P<unfinish>.+)16_skip=^//|^[\x20-\x7E\s]+$|//|^;|^\s;|^$|^<|^\t.?<17_search=(?P<unfinish>.+)>$18_search=(?P<unfinish>.+)structure=paragraph
选择BIN,导出格式选择json[{name,messageRN}],如图:按下【提取/写入】按钮导出文本。
2、翻译
生成的all.orig.json可以直接用GalTransl翻译;如果要使用AiNiee翻译按照all.orig.json的key值导出文本就行,然后复制文本内容到xlsx表格文件即可,使用T++模式翻译。(建议将人名和对话放到同一单元格中,如:周治「はい。今日の夕飯をどっかで、って。\r\n 俺、今はあんまり金もないんで」)该引擎不支持自动换行,要根据每行最大字符数插入换行符。该引擎支持半角字符,不需要转换成全角字符。
3、导入
在设置页选择生成UniversalInjector,如图:选择BIN,导出格式选择json{origRN:origRN},如图:使用此格式导入需要先将翻译转成词典形式,如:{"女の子": "女孩子","「日文」": "「中文」","周治": "周治","「日文」": "「中文」"}将字典文件命名为transDic.json,放入ctrl文件夹中。之后按下【提取/写入】按钮导入翻译。在这一步可能会遇到报错,说是cp932不包含某字符。修复方法有两个,一个是用其他字符替换它;另一个是用https://github.com/satan53x/SExtractor/tree/main/tools/Font中的font_CN_JP.py,在字体中增加该字符。
三、封包
以下是根据GARbro的解包代码写的封包:
import osimport structimport zlibdef walk(adr):mylist=[]for root,dirs,files in os.walk(adr):for name in files:adrlist=os.path.join(root, name)relpath = os.path.relpath(adrlist, adr)mylist.append(relpath)return mylistdef Apricot_pack(path='input'):new_pack = bytearray()new_index_data = bytearray()new_content_data = bytearray()count = 0for file in walk(path):print(file)src = open(f'{path}/{file}', 'rb')unpacked_data = src.read()src.close()file_name = b''.join(struct.pack('<H', ord(c)) for c in file)entry_length = len(file_name)+528is_deleted = 0if file[-4:] == '.txt':is_packed = 1elif file[-4:] == '.bmp':is_packed = 1else: # .png .ogg .xml 不需要压缩is_packed = 0if is_packed == 1:packed_data = zlib.compress(unpacked_data)#print('compress: ',file)else:packed_data = unpacked_datanew_index_data += int.to_bytes(entry_length, 4, byteorder='little') # entry_lengthnew_index_data += int.to_bytes(is_deleted, 4, byteorder='little') # is_deletednew_index_data += int.to_bytes(len(new_content_data), 8, byteorder='little') # offsetnew_index_data += int.to_bytes(is_packed, 4, byteorder='little') # is_packednew_index_data += int.to_bytes(len(packed_data), 4, byteorder='little') # packed_data Sizenew_index_data += int.to_bytes(len(unpacked_data), 4, byteorder='little') # unpacked_data Sizenew_index_data.extend(b'\x00'*500)new_index_data += file_namenew_content_data += packed_datacount += 1new_z_index_data = zlib.compress(new_index_data)new_pack += b'\x4D\x50\x46\x32' # MPF2new_pack += b'\x00\x01\x00\x00'new_pack += int.to_bytes(len(new_z_index_data), 4, byteorder='little') # packed file index_lengthnew_pack += int.to_bytes(len(new_index_data), 4, byteorder='little') # unpacked file index_lengthnew_pack += int.to_bytes(len(new_z_index_data)+32, 4, byteorder='little') # file data_offset 原封包是+36new_pack += b'\x00\x00\x00\x00'new_pack += b'\x01\x00\x00\x00'new_pack += b'\x01\x00\x00\x00'new_pack += new_z_index_datanew_pack += new_content_datapack_name = 'patch0.dat'dst = open(pack_name, 'wb')dst.write(new_pack)dst.close()print(pack_name, ':\tpack done')Apricot_pack()
将要封包的文件夹(如script)放入input文件夹中,执行该程序。生成的patch0.dat属于增量补丁,后续如有新增内容可将新补丁命名为patch1.dat、patch2.dat等等(应该,我没试过)。四、运行
最后安装https://github.com/satan53x/SExtractor/tree/main/tools/Font中的WenQuanYi_msgothic.otf字体,将patch0.dat复制到游戏根目录下即可,转日区启动原版exe。