Diablo II 的DC6图像文件格式
经过n天的细心研究,并且参考了一些E文资料和源程序。终于……(^_^哈哈哈哈哈哈哈,我真是天才啊!接下来就是一阵鸡飞蛋打!惨!)。算了,还是开门见山吧!
简单的来说,DC6文件主要分为3部分:
1. 文件头(24字节);
2. 图像帧在DC6文件中的指针索引(大小还得由文件头的一些数据来确定);
3. 图像帧数据(包括帧头(32字节)和经过编码了的图像帧数据(大小由帧头的一个数据决定));
下面我们就分别来简单地了解一下DC6文件的三部分:
一. 文件头
C语言原型:
typedef struct
{
long version; // 06 00 00 00
long unknown1; // 01 00 00 00
long unknown2; // 00 00 00 00
UBYTE termination[4]; // EE EE EE EE or CD CD CD CD
long directions; // xx 00 00 00
long frames_per_dir; // xx 00 00 00
} DC6_HEADER_S;
下面是mptrlitghhth.dc6的文件头(24字节):
00000000h: 06 00 00 00 01 00 00 00 00 00 00 00 EE EE EE EE ; ............铑铑
1. 2. 3. 4.
00000010h: 08 00 00 00 06 00 00 00 ; ........
5. 6.
这里:
1. version 这是DC6的版本号,一般都为06 00 00 00;
2. unknown1 未知,一般为01 00 00 00;
3. unknown2 未知,一般为00 00 00 00;
4. termination[4] 一般为EE EE EE EE或CD CD CD CD;
5. direction 这是帧集合数目;
6. frames_per_dir 每个帧集合包含的帧数
二. 帧指针索引
有了文件头的数据,我们就可以计算出图像帧指针索引表的大小了,以及这个DC6文件中有多少帧图像了。在mptrlitghhth.dc6中有8个direction(帧集合数目),而每个direction中又有6个图像帧(Frame)。那么整个mptrlitghhth.dc6中就有direction*frames_Per_frm=48帧图像。而图像帧指针索引表的大小就有48*sizeof(long)。
接下来就是mptrlitghhth.dc6图像帧指针索引表:
00000010h: 08 00 00 00 06 00 00 00 D8 00 00 00 EC 0F 00 00 ; ........?..?..
00000020h: F3 1E 00 00 A6 2E 00 00 A8 3E 00 00 0A 4E 00 00 ; ?..?..?...N..
00000030h: DF 5C 00 00 B6 6B 00 00 51 79 00 00 B2 86 00 00 ; 運..秌..Qy..矄..
00000040h: 79 94 00 00 DF A2 00 00 C6 B1 00 00 BE C0 00 00 ; y?.撷..票..纠..
00000050h: 49 D0 00 00 8A DF 00 00 E5 EE 00 00 FE FD 00 00 ; I?.娺..孱....
00000060h: F7 0C 01 00 8E 1B 01 00 A7 27 01 00 4B 34 01 00 ; ?..?..?..K4..
00000070h: 1B 42 01 00 9A 50 01 00 17 5F 01 00 AA 6F 01 00 ; .B..歅..._..猳..
00000080h: C4 7F 01 00 86 90 01 00 F7 A1 01 00 44 B3 01 00 ; ?..啇..鳌..D?.
00000090h: B7 C3 01 00 54 CF 01 00 4A DA 01 00 3E E6 01 00 ; 访..T?.J?.>?.
000000a0h: 2B F2 01 00 56 FD 01 00 F0 08 02 00 22 19 02 00 ; +?.V?.?.."...
000000b0h: BE 28 02 00 2D 38 02 00 DC 47 02 00 C2 57 02 00 ; ?..-8..蹽..耊..
000000c0h: 25 68 02 00 CE 73 02 00 4E 80 02 00 27 8D 02 00 ; %h..蝧..N€..'?.
000000d0h: 54 99 02 00 FD A3 02 00 ; T?...
这里第一个指针D8 00 00 00指向文件mptrlitghhth.dc6中000000d8h的地方,就是第一个帧集合的第一帧图像开始的地方;同理第二个指针EC 0F 00 00就指向文件mptrlitghhth.dc6中00000fech的地方,就是第一个帧集合的第二帧图像开始的地方;紧接着就是第一个帧集合的第三帧图像的指针了,一直到第八个帧集合的第六帧图像的指针而结束。
三. 帧数据
一帧图像的数据,包括两个部分:
1) 帧头(32字节);
C语言原型:
typedef struct
{
long flip;
long width;
long height;
long offset_x;
long offset_y; // from bottom border, not up
long unknown;
long next_block;
long length;
} DC6_FRAME_HEADER_S;
下面是第一个帧集合的第一帧图像的帧头:
000000d0h: 54 99 02 00 FD A3 02 00 00 00 00 00 31 00 00 00 ; T?.......1...
1. 2.
000000e0h: A9 00 00 00 EF FF FF FF 03 00 00 00 00 00 00 00 ; ?..???........
3. 4. 5. 6.
000000f0h: EC 0F 00 00 F1 0E 00 00 ; ?..?..
7. 8.
这里:
1. flip 一个标志,为00 00 00 00图像是由下往上显示的,为为01 00 00 00则反之;
2. width 这一帧图像中有用数据所在的矩形区域的宽度;
3. height 同上;
4.
offset_x 怎么说呢?首先我们将一个帧集合的所有图像帧一张张的摆放在一定的位置,并且按照一定的顺序叠放在一起,最后我们用一颗钉子在适当的位置将这些图象帧钉起来,这样就可以使的顺序播放这些图象帧所形成的动画就不会出现偏差了。那么,我们将钉钉子的位置设为原点,向右设为x的正方向,而向下就设为y的正方向,那么这一帧图像的左下角的坐标就在这个坐标原点的(offset_x,offset_y)上。为什么这样做,是由于DC6各帧的图像尺寸大小是不一样的!
原始图像
“钉”好了的图像
5. offset_y 同上;
6. unknown 未知;
7. next_block 指向下一个图像帧的指针;
8. length 这一帧图像的有用数据经过编码后的长度;
2) 经过编码了的图像数据;
首先,必须了解一下一个很重要的字节,那就是0x80。这个字符在图像数据中是作为换行符来用,也就是换行的标志。接下来,我们就从图像数据的第一个字节取得一个字节BYTE:
if BYTE = 0x80, 本行结束, 将光标移到下一行首
else
if BYTE & 0x80 (判断该字节的第7位是否是1) then 向内存写入BYTE & 0x7F (就是取BYTE的低 7位)个透明象素(这个透明象素还不知道从哪里得到啊!)。
else 读取文件中接下来的BYTE个数据,并写入内存。
如此反复,直至将这一帧的length个字节读取完。需要说明,如果遇到了0x80,而一行像素还未填满,就要用透明色将其填满。两帧数据之间用三个字符(EE EE EE)来分隔开。DC6的一帧图像的最大高宽是256*256。
最后,说明一下DiabloII的调色板,据我在一份E文资料上看到的,不同的场景下使用了不同的调色板!部分原文是这样的:
act1 : act 1 stuffs & inventory gfx
act2 : act 2 stuffs & inventory gfx
act3 : act 3 stuffs & inventory gfx
act4 : act 4 stuffs & inventory gfx
act5 : act 5 stuffs & inventory gfx
endgame : ending screen (Talrasha giving you honorific title)
endgame2 : ending screen (Cain giving you honorific title)
fechar : character creation screen
loading : loading screen (the Wanderer in front of the Monastery doors)
menu0 : Beta screenshot # 1
menu1 : Beta screenshot # 2
menu2 : Beta screenshot # 3
menu3 : Beta screenshot # 4
menu4 : Beta screenshot # 5
sky : game selection screen
static : all GUI (Graphic User Interface) stuff (get some random results)
trademark : trademark screen
units : all the GUI icons (but in has been succefully used for the
trademark screen, game select & Gui stuff, without distorsion)
而具体什么DC6文件使用什么调色板,那就要看一看DiabloII的资源MPQ文件里的一些信息了!另外,DiabloII的调色板文件的是以BGR格式来储存的,而并非RGB格式。
^_^瞎编乱写,如有错误请与我联系。E-mail:a-rice@21cn.com QQ:23271576