]> git.localhorst.tv Git - l2e.git/commitdiff
added script assembler
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 14 Oct 2012 15:06:33 +0000 (17:06 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 14 Oct 2012 15:15:45 +0000 (17:15 +0200)
src/loader/Interpreter.cpp
src/loader/Interpreter.h

index 8b9b56a2098eb9ae9a6a4002020f4973fdfa6675..c2ce0d4145abf20ee1b90c291ad7965d2e5446aa 100644 (file)
@@ -14,6 +14,7 @@
 #include "../battle/Resources.h"
 #include "../common/Ikari.h"
 #include "../common/Item.h"
+#include "../common/Script.h"
 #include "../common/Spell.h"
 #include "../common/Stats.h"
 #include "../common/TargetingMode.h"
@@ -34,6 +35,7 @@ using battle::Monster;
 using battle::PartyLayout;
 using common::Ikari;
 using common::Item;
+using common::Script;
 using common::Spell;
 using common::Stats;
 using common::TargetingMode;
@@ -143,7 +145,9 @@ void Interpreter::ReadLiteral(int typeId, int id, char *object, const Literal &l
                        object[literal.GetString().size()] = '\0';
                        break;
                case Literal::SCRIPT:
-                       throw Error("script compiler not implemented");
+                       new (object) Script;
+                       ReadScript(literal.GetScript(), reinterpret_cast<Script *>(object));
+                       break;
                case Literal::STRING:
                        std::memcpy(object, literal.GetString().c_str(), literal.GetString().size());
                        object[literal.GetString().size()] = '\0';
@@ -215,7 +219,12 @@ void *Interpreter::GetObject(int typeId, const Value &v) {
                                        }
                                        break;
                                case Literal::SCRIPT:
-                                       throw Error("script compiler not implemented");
+                                       {
+                                               typeId = TypeDescription::GetTypeId("Script");
+                                               id = values[typeId].size();
+                                               values[typeId].push_back(ReadScript(v.GetLiteral().GetScript()));
+                                       }
+                                       break;
                                case Literal::STRING:
                                        {
                                                typeId = TypeDescription::GetTypeId("String");
@@ -324,6 +333,248 @@ void Interpreter::ReadObject(int typeId, int id, char *object, const PropertyLis
 }
 
 
+void Interpreter::ReadScript(const std::vector<ScriptToken *> &s, Script *script) {
+       int size(0);
+       for (vector<ScriptToken *>::const_iterator i(s.begin()), end(s.end()); i != end; ++i) {
+               if ((*i)->GetType() != ScriptToken::COMMAND) {
+                       throw Error("unexpected script token");
+               }
+               ++size;
+               const string &cmd((*i)->CommandName());
+               if (cmd == "move") {
+                       ++i;
+                       if (i == end) {
+                               throw Error("unexpected script end after move");
+                       }
+                       const string &reg((*i)->RegisterName());
+                       switch (reg[0]) {
+                               case 'a':
+                                       size += sizeof(void *);
+                                       break;
+                               case 'i':
+                                       size += sizeof(int);
+                                       break;
+                               case 'v':
+                                       size += sizeof(Vector<int>);
+                                       break;
+                               default:
+                                       throw Error("unknown register " + reg);
+                       }
+                       ++i;
+                       if (i == end) {
+                               throw Error("unexpected script end after move");
+                       }
+               } else if (cmd == "add") {
+                       ++i;
+                       if (i == end) {
+                               throw Error("unexpected script end after add");
+                       }
+                       const string &reg((*i)->RegisterName());
+                       switch (reg[0]) {
+                               case 'i':
+                                       size += sizeof(int);
+                                       break;
+                               case 'v':
+                                       size += sizeof(Vector<int>);
+                                       break;
+                               default:
+                                       throw Error("expected register after add " + reg);
+                       }
+                       ++i;
+                       if (i == end) {
+                               throw Error("unexpected script end after add");
+                       }
+               } else if (cmd == "mod") {
+                       ++i;
+                       if (i == end) {
+                               throw Error("unexpected script end after mod");
+                       }
+                       size += sizeof(int);
+                       ++i;
+                       if (i == end) {
+                               throw Error("unexpected script end after mod");
+                       }
+               } else if (cmd == "rand") {
+                       ++i;
+                       if (i == end) {
+                               throw Error("unexpected script end after rand");
+                       }
+                       size += sizeof(int);
+                       ++i;
+                       if (i == end) {
+                               throw Error("unexpected script end after rand");
+                       }
+               } else if (cmd == "sysc") {
+
+               } else {
+                       throw Error("unknown command " + cmd);
+               }
+       }
+
+       unsigned char *text(reinterpret_cast<unsigned char *>(alloc.Alloc(size)));
+       int cursor(0);
+       for (vector<ScriptToken *>::const_iterator i(s.begin()), end(s.end()); i != end; ++i) {
+               if ((*i)->GetType() != ScriptToken::COMMAND) {
+                       throw Error("unexpected script token");
+               }
+               const string &cmd((*i)->CommandName());
+               if (cmd == "move") {
+                       ++i;
+                       const string &reg((*i)->RegisterName());
+                       ++i;
+                       if (reg == "a0") {
+                               text[cursor] = Script::CODE_MOVE_A0;
+                               ++cursor;
+                               ReadScriptAddress(**i, text + cursor);
+                               cursor += sizeof(void *);
+                       } else if (reg == "a1") {
+                               text[cursor] = Script::CODE_MOVE_A1;
+                               ++cursor;
+                               ReadScriptAddress(**i, text + cursor);
+                               cursor += sizeof(void *);
+                       } else if (reg == "i0") {
+                               text[cursor] = Script::CODE_MOVE_I0;
+                               ++cursor;
+                               ReadScriptInteger(**i, text + cursor);
+                               cursor += sizeof(int);
+                       } else if (reg == "i1") {
+                               text[cursor] = Script::CODE_MOVE_I1;
+                               ++cursor;
+                               ReadScriptInteger(**i, text + cursor);
+                               cursor += sizeof(int);
+                       } else if (reg == "v0") {
+                               text[cursor] = Script::CODE_MOVE_V0;
+                               ++cursor;
+                               ReadScriptVector(**i, text + cursor);
+                               cursor += sizeof(Vector<int>);
+                       } else if (reg == "v1") {
+                               text[cursor] = Script::CODE_MOVE_V1;
+                               ++cursor;
+                               ReadScriptVector(**i, text + cursor);
+                               cursor += sizeof(Vector<int>);
+                       } else {
+                               throw Error("unknown register " + reg);
+                       }
+               } else if (cmd == "add") {
+                       ++i;
+                       const string &reg((*i)->RegisterName());
+                       ++i;
+                       if (reg == "i0") {
+                               text[cursor] = Script::CODE_ADD_I0;
+                               ++cursor;
+                               ReadScriptInteger(**i, text + cursor);
+                               cursor += sizeof(int);
+                       } else if (reg == "i1") {
+                               text[cursor] = Script::CODE_ADD_I1;
+                               ++cursor;
+                               ReadScriptInteger(**i, text + cursor);
+                               cursor += sizeof(int);
+                       } else if (reg == "v0") {
+                               text[cursor] = Script::CODE_ADD_V0;
+                               ++cursor;
+                               ReadScriptVector(**i, text + cursor);
+                               cursor += sizeof(Vector<int>);
+                       } else if (reg == "v1") {
+                               text[cursor] = Script::CODE_ADD_V1;
+                               ++cursor;
+                               ReadScriptVector(**i, text + cursor);
+                               cursor += sizeof(Vector<int>);
+                       } else {
+                               throw Error("unexpected register " + reg);
+                       }
+               } else if (cmd == "mod") {
+                       ++i;
+                       const string &reg((*i)->RegisterName());
+                       ++i;
+                       if (reg == "i0") {
+                               text[cursor] = Script::CODE_MOD_I0;
+                               ++cursor;
+                               ReadScriptInteger(**i, text + cursor);
+                               cursor += sizeof(int);
+                       } else if (reg == "i1") {
+                               text[cursor] = Script::CODE_MOD_I1;
+                               ++cursor;
+                               ReadScriptInteger(**i, text + cursor);
+                               cursor += sizeof(int);
+                       } else {
+                               throw Error("unexpected register " + reg);
+                       }
+               } else if (cmd == "rand") {
+                       ++i;
+                       const string &reg((*i)->RegisterName());
+                       if (reg == "i0") {
+                               text[cursor] = Script::CODE_RAND_I0;
+                               ++cursor;
+                       } else if (reg == "i1") {
+                               text[cursor] = Script::CODE_RAND_I1;
+                               ++cursor;
+                       } else {
+                               throw Error("unexpected register " + reg);
+                       }
+               } else if (cmd == "sysc") {
+                       text[cursor] = Script::CODE_SYSCALL;
+                       ++cursor;
+               } else {
+                       throw Error("unknown command " + cmd);
+               }
+       }
+
+       script->text = text;
+       script->textlen = size;
+}
+
+char *Interpreter::ReadScript(const vector<ScriptToken *> &s) {
+       char *mem(alloc.Alloc(sizeof(Script)));
+       new (mem) Script;
+       Script *script(reinterpret_cast<Script *>(mem));
+       ReadScript(s, script);
+       return mem;
+}
+
+void Interpreter::ReadScriptAddress(const ScriptToken &t, unsigned char *dest) {
+       if (t.GetType() != ScriptToken::IDENTIFIER) {
+               throw Error("expected identifier for address");
+       }
+       if (source.IsDefined(t.GetIdentifier())) {
+               const ParsedDefinition &def(GetDefinition(t.GetIdentifier()));
+               void *addr(GetObject(def.type, t.GetIdentifier()));
+               *reinterpret_cast<void **>(dest) = addr;
+       } else {
+               throw Error("postponing values in scripts not implemented");
+       }
+}
+
+void Interpreter::ReadScriptInteger(const ScriptToken &t, unsigned char *dest) {
+       if (t.GetType() == ScriptToken::IDENTIFIER) {
+               if (source.IsDefined(t.GetIdentifier())) {
+                       void *num(GetObject(TypeDescription::GetTypeId("Number"), t.GetIdentifier()));
+                       *reinterpret_cast<int *>(dest) = *reinterpret_cast<int *>(num);
+               } else {
+                       throw Error("postponing values in scripts not implemented");
+               }
+       } else if (t.GetType() == ScriptToken::LITERAL) {
+               *reinterpret_cast<int *>(dest) = t.GetLiteral()->GetNumber();
+       } else {
+               throw Error("expected identifier or integer literal");
+       }
+}
+
+void Interpreter::ReadScriptVector(const ScriptToken &t, unsigned char *dest) {
+       if (t.GetType() == ScriptToken::IDENTIFIER) {
+               if (source.IsDefined(t.GetIdentifier())) {
+                       void *vec(GetObject(TypeDescription::GetTypeId("Vector"), t.GetIdentifier()));
+                       *reinterpret_cast<Vector<int> *>(dest) = *reinterpret_cast<Vector<int> *>(vec);
+               } else {
+                       throw Error("postponing values in scripts not implemented");
+               }
+       } else if (t.GetType() == ScriptToken::LITERAL) {
+               *reinterpret_cast<Vector<int> *>(dest) = Vector<int>(t.GetLiteral()->GetX(), t.GetLiteral()->GetY());
+       } else {
+               throw Error("expected identifier or vector literal");
+       }
+}
+
+
 SDL_Surface *Interpreter::GetImage(const string &path) {
        std::map<string, SDL_Surface *>::const_iterator result(imageCache.find(path));
        if (result != imageCache.end()) {
@@ -379,6 +630,11 @@ void Interpreter::CreateTypeDescriptions() {
                td.SetSize(1);
                td.AddSupertype(stringId, 0);
        }
+       {
+               TypeDescription &td(TypeDescription::CreateOrGet("Script"));
+               td.SetDescription("Collection of commands that define a behaviour.");
+               td.SetSize(sizeof(Script));
+       }
        {
                TypeDescription &td(TypeDescription::CreateOrGet("String"));
                td.SetDescription("Some characters.");
index 15cebd5e2ff3f10e2adb57a48418c4efb1d1edf5..5fbded6a0dc4d324971c6d9fea5d5938db1376fd 100644 (file)
@@ -80,6 +80,11 @@ private:
        void ReadLiteral(int typeId, int id, char *dest, const Literal &);
        void *GetObject(int typeId, const Value &value);
        void ReadObject(int typeId, int id, char *dest, const PropertyList &);
+       void ReadScript(const std::vector<ScriptToken *> &, common::Script *);
+       char *ReadScript(const std::vector<ScriptToken *> &);
+       void ReadScriptAddress(const ScriptToken &t, unsigned char *dest);
+       void ReadScriptInteger(const ScriptToken &t, unsigned char *dest);
+       void ReadScriptVector(const ScriptToken &t, unsigned char *dest);
 
        SDL_Surface *GetImage(const std::string &);