]> git.localhorst.tv Git - l2e.git/blob - src/common/ScriptRunner.cpp
c22a76bda797d34410849f2576f59c4c69f77dbf
[l2e.git] / src / common / ScriptRunner.cpp
1 /*
2  * ScriptRunner.cpp
3  *
4  *  Created on: Oct 13, 2012
5  *      Author: holy
6  */
7
8 #include "ScriptRunner.h"
9
10 #include "Script.h"
11 #include "ScriptHost.h"
12
13 #include <cstdlib>
14
15 using geometry::Vector;
16
17 namespace common {
18
19 ScriptRunner::ScriptRunner()
20 : host(0)
21 , script(0)
22 , cursor(0)
23 , compare(0) {
24
25 }
26
27 ScriptRunner::~ScriptRunner() {
28
29 }
30
31
32 bool ScriptRunner::Running() const {
33         return script && cursor < script->textlen;
34 }
35
36 void ScriptRunner::Run(ScriptHost &h, const Script &s) {
37         host = &h;
38         script = &s;
39         Reset();
40         while (cursor < script->textlen) {
41                 Exec(PopCode());
42         }
43         host = 0;
44         script = 0;
45 }
46
47 void ScriptRunner::Reset() {
48         cursor = 0;
49         for (int i(0); i < numRegisters; ++i) {
50                 address[i] = 0;
51                 integer[i] = 0;
52                 vector[i] = Vector<int>(0, 0);
53         }
54 }
55
56 void ScriptRunner::Exec(Script::Code code) {
57         switch (code.command) {
58                 case Script::COMMAND_NOOP:
59                         break;
60
61                 case Script::COMMAND_MOVE:
62                         if (code.reg1 >= numRegisters) {
63                                 break;
64                         }
65                         switch (code.type) {
66                                 case Script::TYPE_ADDRESS: {
67                                         void *value(code.reg2 < numRegisters ? address[code.reg2] : PopAddress());
68                                         address[code.reg1] = value;
69                                         break;
70                                 }
71                                 case Script::TYPE_INTEGER: {
72                                         int value(code.reg2 < numRegisters ? integer[code.reg2] : PopInt());
73                                         integer[code.reg1] = value;
74                                         break;
75                                 }
76                                 case Script::TYPE_VECTOR: {
77                                         Vector<int> value(code.reg2 < numRegisters ? vector[code.reg2] : PopVector());
78                                         vector[code.reg1] = value;
79                                         break;
80                                 }
81                         }
82                         break;
83
84                 case Script::COMMAND_ADD:
85                         if (code.reg1 >= numRegisters) {
86                                 break;
87                         }
88                         switch (code.type) {
89                                 case Script::TYPE_INTEGER: {
90                                         int value(code.reg2 < numRegisters ? integer[code.reg2] : PopInt());
91                                         integer[code.reg1] += value;
92                                         break;
93                                 }
94                                 case Script::TYPE_VECTOR: {
95                                         Vector<int> value(code.reg2 < numRegisters ? vector[code.reg2] : PopVector());
96                                         vector[code.reg1] += value;
97                                         break;
98                                 }
99                         }
100                         break;
101
102                 case Script::COMMAND_MOD: {
103                         if (code.reg1 >= numRegisters) {
104                                 break;
105                         }
106                         int value(code.reg2 < numRegisters ? integer[code.reg2] : PopInt());
107                         integer[code.reg1] %= value;
108                         break;
109                 }
110
111                 case Script::COMMAND_RAND:
112                         if (code.reg1 >= numRegisters) {
113                                 break;
114                         }
115                         integer[code.reg1] = std::rand();
116                         break;
117
118                 case Script::COMMAND_CMP: {
119                         int lhs(code.reg1 < numRegisters ? integer[code.reg1] : PopInt());
120                         int rhs(code.reg2 < numRegisters ? integer[code.reg2] : PopInt());
121                         Compare(lhs, rhs);
122                         break;
123                 }
124
125                 case Script::COMMAND_JMP:
126                         cursor = PopInt();
127                         break;
128                 case Script::COMMAND_JEQ: {
129                         int addr(PopInt());
130                         if (compare == COMPARE_EQUAL) {
131                                 cursor = addr;
132                         }
133                         break;
134                 }
135                 case Script::COMMAND_JNE: {
136                         int addr(PopInt());
137                         if (compare != COMPARE_EQUAL) {
138                                 cursor = addr;
139                         }
140                         break;
141                 }
142                 case Script::COMMAND_JL: {
143                         int addr(PopInt());
144                         if (compare == COMPARE_LESS) {
145                                 cursor = addr;
146                         }
147                         break;
148                 }
149                 case Script::COMMAND_JLE: {
150                         int addr(PopInt());
151                         if (compare != COMPARE_GREATER) {
152                                 cursor = addr;
153                         }
154                         break;
155                 }
156                 case Script::COMMAND_JG: {
157                         int addr(PopInt());
158                         if (compare == COMPARE_GREATER) {
159                                 cursor = addr;
160                         }
161                         break;
162                 }
163                 case Script::COMMAND_JGE: {
164                         int addr(PopInt());
165                         if (compare != COMPARE_LESS) {
166                                 cursor = addr;
167                         }
168                         break;
169                 }
170                 case Script::COMMAND_SYSC:
171                         host->HandleSyscall(*this);
172                         break;
173         }
174 }
175
176 Script::Code ScriptRunner::PopCode() {
177         const Script::Code *i(reinterpret_cast<const Script::Code *>(script->text + cursor));
178         cursor += sizeof(Script::Code);
179         return *i;
180 }
181
182 void *ScriptRunner::PopAddress() {
183         void *const *addr(reinterpret_cast<void *const *>(script->text + cursor));
184         cursor += sizeof(void *);
185         return *addr;
186 }
187
188 int ScriptRunner::PopInt() {
189         const int *i(reinterpret_cast<const int *>(script->text + cursor));
190         cursor += sizeof(int);
191         return *i;
192 }
193
194 const Vector<int> &ScriptRunner::PopVector() {
195         const Vector<int> *vec(reinterpret_cast<const Vector<int> *>(script->text + cursor));
196         cursor += sizeof(Vector<int>);
197         return *vec;
198 }
199
200 void ScriptRunner::Compare(int lhs, int rhs) {
201         if (lhs < rhs) {
202                 compare = COMPARE_LESS;
203         } else if (lhs > rhs) {
204                 compare = COMPARE_GREATER;
205         } else {
206                 compare = COMPARE_EQUAL;
207         }
208 }
209
210 }