📄 mpq_libmpq.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 + -