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 | uint32 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 | } |
---|