4 * Created on: Sep 13, 2012
22 for(map<string, LoadedObjectFile>::const_iterator i(objectFiles.begin()), end(objectFiles.end()); i != end; ++i) {
23 if (i->second.surfaceCount) {
24 for (int j(0); j < i->second.surfaceCount; ++j) {
25 SDL_FreeSurface(i->second.surfaces[j]);
27 delete[] i->second.surfaces;
29 delete[] i->second.allocPtr;
34 void Loader::Load(const std::string &filePath) {
35 std::ifstream file(filePath.c_str());
36 file.seekg(0, std::ios::end);
37 int fileLength(file.tellg());
38 int length(fileLength + 15);
40 LoadedObjectFile &object(objectFiles[filePath]);
41 object.allocPtr = new char[length];
43 if (reinterpret_cast<unsigned long>(object.allocPtr) % 16) {
44 object.fileHeader = reinterpret_cast<ObjectFileHeader *>(object.allocPtr + (16 - (reinterpret_cast<unsigned long>(object.allocPtr) % 16)));
46 object.fileHeader = reinterpret_cast<ObjectFileHeader *>(object.allocPtr);
49 file.seekg(0, std::ios::beg);
50 file.read(reinterpret_cast<char *>(object.fileHeader), fileLength);
52 if (object.fileHeader->versionId != FORMAT_ID) {
53 throw std::runtime_error("mismatched version id of file " + filePath);
60 LinkExternals(object);
63 void Loader::LoadHeader(LoadedObjectFile &object) {
64 ObjectFileHeader *header(object.fileHeader);
65 char *charHeader(reinterpret_cast<char *>(header));
67 object.typeOffsetsBegin = reinterpret_cast<TypeOffset *>(charHeader + sizeof(ObjectFileHeader));
68 for (object.typeOffsetsEnd = object.typeOffsetsBegin; object.typeOffsetsEnd->begin != 0 && object.typeOffsetsEnd->end != 0; ++object.typeOffsetsEnd);
70 object.exportsBegin = reinterpret_cast<Export *>(charHeader + header->exportsBegin);
71 object.exportsEnd = reinterpret_cast<Export *>(charHeader + header->exportsEnd);
73 object.externalsBegin = reinterpret_cast<External *>(charHeader + header->externalsBegin);
74 object.externalsEnd = reinterpret_cast<External *>(charHeader + header->externalsEnd);
76 object.exportStringsBegin = charHeader + header->exportStringsBegin;
77 object.exportStringsEnd = charHeader + header->exportStringsEnd;
79 object.externalStringsBegin = charHeader + header->externalStringsBegin;
80 object.externalStringsEnd = charHeader + header->externalStringsEnd;
82 object.imagesBegin = charHeader + header->imagesBegin;
83 object.imagesEnd = charHeader + header->imagesEnd;
85 object.objectsBegin = charHeader + header->objectsBegin;
86 object.objectsEnd = charHeader + header->objectsEnd;
89 void Loader::LoadExports(LoadedObjectFile &object) {
90 for (Export *i(object.exportsBegin); i != object.exportsEnd; ++i) {
91 string identifier(object.At(i->nameOffset));
92 LoadedExport &exp(exports[identifier]);
93 exp.typeId = i->typeId;
94 exp.location = object.At(i->dataOffset);
98 void Loader::LinkExternals(LoadedObjectFile &object) {
99 for (External *i(object.externalsBegin); i != object.externalsEnd; ++i) {
100 string identifier(object.At(i->nameOffset));
101 map<string, LoadedExport>::const_iterator exp(exports.find(identifier));
102 if (exp == exports.end()) {
103 throw std::runtime_error("undefined reference to " + identifier);
105 const TypeDescription &td(TypeDescription::Get(exp->second.typeId));
106 char *dest(object.At(i->referenceOffset));
108 std::memcpy(dest, exp->second.location, td.Size());
110 std::memcpy(dest, &exp->second.location, sizeof(char *));
115 void Loader::LoadImages(LoadedObjectFile &object) {
116 for (char *i(object.imagesBegin); i != object.imagesEnd;) {
117 ImageProperties *props(reinterpret_cast<ImageProperties *>(i));
118 i += sizeof(ImageProperties) + props->width * props->height * (props->depth / CHAR_BIT + (props->depth % CHAR_BIT ? 1 : 0));
119 ++object.surfaceCount;
121 if (object.surfaceCount == 0) return;
123 object.surfaces = new SDL_Surface *[object.surfaceCount];
125 for (char *i(object.imagesBegin); i != object.imagesEnd;) {
126 ImageProperties *props(reinterpret_cast<ImageProperties *>(i));
127 i += sizeof(ImageProperties);
128 SDL_Surface *image(SDL_CreateRGBSurfaceFrom(
138 i += props->width * props->height * (props->depth / CHAR_BIT + (props->depth % CHAR_BIT ? 1 : 0));
139 object.surfaces[index] = image;
144 void Loader::LinkObjects(LoadedObjectFile &object) {
145 for (TypeOffset *type(object.typeOffsetsBegin); type != object.typeOffsetsEnd; ++type) {
146 const TypeDescription &td(TypeDescription::Get(type->typeId));
147 for (int offset(type->begin); offset != type->end; offset += td.Size()) {
148 LinkObject(object, td, object.At(offset));
153 void Loader::LinkObject(LoadedObjectFile &file, const TypeDescription &td, char *object) {
154 for (TypeDescription::FieldIterator i(td.FieldsBegin()), end(td.FieldsEnd()); i != end; ++i) {
155 const FieldDescription &field(i->second);
156 if (!field.IsReferenced()) continue;
157 char **dest(reinterpret_cast<char **>(object + field.Offset()));
158 *dest = file.At(*reinterpret_cast<int *>(*dest));