[其他] 光榮遊戲頭像儲存格式解析

作者: 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