]> git.localhorst.tv Git - l2e.git/blob - src/common/ScriptRunner.cpp
renamed namespace geometry -> math
[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                         }
75                         break;
76
77                 case Script::COMMAND_ADD:
78                         if (code.reg1 >= numRegisters) {
79                                 break;
80                         }
81                         switch (code.type) {
82                                 case Script::TYPE_INTEGER: {
83                                         int value(code.reg2 < numRegisters ? integer[code.reg2] : PopInt());
84                                         integer[code.reg1] += value;
85                                         break;
86                                 }
87                                 case Script::TYPE_VECTOR: {
88                                         Vector<int> value(code.reg2 < numRegisters ? vector[code.reg2] : PopVector());
89                                         vector[code.reg1] += value;
90                                         break;
91                                 }
92                         }
93                         break;
94
95                 case Script::COMMAND_MOD: {
96                         if (code.reg1 >= numRegisters) {
97                                 break;
98                         }
99                         int value(code.reg2 < numRegisters ? integer[code.reg2] : PopInt());
100                         integer[code.reg1] %= value;
101                         break;
102                 }
103
104                 case Script::COMMAND_RAND:
105                         if (code.reg1 >= numRegisters) {
106                                 break;
107                         }
108                         integer[code.reg1] = std::rand();
109                         break;
110
111                 case Script::COMMAND_CMP: {
112                         int lhs(code.reg1 < numRegisters ? integer[code.reg1] : PopInt());
113                         int rhs(code.reg2 < numRegisters ? integer[code.reg2] : PopInt());
114                         Compare(lhs, rhs);
115                         break;
116                 }
117
118                 case Script::COMMAND_JMP:
119                         cursor = PopInt();
120                         break;
121                 case Script::COMMAND_JEQ: {
122                         int addr(PopInt());
123                         if (compare == COMPARE_EQUAL) {
124                                 cursor = addr;
125                         }
126                         break;
127                 }
128                 case Script::COMMAND_JNE: {
129                         int addr(PopInt());
130                         if (compare != COMPARE_EQUAL) {
131                                 cursor = addr;
132                         }
133                         break;
134                 }
135                 case Script::COMMAND_JL: {
136                         int addr(PopInt());
137                         if (compare == COMPARE_LESS) {
138                                 cursor = addr;
139                         }
140                         break;
141                 }
142                 case Script::COMMAND_JLE: {
143                         int addr(PopInt());
144                         if (compare != COMPARE_GREATER) {
145                                 cursor = addr;
146                         }
147                         break;
148                 }
149                 case Script::COMMAND_JG: {
150                         int addr(PopInt());
151                         if (compare == COMPARE_GREATER) {
152                                 cursor = addr;
153                         }
154                         break;
155                 }
156                 case Script::COMMAND_JGE: {
157                         int addr(PopInt());
158                         if (compare != COMPARE_LESS) {
159                                 cursor = addr;
160                         }
161                         break;
162                 }
163                 case Script::COMMAND_SYSC:
164                         host->HandleSyscall(*this);
165                         break;
166         }
167 }
168
169 Script::Code ScriptRunner::PopCode() {
170         const Script::Code *i(reinterpret_cast<const Script::Code *>(script->text + cursor));
171         cursor += sizeof(Script::Code);
172         return *i;
173 }
174
175 void *ScriptRunner::PopAddress() {
176         void *const *addr(reinterpret_cast<void *const *>(script->text + cursor));
177         cursor += sizeof(void *);
178         return *addr;
179 }
180
181 int ScriptRunner::PopInt() {
182         const int *i(reinterpret_cast<const int *>(script->text + cursor));
183         cursor += sizeof(int);
184         return *i;
185 }
186
187 const Vector<int> &ScriptRunner::PopVector() {
188         const Vector<int> *vec(reinterpret_cast<const Vector<int> *>(script->text + cursor));
189         cursor += sizeof(Vector<int>);
190         return *vec;
191 }
192
193 void ScriptRunner::Compare(int lhs, int rhs) {
194         if (lhs < rhs) {
195                 compare = COMPARE_LESS;
196         } else if (lhs > rhs) {
197                 compare = COMPARE_GREATER;
198         } else {
199                 compare = COMPARE_EQUAL;
200         }
201 }
202
203 }