一.圖片數據
CrossGate | GraphicInfo*_*.bin |
StoneAge | Adrn_*.bin |
這個文件存放了圖片的地址索引,由若干個大小一樣的塊組成,每個塊長度為40字節(StoneAge為80字節),格式如下:
字段類型 | 內容 | 說明 |
LONG | 序號; | 圖片的編號 |
DWORD | 地址; | 指明圖片在數據文件中的起始位置 |
DWORD | 塊長度; | 圖片數據塊的大小 |
LONG | 偏移量X; | 顯示圖片時,橫坐標偏移X |
LONG | 偏移量Y; | 顯示圖片時,縱坐標偏移Y |
LONG | 圖片寬度; | ... |
LONG | 圖片高度; | ... |
BYTE | 佔地面積-東; | 佔地面積是物件所佔的大小,1就表示占1格 |
BYTE | 佔地面積-南; | 同上 |
BYTE | 標誌; | 用於地圖,0表示障礙物,1表示可以走上去 |
BYTE[5] | 未知; | 在StoneAge中本字段長度為45字節 |
LONG | 地圖編號; | 低16位表示在地圖文件裡的編號,高16位可能表示版本,非地圖單位的此項均為0 |
其中偏移量XY是用於圖片定位的,比如X=-18,Y=-19,如果將圖片顯示在(100,100),那麼實際位置應該是(82,81),這樣才可以和其它圖片協調,在做人物動作gif的時候必須用這個參數來調整每一幀的位置,否則動作是抖動的,做地圖也需要,否則會錯位。
CrossGate | Graphic*_*.bin |
StoneAge | Real_*.bin |
這個文件包含了所有圖片的原始數據,每個數據塊由數據頭+數據組成,每個數據頭長度16字節,格式為:
字段類型 | 內容 | 說明 |
BYTE[2] | 魔數; | 固定為'RD' |
BYTE | 版本; | 偶數表示未壓縮,按位圖存放;奇數則表示壓縮過 |
BYTE | 未知; | ... |
LONG | 寬度; | ... |
LONG | 高度; | ... |
LONG | 塊長度; | 數據塊的長度,包括數據頭本身的長度(16BYTE) |
後三項和地址文件中的一樣,圖像數據緊跟在數據頭後面。
例如,要解開第100個圖片,首先在GraphicInfo_*.bin裡定位到第100條記錄,即偏移(40*100)字節的位置,根據讀出的地址在Graphic_*.bin中找到對應的數據塊,就可以讀出圖片數據了。
絕大部分圖片數據都是壓縮過的,算法後面會介紹。
二.動畫信息
動畫地址文件
CrossGate | AnimeInfo*_*.bin |
StoneAge | Spradrn_*.bin |
存放每個動畫在動畫序列文件中的地址索引,每個數據塊大小12字節
字段類型 | 內容 | 說明 |
DWORD | 序號; | 動畫序號 |
DWORD | 地址; | 指明在動畫信息文件中的地址 |
WORD | 動作數目; | 表示該角色有多少個完整的動作(包括各個方向) |
WORD | 未知; |
CrossGate | Anime*_*.bin |
StoneAge | Spr_*.bin |
該文件存放了全部動作的圖片序列,每個動作由數據頭+若干序列號組成,數據頭長度12字節。
字段類型 | 內容 | 說明 |
WORD | 方向號; | 0-7分別表示8個方向 |
WORD | 動作號; | 表示該動作的含義,比如坐下或者走路 |
DWORD | 時間; | 該動作完成一遍所需時間,單位為毫秒 |
DWORD | 幀數; | 該動畫有多少幀,決定後面數據的大小 |
某些動作號不是所有角色都有,比如跑步前的準備動作。
有多少幀,後面就跟有多少個序列號,每個序列號長10字節。
字段類型 | 內容 | 說明 |
DWORD | 圖片號; | 該幀所使用的圖片 |
CHAR[6] | 未知; | ... |
圖片號就是該幀所用的圖片序號,用圖片數據裡說的方法就可解出每一幀的圖片數據。。
例如要解出340號角色的1方向的第5個動作,先在AnimeInfo_*.bin中定位到第340號數據塊,即偏移(12*340)字節的位置,讀出地址和動作數,然後根據地址在Anime_*.bin中定位到對應的位置,然後從該位置開始查找方向1動作5的序列,根據幀數讀出每一幀的圖片號,通過圖片號解出對應的圖片就行了。
其中未知的字段表示我還不知道用處的。
注意:CrossGate的動畫序列地址文件AnimeInfo_*.bin,可能由於開發時的某些原因,造成存放了3遍序列,並且按前兩遍解出的動畫是錯誤的,要以第3遍為準,第2375號角色才是第0號,其他的版本沒有這問題。
三.地圖格式
地圖文件就是map目錄下的那些,CrossGate的地圖檔在最前面有12個字節的文件頭,內容為"MAP"(後9字節為0),StoneAge則沒有文件頭,其它完全一樣。
字段類型 | 說明 |
DWORD | 地圖長度-東(W) |
DWORD | 地圖長度-南(H) |
BYTE[W*H*2] | 地面的數據,每一個單位2字節,為0表示無地面 |
BYTE[W*H*2] | 地上的物件等,每一個物體2字節,為0表示該處無物件 |
BYTE[W*H*2] | 地圖標誌,每一個單位2字節,具體不清楚,只知道對會引起地圖切換的地方有標識 |
3 | ||||
2 | 6 | |||
1 | 5 | 9 | ||
4 | 8 | |||
7 |
四.壓縮算法
這是JSS自定的一種Run-Length算法,用於StoneAge和CrossGate,下面是說明:
首字節(00) | 01 | 02 | 03 | 說明 |
0n | String | 長度為n的字符串 | ||
1n | m | String | 長度為n*0x100+m的字符串 | |
2x | y | z | String | 長度為x*0x10000+y*0x100+z的字符串 |
8n | X | 填充n個X | ||
9n | X | m | 填充n*0x100+m個X | |
Ax | X | y | z | 填充x*0x10000+y*0x100+z個X |
Cn | 填充n個背景色 | |||
Dn | m | 填充n*0x100+m個背景色 | ||
Ex | y | z | 填充x*0x10000+y*0x100+z個背景色 |
比如,C9表示填充9個背景色,D1 10表示填充0x110個背景色,12 50表示後面跟著一個長度為0x250的字符串,91 02 30則表示將0x02重複0x130遍。
五.調色板
StoneAge的調色板文件是位於data/pal目錄下的palet_*.sap,CrossGate的則為bin/pal目錄下的palet_*.cgp,每個文件長度均為708字節,每種顏色3字節,所以每個文件都包含了236種顏色,要注意的是它不是從0號顏色開始排列的,而是從16號,即16-252,但實際上是16-240,前16種顏色和後16種顏色都是指定,文件中的240-252號顏色並沒有使用,下面是指定的32種顏色:
顏色號 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
RGB值 | (00,00,00) | (00,00,80) | (00,80,00) | (00,80,80) | (80,00,00) | (80,00,80) | (80,80,00) | (C0,C0,C0) |
顏色號 | 8 | 9 | A | B | C | D | E | F |
RGB值 | (C0,DC,C0) | (F0,CA,A6) | (00,00,DE) | (00,5F,FF) | (A0,FF,FF) | (D2,5F,00) | (FF,D2,50) | (28,E1,28) |
顏色號 | F0 | F1 | F2 | F3 | F4 | F5 | F6 | F7 |
RGB值 | (96,C3,F5) | (5F,A0,1E) | (46,7D,C3) | (1E,55,9B) | (37,41,46) | (1E,23,28) | (F0,FB,FF) | (A5,6E,3A) |
顏色號 | F8 | F9 | FA | FB | FC | FD | FE | FF |
RGB值 | (80,80,80) | (00,00,FF) | (00,FF,00) | (00,FF,FF) | (FF,00,00) | (FF,80,FF) | (FF,FF,00) | (FF,FF,FF) |
說一下常用的幾個調色板:
白天 | 傍晚 | 黑夜 | 凌晨 | |
StoneAge | palet_01.sap | palet_02.sap | palet_03.sap | palet_04.sap |
CrossGate | palet_00.cgp | palet_01.cgp | palet_02.cgp | palet_03.cgp |
六.各版本對應的文件
CrossGate每個大版本都有相對獨立的文件,比如最初的版本圖片數據文件是Graphic_*.bin等,而龍沙的則是GraphicEx_*.bin,附加上了"Ex",下面是各個版本所使用的附加名。
版本 | 附加名 |
龍之沙時計 | Ex |
樂園之卵(精靈) | V3 |
樂園之卵 | _PUK2 |
七.後續版本的改動
這裡說的是CrossGatePuk2(樂園之卵)的數據格式變動。
樂園之卵中的圖片不再使用全局調色板,靜態圖片都自帶調色板,動畫則是用隱藏調色板。
首先是自帶調色板,圖片數據中的文件頭被擴充至20字節,且版本字段大於等於2(之前的為0和1)。
字段類型 | 內容 | 說明 |
BYTE[2] | 魔數; | 固定為'RD' |
BYTE | 版本; | 偶數表示未壓縮,按位圖存放;奇數則表示壓縮過 |
BYTE | 未知; | ... |
LONG | 寬度; | ... |
LONG | 高度; | ... |
LONG | 塊長度; | 數據塊的長度,包括數據頭本身的長度(20BYTE) |
LONG | 調色板長度; | 調色板數據所佔的長度,通常為0x300,即256*3=768 |
還原後的數據最後那部分則是自帶的調色板數據,大小和調色板長度字段的內容相同。
隱藏調色板本身其實是一些4X1的自帶調色板的圖片,它們的地圖編號字段被重新解釋了,表示使用這個調色板的動畫序號,比如地圖編號為0x1B680,那麼在還原第0x1B680號動畫的時候,就要使用該圖片所帶的調色板。
隱藏調色板存在於GraphicInfoV3_*.bin中,即使是AnimeInfo_PUK2_*.bin中的動畫也是使用這裡的調色板,從3840幅圖片開始是隱藏調色板,不過並不是全部連續存在的,所以需要判斷,除了寬4高1外,普通圖片的地圖編號高位為0或者3(樂園版本的地圖),調色板的則不是,可以依此辨別。
樂園之卵的動畫也有很大改變,同一類型的各種寵物,以前是各自有獨立的圖片,現在是通過改變調色板來區別的(我認為如果能將玩家角色這樣簡化就好了,寵物反而不應這樣),方向也簡化了,右邊的三個方向是左邊對稱過去的,這是一種偷工減料,不過也減少了文件的體積……同時也導致了數據格式的改變。動畫信息文件中的數據頭結構變化:
字段類型 | 內容 | 說明 |
WORD | 方向號; | 0-7分別表示8個方向 |
WORD | 動作號; | 表示該動作的含義,比如坐下或者走路 |
DWORD | 時間; | 該動作完成一遍所需時間,單位為毫秒 |
DWORD | 幀數; | 該動畫有多少幀,決定後面數據的大小 |
WORD | 調色板號; | 沒完全弄清楚,我不用它來判斷 |
WORD | 反向; | 若為奇數表示該序列的圖片左右反向 |
DWORD | 未知; | 為0xFFFFFFFF,可能是結束符,便於以後再擴充? |
本文分析了CrossGate(魔力寶貝)的文件格式,因為StoneAge(石器時代)和它差不多(最初均為同一小組作品),所以一併介紹。
原文作者為夢見草,由野風信子整理和完善。