3 #include "../common/Script.h"
11 #include <SDL_image.h>
23 for(map<string, char *>::const_iterator
24 i(objectFiles.begin()), end(objectFiles.end());
31 void Loader::Load(const std::string &filePath) {
32 std::ifstream file(filePath.c_str());
33 file.seekg(0, std::ios::end);
34 int fileLength(file.tellg());
35 int length(fileLength + 15);
37 char *block = new char[length];
38 ObjectFileHeader *header =
39 reinterpret_cast<ObjectFileHeader *>(block);
41 unsigned long padding =
42 reinterpret_cast<unsigned long>(block) % 16;
44 header = reinterpret_cast<ObjectFileHeader *>(
45 block + (16 - padding));
48 file.seekg(0, std::ios::beg);
49 file.read(reinterpret_cast<char *>(header), fileLength);
52 header->IntegrityCheck(fileLength);
54 LoadExports(header->ident,
55 header->ExportsBegin(),
56 header->ExportsEnd());
57 LoadExternals(header->ident,
58 header->ExternalsBegin(),
59 header->ExternalsEnd());
60 LoadObjects(header->ident,
61 header->ObjectsBegin(),
62 header->ObjectsEnd());
63 LoadArrays(header->ident,
64 header->ArraysBegin(),
66 LoadImages(header->ident,
67 header->ImagesBegin(),
69 LoadScripts(header->ident,
70 header->ScriptsBegin(),
71 header->ScriptsEnd());
74 header->ObjectsBegin(),
75 header->ObjectsEnd());
77 header->ArraysBegin(),
83 objectFiles.insert(make_pair(filePath, block));
85 if (objectFiles.size() > 1) {
86 for (std::vector<MissingExternal>::iterator
87 i(unlinked.begin()); i != unlinked.end();) {
88 std::map<string, LoadedExport>::const_iterator
89 found(exports.find(i->identifier));
90 if (found != exports.end()) {
91 LinkExternal(*i, found->second);
92 i = unlinked.erase(i);
100 void Loader::LinkExternal(
101 const MissingExternal &ext,
102 const LoadedExport &exp) {
103 if (ext.typeId != exp.typeId) {
104 throw std::runtime_error("casting not implemented in loader");
106 const TypeDescription &td = TypeDescription::Get(ext.typeId);
108 std::memcpy(ext.dest, exp.location, td.Size());
110 std::memcpy(ext.dest, &exp.location, sizeof(void *));
114 void Loader::LoadExports(char *src, Export *begin, Export *end) {
115 for (Export *i = begin; i < end; ++i) {
116 string identifier(src + i->nameOffset);
117 LoadedExport &exp(exports[identifier]);
118 exp.typeId = i->typeId;
119 exp.location = src + i->dataOffset;
120 exports.insert(make_pair(identifier, exp));
124 void Loader::LoadExternals(char *src, External *begin, External *end) {
125 for (External *i = begin; i < end; ++i) {
126 string identifier(src + i->nameOffset);
127 char *dest = src + i->referenceOffset;
129 map<string, LoadedExport>::const_iterator
130 exp(exports.find(identifier));
131 if (exp == exports.end()) {
133 m.identifier = identifier;
135 m.typeId = i->typeId;
136 m.inlined = i->inlined;
137 unlinked.push_back(m);
139 const TypeDescription &td(TypeDescription::Get(exp->second.typeId));
141 std::memcpy(dest, exp->second.location, td.Size());
143 std::memcpy(dest, &exp->second.location, sizeof(char *));
149 void Loader::LoadImages(char *src, Image *begin, Image *end) {
150 for (Image *i = begin; i != end; ++i) {
151 const string path(src + i->pathOffset);
152 SDL_Surface **dest = reinterpret_cast<SDL_Surface **>(src + i->destOffset);
153 std::map<string, SDL_Surface *>::const_iterator
154 found(images.find(path));
155 if (found != images.end()) {
156 *dest = found->second;
158 SDL_Surface *loaded = IMG_Load(path.c_str());
159 images.insert(make_pair(path, loaded));
165 void Loader::LoadObjects(char *src, Object *begin, Object *end) {
166 for (Object *i = begin; i < end; i = i->Next()) {
167 const TypeDescription &td =
168 TypeDescription::Get(i->typeId);
169 LoadObject(src, i->RawObject(), td);
173 void Loader::LoadObject(char *src, char *object, const TypeDescription &td) {
174 for (TypeDescription::FieldIterator
175 i(td.FieldsBegin()), end(td.FieldsEnd());
177 const FieldDescription &field = i->second;
178 if (field.IsReferenced() || field.IsAggregate()) {
179 char **dest(reinterpret_cast<char **>(object + field.Offset()));
181 *dest = src + *reinterpret_cast<unsigned int *>(dest);
184 const TypeDescription &nestedType
185 = TypeDescription::Get(field.TypeId());
186 LoadObject(src, object + field.Offset(), nestedType);
191 void Loader::LoadArrays(char *src, Array *begin, Array *end) {
192 for (Array *i = begin; i < end; i = i->Next()) {
194 for (char *j = i->Data(), *end = i->Data() + i->size;
195 j < end; j += sizeof(void *)) {
196 unsigned int offset = *reinterpret_cast<unsigned int *>(j);
198 *reinterpret_cast<char **>(j) = src + offset;
202 const TypeDescription &td = TypeDescription::Get(i->typeId);
203 for (char *j = i->Data(), *end = i->Data() + i->size;
204 j < end; j += td.Size()) {
205 LoadObject(src, j, td);
211 void Loader::LoadScripts(char *src, Script *begin, Script *end) {
212 for (Script *s = begin; s < end; s = s->Next()) {
213 for (char *i = s->Text(), *end = s->Text() + s->size; i < end;) {
214 common::Script::Code *code =
215 reinterpret_cast<common::Script::Code *>(i);
216 if (code->type == common::Script::TYPE_ADDRESS && code->numParams > 0) {
217 if (code->reg1 == 7) {
218 char *addr = i + sizeof(common::Script::Code);
219 unsigned int offset = *reinterpret_cast<unsigned int *>(addr);
221 *reinterpret_cast<const char **>(addr) = src + offset;
225 if (code->numParams > 1 && code->reg2 == 7) {
226 char *addr = i + sizeof(common::Script::Code);
227 if (code->reg1 == 7) {
228 addr += sizeof(void *);
230 unsigned int offset = *reinterpret_cast<unsigned int *>(addr);
232 *reinterpret_cast<const char **>(addr) = src + offset;
242 void Loader::InitObjects(Object *begin, Object *end) {
243 for (Object *i = begin; i < end; i = i->Next()) {
244 const TypeDescription &td =
245 TypeDescription::Get(i->typeId);
246 InitObject(i->RawObject(), td);
250 void Loader::InitObject(char *object, const TypeDescription &td) {
253 for (TypeDescription::FieldIterator
254 i(td.FieldsBegin()), end(td.FieldsEnd());
256 const FieldDescription &field = i->second;
257 if (field.IsReferenced() || field.IsAggregate()) {
260 const TypeDescription &nestedType
261 = TypeDescription::Get(field.TypeId());
262 InitObject(object + field.Offset(), nestedType);
266 void Loader::InitArrays(Array *begin, Array *end) {
267 for (Array *i = begin; i < end; i = i->Next()) {
271 const TypeDescription &td = TypeDescription::Get(i->typeId);
272 for (char *j = i->Data(), *end = i->Data() + i->size;
273 j < end; j += td.Size()) {
280 ostream &Loader::Dump(ostream &out) const {
281 out << "loaded objects" << endl;
282 out << "==============" << endl;
284 out << objectFiles.size() << " object files" << endl;
285 for (std::map<string, char *>::const_iterator
286 i(objectFiles.begin()), end(objectFiles.end());
288 out << " - " << i->first << endl;
291 out << exports.size() << " exports" << endl;
292 for (std::map<string, LoadedExport>::const_iterator
293 i(exports.begin()), end(exports.end());
295 const TypeDescription &td = TypeDescription::Get(i->second.typeId);
296 out << " - " << td.TypeName() << ' ' << i->first << endl;
299 out << images.size() << " images" << endl;
300 for (std::map<string, SDL_Surface *>::const_iterator
301 i(images.begin()), end(images.end());
303 out << " - " << i->first << endl;
306 out << unlinked.size() << " missing objects" << endl;
307 for (std::vector<MissingExternal>::const_iterator
308 i(unlinked.begin()), end(unlinked.end());
310 const TypeDescription &td = TypeDescription::Get(
312 out << " - " << td.TypeName() << ' ';
316 out << i->identifier << endl;