游戏汉化笔记

最后由 Tabing010102 更新于 2024年3月11日

主要记录下折腾的记录,废物笔者并不会逆向,全靠前人的铺垫,在此感谢先辈们。

图片模糊问题,目前建议新标签打开图片,把链接后的-1024x???删除(如image-1024x597.jpg更改为image.jpg

《リトルプリンセスGO!》

首先是《リトルプリンセスGO!》,引擎BGI/Ethornell(Shift_JIS版,新版BGI原生支持UTF-8,处理起来更简单),这个处理起来算是比较简单的,把data01110data01120解包,用VNTranslationTools提取json,翻译,封回去就行了

需要注意的是,这里的脚本有工具不支持的opcode,需要改下代码(笔者这里设置的未知opcode直接跳过,暂时没有出问题)

封包时使用VNTextProxy的dll,打包使用MoleBox,可能需要取消勾选Relink,否则dll可能不会正确加载;Enigma Virtual Box貌似不能正确处理

《海と雪のシアンブルー》

下面是《海と雪のシアンブルー》,引擎krkrz

文本方面,使用KrkrExtract,解包data.xp3(这里的文本之类的全部在这里,且封包不大),使用VNTranslationTools提取json,翻译,封回去

程序方面,修改forcedataxp3()处3个括号里的值为0

将下面的data.xp3换成任意其他字符串(游戏目录中没有的文件名),这时引擎会读取data文件夹内容

字体修复部分,这里懒了,改了data.xp3>system/Initialize.tjs,删掉了AddAutoPath("parts.xp3>font/");,这时引擎会回落到默认字体(win10和win11中可能是微软雅黑)

打包时把修改后的程序和data目录一起打包即可(Enigma Virtual Box)

《アイコトバ-Silver Snow Sister-》(失败)

下面是《アイコトバ-Silver Snow Sister-》,引擎Artemis,这个理论上是最好改的引擎之一,原生使用UTF-8编码,可惜VNTextPatch不支持此版本的ast脚本,再加上我也快玩完了,也就作罢

可以参考chinesize这个项目的Artemis部分,可能会有所帮助

《恋想リレーション》

下面是《恋想リレーション》,引擎BGI/Ethornell(Shift_JIS版)

这一版的BGI相对麻烦一点,需要去除区域认证,可以使用OD或者x64dbg改,不过x64dbg需要先使用LordPE去除redirect后再改(勾选重定向已分离)

OD(可能需要全英文路径,否则可能进不到断点就直接退出):使用OD打开rensou.exe后,F9运行程序至进入主模块,在CPU窗口中Ctrl+N(或右键->查找->当前模块中的名称),查找GetSystemDefaultLangID,查找函数参考,双击跳转至函数调用处

然后直接返回0x411(将call调用改为mov eax, 411

更改完后在CPU窗口右键->复制到可执行文件->所有修改,之后保存文件即可

x64dbg:

首先使用LordPE去除重定向

LordPE去除重定向

保存后使用x64dbg打开,运行至主模块,右键搜索->当前模块->跨模块调用,搜索GetSystemDefaultLangID后,双击跳转至CPU窗口

修改同OD,使用Space键汇编为mov eax, 0x411

最后Ctrl-P(右键补丁)->全选->修补文件,保存即可

文本方面,同《リトルプリンセスGO!》,使用VNTranslationTools提取json,翻译,封回去

修改过的文件放在游戏exe旁边,放入VNTextProxy的dll即可

字体修改方面,懒了,直接使用FontMod,根目录放自定义字体(这里是simhei.ttf),配置(简体中文系统):

fonts:
  # MS ゴシック:
  俵俽 僑僔僢僋:
    replace: simhei.ttf
    <<: *style
  SimSun: &zh-cn-font # Chinese (Simplified) fallback font
    replace: simhei.ttf
    <<: *style

本游戏笔者打包失败,于是就散装用了

《D.C.4 Sweet Harmony》

下个是《D.C.4 Sweet Harmony》,krkrz引擎

也是用KrkrExtract解包,程序修改forcedataxp3data.xp3,和《海と雪のシアンブルー》不同的是,本作使用的TJS2脚本,无法作为文本修改

笔者用的解决办法,用WinHex打开startup.tjs,查找Initialize.tjs,将其修改为其他值(这里假设修改为Initializa.tjs,最后一位修改为a)

然后在data/system/文件夹下,建立Initializa.tjs,写入以下代码。其中最后一行为加载原有的Initialize.tjs,上面的很多行为加载原始data.xp3中的文件,注意所有子目录都需要添加一行加载语句。加载原始封包的文件就可以从data文件夹删除,减小data文件夹大小

Storages.addAutoPath(System.exePath+'data.xp3>bgm/');
Storages.addAutoPath(System.exePath+'data.xp3>font/');
Storages.addAutoPath(System.exePath+'data.xp3>image/');
Storages.addAutoPath(System.exePath+'data.xp3>image/comu/');
Storages.addAutoPath(System.exePath+'data.xp3>image/cut/');
Storages.addAutoPath(System.exePath+'data.xp3>image/ED/');
Storages.addAutoPath(System.exePath+'data.xp3>image/ED/asa/');
Storages.addAutoPath(System.exePath+'data.xp3>image/ED/asu/');
Storages.addAutoPath(System.exePath+'data.xp3>image/ED/endroll/');
Storages.addAutoPath(System.exePath+'data.xp3>image/ED/hiy/');
Storages.addAutoPath(System.exePath+'data.xp3>image/ED/miu/');
Storages.addAutoPath(System.exePath+'data.xp3>image/ED/nin/');
Storages.addAutoPath(System.exePath+'data.xp3>image/ED/sii/');
Storages.addAutoPath(System.exePath+'data.xp3>image/ED/sor/');
Storages.addAutoPath(System.exePath+'data.xp3>image/ED/tiy/');
Storages.addAutoPath(System.exePath+'data.xp3>image/effect/');
Storages.addAutoPath(System.exePath+'data.xp3>image/eyecatch/');
Storages.addAutoPath(System.exePath+'data.xp3>image/log/');
Storages.addAutoPath(System.exePath+'data.xp3>image/MAP/');
Storages.addAutoPath(System.exePath+'data.xp3>image/other/');
Storages.addAutoPath(System.exePath+'data.xp3>image/sys/');
Storages.addAutoPath(System.exePath+'data.xp3>image/thum/');
Storages.addAutoPath(System.exePath+'data.xp3>k2compat/');
Storages.addAutoPath(System.exePath+'data.xp3>main/');
Storages.addAutoPath(System.exePath+'data.xp3>rule/');
Storages.addAutoPath(System.exePath+'data.xp3>scenario/');
Storages.addAutoPath(System.exePath+'data.xp3>scenario/scripts/');
Storages.addAutoPath(System.exePath+'data.xp3>scenario/simpleanim/');
Storages.addAutoPath(System.exePath+'data.xp3>scenario/transitions/');
Storages.addAutoPath(System.exePath+'data.xp3>sound/');
Storages.addAutoPath(System.exePath+'data.xp3>sysscn/');
Storages.addAutoPath(System.exePath+'data.xp3>thum/');
Storages.addAutoPath(System.exePath+'data.xp3>uipsd/');
Storages.addAutoPath(System.exePath+'data.xp3>uipsd/func/');
Storages.addAutoPath(System.exePath+'data.xp3>video/');

Scripts.execStorage("system/Initialize.tjs");

本作可以选择字体,使用黑体或其他等宽中文字体

最后将汉化的游戏脚本、修改后的主程序和data文件夹用Enigma Virtual Box打包即可

《ここから夏のイノセンス!》

下面一个游戏是《ここから夏のイノセンス!》,引擎cs2/CatSystem2

文本方面,笔者一开始使用VNTranslationTools封包,但VNTextProxy的dll库无法正常加载/加载崩溃,后来使用Ineditor,但执行到某个地方回直接回到主菜单,无法正常进行游戏,最后修改VNTextPatch,使用GBK编码才算解决,参考GitHub项目

程序部分,主要需要破解key验证、修改编码、修改字符验证范围,主要参考Dir-A大佬的视频(链接

破解key验证部分,使用x64dbg打开,运行至主模块,搜索字符串key.dat

双击跳转至对应汇编,修改下方的jne xxxjmp xxx

最后应用补丁,保存

修改读取编码部分,x64dbg打开,运行至主模块搜索跨模块调用CreateFontIndirectA

双击跳转至汇编,向上翻2个函数,双击call指令

修改下方参数0x800x86

最后应用补丁、保存

修改字符边界部分,使用OD打开,运行至主模块,右键查找所有常量0x9F

找到cmp al, 0x9F,双击跳转

每隔一个修改cmp al, 0xXXcmp al, 0xFE

修改完,复制所有修改到可执行文件,保存

字体修复部分,游戏字体可能在config/startup.xmlfont相关位置,但本游戏修改并没有用,笔者更改了游戏主程序。使用WinHex打开游戏exe,搜索”俵俽 僑僔僢僋“或”MS ゴシック”或16进制数值”826C827220835383568362834E“,修改为”simhei“(后面补16进制0),将出现的所有进行更改,最后保存即可

封包部分,cs2引擎支持免封包读取,将汉化脚本放至scene文件夹下,打包时将修改后的主程序和scene文件夹一并打包即可

《ラブラブル~lover able~》

这游戏是SMEE老作,封包格式ykc,引擎是yuka script(或yuka system),现在倒是有一个针对这个引擎的工具,但是这玩意貌似只能处理英文(使用Shift_JIS),又因为我短时间内没找到现有的更改此引擎文字编码的资料(加上瞎折腾失败),就偷了VNTranslationTools里的VNTextProxy,把SjisTunnelEncoding抄过来了(项目地址

总体流程:把DATA01.ykc解包,删除除了story文件夹以外的脚本,翻译story里的csv,封包,patch原始包。用到的指令如下

yuka.exe unpack DATA01.ykc
yuka.exe pack DATA01CN
yuka.exe patch DATA01.ykc DATA01CN.ykc

VNTextProxy里的预编译proxydll貌似只有winmm.dll能用,不能输入文字,而且还会占满一个CPU核,属于是真勉强能动水平

在Enigma Virtual Box打包的时候,将这些文件(游戏主程序,修改后的DATA01.ykcsjis_ext.binwinmm.dll)打包进一个exe就不能让VNTextProxy正常加载。但是把除了游戏主程序之外的文件打包成一个封装,让打包的exe加载这个外部封包就正常,不知原理是什么。

最后,若想使用VNTextProxy的强制指定字体功能,貌似不能打包进封装,直接放在exe旁边就能正常加载。最后的补丁大概长这个样子:

贴一个csv插入的屎山片段

def process_csv_files(file_paths):
    for file_path in file_paths:
        f = open(file_path, encoding='utf8')
        # read csv
        reader = csv.reader(f)
        # write
        wfn = file_path.replace("JP", "CN")
        wfndir = os.path.dirname(wfn)
        if not os.path.isdir(wfndir):
            os.makedirs(wfndir)
        writer = csv.writer(open(wfn, 'w', encoding='utf8', newline=""))
        for row in reader:
            try:
                if len(row[2].strip()) == 0:
                    writer.writerow(row)
                    continue
                if row[0] == "ID":
                    writer.writerow(row)
                    continue
                if row[0].startswith("N"):
                    if len(row) != 3:
                        print("W: {} len = {}".format(row[0], len(row)))
                    row.append(get_trans_name(row[2]))
                    writer.writerow(row)
                elif row[0].startswith("L"):
                    if len(row) != 3:
                        print("W: {} len = {}".format(row[0], len(row)))
                    row.append(get_trans_msg(row[2]))
                    writer.writerow(row)
                elif row[0].startswith("S"):
                    if len(row) != 3:
                        print("W: {} len = {}".format(row[0], len(row)))
                    row.append(get_trans_sw(row[2]))
                    writer.writerow(row)
                else:
                    writer.writerow(row)
                    print("W: unknown prefix, row[0] = {}".format(row[0]))
            except Exception as e:
                writer.writerow(row)
                continue

《同棲ラブラブル》

同上

《Pieces/揺り籠のカナリア》

引擎YU-RIS 0.5xx,漩涡社的特制引擎,有sc.ypf,主要针对解包出来的scenario脚本进行处理(明文),方法和工具主要参考Dir-A佬的YU-RIS汉化演示实例(链接

首先使用Replace_RangTable.exe替换程序字符检测范围表(或按视频中更改),然后使用x64dbg打开,运行至主模块,搜索常数0x9F,找到cmp xxx,9F,点进去

根前面的字符边界检测类似,将81 9F E0 FC更改为81 FE E0 FE(隔位修改为0xFE

然后根据Dir-A的教程,需要运行至主模块,转至内存布局页面,全选,右键搜索匹配特征,搜索C1 E0 08 ?? ?? ?? ?? ?? ?? 99 E9

点进去后,将shl xxxcdq上方指令使用nop填充(右键二进制,使用NOP填充),并根据shl操作的寄存器写入mov ax,9F00(比如shl eax,8->mov ax,9F00shl ecx,8->mov cx,9F00

最后的免封包处理,需要让程序读取yscfg.ybn加载配置,但本游戏不会读取在外面的yscfg.ybn

在当前模块中搜索跨模块调用的GetFileAttributes,点进去找到函数比较短的(一共只有几行汇编的),在call00440511)指令上加断点,重新运行至此

返回至调用函数,再点进上面的call,即是函数入口点(这里为call GetFileAttributeA上面的push eax

在函数入口点右键,查找引用,选定的地址

这里的程序在读取文件时又封装了一层,所以需要点进没个引用处,断下调用处上方的两个mov xx:[]xx,0

运行,直到看到yscfg.ybn,将其改为mov byte ptr ss:[esp+C],3

至此,主程序修改完成,字体笔者偷懒使用Dir-A提供的HookFont,不改的话默认是宋体。

接下来修改yscfg.ybn,最后为标题名字字符串,向前数8个字节,修改紫色框二进制为01,修改后引擎将会默认从外部文件读取(原理参考yscfg分析)

下面处理人物名称不显示在人物名称栏的问题,本游戏脚本有加密,首先使用GARbro解包bn.ypf,选择文件大小最大的yst00xxx.ybn,拖到上YSTB_GuessXorKey.exe打开,得到Key.txt。然后使用YSTB_Xor.exe得到解密的ysbin_dec文件夹。

接下来将YSTL_Parse.exeysbin_dec文件夹放入一个新文件夹中,从原始加密的ysbin中,复制除yst00xxx.ybn的文件到ysbin_dec中,最后将ysbin_dec重命名为ysbin,命令行执行YSTL_Parse.exe -json得到ystl.json;再运行YSTL_Parse.exe -make得到有原始名字的scripts文件夹。

scripts文件夹中使用010 Editor或其他软件,搜索es.CHAR.NAME,一般为userdefine\キャラ名定義.txt(其他特殊情况参考教程)

使用extYbn提取文字,根据翻译结果替换相应文字,再封回去,命令如下:

# extract
for %%a in (*.ybn) do extYbn.exe -e -ybn %%a -op-msg 108 -op-call 43 -txt %%a.txt -cp 932 -key 0x0

# insert
for %%a in (*.ybn) do extYbn.exe -p -ybn %%a -txt %%a.txt -op-msg 108 -op-call 43 -cp 936 -new-ybn %%a.new.ybn -key 0x0

最后新建一个ysbin目录,将生成的キャラ名定義.txt.ybn.new.ybn放进去,将YSTB_Xor.exe和前面生成的Key.txt放在一个目录下,执行YSTB_Xor.exe加密回去。接下来通过ystl.json文件找到キャラ名定義脚本对应的原始文件名,这里Sequence为274,所以原始文件名为yst00274.ybn

scenario内文件修改时需要注意的是,由于使用gbk编码,\u266a)、\u4337)、\u30fb)字符无法编码,需要删除或使用gbk中有的字符进行替代。

此外,在处理指令(\XX(xxxx))时,笔者使用的sjis编码,但是指令包含游戏目录下pac文件夹内的文件时需要使用gbk编码,否则会出现读不到文件的错误,但有部分\u30fb)无法被gbk编码,笔者处理时仅把\u30fb)使用sjis编码,其他使用gbk编码,具体参考以下代码(链接),笔者初步测试没出现崩溃,凑合能动水平。

最终打包结构如下图:

参考:

Dir-A的个人空间-Dir-A个人主页-哔哩哔哩视频 (bilibili.com)

Galgame 汉化破解初级教程:以 BGI 为例,从解包到测试|【汉化破解研讨室】|【游戏汉化交流区】 – 『澄空学园』 GalGame专题网 (sumisora.net)

「さくら、もゆ。」的空白字体列表——一次逆向问题定位过程实录 – (o・∇・o) (mmf.moe)

DC2PC汉化实战|【汉化破解研讨室】|【游戏汉化交流区】 – 『澄空学园』 GalGame专题网 (sumisora.net)

Galgame引擎、破解与资料大全 (ultrapre.github.io)

Dir-A/VN_Localization_Tutorials: Galgames汉化教程 (github.com)

用到的工具/开源项目:

Software Protection, Software Licensing, Software Virtualization (enigmaprotector.com)

arcusmaximus/VNTranslationTools: Tools for translating visual novels (github.com)

sudachen/Molebox: MoleBox lets you convert your application into an all-sufficient stand-alone executable, containing everything needed: components, media assets, registry entries. (github.com)

xmoezzz/KrkrExtract: A tool that can extract and pack krkr2 and krkrz’s xp3 files (github.com)

regomne/chinesize: My chinesize tools, scripts and codes (github.com)

regomne/lneditor: [deprecated] A multiline editor for translators (github.com)

ysc3839/FontMod: Simple hook tool to change Win32 program font. (github.com)

AtomCrafty/yukatool: A collection of tools for the “Yuka System” visual novel engine (github.com)

Dir-A/YurisTools: Yu-Ris Engine Tools. | .ypf .ybn (github.com)

Visits: 98

发布者:Tabing010102

???

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据