Neople是一家韩国的游戏公司,地下城勇士DNF就是出自他之手。为了帮弟弟提取DNF创建人物时的漫画,小宝简单地分析了下DNF使用的资源格式。这篇文章是我的分析笔记,完全是凭经验推理出来的,可能不全面的,也可能存在错误,本人不对参考本文而产生的任何问题负责。
作者:leexuany(小宝)
第一部分 解包
DNF使用的资源包是NPK格式,即"NeoplePack"的缩写,于是推测这篇分析也许能用在Neople其他的几款游戏上,呵呵~~。
struct NPK_Header
{
char flag[16]; // 文件标识 "NeoplePack_Bill"
int count; // 包内文件的数目
};
struct NPK_Index
{
DWORD offset; // 文件的包内偏移量
DWORD size; // 文件的大小
char name[256];// 文件名
};
NPK文件就是由一个NPK_Header和N个NPK_Index以及实际的数据组成的。
注:NPK分加密(ImagePacks4文件夹下)和未加密(ImagePacks2文件夹下)的两个版本,加密的版本需要用"puchikon@neople dungeon and fighter DNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNFDNF"(共256字节,最后一字节是'/0')异或文件名部分。
第二部分 格式转换
解包之后得到的文件基本都是".img"格式,但根据文件标识的不同,可分为"Neople Image File"和"Neople Img File"。
【"Neople Image File"的格式】
struct NImageF_Header
{
char flag[24]; // 文件标识 "Neople Image File"
int unknown1; // 未知数据,也许是版本号什么的?
int index_count; // 索引项的数目,也可以理解为包含的小图片的个数。
};
struct NImageF_Index
{
DWORD dwType; // 目前已知的类型有 0x0E(1555格式) 0x0F(4444格式) 0x10(8888格式) 0x11(不包含任何数据,可能是指内容同上一帧)
DWORD dwCompress; // 目前已知的类型有 0x06(zlib压缩) 0x05(未压缩)
int width; // 宽度
int height; // 高度
int size; // 压缩时size为压缩后大小,未压缩时size为转换成8888格式时占用的内存大小
int key_x; // X关键点,当前图片在整图中的X坐标
int key_y; // Y关键点,当前图片在整图中的Y坐标
int max_width; // 整图的宽度
int max_height; // 整图的高度,有此数据是为了对其精灵
BYTE Data[实际长度]; // 紧跟在索引后面的就是实际的数据(将数据放在索引结构中只是为了向大家展示索引与数据的关系。)
};
"Neople Image File"由一个NImageF_Header和N个NImageF_Index结构组成。
注:对于类型0x11其索引表仅包含前2项,即
struct NImageF_Index_0x11
{
DWORD dwType; // 类型0x11
DWORD dwCompress; // 可取很多种数值,作用未知(其中零最为常见)
};
【"Neople Img File"的格式】
struct NImgF_Header
{
char flag[16]; // 文件标识 "Neople Img File"
int index_size; // 以字节为单位,索引表的大小
int unknown1; // 未知1
int unknown2; // 未知2
int index_count;// 索引表项数目
};
struct NImgF_Index
{
DWORD dwType; // 与"NImageF_Index"是一致的,要看注释往上翻。
DWORD dwCompress;
int width;
int height;
int size;
int key_x;
int key_y;
int max_width;
int max_height;
};
"Neople Img File"是由一个NImgF_Header和N个NImgF_Index索引表 + 连续存储的实际数据组成。换句话说就是,"Neople Image File"的索引与自己的数据挨在一起,而"Neople Img File"的索引表和数据是分开存放的。
第三部分 总结
从几个未知数据来看,还不能算是完美的格式分析,实在是遗憾。(现在的网游越加壳越厉害,看来我得再多研究研究脱壳啦。)
不过对于资源提取还是不成问题的。按住惯例上传一张提取图片。