⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpq_libmpq.cpp

📁 wowmodelview魔兽世界的模型查看工具。下了看看吧
💻 CPP
字号:
#include "mpq_libmpq.h"

#include <wx/log.h>
#include <wx/file.h>

#include <vector>

#include "util.h"

typedef std::vector<mpq_archive*> ArchiveSet;
ArchiveSet gOpenArchives;

MPQArchive::MPQArchive(const char* filename)
{
	int result = libmpq_archive_open(&mpq_a, (unsigned char*)filename);
	wxLogMessage("Opening %s", filename);
	if(result) {
		wxLogMessage("Error opening archive %s", filename);
		return;
	}
	gOpenArchives.push_back(&mpq_a);
}

MPQArchive::~MPQArchive()
{
	/*
	for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
	{
		mpq_archive &mpq_a = **i;
		
		free(mpq_a.header);
	}
	*/
	//gOpenArchives.erase(gOpenArchives.begin(), gOpenArchives.end());
}

void MPQArchive::close()
{
	libmpq_archive_close(&mpq_a);
	for(ArchiveSet::iterator it=gOpenArchives.begin(); it!=gOpenArchives.end();++it)
	{
		mpq_archive &mpq_b = **it;
		if (&mpq_b == &mpq_a) {
			gOpenArchives.erase(it);
			return;
		}
	}
	
}

MPQFile::MPQFile(const char* filename):
	eof(false),
	buffer(0),
	pointer(0),
	size(0)
{
	if( useLocalFiles ) {
		wxString fn;

		fn = gamePath;
		fn.Append(filename);

		if (wxFile::Exists(fn.fn_str())) {
			// success
			wxFile file;
			// if successfully opened
			if (file.Open(fn.fn_str(), wxFile::read)) {
				size = file.Length();
				if (size > 0) {
					buffer = new unsigned char[size];
					// if successfully read data
					if (file.Read(buffer, size) > 0) {
						eof = false;
						return;
					} else {
						delete [] buffer;
						buffer = 0;
						eof = true;
						size = 0;
					}
				}
			}
		}
	}

	for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end(); ++i)
	{
		mpq_archive &mpq_a = **i;
		int fileno = libmpq_file_number(&mpq_a, filename);
		if(fileno == LIBMPQ_EFILE_NOT_FOUND)
			continue;

		// Found!
		size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, fileno);

		// HACK: in patch.mpq some files don't want to open and give 1 for filesize
		if (size<=1) {
			eof = true;
			buffer = 0;
			return;
		}

		buffer = new unsigned char[size];
 		libmpq_file_getdata(&mpq_a, fileno, buffer);
		return;
	}

	eof = true;
	buffer = 0;
}

MPQFile::~MPQFile()
{
	close();
}

bool MPQFile::exists(const char* filename)
{
	if( useLocalFiles ) {
		wxString fn = gamePath;
		fn.Append(filename);
		if (wxFile::Exists(fn.fn_str()))
			return true;
	}

	for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
	{
		mpq_archive &mpq_a = **i;
		int fileno = libmpq_file_number(&mpq_a, filename);
		if (fileno != LIBMPQ_EFILE_NOT_FOUND) 
			return true;
	}

	return false;
}

size_t MPQFile::read(void* dest, size_t bytes)
{
	if (eof) 
		return 0;

	size_t rpos = pointer + bytes;
	if (rpos > size) {
		bytes = size - pointer;
		eof = true;
	}

	memcpy(dest, &(buffer[pointer]), bytes);

	pointer = rpos;

	return bytes;
}

bool MPQFile::isEof()
{
    return eof;
}

void MPQFile::seek(int offset)
{
	pointer = offset;
	eof = (pointer >= size);
}

void MPQFile::seekRelative(int offset)
{
	pointer += offset;
	eof = (pointer >= size);
}

void MPQFile::close()
{
	if (buffer) 
		delete [] buffer;
	buffer = NULL;
	eof = true;
}

size_t MPQFile::getSize()
{
	return size;
}

size_t MPQFile::getPos()
{
	return pointer;
}

unsigned char* MPQFile::getBuffer()
{
	return buffer;
}

unsigned char* MPQFile::getPointer()
{
	return buffer + pointer;
}

void getFileLists(std::set<std::string> &dest, bool filterfunc(std::string))
{
	for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
	{
		mpq_archive &mpq_a = **i;
		int fileno = libmpq_file_number(&mpq_a, "(listfile)");
		
		if(fileno != LIBMPQ_EFILE_NOT_FOUND) {
			// Found!
			size_t size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, fileno);
			int retVal = libmpq_file_info(&mpq_a, LIBMPQ_FILE_COMPRESSION_TYPE, fileno);

			// TODO: Add handling for uncompressed files.
			//if () {
			if (size > 0 && retVal != 0) {
				unsigned char *buffer = new unsigned char[size];
				libmpq_file_getdata(&mpq_a, fileno, buffer);
				unsigned char *p = buffer, *end = buffer + size;

				while (p <= end) {
					unsigned char *q=p;
					do {
						if (*q==13) 
							break;
					} while (q++<=end);

					wxString line(p,q-p);
					if (line.Length()==0) 
						break;
					//p += line.length();
					p = q + 2;
					//line.erase(line.length()-2, 2); // delete \r\n

					if (filterfunc(line.c_str())) {
						bool bFirst = true;
						
						// This is just to help cleanup Duplicates
						// Ideally I should tokenise the string and clean it up automatically
						/*
						for (std::set<string>::iterator it=dest.begin(); it!=dest.end(); ++it) {
							if (line.IsSameAs(it->c_str(), false)) {
								bFirst = false;
								break;
							}
						}
						*/
						
						if (bFirst) {
							if (line.Mid(0,9) == "CHARACTER") {
								line.replace(0,9,"Character");

								if (line.Mid(10,8) == "NIGHTELF") {
									line.replace(10, 8, "NightElf");
									line.replace(19, 4, "Male");									
								}
							}

							if (line.Mid(0,8) == "CREATURE")
								line.replace(0, 8, "Creature");

							if (line.Mid(0,4) == "ITEM")
								line.replace(0, 4, "Item");

							if (line.Mid(0,6) == "SPELLS")
								line.replace(0, 6, "Spells");

							if (line.Mid(0,6) == "spells")
								line.replace(0, 6, "Spells");

							//dest.push_back(line);
							dest.insert(line);
						}
					}
				}
				
				delete[] buffer;
				p = NULL;
				end = NULL;
			}
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -