一、打包格式 CPK

CPK Packaging Format


概述

CPK 是仙剑三、仙剑三外传和仙剑四使用的打包格式。CPK 打包格式支持保留完整的目录结构,支持文件压缩。仙剑三所使用的 CPK 打包文件没有任何的加密措施,而仙剑四则加入了简易的加密方式。CPK 文件整体格式如下:

内容类型
CPK 文件头CpkHeader
节点表CpkTable
文件数据...

其中 CPK 文件头中包含了 CPK 文件的元信息,诸如版本、文件节点数量、文件数量、节点表起始位置、文件数据其实位置等等。节点表中包含了所有节点的元信息,每个目录和文件都是节点表中的一项,它描述了文件数据的起始位置、文件的原始大小、压缩后大小、父节点、文件路径的 CRC32 值等等。值得一提的是文件路径的 CRC32 值是节点的唯一标识符,在节点表中也会使用父目录的路径 CRC32 值指定父节点。需要注意的是,CRC32 算法在 CRC 多项式表以及异或方式上有很多变种,在仙剑中的具体计算方式参见 crc.rs

虽然 CPK 文件保留了目录结构,但是在游戏读取文件时,并不会真的生成层次化的目录结构,而是通过计算文件完整路径的 CRC32 值后查表得到对应的文件节点。例如,当游戏需要读取一个 CPK 文件包中的 musiuc\P01.mp3 文件时,首先会对字符串 "music\P01.mp3" 计算 CRC32 值,随后在节点表中查找该 CRC32 值对应的文件节点,从而得到文件的起始位置和大小。

CPK 包内文件可以被压缩,如果文件原始大小和压缩后大小不等则可判定其已被压缩,压缩算法为 LZO1X。可使用 minilzo 库进行解压。

CPK 文件可能会存在被加密的部分,可以通过文件头中的 data_start 字段的值是否为 0x00100080 来判断。如果存在加密部分,则自 CPK 文件头之后的 0x1000 个字节采用 xxtea 算法加密,解密密钥为字符串 "Vampire.C.J at Softstar Technology (ShangHai) Co., Ltd"。

妖弓源文件https://github.com/dontpanic92/OpenPAL3/blob/master/yaobow/shared/src/fs/cpk/cpk_archive.rs

参考资料

文件格式描述

CPK 文件头 CpkHeader

字段类型
labelu32
versionu32
table_startu32
data_startu32
max_file_numu32
file_numu32
is_formattedu32
size_of_headeru32
valid_table_numu32
max_table_numu32
fragment_numu32
package_sizeu32
reserved[u32; 20]

节点表 CpkTable

字段类型说明
crcu32文件路径的 CRC32 值
flagu32
father_crcu32父节点路径的 CRC32 值
start_posu32文件数据起始位置
packed_sizeu32压缩后大小
origin_sizeu32原始大小
extra_info_sizeu32用于存放额外数据,例如文件名