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

既然 mgp2 只是将图像数据打包起来的一种方式,而图像的解码看上去不止一种, 那我们就得看看其他图像是如何解码的了,今天看看结局档吧,首先预告下,非常简单。

目录

本系列已完结,以下是各章节说明,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. 动态图、鉴赏模式

拿到一个结局文档

这个反而比较耗时,网上没有找到结局档,我也没有时间认真玩一遍,所以我的选择是: 读取一个最靠近 90 天的进度,然后一直睡,注意 90 天时保存一下。

毫无悬念地得来了抄家乞丐结局:

Untitled

准备 cpu log

接下来我们就要准备记录日志了,首先读 90 日的存档,然后睡觉,进入结局。 一直到最后一个白屏文字:

Untitled

这时打开调试器,下中断断点 bpint 21 3f(读取文件时中断),然后继续运行, 接着点击游戏屏幕继续,很快我们就会进入断点,接下来删去断点,使用 log 10000000, 记录 cpu log,然后我们就可以去喝个茶,等待日志记录完成了,拿到日志后, 我们就可以对结局图的进行分析。

数据和调色板

我们来搜索读取文件的日志:

Untitled

根据读取文件的日志和以前的经验,我们可以很容易判断出来,文件分为两段, 前面 2f97dh 为图像数据,后面 150h 个字节是调色板。

图像数据

图像数据这次异常地简单,只分为两种情况:

  1. 单字节数据,小于等于 c0h
  2. 双字节数据,第一个字节大于 c0h

对于单字节数据我们可以直接写入结果,对于双字节数据,第一个字节减去 c0h 即为个数 n,接下来向结果写入 n 个第二字节数据即可:

while i < end {
  let c = file_content[i];
  if c <= 0xc0 {
      v.push(c);
  } else {
      let count = c - 0xc0;
      i += 1;
      let c = file_content[i];
      for _ in 0..count {
          v.push(c);
      }
  }
  i += 1;
}

如此处理完所有数据,我们就得到了 640 x 479 的结局图。

调色板

调色板的处理与之前相同,PAT 文件头存有基础调色板,使用最后的调色板数据替换掉中间 150h 字节数据,就可以得到最终的调色板,然后我们就可以开始画图了。

总结

结局图共 14 张,前 8 张对应 8 个可攻略妹子,后面六张对应一些其他场景,比如抄家、乞丐、中举、娶亲、单身、出家。不过从结局图来看,不光是压缩算法、美术也偷懒了,比如袭人的结局图和片头:

Untitled

黛玉:

Untitled

这些也都还好,最偷懒的大概算是妙玉:

Untitled

左边是出家结局,右边是妙玉结局。其实妙玉结局就是出家结局图上 p 了一个妙玉, 看来做到结尾这块,开发经费已经烧得差不多了。