基于StormLib,实现的一个MpqFileSystem,没有写入功能,因为游戏的资源包通常没有读取的需求,打包解包工具网上可以找到很多,就不再推荐了。

#ifndef __Mpq_H__
#define __Mpq_H__#include "OgrePrerequisites.h"#include "OgreArchive.h"
#include "OgreArchiveFactory.h"#include "stormlib/StormLib.h"// Forward declaration for zziplib to avoid header file dependency.namespace Ogre {/** Specialisation of the Archive class to allow reading of files from a zipformat source archive.@remarksThis archive format supports all archives compressed in the standardzip format, including iD pk3 files.*/class _OgreExport MpqArchive : public Archive {protected:/// Handle to root zip fileHANDLE m_hMpq;/// Handle any errors from zzipvoid checkZzipError(int zzipError, const String& operation) const;/// File list (since zziplib seems to only allow scanning of dir tree once)FileInfoList mFileList;public:MpqArchive(const String& name, const String& archType );~MpqArchive();/// @copydoc Archive::isCaseSensitivebool isCaseSensitive(void) const { return false; }/// @copydoc Archive::loadvoid load();/// @copydoc Archive::unloadvoid unload();/// @copydoc Archive::openDataStreamPtr open(const String& filename) const;/// @copydoc Archive::listStringVectorPtr list(bool recursive = true, bool dirs = false);/// @copydoc Archive::listFileInfoFileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false);/// @copydoc Archive::findStringVectorPtr find(const String& pattern, bool recursive = true,bool dirs = false);/// @copydoc Archive::findFileInfoFileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,bool dirs = false);/// new add by lingbo \ to /void stringRightToLeft(String& inputStr) const;/// new add by lingbo / to \void stringLeftToRight(String& inputStr) const;/// @copydoc Archive::existsbool exists(const String& filename);};/** Specialisation of ArchiveFactory for Zip files. */class _OgrePrivate MpqArchiveFactory : public ArchiveFactory{public:virtual ~MpqArchiveFactory() {}/// @copydoc FactoryObj::getTypeconst String& getType(void) const;/// @copydoc FactoryObj::createInstanceArchive *createInstance( const String& name ) {return new MpqArchive(name, "Mpq");}/// @copydoc FactoryObj::destroyInstancevoid destroyInstance( Archive* arch) { delete arch; }};/** Specialisation of DataStream to handle streaming data from zip archives. */class _OgrePrivate MpqDataStream : public DataStream{protected:HANDLE m_hFile;public:/// Unnamed constructorMpqDataStream(HANDLE hFile, size_t uncompressedSize);/// Constructor for creating named streamsMpqDataStream(const String& name, HANDLE hFile, size_t uncompressedSize);~MpqDataStream();/// @copydoc DataStream::readsize_t read(void* buf, size_t count);/// @copydoc DataStream::skipvoid skip(long count);/// @copydoc DataStream::seekvoid seek( size_t pos );/// @copydoc DataStream::seeksize_t tell(void) const;/// @copydoc DataStream::eofbool eof(void) const;/// @copydoc DataStream::closevoid close(void);};
}#endif
#include "OgreStableHeaders.h"#include "OgreMpq.h"#include "OgreLogManager.h"
#include "OgreException.h"
#include "OgreStringVector.h"
#include "OgreRoot.h"#include <zzip/zzip.h>namespace Ogre {//-----------------------------------------------------------------------MpqArchive::MpqArchive(const String& name, const String& archType ): Archive(name, archType), m_hMpq(0){}//-----------------------------------------------------------------------MpqArchive::~MpqArchive(){unload();}//-----------------------------------------------------------------------void MpqArchive::stringLeftToRight(String& inputStr) const{for (String::iterator it = inputStr.begin();it!=inputStr.end(); it++){if ((*it) == '/'){(*it) = '\\';}}}//-----------------------------------------------------------------------void MpqArchive::stringRightToLeft(String& inputStr) const{for (String::iterator it = inputStr.begin();it!=inputStr.end(); it++){if ((*it) == '\\'){(*it) = '/';}}}//-----------------------------------------------------------------------void MpqArchive::load(){if (!m_hMpq){//open mpq Archive into HandleMpqif (SFileOpenArchive(mName.c_str(),0,0,&m_hMpq)){SFILE_FIND_DATA sfd;//PARAM2 NULL表示用MPQ内置的filelist,Param3 "*" find any fileHANDLE hFind = SFileFindFirstFile(m_hMpq,"*",&sfd,NULL);if (hFind){FileInfo info;info.archive  = this;//这一步是把转义字符'\\'换成'/'String tempStr = sfd.cFileName;stringRightToLeft(tempStr);StringUtil::splitFilename(tempStr,info.basename,info.path);info.filename         = tempStr;info.compressedSize   = sfd.dwCompSize;info.uncompressedSize = sfd.dwFileSize;mFileList.push_back(info);while(1){SFILE_FIND_DATA sfdTmp;if (SFileFindNextFile(hFind,&sfdTmp)){FileInfo info;info.archive  = this;String tempStr = sfdTmp.cFileName;stringRightToLeft(tempStr);StringUtil::splitFilename(tempStr,info.basename,info.path);info.filename         = tempStr;info.compressedSize   = sfdTmp.dwCompSize;info.uncompressedSize = sfdTmp.dwFileSize;mFileList.push_back(info);}else{SFileFindClose(hFind);break;}}}}}}//-----------------------------------------------------------------------void MpqArchive::unload(){if (m_hMpq){SFileCloseArchive(m_hMpq);m_hMpq = 0;mFileList.clear();}}//-----------------------------------------------------------------------DataStreamPtr MpqArchive::open(const String& filename) const{String tempStr = filename;stringLeftToRight(tempStr);//打开MPQ中指定的文件名的文件(第3个参数是从指定从MPQ文件中找)HANDLE hFile;if(!SFileOpenFileEx(m_hMpq,tempStr.c_str(),SFILE_OPEN_FROM_MPQ,&hFile)){//如果打开失败则输出到LOG,且返回个空指针LogManager::getSingleton().logMessage(mName + " - Unable to open file " + tempStr + ", error was '" + "'" );return DataStreamPtr();}//得到文件解压缩之后的SIZEDWORD size = SFileGetFileSize(hFile);if (SFILE_INVALID_SIZE ==size){LogManager::getSingleton().logMessage(mName + " - Unable to open file " + tempStr + ", error was '" +"size"+ "'" );SFileCloseFile(hFile);return DataStreamPtr();}//如果得到正确return DataStreamPtr(new MpqDataStream(filename.c_str(),hFile,static_cast<size_t>(size)));}//-----------------------------------------------------------------------StringVectorPtr MpqArchive::list(bool recursive, bool dirs){StringVectorPtr ret = StringVectorPtr(new StringVector());FileInfoList::iterator i, iend;iend = mFileList.end();for (i = mFileList.begin(); i != iend; ++i){if ((dirs == (i->compressedSize == size_t (-1))) &&(recursive || i->path.empty())){ret->push_back(i->filename);}             }return ret;}//-----------------------------------------------------------------------FileInfoListPtr MpqArchive::listFileInfo(bool recursive, bool dirs){FileInfoList* fil = new FileInfoList();FileInfoList::const_iterator i, iend;iend = mFileList.end();for (i = mFileList.begin(); i != iend; ++i){if ((dirs == (i->compressedSize == size_t (-1))) &&(recursive || i->path.empty())){fil->push_back(*i);}}return FileInfoListPtr(fil);}//-----------------------------------------------------------------------StringVectorPtr MpqArchive::find(const String& pattern, bool recursive, bool dirs){StringVectorPtr ret = StringVectorPtr(new StringVector());// If pattern contains a directory name, do a full matchbool full_match = (pattern.find ('/') != String::npos) ||(pattern.find ('\\') != String::npos);FileInfoList::iterator i, iend;iend = mFileList.end();for (i = mFileList.begin(); i != iend; ++i){if ((dirs == (i->compressedSize == size_t (-1))) &&(recursive || full_match || i->path.empty())){// Check basename matches pattern (zip is case insensitive)if (StringUtil::match(full_match ? i->filename : i->basename, pattern, false)){ret->push_back(i->filename);}}}return ret;}//-----------------------------------------------------------------------FileInfoListPtr MpqArchive::findFileInfo(const String& pattern, bool recursive, bool dirs){FileInfoListPtr ret = FileInfoListPtr(new FileInfoList());// If pattern contains a directory name, do a full matchbool full_match = (pattern.find ('/') != String::npos) ||(pattern.find ('\\') != String::npos);FileInfoList::iterator i, iend;iend = mFileList.end();for (i = mFileList.begin(); i != iend; ++i){if ((dirs == (i->compressedSize == size_t (-1))) &&(recursive || full_match || i->path.empty())){// Check name matches pattern (zip is case insensitive)if (StringUtil::match(full_match ? i->filename : i->basename, pattern, false)){ret->push_back(*i);}}                    }return ret;}//-----------------------------------------------------------------------bool MpqArchive::exists(const String& filename){//ZZIP_STAT zstat;//int res = zzip_dir_stat(mZzipDir, filename.c_str(), &zstat, ZZIP_CASEINSENSITIVE);//return (res == ZZIP_NO_ERROR);//目的是如果输入的目录符号是'/'转化成'\\'String tempStr = filename;stringLeftToRight(tempStr);return SFileHasFile(m_hMpq,tempStr.c_str());}//-----------------------------------------------------------------------void MpqArchive::checkZzipError(int zzipError, const String& operation) const{//if (zzipError != ZZIP_NO_ERROR)//{//   String errorMsg = getZzipErrorDescription(static_cast<zzip_error_t>(zzipError));//   OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, //       mName + " - error whilst " + operation + ": " + errorMsg,//     "MpqArchive::checkZzipError");//}}//-----------------------------------------------------------------------//-----------------------------------------------------------------------//-----------------------------------------------------------------------MpqDataStream::MpqDataStream(HANDLE hFile, size_t uncompressedSize): m_hFile(hFile){mSize = uncompressedSize;}//-----------------------------------------------------------------------MpqDataStream::MpqDataStream(const String& name, HANDLE hFile, size_t uncompressedSize):DataStream(name), m_hFile(hFile){mSize = uncompressedSize;}//-----------------------------------------------------------------------MpqDataStream::~MpqDataStream(){close();}//-----------------------------------------------------------------------size_t MpqDataStream::read(void* buf, size_t count){//return zzip_file_read(mZzipFile, (char*)buf, count);if(SFileReadFile(m_hFile,buf,static_cast<DWORD>(count))){return count;}else{return 0;}}//-----------------------------------------------------------------------void MpqDataStream::skip(long count){SFileSetFilePointer(m_hFile,count,NULL,FILE_CURRENT);}//-----------------------------------------------------------------------void MpqDataStream::seek( size_t pos ){SFileSetFilePointer(m_hFile,static_cast<long>(pos),NULL,FILE_BEGIN);}//-----------------------------------------------------------------------size_t MpqDataStream::tell(void) const{return (size_t)SFileSetFilePointer(m_hFile, 0, NULL, FILE_CURRENT);}//-----------------------------------------------------------------------bool MpqDataStream::eof(void) const{DWORD pos = SFileSetFilePointer(m_hFile, 0, NULL, FILE_CURRENT);DWORD size = SFileGetFileSize(m_hFile);return pos>=size;}//-----------------------------------------------------------------------void MpqDataStream::close(void){SFileCloseFile(m_hFile);}//-----------------------------------------------------------------------const String& MpqArchiveFactory::getType(void) const{static String name = "Mpq";return name;}}

在Ogre中实现Mpq文件格式的支持相关推荐

  1. 3D中的OBJ文件格式详解(转载)

    OBJ文件是Alias|Wavefront公司为它的一套基于工作站的3D建模和动画软件"Advanced Visualizer"开发的一种标准3D模型文件格式,很适合用于3D软件模 ...

  2. Blizzard的MPQ文件格式搜索算法---来自Gameres bbs

    Blizzard的MPQ文件格式搜索算法 Blizzard被称为最卓越的游戏制作公司,不愧于此. 作者:ghost2006 最近学习了一下Blizzard的MPQ文件格式,颇有一些心得,其中一条就是对 ...

  3. 3D中的OBJ文件格式详解(转)

    常见到的*.obj文件有两种:第一种是基于COFF(Common Object File Format)格式的OBJ文件(也称目标文件),这种格式用于编译应用程序:第二种是Alias|Wavefron ...

  4. autocad形源代码_在开放源代码库中使用AutoCAD文件格式

    autocad形源代码 许多开发人员和地理信息系统(GIS)专业人员无法使用图形交换格式(DXF)或"图形"(DWG)文件. 这些AutoCAD格式通常要求您具有Windows®和 ...

  5. 图形学基础 | 详解3D中的obj文件格式

    详解3D中的obj文件格式 Obj文件格式是一种简单的单独表示3D几何图元的文件格式--也就是,顶点的坐标,每个顶点纹理的UV坐标,顶点法向量,以及组成多边形的面的顶点坐标.以及纹理UV坐标序列. 面 ...

  6. 5.2.2 视频编辑中常用的文件格式

    5.2.2 视频编辑中常用的文件格式 1.AVI文件 AVI是音频视频交错(Audio Video Interleaved)的英文缩写,它是Microsoft公司开发的一种符合RIFF文件规范的数字音 ...

  7. Fat32文件格式不支持大于4G大文件的问题

    Fat32文件格式不支持大于4G大文件,这个问题刚开始不知道,还以为是U盘坏了呢.原先要把NTFS格式转换成 Fat32格式是为了装xp系统用的(盗版用户都知道). 格式化了还是Fat32格式.就出问 ...

  8. keil obj 文件 结构_3D中的OBJ文件格式详解

    常见到的*.obj文件有两种:第一种是基于COFF(Common Object File Format)格式的OBJ文件(也称目标文件),这种格式用于编译应用程序:第二种是Alias|Wavefron ...

  9. anaconda新建python2环境安装不了jupyterlab_Anaconda 5.0.0 JupyterLab 0.27.0 中配置多Python环境支持...

    Anaconda 5.0.0 JupyterLab 0.27.0 中配置多Python环境支持 概述 Anaconda 5.0.0 中自带了 JupyterLab 0.27.0 版本,这是 Anaco ...

  10. ACCESS中的Update语句不支持Select的解决办法

    ACCESS中的Update语句不支持Select的解决办法执行 比如ACCESS中执行SQL语句: UPDATE HN_news AS a SET typeid = (select clid fro ...

最新文章

  1. Python3之set, frozenset记录
  2. Linux 文件基本属性
  3. bp神经网络_BP 神经网络驱动的手写体数字识别软件 EasyOCR
  4. sqoop 增量导入mysql_sqoop增量导入数据库
  5. smb(ms17-010)远程命令执行之msf
  6. JS跨域控制IFrame高度自适应
  7. 混合模式商城的可经销商品池
  8. [JSON].valueOf( keyPath )
  9. elasticsearch+kibana使用中踩的坑,持续更新中。
  10. android computescroll_【Android】Scroller分析
  11. 网易电子邮箱的文档功能是什么?
  12. 从一名Java初级程序员成长为一名合格的架构师
  13. 暴力破解带有密码的压缩文件
  14. Halo博客搭建笔记(以Nginx反向代理 + 负载均衡 + 服务的方式运行Halo博客)
  15. android开发界面转换,ios界面最省时最简单的办法转换成Android界面 – 学ui网
  16. Android震动和自定义铃声
  17. 100以内所有质数的输出。
  18. Linux系统目录简单说明
  19. Linux笔记(27)用户与组(8)groupadd命令
  20. 哈尔滨理工计算机考研真题,哈尔滨理工大学考研真题各专业汇总

热门文章

  1. 魔兽服务器优化,《魔兽世界》画质与流畅最佳优化指南
  2. 人物传记:Kyle Tedford:耐心与思考是优秀交易者的必备素质
  3. Mac电脑动态壁纸怎么设置
  4. 中国工科研究生200多篇英文论文中最常见的习惯(The Most Common Habits from more than 200 English Papers written by Gradua)
  5. 打印机扫描显示服务器拒绝访问,怎么解决打印机拒绝访问问题?打印机拒绝访问的解决方法...
  6. php随机生成18位数,PHP随机生成18位不重复的订单号代码实例
  7. 以太网协议 | ARP协议详解-ARP报文结构解析
  8. aho-corasick php,Aho-Corasick自动机浅析
  9. Ubuntu 安装字体
  10. 浙江省乡村快递寄件数据分析-快递100百递指数