#include "Script.h"
 
+#include "../math/Vector.h"
+
 namespace common {
 
 Script::Script()
 
 }
 
+
+unsigned int Script::Code::Size() const {
+       unsigned int size = sizeof(Code);
+       if (numParams == 0) {
+               return size;
+       }
+       unsigned int argSize = 0;
+       switch (type) {
+               default:
+                       argSize = 0;
+                       break;
+               case TYPE_ADDRESS:
+                       argSize = sizeof(void *);
+                       break;
+               case TYPE_INTEGER:
+                       argSize = sizeof(int);
+                       break;
+               case TYPE_VECTOR:
+                       argSize = sizeof(math::Vector<int>);
+                       break;
+       }
+       switch (numParams) {
+               case 3:
+               case 2:
+                       if (reg2 == 7) {
+                               size += argSize;
+                       }
+               case 1:
+                       if (reg1 == 7) {
+                               size += argSize;
+                       }
+               default:
+                       break;
+       }
+       return size;
+}
+
 }
 
                Type type : 2;
                unsigned int reg1 : 3;
                unsigned int reg2 : 3;
+
+               unsigned int Size() const;
        };
 
 public:
 
 
 #include "Interpreter.h"
 #include "TypeDescription.h"
+#include "../common/Script.h"
 
 #include <climits>
 #include <cstring>
 using std::make_pair;
 using std::map;
 using std::ostream;
+using std::pair;
 using std::runtime_error;
 using std::set;
 using std::string;
        fileHeader.arraysBegin = out.tellp();
        WriteArrays(out);
        fileHeader.arraysEnd = out.tellp();
+       fileHeader.scriptsBegin = out.tellp();
+       WriteScripts(out);
+       fileHeader.scriptsEnd = out.tellp();
        out.seekp(0);
        WriteHeader(out);
        WriteExports(out);
                        Write(out, &object, sizeof(Object));
                        addressMap.insert(make_pair(*j, out.tellp()));
                        Write(out, *j, object.size);
+
+                       if (td.TypeId() == Interpreter::SCRIPT_ID) {
+                               common::Script *script = reinterpret_cast<common::Script *>(*j);
+                               scripts.push_back(make_pair(const_cast<char *>(script->text), script->textlen));
+                       }
                }
        }
 }
        }
 }
 
+void Compiler::WriteScripts(ostream &out) {
+       for (vector<pair<const char *, unsigned int> >::const_iterator
+                       i(scripts.begin()), end(scripts.end());
+                       i != end; ++i) {
+               Script s;
+               s.size = i->second;
+               Write(out, &s, sizeof(Script));
+               addressMap.insert(make_pair(i->first, out.tellp()));
+               Write(out, i->first, s.size);
+       }
+}
+
 
 void Compiler::PrepareExport(Export &exp, const string &str) {
        const Interpreter::ParsedDefinition &dfn
                out.seekg(out.tellp());
                delete[] buffer;
        }
+       Script script;
+       for (; out && out.tellg() < fileHeader.scriptsEnd;) {
+               out.read(reinterpret_cast<char *>(&script), sizeof(Script));
+               buffer = new char[script.size];
+               unsigned int pos = out.tellg();
+               out.read(buffer, script.size);
+               RelocateScript(buffer, script.size);
+               out.seekp(pos);
+               out.write(buffer, script.size);
+               out.seekg(out.tellp());
+               delete[] buffer;
+       }
 }
 
 void Compiler::RelocateArray(char *array, int size) {
        }
 }
 
+void Compiler::RelocateScript(char *text, unsigned int textlen) {
+       for (char *i = text, *end = text + textlen; i < end;) {
+               common::Script::Code *code =
+                               reinterpret_cast<common::Script::Code *>(i);
+               if (code->type == common::Script::TYPE_ADDRESS && code->numParams > 0) {
+                       if (code->reg1 == 7) {
+                               char *addr = i + sizeof(common::Script::Code);
+                               std::map<const void *, unsigned int>::const_iterator
+                                               found(addressMap.find(*reinterpret_cast<void **>(addr)));
+                               if (found == addressMap.end()) {
+                                       throw std::runtime_error("unable to relocate script code");
+                               }
+                               *reinterpret_cast<unsigned int *>(addr) = found->second;
+                       }
+
+                       if (code->numParams > 1 && code->reg2 == 7) {
+                               char *addr = i + sizeof(common::Script::Code);
+                               if (code->reg1 == 7) {
+                                       addr += sizeof(void *);
+                               }
+                               std::map<const void *, unsigned int>::const_iterator
+                                               found(addressMap.find(*reinterpret_cast<void **>(addr)));
+                               if (found == addressMap.end()) {
+                                       throw std::runtime_error("unable to relocate script code");
+                               }
+                               *reinterpret_cast<unsigned int *>(addr) = found->second;
+                       }
+               }
+               i += code->Size();
+       }
+}
+
 
 void Compiler::Write(ostream &out, const void *data, int amount) {
        out.write(reinterpret_cast<const char *>(data), amount);
 
 #include <iosfwd>
 #include <map>
 #include <memory>
+#include <utility>
+#include <vector>
 #include <SDL.h>
 
 namespace loader {
        void WriteExports(std::ostream &);
        void WriteExternals(std::ostream &);
        void WriteImages(std::ostream &);
+       void WriteScripts(std::ostream &);
 
        void Relocate(std::iostream &);
        void RelocateArray(char *, int size);
        void Relocate(unsigned int pos, char *dest, const TypeDescription &);
+       void RelocateScript(char *, unsigned int);
 
        void PrepareExport(Export &, const std::string &);
        void PrepareExternal(External &, const Interpreter::PostponedDefinition &);
 
        std::map<const void *, unsigned int> addressMap;
        std::map<unsigned int, void *> images;
+       std::vector<std::pair<const char *, unsigned int> > scripts;
 
 };
 
 
                td.SetDescription("A signed integer.");
                td.SetSize(sizeof(int));
        }
-       {;
+       {
                TypeDescription &td(TypeDescription::Create(PATH_ID, "Path"));
                td.SetDescription("A path in the filesystem which is interpreted relative to the source file's location.");
                td.SetSize(1);
                td.AddSupertype(STRING_ID, 0);
        }
        {
+               Script s;
                TypeDescription &td(TypeDescription::Create(SCRIPT_ID, "Script"));
                td.SetDescription("Collection of commands that define a behaviour.");
                td.SetSize(sizeof(Script));
+               td.AddField("text", FieldDescription(((char *)&s.text) - ((char *)&s), STRING_ID).SetAggregate());
        }
        {
                TypeDescription &td(TypeDescription::Create(STRING_ID, "String"));
 
 #include "Loader.h"
 
+#include "../common/Script.h"
+
 #include <climits>
 #include <cstring>
 #include <fstream>
                LoadImages(header->ident,
                                header->ImagesBegin(),
                                header->ImagesEnd());
+               LoadScripts(header->ident,
+                               header->ScriptsBegin(),
+                               header->ScriptsEnd());
 
                InitObjects(
                                header->ObjectsBegin(),
        }
 }
 
+void Loader::LoadScripts(char *src, Script *begin, Script *end) {
+       for (Script *s = begin; s < end; s = s->Next()) {
+               for (char *i = s->Text(), *end = s->Text() + s->size; i < end;) {
+                       common::Script::Code *code =
+                                       reinterpret_cast<common::Script::Code *>(i);
+                       if (code->type == common::Script::TYPE_ADDRESS && code->numParams > 0) {
+                               if (code->reg1 == 7) {
+                                       char *addr = i + sizeof(common::Script::Code);
+                                       unsigned int offset = *reinterpret_cast<unsigned int *>(addr);
+                                       if (offset) {
+                                               *reinterpret_cast<const char **>(addr) = src + offset;
+                                       }
+                               }
+       
+                               if (code->numParams > 1 && code->reg2 == 7) {
+                                       char *addr = i + sizeof(common::Script::Code);
+                                       if (code->reg1 == 7) {
+                                               addr += sizeof(void *);
+                                       }
+                                       unsigned int offset = *reinterpret_cast<unsigned int *>(addr);
+                                       if (offset) {
+                                               *reinterpret_cast<const char **>(addr) = src + offset;
+                                       }
+                               }
+                       }
+                       i += code->Size();
+               }
+       }
+}
+
 
 void Loader::InitObjects(Object *begin, Object *end) {
        for (Object *i = begin; i < end; i = i->Next()) {
 
        void LoadObjects(char *src, Object *begin, Object *end);
        void LoadObject(char *src, char *dest, const TypeDescription &);
        void LoadArrays(char *src, Array *begin, Array *end);
+       void LoadScripts(char *src, Script *begin, Script *end);
 
        void InitObjects(Object *begin, Object *end);
        void InitObject(char *object, const TypeDescription &);
 
 , exportsEnd(0)
 , externalsBegin(0)
 , externalsEnd(0)
+, imagesBegin(0)
+, imagesEnd(0)
 , objectsBegin(0)
 , objectsEnd(0)
 , arraysBegin(0)
-, arraysEnd(0) {
+, arraysEnd(0)
+, scriptsBegin(0)
+, scriptsEnd(0) {
        ident[0] = 'L';
        ident[1] = '2';
        ident[2] = 'E';
        return reinterpret_cast<Array *>(data + arraysEnd);
 }
 
+Script *ObjectFileHeader::ScriptsBegin() {
+       char *data = reinterpret_cast<char *>(this);
+       return reinterpret_cast<Script *>(data + scriptsBegin);
+}
+
+Script *ObjectFileHeader::ScriptsEnd() {
+       char *data = reinterpret_cast<char *>(this);
+       return reinterpret_cast<Script *>(data + scriptsEnd);
+}
+
 
 char *Object::RawObject() {
        return reinterpret_cast<char *>(this) + sizeof(Object);
        return reinterpret_cast<Array *>(Data() + size);
 }
 
+char *Script::Text() {
+       return reinterpret_cast<char *>(this) + sizeof(Script);
+}
+
+Script *Script::Next() {
+       return reinterpret_cast<Script *>(Text() + size);
+}
+
 }
 
        Array *Next();
 };
 
+struct Script {
+       unsigned int size;
+
+       char *Text();
+       Script *Next();
+};
+
 struct ObjectFileHeader {
        /// Has to be "L2E\n"
        char ident[4];
        unsigned int arraysBegin;
        unsigned int arraysEnd;
 
+       /// File-relative offsets of the script section's begin
+       /// and end respectively.
+       /// Each script is an unsigned int with the length in
+       /// bytes followed by the script text.
+       unsigned int scriptsBegin;
+       unsigned int scriptsEnd;
+
        ObjectFileHeader();
 
        /// Check if there are any problems with the file header.
        Object *ObjectsEnd();
        Array *ArraysBegin();
        Array *ArraysEnd();
+       Script *ScriptsBegin();
+       Script *ScriptsEnd();
 
 private:
        bool CheckSection(