[其他] 光荣游戏头像储存格式解析

楼主: yuxio (征服世界中)   2023-04-05 00:05:05
之前说到要来写一篇介绍光荣头像储存格式的文章,想不到工作一忙又拖了一个月左右。
趁著这波连假才有一点闲暇时间可以来写。
在进入正文之前先聊点历史。其实个人对于光荣游戏的头像格式研究可以追溯到上个世纪
末,听起来很遥远,不过那时候已经是三国志六代(1998 发行)的时候了。在 1999 年三
月,还是大学生的我用 Visual Basic 写了个可以看四代五代头像的“光荣三国志脸谱浏
览程式”,并且上传到巴哈姆特 BBS 站的 KOEI 板,没错,这个 BBS 站就是今天“巴哈
姆特电玩资讯站”的前身。几年前巴哈姆特 BBS 的资料还可以透过 Web 版查看,并且直
接连结到文章,可惜今天站内的文章都不能网址直连了,只能登入 BBS 后查看。
https://i.imgur.com/8HWIWfo.png
已经是 24 年前的文章了
这个小程式是我的第一个 Side Project,也就是并非为了工作或学校功课,纯粹出于自
己个人喜好的小 Project。可惜程式码已经遗失,也没有截图,只记得是个一次显示一张
头像,可以切换上一张下一张的小程式。这个小程式比大家熟悉 van 修改器还早出来,
也比 van 2004 年在轩辕春秋发的一篇〈三国志系列图像文件格式浅析〉还要早上许多。
接下来停滞了好一段时间,一直到 2013 年初(天啊已经十年前),那时候刚好有点空
闲,于是研究起三国志三代的游戏资料,特别是各剧本武将资料以及武将头像,并且也
解出了大众脸的产生规则,相关的文章版上还可以找到,算是解了小时候玩游戏的谜团
之一。
再来便是今年,年初的时候在整理电脑里的旧档案,意外发现之前 2013 年的研究资料,
但只有残余的部分结果,少了原始程式码与部分过程档案,于是决定重启计画,研究如何
导出三国志的历代头像,并将计划规模扩及到光荣其他的早期游戏,也顺便把这次的研究
结果纪录到 Github 上,方便日后有人有兴趣可以继续深入。
### 基本原理 ###
说回正题,光荣早期游戏的图片格式在不同的游戏里可能有些许差异,但基本原理相同。
图片格式的基本原理不难,难点在于没有线索的情况下找出其规律。当年也是因为四代五
代有了威力加强版,可以自订头像,于是灵机一动,想到可以借由更改头像造成的档案变
化,来反推出其规则。但即便如此,当年仍花了我不少时间研究,研究出来后写程式码反
倒不需要多少时间。
下面便开始说明其格式,往下看之前最好有些“位元(bit)”“字节(byte)”的基本概
念,并熟悉一些可以编辑二进制的编辑器。这些资料网络上都可以找到许多教学,这里就
不赘述。
https://i.imgur.com/AXSSUb2.png
三国志三代 `KAODATA.DAT` 以二进制编辑器打开后的样子
首先我们透过观察三代的头像,或是透过四代威力加强版的脸谱编辑功能,
不难发现,每个头像只用到了八种颜色,
在电脑中只需要 3 个 bit 便可以表现出 8 种变化(2的3次方),
所以头像中每个点只需要 3 个 bit。
但是一个 byte 有 8 个 bit,3 个 3 个一组放会无法对齐。
光荣的工程师在这边用的方式是,将 3 个 byte 当作一组,
每一组三个 byte 可以表示八个点,假设这三个 byte 分别是 A, B, C。
第一个点用 A, B, C 最高位的 bit 来组合,
第二个点用 A, B, C 第二高位的 bit 来组合,以此类推,
到第八个点用 A, B, C 最低位的 bit 来组合。
换个更容易理解的方式。
以三国志三代的头像档案 `KAODATA.DAT` 为例,用二进制编辑器打开后,
可以看到其前三个 byte 分别为 `FF 00 77`, 我们把它用二进制方式写下来:
```
FF -> 1111 1111
00 -> 0000 0000
77 -> 0111 0111
FF 00 77 二进制 颜色代码
== == == =========== ===========
1 0 0 -> 100(二进制) = 4(十进制), 第一个像素点
1 0 1 -> 101(二进制) = 5(十进制), 第二个像素点
1 0 1 -> 101(二进制) = 5(十进制), 第三个像素点
1 0 1 -> 101(二进制) = 5(十进制), 第四个像素点
1 0 0 -> 100(二进制) = 4(十进制), 第五个像素点
1 0 1 -> 101(二进制) = 5(十进制), 第六个像素点
1 0 1 -> 101(二进制) = 5(十进制), 第七个像素点
1 0 1 -> 101(二进制) = 5(十进制), 第八个像素点
```
对照三国志三代伊籍的头像,
我们便可发现一开始的确是一个蓝色像素,后面接着三个青色像素,
然后又一个蓝色像素,再接三个青色像素。
所以“颜色代码 4(十进制)”对应的是蓝色像素,
而“颜色代码 5(十进制)”对应的是青色像素。
https://i.imgur.com/UYUbKKT.png
三代伊籍的头像放大
接着只要按照以上方式,将所有颜色代码找出,并将代码替换成色码画在图片上即可。
三代四代五代的人物头像大小是 64x80 像素, 然后每 3 bytes 代表 8 个像素,
因此一个武将的头像只要 64x80/8x3 = 1920 bytes。
三国志三的 `KAODATA.DAT` 档案大小是 589,440,
故可以得知这个档案里面有 307 (589440/1920) 张头像。
### 其他变化 ###
不止头像,其实光荣早期的游戏都是透过这种方式储存图像资料,只是放在不同的档案中
。然而这些游戏的开发前后跨度长达十几年,每个游戏在实际储存资料上也会有些不一样
的差异。
首先是颜色数。更早期的光荣游戏只有四色,因此只要两个 bit 就够,也就是说每两个
byte 存放八个像素点的颜色。例如三国志初代的 DOS 版就是只有用到四色。
https://i.imgur.com/WaPFIwj.png
三国志一的孔明,只有黑黄红绿四色
再来是图像资料是否只有一半高度(Half Height, 以下简称“半高”)。例如三国志二
代,它每个头像只有 64x40 的宽高资料,但在游戏中的显示却是 64x80,也就是说它的
高度拉扯了两倍,每一横列的像素都重复画了两次。有这种特征的除三国志二,还有维新
之岚、大航海时代初代、拿破仑等早期游戏
https://i.imgur.com/hApfgX6.png
拿破仑,左上角是 4x4 的正方格,可以看出每两列的颜色是重复的
又或者是头像档案经过压缩,这种压缩方式是光荣自家的 `LS11` 压缩算法,不是我们
常见的 ZIP 或 RAR 等公开算法。像这类的档案就无法透过上面方式直接取得图像资料,
要先解压缩后才可进一步解析头像资料。像是大航海时代二代以及三国志十代就都有用到
`LS11` 压缩法。这类有压缩过的档案,可以在档案开头发现 `LS11` 或 `Ls12` 的字样

https://i.imgur.com/gOgkUWN.png
大航海时代二代的头像档,`LS11` 开头
最后,为了避免多年后档案遗失,又得从头研究,我这次把相关代码都放上 Github 了,
除了各个游戏的头像提取方式外,也包含了部分游戏的人物资料汇出,以及关于这些
DOS 游戏里使用的中文字型研究。只是目前同时要兼顾工作,时间有限,文件与说明都还
很不足,希望之后陆续有时间补上。有兴趣的人欢迎直接看程式码,有任何建议或是想法
也欢迎透过 Github 上的 issue 交流。感谢大家看到这边。
Github 专案页面,原始码
https://github.com/tzengyuxio/kaodata
作者: OgamiIchiro (大神一郎)   2023-04-05 02:34:00
赞 强强强
作者: sokayha (sokayha)   2023-04-05 02:58:00
作者: MikageSayo (御影佐夜)   2023-04-05 07:30:00
作者: if4 (if)   2023-04-05 08:02:00
作者: Uliclo (特级冷冻猪肉)   2023-04-05 09:54:00
+推+
作者: zby (泊育)   2023-04-05 12:23:00
强者
作者: susuper (苏舒跑)   2023-04-05 13:39:00
专业 强
作者: qlz (())   2023-04-05 13:58:00
作者: cito (シト)   2023-04-05 14:53:00
推专业
作者: ReganLu (RLU)   2023-04-05 15:03:00
推大神
作者: sa080691 (帕森)   2023-04-05 16:21:00
虽然我看不懂,还是跪着看完了
作者: NewTypeNeo (北大三国哥)   2023-04-05 17:38:00
作者: articlebear (政治真的满狗屁的)   2023-04-05 18:56:00
看不懂也没看还是推一个 XD
作者: yung80111 (洛沁)   2023-04-05 19:26:00
虽然看不懂还是推
作者: CaoPi   2023-04-05 20:00:00
原po获得称号:“艺术支援家”
作者: dabutae (亡筱铭)   2023-04-05 23:42:00
看到 ASCII 码真的很爽XDD
作者: vanchen   2023-04-06 09:38:00
推!
作者: BluffKing (中肯王)   2023-04-06 16:16:00
神人!
作者: Harunobu (武田晴信)   2023-04-06 20:47:00
不明觉厉
作者: xoyster (若隐若现)   2023-04-06 21:42:00
这太专业了
作者: cito (シト)   2023-04-07 18:46:00
作者: game0487 (game)   2023-04-11 08:43:00
大神推
作者: iamcrazyforu (爱吃糖的猫)   2023-04-12 21:17:00
作者: Fiendyux (万变飞龙)   2023-04-14 21:27:00
强耶, 很有趣
作者: hydeeric2002 (大頭)   2023-04-16 16:25:00
你是不是叫neo?
作者: alan52017 (yi-lun)   2023-04-22 12:03:00
推 厉害
作者: insistyou (抽离所有的颜色)   2023-04-27 16:55:00

Links booklink

Contact Us: admin [ a t ] ucptt.com