在Ogre中实现Mpq文件格式的支持
基于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文件格式的支持相关推荐
- 3D中的OBJ文件格式详解(转载)
OBJ文件是Alias|Wavefront公司为它的一套基于工作站的3D建模和动画软件"Advanced Visualizer"开发的一种标准3D模型文件格式,很适合用于3D软件模 ...
- Blizzard的MPQ文件格式搜索算法---来自Gameres bbs
Blizzard的MPQ文件格式搜索算法 Blizzard被称为最卓越的游戏制作公司,不愧于此. 作者:ghost2006 最近学习了一下Blizzard的MPQ文件格式,颇有一些心得,其中一条就是对 ...
- 3D中的OBJ文件格式详解(转)
常见到的*.obj文件有两种:第一种是基于COFF(Common Object File Format)格式的OBJ文件(也称目标文件),这种格式用于编译应用程序:第二种是Alias|Wavefron ...
- autocad形源代码_在开放源代码库中使用AutoCAD文件格式
autocad形源代码 许多开发人员和地理信息系统(GIS)专业人员无法使用图形交换格式(DXF)或"图形"(DWG)文件. 这些AutoCAD格式通常要求您具有Windows®和 ...
- 图形学基础 | 详解3D中的obj文件格式
详解3D中的obj文件格式 Obj文件格式是一种简单的单独表示3D几何图元的文件格式--也就是,顶点的坐标,每个顶点纹理的UV坐标,顶点法向量,以及组成多边形的面的顶点坐标.以及纹理UV坐标序列. 面 ...
- 5.2.2 视频编辑中常用的文件格式
5.2.2 视频编辑中常用的文件格式 1.AVI文件 AVI是音频视频交错(Audio Video Interleaved)的英文缩写,它是Microsoft公司开发的一种符合RIFF文件规范的数字音 ...
- Fat32文件格式不支持大于4G大文件的问题
Fat32文件格式不支持大于4G大文件,这个问题刚开始不知道,还以为是U盘坏了呢.原先要把NTFS格式转换成 Fat32格式是为了装xp系统用的(盗版用户都知道). 格式化了还是Fat32格式.就出问 ...
- keil obj 文件 结构_3D中的OBJ文件格式详解
常见到的*.obj文件有两种:第一种是基于COFF(Common Object File Format)格式的OBJ文件(也称目标文件),这种格式用于编译应用程序:第二种是Alias|Wavefron ...
- 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 ...
- ACCESS中的Update语句不支持Select的解决办法
ACCESS中的Update语句不支持Select的解决办法执行 比如ACCESS中执行SQL语句: UPDATE HN_news AS a SET typeid = (select clid fro ...
最新文章
- Python3之set, frozenset记录
- Linux 文件基本属性
- bp神经网络_BP 神经网络驱动的手写体数字识别软件 EasyOCR
- sqoop 增量导入mysql_sqoop增量导入数据库
- smb(ms17-010)远程命令执行之msf
- JS跨域控制IFrame高度自适应
- 混合模式商城的可经销商品池
- [JSON].valueOf( keyPath )
- elasticsearch+kibana使用中踩的坑,持续更新中。
- android computescroll_【Android】Scroller分析
- 网易电子邮箱的文档功能是什么?
- 从一名Java初级程序员成长为一名合格的架构师
- 暴力破解带有密码的压缩文件
- Halo博客搭建笔记(以Nginx反向代理 + 负载均衡 + 服务的方式运行Halo博客)
- android开发界面转换,ios界面最省时最简单的办法转换成Android界面 – 学ui网
- Android震动和自定义铃声
- 100以内所有质数的输出。
- Linux系统目录简单说明
- Linux笔记(27)用户与组(8)groupadd命令
- 哈尔滨理工计算机考研真题,哈尔滨理工大学考研真题各专业汇总
热门文章
- 魔兽服务器优化,《魔兽世界》画质与流畅最佳优化指南
- 人物传记:Kyle Tedford:耐心与思考是优秀交易者的必备素质
- Mac电脑动态壁纸怎么设置
- 中国工科研究生200多篇英文论文中最常见的习惯(The Most Common Habits from more than 200 English Papers written by Gradua)
- 打印机扫描显示服务器拒绝访问,怎么解决打印机拒绝访问问题?打印机拒绝访问的解决方法...
- php随机生成18位数,PHP随机生成18位不重复的订单号代码实例
- 以太网协议 | ARP协议详解-ARP报文结构解析
- aho-corasick php,Aho-Corasick自动机浅析
- Ubuntu 安装字体
- 浙江省乡村快递寄件数据分析-快递100百递指数