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

我们已经完整解析了 EVENT.PAT,但是其实对于事件图,我们还缺了一环, 今天我们试试看补完这一部分,补完的过程中我们还发现了原图中的一个错误。

目录

本系列已完结,以下是各章节说明,17 之前是 dos 版相关,之后是 2001 版:

  1. 背景、简单分析
  2. 显存位置
  3. 事件图保存算法: LZW
  4. 调色板
  5. MGP2
  6. 结局图
  7. 事件图中的眼睛
  8. 音频文件
  9. 按位读取
  10. 循环之前
  11. 读取循环
  12. 重现 LZW
  13. PAT 的图形格式
  14. STAFF 调色板
  15. 字体文件
  16. 脚本解密
  17. 版本比较
  18. 第一张图
  19. 调色板1
  20. 第二张图
  21. 调色板2
  22. 调色板处理
  23. 静态事件图、结局图
  24. 动态图、鉴赏模式

未完要素

在本篇的第一部分,我们就已经提到了,事件图是有动画的:

output.gif

而 EVENT.PAT 我们也已经分析过,每个都是单一的静态图像,所以显然, 动画存放在另一个地方,扫一眼目录中的文件就猜得到,EVENTEYE.PAT。

EVENTEYE.PAT

EVENTEYE.PAT 的结构也是标准的 MGP2 结构,我们应该不会陌生, 内层的图片结构类似于结局图,但稍有不同,都是 c0h 以下是单个像素, 以上是多个像素,区别在于, EVENTEYE.PAT 中的每个图片后面不再有单独的 150h 字节调色板资料, 全部都是图像数据:

Webp.net-gifmaker.gif

看到原图我们同时也知道,图像是反过来的,不过这是比较理想的情况, 有些情况下的像素颜色似乎不太正确:

Webp.net-gifmaker(1).gif

这种情况推测应该是要使用 EVENT.PAT 对应图像的调色板,我们先把这个问题放一放, 这个问题有机会在我们进一步分析时自行消失,因为我们后面如果要把眼睛画在原图上, 一定是使用静态图像的调色板。

EVENTEYE.PAT 保存了眼睛的图像,那么它是如何跟 EVENT.PAT 对应上的呢, 我们再看一下目录,另一个文件进入了我们的视野:EVENT.DAT。

EVENT.DAT

EVENT.DAT 文件不大,而且在游戏加载初期就被读进内存,CG 鉴赏时没有再读取过, 而我的日志并没有记录 EVENT.DAT 的读取过程,不过我想偷个懒, 直接猜猜看 EVENT.DAT 的内容好了。

EVENT.DAT 的文件头是 MGDA,看来这应该是文件标识。前 40h 个字节应该是文件头, 我们无法得知它们的含义,后面洋洋洒洒的写了一些设定:

Untitled

一共有四组,每行最后看上去像是设定值的地方(05h09h0dh11h……)是个等差数列,看起来像是指明每个属性的索引位置,除此以外似乎也没什么有用信息,不过有一点很重要,就是一张图像里眼睛最多四双,这时我们想到的大概是这张图:

event-0082.png

似乎确实也没有超过四双眼睛的事件图。

接下来从 01c0h 开始到文件尾,是 30h 字节数据加 3 字节分隔符的排列, 多数分隔符是 9c 31 00,但是也有例外比如 a8 30 00, 所以也有可能是散列值用于验证数据。数据一共 123 组,我们大概也就猜到了, 每组对应一个事件图(注意,EVENT 其实有 124 张图,但最后一张没有用到, 而且是重复的),我们看下第一组数据:

Untitled

我们都知道,第一张图是宝钗,只有一双眼睛,所以这里只有一组眼镜的数据, 01 00 我们推测是从 1 开始的眼睛索引,04 00 可能是结束索引,也可能是个数, 根据后面的数据我们可以推断是个数,篇幅问题就只讲结论了,8d 00 是 x 轴偏移量, 76 00 是 y 轴偏移量,不过由于眼睛图像是反过来的,所以实际使用前需要处理一下, 后面两组数据,根据 0040h 开始的属性提示,我们可以估计是动画的速度和延时, 先忽略速度和延时,我们根据上面信息逐帧画出宝钗的动图看看:

ae-0000.gif

眨眼比较快了,不过这是意料之中的,看来大体是这样没错,不过画后面图的时候也有例外:

ae-0082.gif

一共有两幅图有问题,一幅 035 我开始以为只是位置有偏移,后来对了一下, 可能原图画得就有问题,不过那个图贴不了,另外篇幅问题,以后有时间我们再讨论。 082 这幅宝钗的眼睛画斜了,这还挺神奇的,因为代码是一样的。赶紧打开游戏看一看:

dorc-4-eyes.gif

有没有注意到宝钗脸上一个神奇的抖动?看来这双眼睛确实有所不同:

Untitled

Untitled

这组眼睛一共四张图,我列出了两张,恐怕只有火眼金睛才能看出来, 第一幅图的宽度比第二幅要小 1 个像素,四张图只有图 1 的宽度是 62, 其他三张都是 63,而我把一组眼睛的宽度当成相同处理了,所以画斜了。 而游戏的问题在于,由于后三张宽了一个像素,而眼睛的偏移量是四张相同的, 而图像的差异又在开始的地方,所以画出来的眼睛位置向右偏了一个像素。 不过既然我们知道了问题所在,那么我们也就可以试着修复一下:

ae-0082.gif

神奇的抖动没有了!恐怕这是目前像素最正确的图了,当然间隔时间和速度我们还没有处理。

总结

现在我们基本清楚了 CG 图的画法,首先是根据 EVENT.PAT 得到底图和调色板, 然后根据 EVENT.DAT 中的信息,确定 EVENTEYE.PAT 中的眼睛部分, 就可以画出动画效果的 CG 图了。