红楼梦十二金钗游戏资源分析(十三)

到上一篇我们这个系列也算是告一段落了,但其实我们还可以做一些扩展

目录

1-8 是之前的分析,已告一段落,从 9 开始(算)是重置:

  1. 背景、简单分析
  2. 显存位置
  3. 事件图保存算法: LZW
  4. 调色板
  5. MGP2
  6. 结局图
  7. 事件图中的眼睛
  8. 音频文件
  9. 按位读取
  10. 循环之前
  11. 读取循环
  12. 重现 LZW
  13. PAT 的图形格式

其他图形格式

根据之前的分析,我们知道程序中还用到了另一种图形格式,不过这次我们还没见到, 其实找到这个也不难,我们知道 LZW 解码的函数是 FUN_1018_3da2, 那看哪里引用了这个函数,应该就会有收获。

只有一个地方有引用,那就更简单了,这个函数是 FUN_1028_0b64,这个函数很长, 不过我们只看 FUN_1018_3da2 相关的部分就好。

if (cVar1 == '\x02') {
  uVar2 = *(undefined4 *)(iVar5 + 9);
  FUN_1018_3da2(local_92,local_90,(int)uVar2,(int)((ulong)uVar2 >> 0x10),uVar9,uVar10);
}
else if (cVar1 == '\x01') {
  uVar2 = *(undefined4 *)(iVar5 + 9);
  FUN_1028_0a0a(local_92,local_90,(int)uVar2,(int)((ulong)uVar2 >> 0x10),uVar9,uVar10);
}
else if (cVar1 == '\0') {
  uVar2 = *(undefined4 *)(iVar5 + 9);
  FUN_1008_3e43(*(undefined2 *)(iVar5 + 5),*(undefined2 *)(iVar5 + 7),(int)uVar2,
                (int)((ulong)uVar2 >> 0x10),uVar9,uVar10);
}

FUN_1018_3da2 并列有三个函数,所以我们推断,游戏里 PAT 的文件中包含了三种格式, 我们已经知道 FUN_1018_3da2 是 LZW 格式了,所以还有两种。

FUN_1028_0a0a

do {
  if (*local_8 < 0xc1) {
    ……
  }
  else {
    ……
  }
  ……
} while ((local_e <= param_2) && ((local_e < param_2 || (local_10 < param_1))));

看到这个循环,我想系列老读者们应该会会心一笑:这是 PCX 格式。细节我觉得 ghidra 的代码还值得商榷,不过我没有深究,因为我打算用之前的代码,毕竟之前我们的 pcx 代码也没什么问题。

FUN_1008_3e43

这个代码我就不贴了,循环非常长,但是与 FUN_1028_0a0a 一样,函数中不涉及其他函数,只是一个纯粹的复杂循环,所以我的想法是,先在游戏中找一些实际读写的日志,然后根据日志和 ghidra 双管齐下确定代码怎么还原,然后再用游戏数据验证我们还原的程序。

思路有了,但是不晓得你有没有想出要怎么做呢,很简单,其实就是在 dosbox 中下断点,注意我用的是 dosbox-x,因为我发现有些版本的 dosbox 是没有调试功能的,这点需要注意,另外如果你发现调试窗口的排版如果有问题,那么你可能需要用 conhost 命令行来启动 dosbox-x。

对于 dosbox-x,alt + pause 就可以进入调试模式,之前我们说过,ghidra 和 dosbox 默认的段位置有差别,但是偏移量是一样的,所以我们可以先找到 ghidra 中的代码位置,然后根据 cpu log,确认我们要下断点到哪里。

1028:0ec1 c4 be 6c ff     LES        DI,[BP + local_96]
1028:0ec5 26 8a 45 23     MOV        AL,byte ptr ES:[DI + 0x23]
1028:0ec9 3c 02           CMP        AL,0x2
1028:0ecb 75 1f           JNZ        LAB_1028_0eec
1028:0ecd c4 3e ac 24     LES        DI,[DAT_1050_24ac]
……
1028:0ee5 9a a2 3d 18     CALLF      FUN_1018_3da2                                    undefined FUN_1018_3da2(undefine
          10

ghidra 这里,0ec5 行取出值,然后根据 al 值进行不同的解码,比如 2 就是调用我们之前的 LZW 方式解码,那么我们的 cpu log 一定也有 0ec5 这行:

0227:00000EC1  les  di,[bp-0094]               ss:[0000577E]=0825     EAX:00030000 EBX:0000000A ECX:00000064 EDX:00000000 ESI:00000070 EDI:00005752 EBP:00005812 ESP:0000576A DS:0287 ES:028F FS:0000 GS:0000 SS:028F CF:0 ZF:1 SF:0 OF:0 AF:0 PF:1 IF:1
0227:00000EC5  mov  al,es:[di+23]              es:[00000848]=0002     EAX:00030000 EBX:0000000A ECX:00000064 EDX:00000000 ESI:00000070 EDI:00000825 EBP:00005812 ESP:0000576A DS:0287 ES:031F FS:0000 GS:0000 SS:028F CF:0 ZF:1 SF:0 OF:0 AF:0 PF:1 IF:1
0227:00000EC9  cmp  al,02                                             EAX:00030002 EBX:0000000A ECX:00000064 EDX:00000000 ESI:00000070 EDI:00000825 EBP:00005812 ESP:0000576A DS:0287 ES:031F FS:0000 GS:0000 SS:028F CF:0 ZF:1 SF:0 OF:0 AF:0 PF:1 IF:1
0227:00000ECB  jne  00000EEC ($+1f)            (no jmp)               EAX:00030002 EBX:0000000A ECX:00000064 EDX:00000000 ESI:00000070 EDI:00000825 EBP:00005812 ESP:0000576A DS:0287 ES:031F FS:0000 GS:0000 SS:028F CF:0 ZF:1 SF:0 OF:0 AF:0 PF:1 IF:1
0227:00000ECD  les  di,[24AC]                  ds:[000024AC]=0000     EAX:00030002 EBX:0000000A ECX:00000064 EDX:00000000 ESI:00000070 EDI:00000825 EBP:00005812 ESP:0000576A DS:0287 ES:031F FS:0000 GS:0000 SS:028F CF:0 ZF:1 SF:0 OF:0 AF:0 PF:1 IF:1

所以我们可以在 dosbox-x 中找到这里,输入 C 0227:0ec5

ghidra 中 FUN_1008_3e43 的调用位置为 1028:0f2f,所以 dosbox 中应该是 0227:0f2f,我们可以用 c 命令再次定位,也可以直接按下往下拉:

所以我们可以在这里下断点,输入 BP 0227:0f2f,然后 F5 继续游戏,玩一会吧。

神奇的是,我转了一会儿,发现,没有进入断点。

不晓得你们得出了什么结论,我的判断是,这是一段无效代码,可能以前有这种类型的资源,后来替换掉了。当然严格一点我们不应该把话说死,起码,这种图像不是常用类型。

之前的系列中,我们有一个 PAT 文件的列表,现在我们可以更新一下了:

  1. AREA.PAT: MGP2,LZW,额外调色板
  2. END.PAT: MGP2,PCX,额外调色板
  3. EVENT.PAT:MGP2,LZW,额外调色板
  4. EVENTEYE.PAT: MGP2,LZW,套用 EVENT 调色板
  5. FACE.PAT: MGP2,PCX,单一调色板
  6. ITEM.PAT:MGP2,PCX,单一调色板
  7. MAP.PAT:MGP2,LZW,额外调色板
  8. MARK.PAT:视频文件
  9. MOUSE.PAT:MGP2,PCX,单一调色板
  10. OPEN.PAT:视频文件
  11. PERSON.PAT:MGP2,PCX,单一调色板
  12. SAREA.PAT:MGP2,PCX,单一调色板
  13. SETUP.PAT:视频文件
  14. STAFF.PAT:MGP2,LZW,调色板有误
  15. SYSTEM.PAT:MGP2,PCX,单一调色板
  16. TITLE.PAT:MGP2,PCX,单一调色板
  17. WINICON.PAT:MGP2,PCX,单一调色板

这么看来,PAT 文件我们已经全看过了,可能真的没有用到第三种格式。

总结

原来觉得可以扩展一下,结果扩展刚开始,就走到了尽头,游戏图形方面对我们基本也没什么秘密了, 再挖下去估计就是事件和文本了,这也是两个未知的领域,有时间我们再研究好了。