夜行侦探 EVE burst error 游戏文件分析(五)

ghidra / imhex / eve / dosbox / pc98

终于我们开始要接触到文字部分

目录

本系列基本完结,以下是目录供快速翻阅:

  1. 启动、GDT 文件分析一:19 个函数
  2. GDT 文件分析二:ghidra 偏移量、读取、初次绘画
  3. GDT 文件分析三:多次读取、偏移量、调色板
  4. GDT 文件分析四:完整解开及遗留问题
  5. 游戏文本解码
  6. 汉化方案制定
  7. 游戏文本编码
  8. 汉字日文编码、字库、以及第一个汉化文件
  9. 配置一个汉化 demo
  10. 手机游玩、程序文字汉化

研究对象

我们回到最初,启动 EVE 时,依次打开的文件:

  1. EVE.EFC
  2. rogo.gdt (后面是 C’s ware 的 logo)
  3. system.dat
  4. menu2.gdt (推测是新游戏菜单)
  5. menu5.gdt (推测是选角菜单)
  6. a01.cc
  7. system.dat
  8. eve_29.M(后面是 9* 12/3)
  9. waku.gdt
  10. 001.gdt(断点时还没有背景,只有框)
  11. eve_21.M(第一句话后)
  12. 001.gdt (一段剧情后)
  13. 001.gdt

排除一些看上去就不太像的文件后,我们本次的目标放在 A01.CC 上,先打开看一眼:

右侧是 shift-jis 解码后的结果,看上去是不是就很有问题,不过感觉文字是断断续续的, 应该是需要一次解密。

FUN_1860_000b

因为不是第一次定位代码,我们开始跳步骤了,这个函数在我的 ghidra 里面叫 FUN_1860_000b, 如果你之前有跟这个系列,我的 ghidra 是有设偏移量的,所以可能在各位想复现过程的朋友的 ghidra 中, 这个函数最初不叫这个名字,没关系,可以通过程序的字节码来找到这个位置:

这么长一串,相信不会搞错了。那么至于我是怎么找到的,老方法, dosbox-x 调试中 bpint 21 3d 找到打开文件的位置,然后开始记 log, 结合 log 和 ghidra 一起定位。

函数分析

ghidra 的反汇编代码除去变量声明,大概是一百行不到,感觉应该比较简单对不对, 但是因为套嵌了多个条件、循环,再加上各种没有意义的变量名,看起来比较痛苦, 而且有些时候直接看汇编比较快。我们过滤掉痛苦的部分,简单梳理一下读取的机制。

  1. 文件从 0x18 处开始读取
  2. 读取分为两种形式:
    1. 从文件中直接读取
    2. 从文件中读取索引位置和个数,从字典的对应位置复制
  3. 所有输出的内容会更新到字典中

后记:这种压缩算法其实就是 LZSS

看上去应该是一种压缩机制,字典的存在可以使文件包含比原本大小更多的内容。 那么再经过一番痛苦的除错,我们就得到了解压后的内容:

还是有大量的无法阅读的内容,但是可阅读的内容也更清晰了。我们可以先尝试把字符串内容提取出来看看。

看上去,字符串有一个明显的规律,就是 fd 开头,然后一个字节长度,然后是文字内容。当然这是我们观察的结果,程序实际可能不是这个样子,不过这依然不会阻拦我们提取字符串看看,我们按这个规则提取出所有字符串,然后在字符串结尾加上换行 \r\n

waku
         EVE burst error

       テストバージョン Ver0.4
 ロード
 最初から
 System Flag クリア
 キャンセル
 オールクリア
現在のシステムフラグを、オールクリアします。
これを行った後に、今までのセーブデータをロードすると、ハマる可能性があります。
今だったら、XFER + ROLL_UP + ROLL_DOWN キーで、抜けられます。
さぁ、いいですね、いきますよ?
クリア完了しました。
セーブデータファイル(SAVE?.DAT)は、消去しておいてください。
 天城 小次郎
 法条 まりな
 ???

看上去问题不大,我们甚至可以对一下开头:

因为有些控制字符无法复制出来,所以我用了截图,控制字符在 VSCode 中显示为红色,打开游戏看一下:

看来我们解开了游戏的剧本,严格一点说是剧本头吧,因为只研究了一个文件。

休息一下

看上去感觉很顺利对不对,其实在写程序和除错上花了很多时间,痛苦的部分没有写上去, 而且我想到一个问题,试了一下,感觉还挺棘手的,我们下次再说。