]> git.localhorst.tv Git - l2e.git/blob - src/common/ScriptRunner.cpp
handle compare/jump instructions in script assembler
[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 , address0(0)
24 , address1(0)
25 , integer0(0)
26 , integer1(0)
27 , vector0(0, 0)
28 , vector1(0, 0)
29 , compare(0) {
30
31 }
32
33 ScriptRunner::~ScriptRunner() {
34
35 }
36
37
38 bool ScriptRunner::Running() const {
39         return script && cursor < script->textlen;
40 }
41
42 void ScriptRunner::Run(ScriptHost &h, const Script &s) {
43         host = &h;
44         script = &s;
45         Reset();
46         while (cursor < script->textlen) {
47                 unsigned char code(script->text[cursor]);
48                 ++cursor;
49                 Exec(code);
50         }
51         host = 0;
52         script = 0;
53 }
54
55 void ScriptRunner::Reset() {
56         cursor = 0;
57         address0 = 0;
58         address1 = 0;
59         integer0 = 0;
60         integer1 = 0;
61         vector0 = Vector<int>(0, 0);
62         vector1 = Vector<int>(0, 0);
63 }
64
65 void ScriptRunner::Exec(unsigned char code) {
66         switch (code) {
67                 case Script::CODE_MOVE_A0:
68                         address0 = PopAddress();
69                         break;
70                 case Script::CODE_MOVE_A1:
71                         address1 = PopAddress();
72                         break;
73                 case Script::CODE_MOVE_I0:
74                         integer0 = PopInt();
75                         break;
76                 case Script::CODE_MOVE_I1:
77                         integer1 = PopInt();
78                         break;
79                 case Script::CODE_MOVE_V0:
80                         vector0 = PopVector();
81                         break;
82                 case Script::CODE_MOVE_V1:
83                         vector1 = PopVector();
84                         break;
85                 case Script::CODE_ADD_I0:
86                         integer0 += PopInt();
87                         break;
88                 case Script::CODE_ADD_I1:
89                         integer1 += PopInt();
90                         break;
91                 case Script::CODE_ADD_V0:
92                         vector0 += PopVector();
93                         break;
94                 case Script::CODE_ADD_V1:
95                         vector1 += PopVector();
96                         break;
97                 case Script::CODE_MOD_I0:
98                         integer0 %= PopInt();
99                         break;
100                 case Script::CODE_MOD_I1:
101                         integer1 %= PopInt();
102                         break;
103                 case Script::CODE_RAND_I0:
104                         integer0 = std::rand();
105                         break;
106                 case Script::CODE_RAND_I1:
107                         integer1 = std::rand();
108                         break;
109                 case Script::CODE_CMP_I0:
110                         Compare(integer0, PopInt());
111                         break;
112                 case Script::CODE_CMP_I1:
113                         Compare(integer1, PopInt());
114                         break;
115                 case Script::CODE_CMP_I0_I1:
116                         Compare(integer0, integer1);
117                         break;
118                 case Script::CODE_JUMP:
119                         cursor = PopInt();
120                         break;
121                 case Script::CODE_JUMP_EQUAL: {
122                         int addr(PopInt());
123                         if (compare == COMPARE_EQUAL) {
124                                 cursor = addr;
125                         }
126                         break;
127                 }
128                 case Script::CODE_JUMP_NOT_EQUAL: {
129                         int addr(PopInt());
130                         if (compare != COMPARE_EQUAL) {
131                                 cursor = addr;
132                         }
133                         break;
134                 }
135                 case Script::CODE_JUMP_LESS: {
136                         int addr(PopInt());
137                         if (compare == COMPARE_LESS) {
138                                 cursor = addr;
139                         }
140                         break;
141                 }
142                 case Script::CODE_JUMP_LESS_EQUAL: {
143                         int addr(PopInt());
144                         if (compare != COMPARE_GREATER) {
145                                 cursor = addr;
146                         }
147                         break;
148                 }
149                 case Script::CODE_JUMP_GREATER: {
150                         int addr(PopInt());
151                         if (compare == COMPARE_GREATER) {
152                                 cursor = addr;
153                         }
154                         break;
155                 }
156                 case Script::CODE_JUMP_GREATER_EQUAL: {
157                         int addr(PopInt());
158                         if (compare != COMPARE_LESS) {
159                                 cursor = addr;
160                         }
161                         break;
162                 }
163                 case Script::CODE_SYSCALL:
164                         host->HandleSyscall(*this);
165                         break;
166         }
167 }
168
169 void *ScriptRunner::PopAddress() {
170         void *const *addr(reinterpret_cast<void *const *>(script->text + cursor));
171         cursor += sizeof(void *);
172         return *addr;
173 }
174
175 int ScriptRunner::PopInt() {
176         const int *i(reinterpret_cast<const int *>(script->text + cursor));
177         cursor += sizeof(int);
178         return *i;
179 }
180
181 const Vector<int> &ScriptRunner::PopVector() {
182         const Vector<int> *vec(reinterpret_cast<const Vector<int> *>(script->text + cursor));
183         cursor += sizeof(Vector<int>);
184         return *vec;
185 }
186
187 void ScriptRunner::Compare(int lhs, int rhs) {
188         if (lhs < rhs) {
189                 compare = COMPARE_LESS;
190         } else if (lhs > rhs) {
191                 compare = COMPARE_GREATER;
192         } else {
193                 compare = COMPARE_EQUAL;
194         }
195 }
196
197 }