| 1 | #include "mpq_libmpq.h" |
|---|
| 2 | #include <deque> |
|---|
| 3 | |
|---|
| 4 | ArchiveSet gOpenArchives; |
|---|
| 5 | |
|---|
| 6 | MPQArchive::MPQArchive(const char* filename) |
|---|
| 7 | { |
|---|
| 8 | int result = libmpq_archive_open(&mpq_a, (unsigned char*)filename); |
|---|
| 9 | printf("Opening %s\n", filename); |
|---|
| 10 | if(result) { |
|---|
| 11 | switch(result) { |
|---|
| 12 | case LIBMPQ_EFILE : /* error on file operation */ |
|---|
| 13 | printf("Error opening archive '%s': File operation Error\n", filename); |
|---|
| 14 | break; |
|---|
| 15 | case LIBMPQ_EFILE_FORMAT : /* bad file format */ |
|---|
| 16 | printf("Error opening archive '%s': Bad file format\n", filename); |
|---|
| 17 | break; |
|---|
| 18 | case LIBMPQ_EFILE_CORRUPT : /* file corrupt */ |
|---|
| 19 | printf("Error opening archive '%s': File corrupt\n", filename); |
|---|
| 20 | break; |
|---|
| 21 | case LIBMPQ_EFILE_NOT_FOUND : /* file in archive not found */ |
|---|
| 22 | printf("Error opening archive '%s': File in archive not found\n", filename); |
|---|
| 23 | break; |
|---|
| 24 | case LIBMPQ_EFILE_READ : /* Read error in archive */ |
|---|
| 25 | printf("Error opening archive '%s': Read error in archive\n", filename); |
|---|
| 26 | break; |
|---|
| 27 | case LIBMPQ_EALLOCMEM : /* maybe not enough memory? :) */ |
|---|
| 28 | printf("Error opening archive '%s': Maybe not enough memory\n", filename); |
|---|
| 29 | break; |
|---|
| 30 | case LIBMPQ_EFREEMEM : /* can not free memory */ |
|---|
| 31 | printf("Error opening archive '%s': Cannot free memory\n", filename); |
|---|
| 32 | break; |
|---|
| 33 | case LIBMPQ_EINV_RANGE : /* Given filenumber is out of range */ |
|---|
| 34 | printf("Error opening archive '%s': Given filenumber is out of range\n", filename); |
|---|
| 35 | break; |
|---|
| 36 | case LIBMPQ_EHASHTABLE : /* error in reading hashtable */ |
|---|
| 37 | printf("Error opening archive '%s': Error in reading hashtable\n", filename); |
|---|
| 38 | break; |
|---|
| 39 | case LIBMPQ_EBLOCKTABLE : /* error in reading blocktable */ |
|---|
| 40 | printf("Error opening archive '%s': Error in reading blocktable\n", filename); |
|---|
| 41 | break; |
|---|
| 42 | default: |
|---|
| 43 | printf("Error opening archive '%s': Unknown error\n", filename); |
|---|
| 44 | break; |
|---|
| 45 | } |
|---|
| 46 | return; |
|---|
| 47 | } |
|---|
| 48 | gOpenArchives.push_front(this); |
|---|
| 49 | } |
|---|
| 50 | |
|---|
| 51 | void MPQArchive::close() |
|---|
| 52 | { |
|---|
| 53 | //gOpenArchives.erase(erase(&mpq_a); |
|---|
| 54 | libmpq_archive_close(&mpq_a); |
|---|
| 55 | } |
|---|
| 56 | |
|---|
| 57 | MPQFile::MPQFile(const char* filename): |
|---|
| 58 | eof(false), |
|---|
| 59 | buffer(0), |
|---|
| 60 | pointer(0), |
|---|
| 61 | size(0) |
|---|
| 62 | { |
|---|
| 63 | for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i) |
|---|
| 64 | { |
|---|
| 65 | mpq_archive &mpq_a = (*i)->mpq_a; |
|---|
| 66 | |
|---|
| 67 | mpq_hash hash = (*i)->GetHashEntry(filename); |
|---|
| 68 | uint32 blockindex = hash.blockindex; |
|---|
| 69 | |
|---|
| 70 | if ((blockindex == 0xFFFFFFFF) || (blockindex == 0)) { |
|---|
| 71 | continue; //file not found |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | int fileno = blockindex; |
|---|
| 75 | |
|---|
| 76 | //int fileno = libmpq_file_number(&mpq_a, filename); |
|---|
| 77 | //if(fileno == LIBMPQ_EFILE_NOT_FOUND) |
|---|
| 78 | // continue; |
|---|
| 79 | |
|---|
| 80 | // Found! |
|---|
| 81 | size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, fileno); |
|---|
| 82 | // HACK: in patch.mpq some files don't want to open and give 1 for filesize |
|---|
| 83 | if (size<=1) { |
|---|
| 84 | eof = true; |
|---|
| 85 | buffer = 0; |
|---|
| 86 | return; |
|---|
| 87 | } |
|---|
| 88 | buffer = new char[size]; |
|---|
| 89 | |
|---|
| 90 | //libmpq_file_getdata |
|---|
| 91 | libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer); |
|---|
| 92 | return; |
|---|
| 93 | |
|---|
| 94 | } |
|---|
| 95 | eof = true; |
|---|
| 96 | buffer = 0; |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | size_t MPQFile::read(void* dest, size_t bytes) |
|---|
| 100 | { |
|---|
| 101 | if (eof) return 0; |
|---|
| 102 | |
|---|
| 103 | size_t rpos = pointer + bytes; |
|---|
| 104 | if (rpos > size) { |
|---|
| 105 | bytes = size - pointer; |
|---|
| 106 | eof = true; |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | memcpy(dest, &(buffer[pointer]), bytes); |
|---|
| 110 | |
|---|
| 111 | pointer = rpos; |
|---|
| 112 | |
|---|
| 113 | return bytes; |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | void MPQFile::seek(int offset) |
|---|
| 117 | { |
|---|
| 118 | pointer = offset; |
|---|
| 119 | eof = (pointer >= size); |
|---|
| 120 | } |
|---|
| 121 | |
|---|
| 122 | void MPQFile::seekRelative(int offset) |
|---|
| 123 | { |
|---|
| 124 | pointer += offset; |
|---|
| 125 | eof = (pointer >= size); |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | void MPQFile::close() |
|---|
| 129 | { |
|---|
| 130 | if (buffer) delete[] buffer; |
|---|
| 131 | buffer = 0; |
|---|
| 132 | eof = true; |
|---|
| 133 | } |
|---|