]> git.localhorst.tv Git - l2e.git/blobdiff - src/loader/Loader.cpp
initialize objects after loading
[l2e.git] / src / loader / Loader.cpp
index 2403044ad20fb819a23fafc0b43c2ded125a317c..961ec7cff6d315dec5537338fe08ba8cfc0b9450 100644 (file)
@@ -4,7 +4,10 @@
 #include <cstring>
 #include <fstream>
 #include <stdexcept>
+#include <utility>
+#include <SDL_image.h>
 
+using std::make_pair;
 using std::map;
 using std::string;
 using std::vector;
@@ -52,6 +55,19 @@ void Loader::Load(const std::string &filePath) {
                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;
@@ -65,6 +81,7 @@ void Loader::LoadExports(char *src, Export *begin, Export *end) {
                LoadedExport &exp(exports[identifier]);
                exp.typeId = i->typeId;
                exp.location = src + i->dataOffset;
+               exports.insert(make_pair(identifier, exp));
        }
 }
 
@@ -87,13 +104,27 @@ void Loader::LoadExternals(char *src, External *begin, External *end) {
        }
 }
 
+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<SDL_Surface **>(src + i->destOffset);
+               std::map<string, SDL_Surface *>::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;
+               }
+       }
+}
+
 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);
-               if (td.NeedsLinking()) {
-                       LoadObject(src, i->RawObject(), td);
-               }
+               LoadObject(src, i->RawObject(), td);
        }
 }
 
@@ -102,12 +133,73 @@ void Loader::LoadObject(char *src, char *object, const TypeDescription &td) {
                        i(td.FieldsBegin()), end(td.FieldsEnd());
                        i != end; ++i) {
                const FieldDescription &field = i->second;
-               if (!field.IsReferenced() && !field.IsAggregate()) {
+               if (field.IsReferenced() || field.IsAggregate()) {
+                       char **dest(reinterpret_cast<char **>(object + field.Offset()));
+                       if (*dest) {
+                               *dest = src + *reinterpret_cast<unsigned int *>(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<unsigned int *>(j);
+                               if (offset) {
+                                       *reinterpret_cast<char **>(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::InitArrays(Array *begin, Array *end) {
+       for (Array *i = begin; i < end; i = i->Next()) {
+               if (i->ref) {
                        continue;
                }
-               char **dest(reinterpret_cast<char **>(object + field.Offset()));
-               if (*dest) {
-                       *dest = src + *reinterpret_cast<unsigned int *>(dest);
+               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);
                }
        }
 }