龙之谷PAK资源文件格式说明及资源打包程序
实际上我没玩过龙之谷这游戏,这篇东西的出现其实是某人要我为这个资源文件写一个打包程序。网上只有资源文件提取工具,而没有资源文件打包程序。这种资源文件的格式在网上也有说明,但是我看那些说明太乱了,其重点似乎是在如何分析这个文件的结构,而不是描述这个文件的结构。既然我弄了这个打包工具出来,就顺便描述一下资源文件格式好了。
为了方便说明,我依照网上给出这个文件格式说明的那篇文章的约定,把被打包成资源文件的那些文件,称为虚拟文件。
另外,本文中出现的“偏移地址”,如果没有特殊说明,都是指从文件头开始计算的偏移地址。文件的虚拟路径指在资源文件中指定的虚拟文件的路径。
资源文件整体结构
资源文件由三个部份组成,首先是文件头,接着是虚拟文件内容,最后是虚拟文件信息。
文件头部分大小是固定的,为1024字节。在这1KB的长度中只有很少一部分被使用。
虚拟文件内容部分,保存着所有虚拟文件的内容。虚拟文件内容是经过压缩的,压缩的时候按照单个文件分别压缩。
文件信息部分包含所有虚拟文件的信息,包括原始文件大小,压缩后大小,文件的虚拟路径等。
文件头部分
在西语言中为文件头定义结构体如下:
view plaincopy to clipboardprint?
- typedefstruct pak_info_t {
- charhead[256];
- unsigned charstatic1[4]; // 意义不明的固定字节
- unsigned intfile_num; // 文件总数
- unsigned intfilelist_offset; // 文件信息偏移地址
- } pak_info_t;
文件头开头的256个字节是一个字符串,这个字符串的值是固定的,恒为:
view plaincopy to clipboardprint?
- “EyedentityGames Packing File 0.1”
程序会根据用户给出的目录(必须是相对路径),遍历目录下的文件,然后将文件信息保存到一个链表中。接着调用zlib一次
接下来的4个字节是一个意义不明的东西。可以认为这四个字节是一个长度为4的字符数组,也可以认为这是一个整型。其值也是固定的,第一个字节可以是0x0B或0x0A,后面三个字节恒为0×00.
再接下来的4个字节是一个无符号整型,记录资源文件中虚拟文件的总数。
最后的四个字节是一个指针,指向资源文件的虚拟文件信息部分的地址。由于虚拟文件信息紧跟着虚拟文件内容,而虚拟文件内容的长度是不定的,所以这个偏移地址也是不定的。故我们需要在写完了虚拟文件内容,确定了虚拟文件信息的偏移地址以后,才能回过头来填写这个值。
注意,前面说过,文件头的大小是固定的,长度是1024字节,而我们定义的这个文件头结构体只有268字节,还差756个字节才够1024字节。实际上,对这个地方可以有两种理解。一种理解是,文件头除了前面的268字节外,后面还有一块长度为756字节的空白区域。另一种理解是,文件头虽然只使用了268字节,但是文件内容必须从0×400位置开始。两种理解都是同样的描述,就看喜欢哪种了。
虚拟文件内容部分
虚拟文件内容从0×400位置开始。首先将每一个虚拟文件的原始文件压缩,然后将压缩后的内容从0×400开始依次写入文件。每个文件内容之间没有空隙,要紧凑地存放。图示如下:
文件的内容是按照单个文件进行压缩的。使用的压缩方法是zlib,压缩级别为1,也就是最快压缩。
文件信息部分
文件信息部分的总体结构和虚拟文件内容部分相似,每个文件都有一个固定大小的文件描述块,长度为316字节,图示如下:
在西语言中定义结构体为:
view plaincopy to clipboardprint?
- typedefstruct pak_file_info_t {
- charpath[256];
- unsigned intzip_size; // 原始文件大小
- unsigned intsize; // 压缩后的文件大小
- unsigned intzip_size1; // 原始文件大小,和size一样
- unsigned intoffset; // 文件内容偏移地址
- charempty[44]; //填充用
- } pak_file_info_t;
开头的256字节是虚拟文件的虚拟路径。虚拟路径似乎必须以“\”开头,而且不能使用“/”。
接下来的4个字节是一个无符号整型,是虚拟文件对应的原始文件的大小。
再接下来的4个字节是一个无符号整型,是虚拟文件对应的原始文件内容压缩后的大小。
再接着的4个字节是一个无符号整型,和第二个成员一样,也是原始文件内容的大小。
接着的4个字节是一个指针,指向这个虚拟文件的内容的偏移地址。
最后的44个字节是没有意义的,或者说可能是保留用的,总之留出空间即可,其他的不用理会。
这就是一个虚拟文件的描述块,每个虚拟文件的描述块依次紧凑存放。用西语言来描述可以是这个样子的:
view plaincopy to clipboardprint?
- pak_file_info_t fileinfo[n]; //共有n个虚拟文件
- /* 在这里设置这些虚拟文件的信息*/
- fwrite(fileinfo, sizeof(pak_file_info_t), n, fp);
打包程序
程序会根据用户给出的目录(必须是相对路径),遍历目录下的文件,然后将文件信息保存到一个链表中。接着调用zlib依次压缩和保存文件,记录文件的偏移地址和压缩后的大小。完成以后就继续写入文件信息块。最后回头写入文件头。
只有源码,在Linux下编译通过。
pakpack.c
暂无评论内容