]> git.localhorst.tv Git - l2e.git/commitdiff
added (untested) loader
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Sat, 15 Sep 2012 18:29:52 +0000 (20:29 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 24 Feb 2013 21:33:57 +0000 (22:33 +0100)
src/loader/Loader.cpp [new file with mode: 0644]
src/loader/Loader.h [new file with mode: 0644]

diff --git a/src/loader/Loader.cpp b/src/loader/Loader.cpp
new file mode 100644 (file)
index 0000000..a1183f7
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Loader.cpp
+ *
+ *  Created on: Sep 13, 2012
+ *      Author: holy
+ */
+
+#include "Loader.h"
+
+#include <climits>
+#include <cstring>
+#include <fstream>
+#include <stdexcept>
+
+using std::map;
+using std::string;
+using std::vector;
+
+namespace loader {
+
+Loader::~Loader() {
+       for(map<string, LoadedObjectFile>::const_iterator i(objectFiles.begin()), end(objectFiles.end()); i != end; ++i) {
+               if (i->second.surfaceCount) {
+                       for (int j(0); j < i->second.surfaceCount; ++j) {
+                               SDL_FreeSurface(i->second.surfaces[j]);
+                       }
+                       delete[] i->second.surfaces;
+               }
+               delete[] i->second.allocPtr;
+       }
+}
+
+
+void Loader::Load(const std::string &filePath) {
+       std::ifstream file(filePath.c_str());
+       file.seekg(0, std::ios::end);
+       int fileLength(file.tellg());
+       int length(fileLength + 15);
+
+       LoadedObjectFile &object(objectFiles[filePath]);
+       object.allocPtr = new char[length];
+
+       if (reinterpret_cast<unsigned long>(object.allocPtr) % 16) {
+               object.fileHeader = reinterpret_cast<ObjectFileHeader *>(object.allocPtr + (16 - (reinterpret_cast<unsigned long>(object.allocPtr) % 16)));
+       } else {
+               object.fileHeader = reinterpret_cast<ObjectFileHeader *>(object.allocPtr);
+       }
+
+       file.seekg(0, std::ios::beg);
+       file.read(reinterpret_cast<char *>(object.fileHeader), fileLength);
+
+       if (object.fileHeader->versionId != FORMAT_ID) {
+               throw std::runtime_error("mismatched version id of file " + filePath);
+       }
+
+       LoadHeader(object);
+       LoadExports(object);
+       LoadImages(object);
+       LinkObjects(object);
+       LinkExternals(object);
+}
+
+void Loader::LoadHeader(LoadedObjectFile &object) {
+       ObjectFileHeader *header(object.fileHeader);
+       char *charHeader(reinterpret_cast<char *>(header));
+
+       object.typeOffsetsBegin = reinterpret_cast<TypeOffset *>(charHeader + sizeof(ObjectFileHeader));
+       for (object.typeOffsetsEnd = object.typeOffsetsBegin; object.typeOffsetsEnd->begin != 0 && object.typeOffsetsEnd->end != 0; ++object.typeOffsetsEnd);
+
+       object.exportsBegin = reinterpret_cast<Export *>(charHeader + header->exportsBegin);
+       object.exportsEnd = reinterpret_cast<Export *>(charHeader + header->exportsEnd);
+
+       object.externalsBegin = reinterpret_cast<External *>(charHeader + header->externalsBegin);
+       object.externalsEnd = reinterpret_cast<External *>(charHeader + header->externalsEnd);
+
+       object.exportStringsBegin = charHeader + header->exportStringsBegin;
+       object.exportStringsEnd = charHeader + header->exportStringsEnd;
+
+       object.externalStringsBegin = charHeader + header->externalStringsBegin;
+       object.externalStringsEnd = charHeader + header->externalStringsEnd;
+
+       object.imagesBegin = charHeader + header->imagesBegin;
+       object.imagesEnd = charHeader + header->imagesEnd;
+
+       object.objectsBegin = charHeader + header->objectsBegin;
+       object.objectsEnd = charHeader + header->objectsEnd;
+}
+
+void Loader::LoadExports(LoadedObjectFile &object) {
+       for (Export *i(object.exportsBegin); i != object.exportsEnd; ++i) {
+               string identifier(object.At(i->nameOffset));
+               LoadedExport &exp(exports[identifier]);
+               exp.typeId = i->typeId;
+               exp.location = object.At(i->dataOffset);
+       }
+}
+
+void Loader::LinkExternals(LoadedObjectFile &object) {
+       for (External *i(object.externalsBegin); i != object.externalsEnd; ++i) {
+               string identifier(object.At(i->nameOffset));
+               map<string, LoadedExport>::const_iterator exp(exports.find(identifier));
+               if (exp == exports.end()) {
+                       throw std::runtime_error("undefined reference to " + identifier);
+               }
+               const TypeDescription &td(TypeDescription::Get(exp->second.typeId));
+               char *dest(object.At(i->referenceOffset));
+               if (i->inlined) {
+                       std::memcpy(dest, exp->second.location, td.Size());
+               } else {
+                       std::memcpy(dest, &exp->second.location, sizeof(char *));
+               }
+       }
+}
+
+void Loader::LoadImages(LoadedObjectFile &object) {
+       for (char *i(object.imagesBegin); i != object.imagesEnd;) {
+               ImageProperties *props(reinterpret_cast<ImageProperties *>(i));
+               i += sizeof(ImageProperties) + props->width * props->height * (props->depth / CHAR_BIT + (props->depth % CHAR_BIT ? 1 : 0));
+               ++object.surfaceCount;
+       }
+       if (object.surfaceCount == 0) return;
+
+       object.surfaces = new SDL_Surface *[object.surfaceCount];
+       int index(0);
+       for (char *i(object.imagesBegin); i != object.imagesEnd;) {
+               ImageProperties *props(reinterpret_cast<ImageProperties *>(i));
+               i += sizeof(ImageProperties);
+               SDL_Surface *image(SDL_CreateRGBSurfaceFrom(
+                               i,
+                               props->width,
+                               props->height,
+                               props->depth,
+                               props->pitch,
+                               props->rmask,
+                               props->gmask,
+                               props->bmask,
+                               props->amask));
+               i += props->width * props->height * (props->depth / CHAR_BIT + (props->depth % CHAR_BIT ? 1 : 0));
+               object.surfaces[index] = image;
+               ++index;
+       }
+}
+
+void Loader::LinkObjects(LoadedObjectFile &object) {
+       for (TypeOffset *type(object.typeOffsetsBegin); type != object.typeOffsetsEnd; ++type) {
+               const TypeDescription &td(TypeDescription::Get(type->typeId));
+               for (int offset(type->begin); offset != type->end; offset += td.Size()) {
+                       LinkObject(object, td, object.At(offset));
+               }
+       }
+}
+
+void Loader::LinkObject(LoadedObjectFile &file, const TypeDescription &td, char *object) {
+       for (TypeDescription::FieldIterator i(td.FieldsBegin()), end(td.FieldsEnd()); i != end; ++i) {
+               const FieldDescription &field(i->second);
+               if (!field.IsReferenced()) continue;
+               char **dest(reinterpret_cast<char **>(object + field.Offset()));
+               *dest = file.At(*reinterpret_cast<int *>(*dest));
+       }
+}
+
+}
diff --git a/src/loader/Loader.h b/src/loader/Loader.h
new file mode 100644 (file)
index 0000000..7717167
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Loader.h
+ *
+ *  Created on: Sep 13, 2012
+ *      Author: holy
+ */
+
+#ifndef LOADER_LOADER_H_
+#define LOADER_LOADER_H_
+
+#include "ObjectFile.h"
+#include "TypeDescription.h"
+
+namespace loader {
+
+#include <map>
+#include <string>
+#include <vector>
+
+class Loader {
+
+public:
+       Loader() { }
+       ~Loader();
+
+public:
+       void Load(const std::string &file);
+
+private:
+       void LoadHeader(LoadedObjectFile &);
+       void LoadExports(LoadedObjectFile &);
+       void LinkExternals(LoadedObjectFile &);
+       void LoadImages(LoadedObjectFile &);
+       void LinkObjects(LoadedObjectFile &);
+       void LinkObject(LoadedObjectFile &, const TypeDescription &, char *object);
+
+private:
+       std::map<std::string, LoadedObjectFile> objectFiles;
+       std::map<std::string, LoadedExport> exports;
+
+};
+
+}
+#endif /* LOADER_LOADER_H_ */