本文章原文來自 http://www.fanicer.com/gallery/FileFmt.htm
以下內容沒有任何刪減及添加,本頁目的是讓更多人看到此文章。
若有任何版權問題,請到留言版留言。

下文分析了CrossGate(魔力寶貝)的文件格式,因為StoneAge(石器時代)和它差不多(最初均為同一小組作品),所以一併介紹。
原文作者為夢見草,由野風信子整理和完善。

一.圖片數據
二.動畫信息
三.地圖格式
四.壓縮算法
五.調色板
六.各版本對應的文件
七.後續版本的改動
一.圖片數據
圖片地址文件
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字節,具體不清楚,只知道對會引起地圖切換的地方有標識

地圖是45度視角的四邊形,數據的存放順序是從東到西,由南至北,起點為左邊角(東0,南0)。
假設讀入的3X3地圖數據順序為123456789,對應的地圖顯示:
3
2 6
1 5 9
4 8
7

這樣讀出來的數據是地圖編號,在圖片數據中說過,圖片地址文件的每一條記錄的最後一個字段就是地圖編號,現在就是根據這個編號反查出對應的圖片序號,將它顯示出來,由於遊戲本身沒有地圖索引文件(那是在運行遊戲的時候生成的),所以要自制一份方便查找,這裡要注意的是地圖編號並不是連貫的,比如StoneAge最大的編號為41000,實際上用到的只有1萬多點,中間有很多編號是未使用的。

前面說過,每個圖片都有偏移量用於對齊,畫地圖的時候也需要的,不過這裡有點問題,若只是將偏移量加上坐標,地面沒有問題,而建築物縱坐標則會錯位,我並不知道正確的做法,我是這樣處理的:
假設縱坐標偏移量為y,圖片高度h,要畫的坐標為y0,那麼實際的坐標y1就是
y1=y0+h-47+y
47是一個單位地面的高度(所以地面不必這樣處理,因為h-47=0),這樣做可以基本對齊,希望有朋友提供更標準的方法。

另外,關於縮略圖,就是將每個單位(佔地面積1X1)縮成如下的四個點:
 □
□□□
如果一個物件面積為2X1,那麼就是
   □
 □□□□
□□□
縮略圖中每個圖片都只用一種顏色表示,而這個顏色好像也是遊戲自動生成的,所以要做縮略圖的話,自己要製作一份顏色表。


四.壓縮算法

這是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-15號色
顏色號 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)

240-255號色
顏色號 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,可能是結束符,便於以後再擴充?

要提取樂園之卵後的圖片和動畫,就必須用以上新的格式。地圖的格式本身沒有變化,不過增加了附屬的文件,主要是和圖片分割有關…… 目前沒有研究,所以沒有資料了。