【技术发布】《美少女万华镜2.5》QLIE引擎字体底层重构与排版修复补丁 (qliehook.dll)
各位玩家好。
《美少女万华镜2.5》汉化版长期以来一直受困于极其严重的底层文本渲染与排版缺陷:
- 字符断裂与方块字(豆腐块):文本推进过程中频繁出现“口口口口”或无规律的问号乱码,导致关键剧情汉字缺失;
- 字符间距异常与重叠:部分中文字符间距抽风,字与字之间偶尔紧贴重叠,偶尔异常拉长;
- 字体选择器功能锁死:设置菜单中的字体选项实为“假选项”,无论如何更改,游戏内文本始终被强制回落到生硬的系统“黑体”;
- 现代中文字体隐匿:系统内安装的现代字体(如 MiSans、OPPO Sans、思源黑体、微软雅黑等)均无法在游戏字体列表中被识别列出;
- 字符横向畸变拉伸(“宽体”化):即使强行置换字体,由于引擎渲染管线的逻辑错误,文字会遭受近 35% 的强制横向拉伸,汉字扁宽发虚。
当年汉化补丁留下的这套底层渲染逻辑,其诡异程度堪比张将军的驱逐舰——表面上指令都发出去了,底层判定全掉进虚空,最后还给玩家回传了一屏幕的方块乱码与拉伸变形。
为彻底解决上述问题,我们对 QLIE 引擎的优质管线与老汉化补丁进行了全面逆向分析,重写并构建了 1:1 原生兼容的 qliehook.dll。
问题成因技术溯源
-
方块字与乱码根因:GBK 编码双字节判定断裂
QLIE 原版基于日文 Shift-JIS 架构,其双字节字符前导码(Lead Byte)上限仅截断至0xFC,引擎内部的字符扫描只处理到0xFE。
汉化文本采用的是中文 GBK 编码(前导字节0x81~0xFE,尾字节0x40~0xFE,偶见高位边界0xFF)。由于汉化组未对引擎内部的字符扫描逻辑做完整重构,导致汉字经常被引擎当成单字节截断,尾字节剥离后 GDI 无法匹配字形,直接跌落为方块字(□)或不可识别乱码。 -
对话文本底层锁死“黑体”
老汉化组提供的qliehook.dll在模块加载时,直接硬编码挂钩了文本渲染函数sub_492594(0x49279E),强制将传入的LOGFONTA.lfFaceName改写为 GBK 编码的“黑体”。无论上层 UI 脚本传参为何值,底层均被无差别拦截改写。 -
字体枚举的字符集与等宽属性拦截
-
字符集限制:枚举入口
sub_493C20硬编码了lfCharSet = 0x80(Shift-JIS),且在多处回调函数中设置了非 0x80 即丢弃的条件跳转; -
Pitch 属性过滤:游戏脚本配置了
system_fix等宽限制,导致引擎在回调中检测到 Variable-Pitch(现代比例中文字体的常规标志0x02)时直接过滤。
-
-
字距步进错位(ExtTextOutA 步距未折叠)
GDI 底层在调用ExtTextOutA渲染文本时,需要传入与字符一一对应的字符间距数组lpDx。由于汉化层未正确处理双字节跨度,导致步距信息未能按双字节折叠,字符间距随之错乱。 -
横向拉伸(宽体普京)机理
在sub_492594(0x4926C7)中,引擎存在如下硬编码逻辑:sar ebx, 1 ; ebx = (fontSize * supersample) / 2 mov [ebp-4Ch], ebx ; lf.lfWidth = ebx引擎将字体的平均字宽(
tmAveCharWidth)硬编码设为字高的 0.5 倍。这虽然吻合日文等宽字体的半角/全角混合比例,但现代中文比例字体由于英文字符与标点的紧凑设计,天然平均字宽仅为 0.35~0.38 倍字高。强制传入0.5 * height会迫使 GDI 判定调用方需要额外加宽,进而将整套中文字形横向等比拉长 33%~37%,造成字形严重畸变。
修复方案与补丁特性
-
完整 GBK 编码判定链注入:
-
全局拦截并纠正
IsDBCSLeadByte与IsDBCSLeadByteEx,适配标准的 GBK 双字节边界; -
热修补引擎内部 9 处双字节截断与边界检查地址(
0x49100F,0x49177D,0x491CD0,0x493027,0x4D4176,0x48286E,0x482D25,0x4E6E7D,0x56625D),将比较上限由0xFE拓宽至0xFF,根除汉字截断,方块字全数消除。
-
-
字距步进折叠重写:
- 拦截 GDI
ExtTextOutA,在双字节场景下重算并折叠wDx步进,确保字符间距均匀平整,杜绝字符重叠。
- 拦截 GDI
-
天然字形比例还原(消除拉伸):
- 补丁修补
0x4926C7处硬编码字宽计算,并在 Hook 入口强制指定lfWidth = 0,交还 GDI 遵循字体原生设计度量,字形回归周正端庄的标准长宽比。
- 补丁修补
-
字体选择器全面解封:
-
修正
sub_493C20字符集为DEFAULT_CHARSET(0x01),并 NOP 移除 3 处字符集过滤跳转; -
移除 Fixed-Pitch 等宽校验,允许系统中所有 TrueType / OpenType 比例字体进入游戏选择列表。
-
-
平滑回退与高质量渲染:
-
默认优先探测并载入优质无衬线字体(优先级:OPPO Sans 4.0 → 微软雅黑 → 系统默认 UI 字体),同时忠实保留玩家在设置菜单中的手动选择;
-
全局启用 GDI ClearType 抗锯齿(
CLEARTYPE_QUALITY)。
-
-
二进制兼容:
- 导出
?Empty@@YGXXZ符号,严格保证对汉化主程序的原生兼容性。
- 导出
【重要】部署与脱壳指南
核心机制说明:
汉化补丁原版使用了 Enigma Virtual Box (EVB) 虚拟化封装工具,将真正的可执行文件与旧版依赖打包成了一个体积约 55MB 的单文件美少女万華鏡2.5_CHS.EXE。
这种虚拟化壳就像带有反应装甲的重装载具——如果直接把新qliehook.dll放入游戏根目录,虚拟内存层会优先挂载内部封装的旧 DLL,导致新补丁完全被隔离吃掉。
因此,必须先执行一次解包操作(脱壳),方可完成有效覆盖。
步骤一:准备解包工具(二选一)
-
推荐方案(通过 Python 官方 PyPI,干净轻量):
打开命令行终端,运行以下命令安装解包工具:pip install evbunpack -
备选方案(图形界面工具):
下载常用的EnigmaVBUnpacker(或EVB Extractor)独立可执行程序。
步骤二:解包抽取真实主程序
-
使用
evbunpack(推荐):
在游戏目录下打开终端执行:evbunpack 美少女万華鏡2.5_CHS.EXE unpacked解包完成后,所有封装文件将输出至
unpacked目录中。 -
使用图形界面工具:
运行工具,载入 55MB 的美少女万華鏡2.5_CHS.EXE,选择输出目录并点击解包。
解包后可以发现,核心的真实主程序 美少女万華鏡2.5_CHS.EXE 实际仅约 1.8MB。
步骤三:覆盖与生效
- 将解包出的所有文件及文件夹覆盖回游戏根目录;
- 将原先 55MB 的打包文件重命名备份(如
美少女万華鏡2.5_CHS_EVB_packed.EXE)或移出目录; - 将本补丁提供的
qliehook.dll放入游戏根目录,覆盖旧版本文件; - 直接双击运行 1.8MB 的
美少女万華鏡2.5_CHS.EXE即可启动游戏。
启动游戏后进入“环境设定”->“字体”:
-
方块字与乱码问题已彻底清除;
-
本地中文字体已完整列出,支持自由切换;
-
字体长宽比例恢复正常,不再存在横向拉伸变形。
本文及代码注释使用哈鸡米3.8闪电降智流口水版编写。


