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