DISCOVERY 自研引擎解包和破解

逆向工程自研引擎DISCOVERY人妻戦隊人妻战队
浏览数 - 754发布于 - 2025-10-10 - 06:57

重新编辑于 - 2025-10-10 - 07:13

DISCOVERY 是一家小公司,曾经活跃在 1991 ~ 2008 年,现在已经倒闭。这是 VNDB 的相关页面:DISCOVERY | vndb

代表作是在冷门黄油里相对有点点名气的:《人妻戦隊アイサイガー》系列。第一部的介绍可以在 2DFAN 这里找到:人妻戦隊アイサイガー_​人妻战队Aisaiger_​Hitozuma Sentai Aisaiger_2DFan

在介绍页面下面的评论区里可以看到,《人妻戦隊アイサイガー》系列直到今天还存在一定的热度,并且有人需要汉化补丁。

然而,90年代和00年代的 Galgame,往往采用自研引擎,而不像现在的引擎多用 KiriKiri 等引擎。这就使得引擎破解变得分散而困难。

所以,本人尝试逆向了一下 DISCOVERY 的自研引擎,主要关心的是游戏文本的解包和封包(图片的话可以用 GARBro 解包,故本篇教程不涉及图片解包封包),以方便制作汉化补丁。

以第一部《人妻戦隊アイサイガー》的旧版 EXE 程序为例,DISCOVERY 引擎的游戏文本存储在 AISAI.ID 这个二进制文件中。然而,我们发现 GARBro 无法解包这个文件。这也是本篇教程存在的意义。

image.png我们接下来使用 WinHex 查看,使用 SJIS 编码。找了一阵后发现了端倪:

image.png这些字符似乎很像是文本,都是些汉字字符。但却都是些乱码,应该这里就是游戏文本的位置,但是被加密了。

于是我们采用 IDA 进行静态逆向,搜索 AISAI.ID,定位到 0x446A30 的函数的 0x446CAA 的位置:

image.png在这个位置的右下面,直接就是解密代码了:

image.png我们按 F5 反汇编,得到伪 C 代码:

image.png这样就十分清晰了。首先,是文件数据被读取到 0xD3866C 这个位置。然后我们关注到 v26 这个变量,它是 4 * dword_D3866C + 13862508,而这个 13862508,正巧就是 0xD3866C。也就是说,v26,就是将 0xD3866C 这个位置读取到的 DWORD 数据乘以 4,再加上 0xD3866C。而 AISAI.ID 的数据被读取到 0xD3886C 这个位置,说明这个位置是文件头,那么,4 * dword_D3866C 应该就是文件头到文本位置的偏移。于是,v26 就代表文本开始的位置。我们观察 WinHEX 的截图,恰好就是 0x8DC40,乱码开始的位置。

我们再关注 v27 这个变量,它是 2 * dword_D38670 - 2 * dword_D3866C,但我们不妨写成 (4 * dword_D38670 - 4 * dword_D3866C)/ 2。我们已经知道了 4 * dword_D3866C 是文本开始的位置,而 0xD38670 恰好是 0xD3866C + 4,是文件头开始的第二个 DWORD。观察 v27  的作用,似乎是计数用的。这不难猜出,4 * dword_D38670 是文本结束的位置,v27 代表文本的长度。这里有个细节,v27 是文本长度字节数除以2,这说明所有的文本字符,都是双字节的。

然后,我们再关注解码代码。代码逻辑特别简单,逐 int16 (也就是双字节)读取。如果最后一个 bit 为 1,则和 0xFFFE 与运算,将最后一个 bit 变成 0。如果最后一个 bit 为 0,那么就与 1 进行或运算,将最后一bit 变成 1。一句话总结,就是和 0x0001 异或。

因为异或是自身的逆运算,因此加解密,封包和解包,都能用一个简单的 0x0001 异或解决了。如下图所示:

image.png于是,DISCOVERY 自研引擎的加密就这么破解掉了。

但是。。。。还是有个小问题,这是提取出的文本:

image.png我们发现,提取出的文本里,除了纯文字以外,还有一些其它的组成部分。有 0x0000, 0x0100,0x0200,0x0300,这四个双字节将纯文字语句分开。除此以外,在一些纯文字语句,尤其是角色的发言的前面,会存在一个奇怪的四字节。

比如在图里,???这个角色的发言,前面就有 0x8196D1B2 这个四字节,并且明显不像是游戏里显示的文字(文字是从???开始的)。

根据笔者的探索,发现 0x0100 的作用是换行,角色发言前面的奇怪的四字节,则代表音频文件。众所周知,角色发言时会有语音,游戏将每一段语音都用一个四字节的二进制数据标示。当运行到角色文本的地方时候,会先读取文字之前的四字节,查找到对应的语音并播放。比如,图片中 ???的发言,就对应标号为 0x8196D1B2 的这段语音。旁白(也就是不发出语音),对应四字节为 0x005ED0B2。

可是,至于 0x0000,0x0200,0x0300,这三个双字节是什么作用。笔者就不知道了。但所幸,这并不影响我们解包、封包和制作汉化补丁。写解包代码时候当成分隔符就行了。如果有大佬能找出 0x0000,0x0200,0x0300 代表什么含义,欢迎随时在评论区告诉我。

image.png笔者写了个解包代码,提取文本到 AISAI.txt,格式如上。这是为了与天诛熊这款软件做配合。天诛熊是一个 GalGame 二进制文本注入软件。就是根据这种格式的汉化文件:


No.XXXXX(序号) [D:0xXXXXXXXX](原文本在游戏二进制文件中的起始位置)[L:XXX](原文本以字节数计数的长度)

XXXXXXXXXXXXXXXXX(原文本)
>XXXXXXXXXXXXXXXXXXXX(汉化文本)


将汉化文本注入到二进制文件中。比如本例子中的 AISAI.ID。但是一般的,笔者的方法是将中文汉字替换成日文汉字,并将替换字符后汉化文本以 SJIS 编码注入到二进制文件。然后,再用 JIS 替换工具,如 UniversalInjectorFramework (原理是 HOOK 游戏里的字符显示函数,如 GetGlyphOutline),将日文字符替换回中文字符。详情可以参考:GalTransl/GalTransl: 支持GPT-4/Claude/Deepseek/Sakura等大语言模型的Galgame自动化翻译解决方案 Automated translation solution for visual novels supporting GPT-4/Claude/Deepseek/Sakura 。Repo 里面有对 JIS 隧道 和 JIS 替换的介绍,并且在 useful_tools 目录里提供了相关工具。更多的这里就不赘述了。

注意!如果你想使用 JIS 替换法的话,你需要自己写一个字典!比如,你在使用 UniversalInjectorFramework 下的 winmm.dll 的时候,你需要自己写一个 uif_​config.json,并且在中文->日文->中文的流程中保证字典的一致性。

笔者现已经将相关解密、解包(提取文本)、天诛熊工具放在 github 上了,欢迎随时下载:

zhongweili0204/Decrypt-DISCOVERY-Engine: A simple python script to decrypt the text file of DISCOVERY engine, which is usually named with XXXX.id.

其中,decrpypt & encrypt.py 是解密加密,get_text.py 是提取文本。

因为解包工具写的并不系统,因此代码只作解包和参考使用,不建议直接拿来封包游戏文本。如果想自己封包,还是建议在参考笔者的代码后,用 AI 自己写一个脚本。

PS:笔者的代码也是 AI 写的。

本篇文章欢迎任何人转载。

本文版权遵循 CC BY-NC 协议 本站版权政策

2 条回复

LikeInYou
发布于 2025-10-10 - 10:58

任何人有疑问,或者想汉化 DISCOVERY 的作品,需要帮忙,我都可以提供。

LikeInYou
发布于 2025-10-13 - 09:59

真就没人想汉化 DISCOVERY 的作品吗?

(。>︿<。) 已经一滴回复都不剩了哦~