lihuiba

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  5 随笔 :: 1 文章 :: 1 评论 :: 0 Trackbacks
MPQ文件是暴雪公司的一种私有文档打包格式,广泛应用在其游戏产品中,如魔兽争霸系列、星际争霸系列等、暗黑破坏神系列以及魔兽世界等。MPQ包内保存了几乎全部的游戏资源,包括模型、纹理、材质、动画、音频、视频、单位属性等等。除了游戏资源之外,这些游戏的地图、战役以及一些游戏的进度存档也是都MPQ格式,只是扩展名用了其他的标识。MPQ文档兼具打包和压缩的功能,并且其压缩算法可以根据具体文件格式而有所不同。例如,根据StormLib源代码结构信息,MPQ包至少支持bzip2、huffman、pklib以及一种专门针对wav格式的压缩算法。

MPQ是一种针对读取优化的文档,与其他格式(如zip)相比,它最大的特点是没有树形结构,甚至连文件名都不保存。在存取时,它将文件的全路径名称做两次不同的哈希:h1 = hash1(pathname)、h2 = hash2(pathname),并将这两个哈希值作为索引信息。由于将路径文件名整体作为字符串计算哈希值,整个MPQ包构成平板模式,在物理上没有目录结构。在检索文件时,由于不需要逐级深入目录,MPQ包的读取较为简洁高效。

MPQ是一种古老的包格式,现有许多第三方工具可以读写这种格式,其中很多都公布了源代码,甚至形成了专门的读写库。我找到的各个MPQ相关库总结如下:

名称(标配工具)

作者

备注

Storm.dll

Blizzard

Diablo I附带的Storm.dll可被其他工具调用。

StormLess MPQ Editor

Tom Amigo

提供VC6源代码。最新版本发布与2000年。

StormLib

(MPQEditor)

Ladislav Zezula

由Marko Friedemann将其移植到Linux平台。

Libmpq

(MPQ-tools)

Maik Broemme

似乎只支持Linux。

SFmpq.dll

(WinMPQ)

ShadowFlare Software

SFmpq.dll由VC++编写,WinMPQ应用由VB4编写。

MPQlib

(MPQMaster)

Quixotic Yawl Studio

没有找到源代码,不过从它暴露的语言扩展接口来看,似乎是Delphi写的。

Ladislav Zezula同志的StormLib成为使用毫无疑问是Windows平台下C++程序访问MPQ包的最佳选择。我将StormLib的使用心得以要点形式总结如下:

1. 所有的API函数、常量定义、结构体定义都可以在StormLib.h中查到,Zezula的主页上也有大部分函数的介绍,在此就不copy & paste了。

2. 读取文件所需函数:SFileOpenArchive()、SFileCloseArchive()分别为打开、关闭MPQ文件;SFileOpenFileEx()、SFileCloseFile()分别为打开、关闭MPQ包中的文件;SFileReadFile()读取实际数据,隐含解压缩过程。

3. 一个关于FilePointer的小陷阱:SFileSetFilePointer()函数用于设置文件指针,类似于C标准库中的fseek()函数,然而SFileGetFilePos()并不是返回文件指针,而是返回该文件在MPQ包中的物理位置。要得到当前文件指针位置,仍然需要SFileSetFilePointer()函数,将文件指针相对当前位置移动0,其返回值则为当前指针位置,如:

virtual size_t tell() const
{
	return (size_t)SFileSetFilePointer(m_hFile, 0, NULL, FILE_CURRENT);
}
4. StormLib没有提供feof()之类的调用,可以用当前文件指针与文件大小进行比较得到,如
virtual bool eof() const 
{
	DWORD pos = SFileSetFilePointer(m_hFile, 0, NULL, FILE_CURRENT);
	DWORD size = SFileGetFileSize(m_hFile);
	return pos>=size;
}

5. StormLib还提供了创建MPQ包、写入文件、包内搜索文件等功能,本文从略。

posted on 2009-09-23 22:49 lihuiba 阅读(4996) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理