aboutsummaryrefslogtreecommitdiff
path: root/contrib/extractor/mpq_libmpq.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/extractor/mpq_libmpq.cpp')
-rw-r--r--contrib/extractor/mpq_libmpq.cpp133
1 files changed, 133 insertions, 0 deletions
diff --git a/contrib/extractor/mpq_libmpq.cpp b/contrib/extractor/mpq_libmpq.cpp
new file mode 100644
index 00000000000..98d114c572f
--- /dev/null
+++ b/contrib/extractor/mpq_libmpq.cpp
@@ -0,0 +1,133 @@
+#include "mpq_libmpq.h"
+#include <deque>
+
+ArchiveSet gOpenArchives;
+
+MPQArchive::MPQArchive(const char* filename)
+{
+ int result = libmpq_archive_open(&mpq_a, (unsigned char*)filename);
+ printf("Opening %s\n", filename);
+ if(result) {
+ switch(result) {
+ case LIBMPQ_EFILE : /* error on file operation */
+ printf("Error opening archive '%s': File operation Error\n", filename);
+ break;
+ case LIBMPQ_EFILE_FORMAT : /* bad file format */
+ printf("Error opening archive '%s': Bad file format\n", filename);
+ break;
+ case LIBMPQ_EFILE_CORRUPT : /* file corrupt */
+ printf("Error opening archive '%s': File corrupt\n", filename);
+ break;
+ case LIBMPQ_EFILE_NOT_FOUND : /* file in archive not found */
+ printf("Error opening archive '%s': File in archive not found\n", filename);
+ break;
+ case LIBMPQ_EFILE_READ : /* Read error in archive */
+ printf("Error opening archive '%s': Read error in archive\n", filename);
+ break;
+ case LIBMPQ_EALLOCMEM : /* maybe not enough memory? :) */
+ printf("Error opening archive '%s': Maybe not enough memory\n", filename);
+ break;
+ case LIBMPQ_EFREEMEM : /* can not free memory */
+ printf("Error opening archive '%s': Cannot free memory\n", filename);
+ break;
+ case LIBMPQ_EINV_RANGE : /* Given filenumber is out of range */
+ printf("Error opening archive '%s': Given filenumber is out of range\n", filename);
+ break;
+ case LIBMPQ_EHASHTABLE : /* error in reading hashtable */
+ printf("Error opening archive '%s': Error in reading hashtable\n", filename);
+ break;
+ case LIBMPQ_EBLOCKTABLE : /* error in reading blocktable */
+ printf("Error opening archive '%s': Error in reading blocktable\n", filename);
+ break;
+ default:
+ printf("Error opening archive '%s': Unknown error\n", filename);
+ break;
+ }
+ return;
+ }
+ gOpenArchives.push_front(this);
+}
+
+void MPQArchive::close()
+{
+ //gOpenArchives.erase(erase(&mpq_a);
+ libmpq_archive_close(&mpq_a);
+}
+
+MPQFile::MPQFile(const char* filename):
+ eof(false),
+ buffer(0),
+ pointer(0),
+ size(0)
+{
+ for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
+ {
+ mpq_archive &mpq_a = (*i)->mpq_a;
+
+ mpq_hash hash = (*i)->GetHashEntry(filename);
+ uint32 blockindex = hash.blockindex;
+
+ if ((blockindex == 0xFFFFFFFF) || (blockindex == 0)) {
+ continue; //file not found
+ }
+
+ int fileno = blockindex;
+
+ //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 char[size];
+
+ //libmpq_file_getdata
+ libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);
+ return;
+
+ }
+ eof = true;
+ buffer = 0;
+}
+
+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;
+}
+
+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 = 0;
+ eof = true;
+}