]> git.localhorst.tv Git - l2e.git/blobdiff - src/loader/Compiler.cpp
relocate scripts
[l2e.git] / src / loader / Compiler.cpp
index b2d23be9c5cb984ee969ae3402706fbe02cf6289..13f3dfc24ba0b1416ef87bfdd2976b9f9c8003dd 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "Interpreter.h"
 #include "TypeDescription.h"
+#include "../common/Script.h"
 
 #include <climits>
 #include <cstring>
@@ -18,6 +19,7 @@ using std::iostream;
 using std::make_pair;
 using std::map;
 using std::ostream;
+using std::pair;
 using std::runtime_error;
 using std::set;
 using std::string;
@@ -51,6 +53,9 @@ void Compiler::Write(iostream &out) {
        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);
@@ -148,6 +153,11 @@ void Compiler::WriteObjects(ostream &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));
+                       }
                }
        }
 }
@@ -180,6 +190,18 @@ void Compiler::WriteImages(ostream &out) {
        }
 }
 
+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
@@ -253,6 +275,18 @@ void Compiler::Relocate(iostream &out) {
                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) {
@@ -306,6 +340,38 @@ void Compiler::Relocate(
        }
 }
 
+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);