X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Floader%2FLoader.cpp;h=961ec7cff6d315dec5537338fe08ba8cfc0b9450;hb=0e7b9eca67383e45e04aa419cb783c92722f7801;hp=a1183f790f2b0b98af6bc90dd0c9c092e7413380;hpb=d93a406fe997af6035ace4fa8720a5bde1743456;p=l2e.git diff --git a/src/loader/Loader.cpp b/src/loader/Loader.cpp index a1183f7..961ec7c 100644 --- a/src/loader/Loader.cpp +++ b/src/loader/Loader.cpp @@ -1,17 +1,13 @@ -/* - * Loader.cpp - * - * Created on: Sep 13, 2012 - * Author: holy - */ - #include "Loader.h" #include #include #include #include +#include +#include +using std::make_pair; using std::map; using std::string; using std::vector; @@ -19,14 +15,10 @@ 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; + for(map::const_iterator + i(objectFiles.begin()), end(objectFiles.end()); + i != end; ++i) { + delete[] i->second; } } @@ -37,73 +29,73 @@ void Loader::Load(const std::string &filePath) { int fileLength(file.tellg()); int length(fileLength + 15); - LoadedObjectFile &object(objectFiles[filePath]); - object.allocPtr = new char[length]; + char *block = new char[length]; + ObjectFileHeader *header = + reinterpret_cast(block); - 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); + unsigned long padding = + reinterpret_cast(block) % 16; + if (padding) { + header = reinterpret_cast( + block + (16 - padding)); } 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); + file.read(reinterpret_cast(header), fileLength); + + try { + header->IntegrityCheck(fileLength); + + LoadExports(header->ident, + header->ExportsBegin(), + header->ExportsEnd()); + LoadExternals(header->ident, + header->ExternalsBegin(), + header->ExternalsEnd()); + LoadObjects(header->ident, + header->ObjectsBegin(), + header->ObjectsEnd()); + LoadArrays(header->ident, + header->ArraysBegin(), + header->ArraysEnd()); + LoadImages(header->ident, + header->ImagesBegin(), + header->ImagesEnd()); + + InitObjects( + header->ObjectsBegin(), + header->ObjectsEnd()); + InitArrays( + header->ArraysBegin(), + header->ArraysEnd()); + } catch (...) { + delete[] block; + throw; } - - LoadHeader(object); - LoadExports(object); - LoadImages(object); - LinkObjects(object); - LinkExternals(object); + objectFiles.insert(make_pair(filePath, block)); } -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)); +void Loader::LoadExports(char *src, Export *begin, Export *end) { + for (Export *i = begin; i < end; ++i) { + string identifier(src + i->nameOffset); LoadedExport &exp(exports[identifier]); exp.typeId = i->typeId; - exp.location = object.At(i->dataOffset); + exp.location = src + i->dataOffset; + exports.insert(make_pair(identifier, exp)); } } -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)); +void Loader::LoadExternals(char *src, External *begin, External *end) { + for (External *i = begin; i < end; ++i) { + string identifier(src + i->nameOffset); + map::const_iterator + exp(exports.find(identifier)); if (exp == exports.end()) { - throw std::runtime_error("undefined reference to " + identifier); + throw std::runtime_error("undefined reference to " + + identifier); } const TypeDescription &td(TypeDescription::Get(exp->second.typeId)); - char *dest(object.At(i->referenceOffset)); + char *dest = src + i->referenceOffset; if (i->inlined) { std::memcpy(dest, exp->second.location, td.Size()); } else { @@ -112,50 +104,103 @@ void Loader::LinkExternals(LoadedObjectFile &object) { } } -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; +void Loader::LoadImages(char *src, Image *begin, Image *end) { + for (Image *i = begin; i != end; ++i) { + const string path(src + i->pathOffset); + SDL_Surface **dest = reinterpret_cast(src + i->destOffset); + std::map::const_iterator + found(images.find(path)); + if (found != images.end()) { + *dest = found->second; + } else { + SDL_Surface *loaded = IMG_Load(path.c_str()); + images.insert(make_pair(path, loaded)); + *dest = loaded; + } } - 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::LoadObjects(char *src, Object *begin, Object *end) { + for (Object *i = begin; i < end; i = i->Next()) { + const TypeDescription &td = + TypeDescription::Get(i->typeId); + LoadObject(src, i->RawObject(), td); } } -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::LoadObject(char *src, char *object, const TypeDescription &td) { + for (TypeDescription::FieldIterator + i(td.FieldsBegin()), end(td.FieldsEnd()); + i != end; ++i) { + const FieldDescription &field = i->second; + if (field.IsReferenced() || field.IsAggregate()) { + char **dest(reinterpret_cast(object + field.Offset())); + if (*dest) { + *dest = src + *reinterpret_cast(dest); + } + } else { + const TypeDescription &nestedType + = TypeDescription::Get(field.TypeId()); + LoadObject(src, object + field.Offset(), nestedType); + } + } +} + +void Loader::LoadArrays(char *src, Array *begin, Array *end) { + for (Array *i = begin; i < end; i = i->Next()) { + if (i->ref) { + for (char *j = i->Data(), *end = i->Data() + i->size; + j < end; j += sizeof(void *)) { + unsigned int offset = *reinterpret_cast(j); + if (offset) { + *reinterpret_cast(j) = src + offset; + } + } + } else { + const TypeDescription &td = TypeDescription::Get(i->typeId); + for (char *j = i->Data(), *end = i->Data() + i->size; + j < end; j += td.Size()) { + LoadObject(src, j, td); + } + } + } +} + + +void Loader::InitObjects(Object *begin, Object *end) { + for (Object *i = begin; i < end; i = i->Next()) { + const TypeDescription &td = + TypeDescription::Get(i->typeId); + InitObject(i->RawObject(), td); + } +} + +void Loader::InitObject(char *object, const TypeDescription &td) { + td.Init(object); + td.Load(object); + for (TypeDescription::FieldIterator + i(td.FieldsBegin()), end(td.FieldsEnd()); + i != end; ++i) { + const FieldDescription &field = i->second; + if (field.IsReferenced() || field.IsAggregate()) { + continue; } + const TypeDescription &nestedType + = TypeDescription::Get(field.TypeId()); + InitObject(object + field.Offset(), nestedType); } } -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)); +void Loader::InitArrays(Array *begin, Array *end) { + for (Array *i = begin; i < end; i = i->Next()) { + if (i->ref) { + continue; + } + const TypeDescription &td = TypeDescription::Get(i->typeId); + for (char *j = i->Data(), *end = i->Data() + i->size; + j < end; j += td.Size()) { + InitObject(j, td); + } } }