From d93a406fe997af6035ace4fa8720a5bde1743456 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Sat, 15 Sep 2012 20:29:52 +0200 Subject: [PATCH] added (untested) loader --- src/loader/Loader.cpp | 162 ++++++++++++++++++++++++++++++++++++++++++ src/loader/Loader.h | 44 ++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 src/loader/Loader.cpp create mode 100644 src/loader/Loader.h diff --git a/src/loader/Loader.cpp b/src/loader/Loader.cpp new file mode 100644 index 0000000..a1183f7 --- /dev/null +++ b/src/loader/Loader.cpp @@ -0,0 +1,162 @@ +/* + * Loader.cpp + * + * Created on: Sep 13, 2012 + * Author: holy + */ + +#include "Loader.h" + +#include +#include +#include +#include + +using std::map; +using std::string; +using std::vector; + +namespace loader { + +Loader::~Loader() { + for(map::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(object.allocPtr) % 16) { + object.fileHeader = reinterpret_cast(object.allocPtr + (16 - (reinterpret_cast(object.allocPtr) % 16))); + } else { + object.fileHeader = reinterpret_cast(object.allocPtr); + } + + file.seekg(0, std::ios::beg); + file.read(reinterpret_cast(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(header)); + + object.typeOffsetsBegin = reinterpret_cast(charHeader + sizeof(ObjectFileHeader)); + for (object.typeOffsetsEnd = object.typeOffsetsBegin; object.typeOffsetsEnd->begin != 0 && object.typeOffsetsEnd->end != 0; ++object.typeOffsetsEnd); + + object.exportsBegin = reinterpret_cast(charHeader + header->exportsBegin); + object.exportsEnd = reinterpret_cast(charHeader + header->exportsEnd); + + object.externalsBegin = reinterpret_cast(charHeader + header->externalsBegin); + object.externalsEnd = reinterpret_cast(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::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(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(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(object + field.Offset())); + *dest = file.At(*reinterpret_cast(*dest)); + } +} + +} diff --git a/src/loader/Loader.h b/src/loader/Loader.h new file mode 100644 index 0000000..7717167 --- /dev/null +++ b/src/loader/Loader.h @@ -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 +#include +#include + +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 objectFiles; + std::map exports; + +}; + +} +#endif /* LOADER_LOADER_H_ */ -- 2.39.2