TrinityCore
loadlib.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#define _CRT_SECURE_NO_DEPRECATE
19
20#include "loadlib.h"
21#include <CascLib.h>
22
23u_map_fcc MverMagic = { { 'R','E','V','M' } };
24
26{
27 data = nullptr;
28 data_size = 0;
29}
30
32{
33 free();
34}
35
36bool ChunkedFile::loadFile(std::shared_ptr<CASC::Storage const> mpq, std::string const& fileName, bool log)
37{
38 free();
39 std::unique_ptr<CASC::File> file(mpq->OpenFile(fileName.c_str(), CASC_LOCALE_ALL_WOW, log));
40 if (!file)
41 return false;
42
43 int64 fileSize = file->GetSize();
44 if (fileSize == -1)
45 return false;
46
47 data_size = uint32(fileSize);
48 data = new uint8[data_size];
49 uint32 bytesRead = 0;
50 if (!file->ReadFile(data, data_size, &bytesRead) || bytesRead != data_size)
51 return false;
52
55 return true;
56
57 printf("Error loading %s\n", fileName.c_str());
58 free();
59
60 return false;
61}
62
63bool ChunkedFile::loadFile(std::shared_ptr<CASC::Storage const> mpq, uint32 fileDataId, std::string const& description, bool log)
64{
65 free();
66 std::unique_ptr<CASC::File> file(mpq->OpenFile(fileDataId, CASC_LOCALE_ALL_WOW, log));
67 if (!file)
68 return false;
69
70 int64 fileSize = file->GetSize();
71 if (fileSize == -1)
72 return false;
73
74 data_size = fileSize;
75 data = new uint8[data_size];
76 uint32 bytesRead = 0;
77 if (!file->ReadFile(data, data_size, &bytesRead) || bytesRead != data_size)
78 return false;
79
82 return true;
83
84 printf("Error loading %s\n", description.c_str());
85 free();
86
87 return false;
88}
89
91{
92 FileChunk* chunk = GetChunk("MVER");
93 if (!chunk)
94 return false;
95
96 // Check version
97 file_MVER* version = chunk->As<file_MVER>();
98 if (version->fcc != MverMagic.fcc)
99 return false;
100 if (version->ver != FILE_FORMAT_VERSION)
101 return false;
102 return true;
103}
104
106{
107 for (auto& chunk : chunks)
108 delete chunk.second;
109
110 chunks.clear();
111
112 delete[] data;
113 data = nullptr;
114 data_size = 0;
115}
116
118{
119 { { 'R', 'E', 'V', 'M' } },
120 { { 'N', 'I', 'A', 'M' } },
121 { { 'O', '2', 'H', 'M' } },
122 { { 'K', 'N', 'C', 'M' } },
123 { { 'T', 'V', 'C', 'M' } },
124 { { 'O', 'M', 'W', 'M' } },
125 { { 'Q', 'L', 'C', 'M' } },
126 { { 'O', 'B', 'F', 'M' } },
127 { { 'D', 'H', 'P', 'M' } },
128 { { 'D', 'I', 'A', 'M' } }
129};
130
132{
133 for (u_map_fcc const& f : InterestingChunks)
134 if (f.fcc == fcc.fcc)
135 return true;
136
137 return false;
138}
139
141{
142 uint8* ptr = GetData();
143 // Make sure there's enough data to read u_map_fcc struct and the uint32 size after it
144 while (ptr <= GetData() + GetDataSize() - 8)
145 {
146 u_map_fcc header = *(u_map_fcc*)ptr;
147 if (IsInterestingChunk(header))
148 {
149 uint32 size = *(uint32*)(ptr + 4);
150 if (size <= data_size)
151 {
152 std::swap(header.fcc_txt[0], header.fcc_txt[3]);
153 std::swap(header.fcc_txt[1], header.fcc_txt[2]);
154
155 FileChunk* chunk = new FileChunk(ptr, size);
156 chunk->parseSubChunks();
157 chunks.insert({ std::string(header.fcc_txt, 4), chunk });
158 }
159
160 // move to next chunk
161 ptr += size + 8;
162 }
163 else
164 ++ptr;
165 }
166}
167
168FileChunk* ChunkedFile::GetChunk(std::string const& name)
169{
170 auto range = chunks.equal_range(name);
171 if (std::distance(range.first, range.second) == 1)
172 return range.first->second;
173
174 return nullptr;
175}
176
178{
179 for (auto& subchunk : subchunks)
180 delete subchunk.second;
181
182 subchunks.clear();
183}
184
186{
187 uint8* ptr = data + 8; // skip self
188 while (ptr < data + size)
189 {
190 u_map_fcc header = *(u_map_fcc*)ptr;
191 if (IsInterestingChunk(header))
192 {
193 uint32 subsize = *(uint32*)(ptr + 4);
194 if (subsize < size)
195 {
196 std::swap(header.fcc_txt[0], header.fcc_txt[3]);
197 std::swap(header.fcc_txt[1], header.fcc_txt[2]);
198
199 FileChunk* chunk = new FileChunk(ptr, subsize);
200 chunk->parseSubChunks();
201 subchunks.insert({ std::string(header.fcc_txt, 4), chunk });
202 }
203
204 // move to next chunk
205 ptr += subsize + 8;
206 }
207 else
208 ++ptr;
209 }
210}
211
212FileChunk* FileChunk::GetSubChunk(std::string const& name)
213{
214 auto range = subchunks.equal_range(name);
215 if (std::distance(range.first, range.second) == 1)
216 return range.first->second;
217
218 return nullptr;
219}
uint8_t uint8
Definition: Define.h:144
int64_t int64
Definition: Define.h:137
uint32_t uint32
Definition: Define.h:142
void free()
Definition: loadlib.cpp:105
virtual ~ChunkedFile()
Definition: loadlib.cpp:31
FileChunk * GetChunk(std::string const &name)
Definition: loadlib.cpp:168
uint8 * data
Definition: loadlib.h:76
void parseChunks()
Definition: loadlib.cpp:140
std::multimap< std::string, FileChunk * > chunks
Definition: loadlib.h:90
uint32 GetDataSize()
Definition: loadlib.h:80
bool loadFile(std::shared_ptr< CASC::Storage const > mpq, std::string const &fileName, bool log=true)
Definition: loadlib.cpp:36
uint8 * GetData()
Definition: loadlib.h:79
bool prepareLoadedData()
Definition: loadlib.cpp:90
uint32 data_size
Definition: loadlib.h:77
~FileChunk()
Definition: loadlib.cpp:177
uint32 size
Definition: loadlib.h:64
void parseSubChunks()
Definition: loadlib.cpp:185
uint8 * data
Definition: loadlib.h:63
T * As()
Definition: loadlib.h:67
FileChunk(uint8 *data_, uint32 size_)
Definition: loadlib.h:60
std::multimap< std::string, FileChunk * > subchunks
Definition: loadlib.h:69
FileChunk * GetSubChunk(std::string const &name)
Definition: loadlib.cpp:212
u_map_fcc MverMagic
Definition: loadlib.cpp:23
bool IsInterestingChunk(u_map_fcc const &fcc)
Definition: loadlib.cpp:131
u_map_fcc InterestingChunks[]
Definition: loadlib.cpp:117
#define FILE_FORMAT_VERSION
Definition: loadlib.h:27
constexpr std::size_t size()
Definition: UpdateField.h:796
uint32 ver
Definition: loadlib.h:47
uint32 fcc
Definition: loadlib.h:43
uint32 fcc
Definition: loadlib.h:34
char fcc_txt[4]
Definition: loadlib.h:33