有段时间没开新的分析系列了,这个是我最近想到的一个游戏,EVE burst error。
本系列基本完结,以下是目录供快速翻阅:
这个游戏说实在的我没玩过,因为在我的年代,没有中文版, 而游戏令人称道的地方是剧情,那这个就很尴尬了,我大学念完也只会五十音。 而且这个系列是从第二作开始有中文游戏的,这就更加尴尬。看相关介绍, 这个系列被一遍又一遍移植到各种平台,让我更加确认,这个游戏应该是不错。 而且很多资料会提到,原作者「剣乃 ゆきひろ」在开发后就从 C‘sware 离职了, 后续所有的移植、改编,都和原作者无关。这反而让我对原作的兴趣越来越大。
然后似乎很多玩家对「夜行侦探」这个译名很有意见,我还没有玩过,所以无法做出判断, 不过听人劝,吃饱饭,而且读英文对我也不是困难的事情,我就还称之为 EVE。
之前几个系列,收获了一些经验,让我稍微有些膨胀,我觉得,如果搞懂游戏的资源, 那么基本上,我应该可以借助翻译软件看懂故事,更进一步,也许能做一个简陋的汉化版, 那我们就以此为小目标好了,这个目标说实在的对我着实不小。
有了兴趣就去做,这是我的作风,所以我研究了一段时间, 之前的 llm.rs 系列 可能要坑一段时间了,别太担心,我应该会填平的, 不过,想看这个系列的朋友,也不用太开心,我写这篇文,其实是因为, 这个坑我也只是挖开而已,先总结下我目前的成果。后面因为有读者想看另一个游戏, 我可能会开始搞那个,不过那个会不会也变成坑,可能也说不准了。
现在我们不像大富翁那会儿是个没头苍蝇了,捡几个顺手的工具吧:
因为 EVE 是使用 EVE.BAT 启动,这里面实际打开的程序是 AGS.EXE,这可能是个游戏引擎, 引擎可能是borland c++ 写的,没有找到什么资料。可能是 FAIRYTALE 和 Cocktail Soft 常用的 AGS(Advanced Game Script Interpreter),不能确定。
这个使用 dosbox-x,启动游戏前下断点 bpint 21 3d
,进入断点时 d ds dx
,
即可看到文件名:
日本人的英语我们就暂且不吐槽了,我们第一个要看的文件,大概率是 rogo.gdt。 因为打开了多个 gdt 文件,而且第一个文件不长,一般第一个文件也都是设定, 应该没装什么值得注意的东西。
老方法,bpint 21 3d
,d ds dx
查看文件名,一直到 rogo.gdt 文件打开,
logl 1ffffff
记日志。
说起来,我看名字感觉可能是脚本,因为游戏中公司的 logo 有动画, 而且怎么看都会想起来 godot engine。不过现在看来,大概率是图形文件:
前四字节估计是头,然后是文件长度,后面花花绿绿的是几个单独读出来的参数。
然后跳过了 24(18h
)个字节,接下来记录了四个长度,
从 30h
开始,是文件正式的内容。
这四个长度,很容易让我想到之前的四平面, 那么我猜这是个 16 色的游戏,只是还不知道调色板在哪里。
而读取才是刚刚开始,程序保存了一个 256 长度的函数表:
index(hex) | count(hex) | bx | cutter offset |
---|---|---|---|
0 | 20 | 3b34 | 7bb4 |
20 | 20 | 3b55 | 7BD5 |
40 | 20 | 3d4c | 7DCC |
60 | 20 | 3d6a | 7dea |
80 | 20 | 3d88 | 7E08 |
a0 | 10 | 3da6 | 7E26 |
b0 | 10 | 3dce | 7e4e |
c0 | 10 | 3df6 | 7e76 |
d0 | 10 | 3e1e | 7e9e |
e0 | 10 | 3e46 | 7ec6 |
f0 | 1 | 3b18 | 7b98 |
f1 | 8 | 3b0c | 7b8c |
f9 | 1 | 3b24 | 7ba4 |
fa | 1 | 3b77 | 7bf7 |
fb | 1 | 3b86 | 7C06 |
fc | 1 | 3be1 | 7C61 |
fd | 1 | 3c11 | 7C91 |
fe | 1 | 3cb1 | 7D31 |
ff | 1 | 3e6d | 7EED |
bx
对应了程序跳转的位置,我举个例子,可能会比较好理解,
比如如果程序读到了 10h
,就会执行 3b34h
处的程序,
读到了 e9h
,就会去执行 3b24h
处的程序。
我为什么又写了一列 cutter offset, 是因为 dosbox-x 印出来的日志中的 segment:offset,和 cutter 有差,比如在 log 中:
1427:00000137 call 00000166 ($+2c) E8 2C 00 EAX:00000028 EBX:00000DC6 ECX:00000000 EDX:0000434E ESI:00000001 EDI:000000A0 EBP:00000F78 ESP:00000F70 DS:1427 ES:1427 FS:0000 GS:0000 SS:218C CF:0 ZF:1 SF:0 OF:0 AF:0 PF:1 IF:1 TF:0 VM:0 FLG:00007216 CR0:00000010
1427:00000166 cmp byte cs:[00DE],00 cs:[00DE]=8C14 2E 80 3E DE 00 00 EAX:00000028 EBX:00000DC6 ECX:00000000 EDX:0000434E ESI:00000001 EDI:000000A0 EBP:00000F78 ESP:00000F6E DS:1427 ES:1427 FS:0000 GS:0000 SS:218C CF:0 ZF:1 SF:0 OF:0 AF:0 PF:1 IF:1 TF:0 VM:0 FLG:00007216 CR0:00000010
1427:0000016C jne 0000016F ($+1) (down) 75 01 EAX:00000028 EBX:00000DC6 ECX:00000000 EDX:0000434E ESI:00000001 EDI:000000A0 EBP:00000F78 ESP:00000F6E DS:1427 ES:1427 FS:0000 GS:0000 SS:218C CF:0 ZF:0 SF:0 OF:0 AF:0 PF:1 IF:1 TF:0 VM:0 FLG:00007216 CR0:00000010
1427:0000016F test word cs:[00A4],4000 cs:[00A4]=CF00 2E F7 06 A4 00 00 40 EAX:00000028 EBX:00000DC6 ECX:00000000 EDX:0000434E ESI:00000001 EDI:000000A0 EBP:00000F78 ESP:00000F6E DS:1427 ES:1427 FS:0000 GS:0000 SS:218C CF:0 ZF:0 SF:0 OF:0 AF:0 PF:1 IF:1 TF:0 VM:0 FLG:00007216 CR0:00000010
而在 cutter 中,这段是这样:
0000:41e6 2e803ede0000 cmp byte cs:[0xde], 0 ; compare two operands
0000:41ec 7501 jne 0x41ef ; jump short if not equal/not zero (zf=0)
0000:41ee c3 ret ; return from subroutine. pop 4 bytes from esp and jump there.
0000:41ef 2ef706a4000040 test word cs:[0xa4], 0x4000 ; set eflags after comparing two registers (AF, CF, OF, PF, SF, ZF)
0166h
行对应的是 cutter 的 41e6h
行,我们忽略前面的段位置 1427h
,
两者偏差 4080h
,所以我要手工算一下,才能在 cutter 中找到这段代码,
很头疼,不知道两边怎么对齐。
看上去,要写完这 19 个函数,我们起码才能读完一个平面,简单过了一遍, 前面几个比较好写,后面几个计数为 1 的,反而是比较复杂, 不过这就是我目前研究到的内容了,下次我们再完成这 19 个函数吧。