ScummVM API documentation
script.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 /*
23  * Based on
24  * WebVenture (c) 2010, Sean Kasun
25  * https://github.com/mrkite/webventure, http://seancode.com/webventure/
26  *
27  * Used with explicit permission from the author
28  */
29 
30 #ifndef MACVENTURE_SCRIPT_H
31 #define MACVENTURE_SCRIPT_H
32 
33 #include "macventure/container.h"
34 #include "macventure/world.h"
35 #include "macventure/macventure.h"
36 #include "macventure/controls.h"
37 
38 namespace MacVenture {
39 
40 class Container;
41 class World;
42 
43 typedef uint32 ObjID;
44 
45 class ScriptAsset {
46 public:
47  ScriptAsset(ObjID id, Container *container);
48  ~ScriptAsset() {}
49 
50  void reset();
51  uint8 fetch();
52  bool hasNext();
53  void branch(int16 amount);
54 
55  ObjID getId();
56 
57 private:
58 
59  void loadInstructions();
60 
61 private:
62  ObjID _id;
63  Container *_container;
64 
65  Common::Array<uint8> _instructions;
66  uint32 _ip; // Instruction pointer
67 };
68 
69 class EngineState {
70 public:
71  EngineState() {
72  clear();
73  }
74 
75  void push(int16 data) {
76  sp--;
77  stack[sp] = unneg16(data);
78  }
79 
80  int16 pop() {
81  int16 v = stack[sp];
82  sp++;
83  return v;
84  }
85 
86  int16 peek(int16 off) {
87  return stack[sp + off];
88  }
89 
90  void poke(int16 off, int16 val) {
91  stack[sp + off] = unneg16(val);
92  }
93 
94  void clear() {
95  sp = 0x80;
96  for (int i = 0; i < sp; i++) {
97  stack[i] = 0;
98  }
99  }
100 
101  int16 size() {
102  return 0x80 - sp;
103  }
104 
105 private:
106  int16 unneg16(int16 data) {
107  if (data < 0)
108  data = ((-data) ^ 0xFFFF) + 1;
109 
110  return data;
111  }
112 
113 private:
114 
115  int16 stack[0x80];
116  int16 sp;
117 };
118 
119 struct FunCall {
120  int16 func;
121  int16 rank;
122 
123  FunCall(int16 f, int16 r) {
124  func = f;
125  rank = r;
126  }
127 };
128 
129 struct EngineFrame {
130  ControlAction action;
131  ObjID src;
132  ObjID dest;
133  int x;
134  int y;
135  EngineState state;
138  uint32 familyIdx;
139 
140  bool haltedInFirst;
141  bool haltedInFamily;
142  bool haltedInSaves;
143 };
144 
146 public:
147  ScriptEngine(MacVentureEngine *engine, World *world);
148  ~ScriptEngine();
149 
150 public:
151  bool runControl(ControlAction action, ObjID source, ObjID destination, Common::Point delta);
152  bool resume(bool execAll);
153  void reset();
154 
155 private:
156  bool execFrame(bool execAll);
157  bool loadScript(EngineFrame *frame, uint32 scriptID);
158  bool resumeFunc(EngineFrame *frame);
159  bool runFunc(EngineFrame *frame);
160 
161 private:
162 
163  // Aux
164  int16 neg16(int16 val);
165  int16 neg8(int16 val);
166  int16 sumChildrenAttr(int16 obj, int16 attr, bool recursive);
167  void ensureNonzeroDivisor(int16 divisor, byte opcode);
168 
169  // Opcodes
170  void op80GATT(EngineState *state, EngineFrame *frame); //get attribute
171  void op81SATT(EngineState *state, EngineFrame *frame); //set attribute
172  void op82SUCH(EngineState *state, EngineFrame *frame); //sum children attribute
173  void op83PUCT(EngineState *state, EngineFrame *frame); //push selected control
174  void op84PUOB(EngineState *state, EngineFrame *frame); //push selected object
175  void op85PUTA(EngineState *state, EngineFrame *frame); //push target
176  void op86PUDX(EngineState *state, EngineFrame *frame); //push deltax
177  void op87PUDY(EngineState *state, EngineFrame *frame); //push deltay
178  void op88PUIB(EngineState *state, EngineFrame *frame, ScriptAsset *script);//push immediate.b
179  void op89PUI(EngineState *state, EngineFrame *frame, ScriptAsset *script);//push immediate
180  void op8aGGLO(EngineState *state, EngineFrame *frame); //get global
181  void op8bSGLO(EngineState *state, EngineFrame *frame); //set global
182  void op8cRAND(EngineState *state, EngineFrame *frame); //random
183  void op8dCOPY(EngineState *state, EngineFrame *frame); //copy
184  void op8eCOPYN(EngineState *state, EngineFrame *frame); //copyn
185  void op8fSWAP(EngineState *state, EngineFrame *frame); //swap
186 
187  void op90SWAPN(EngineState *state, EngineFrame *frame); //swapn
188  void op91POP(EngineState *state, EngineFrame *frame); //pop
189  void op92COPYP(EngineState *state, EngineFrame *frame); //copy+1
190  void op93COPYPN(EngineState *state, EngineFrame *frame);//copy+n
191  void op94SHUFF(EngineState *state, EngineFrame *frame); //shuffle
192  void op95SORT(EngineState *state, EngineFrame *frame); //sort
193  void op96CLEAR(EngineState *state, EngineFrame *frame); //clear stack
194  void op97SIZE(EngineState *state, EngineFrame *frame); //get stack size
195  void op98ADD(EngineState *state, EngineFrame *frame); //add
196  void op99SUB(EngineState *state, EngineFrame *frame); //subtract
197  void op9aMUL(EngineState *state, EngineFrame *frame); //multiply
198  void op9bDIV(EngineState *state, EngineFrame *frame); //divide
199  void op9cMOD(EngineState *state, EngineFrame *frame); //mod
200  void op9dDMOD(EngineState *state, EngineFrame *frame); //divmod
201  void op9eABS(EngineState *state, EngineFrame *frame); //abs
202  void op9fNEG(EngineState *state, EngineFrame *frame); //neg
203 
204  void opa0AND(EngineState *state, EngineFrame *frame); //and
205  void opa1OR(EngineState *state, EngineFrame *frame); //or
206  void opa2XOR(EngineState *state, EngineFrame *frame); //xor
207  void opa3NOT(EngineState *state, EngineFrame *frame); //not
208  void opa4LAND(EngineState *state, EngineFrame *frame); //logical and
209  void opa5LOR(EngineState *state, EngineFrame *frame); //logical or
210  void opa6LXOR(EngineState *state, EngineFrame *frame); //logical xor
211  void opa7LNOT(EngineState *state, EngineFrame *frame); //logical not
212  void opa8GTU(EngineState *state, EngineFrame *frame); //gt? unsigned
213  void opa9LTU(EngineState *state, EngineFrame *frame); //lt? unsigned
214  void opaaGTS(EngineState *state, EngineFrame *frame); //gt? signed
215  void opabLTS(EngineState *state, EngineFrame *frame); //lt? signed
216  void opacEQ(EngineState *state, EngineFrame *frame); //eq?
217  void opadEQS(EngineState *state, EngineFrame *frame); //eq string?
218  void opaeCONT(EngineState *state, EngineFrame *frame); //contains
219  void opafCONTW(EngineState *state, EngineFrame *frame); //contains word
220 
221  void opb0BRA(EngineState *state, EngineFrame *frame, ScriptAsset *script); //bra
222  void opb1BRAB(EngineState *state, EngineFrame *frame, ScriptAsset *script); //bra.b
223  void opb2BEQ(EngineState *state, EngineFrame *frame, ScriptAsset *script); //beq
224  void opb3BEQB(EngineState *state, EngineFrame *frame, ScriptAsset *script); //beq.b
225  void opb4BNE(EngineState *state, EngineFrame *frame, ScriptAsset *script); //bne
226  void opb5BNEB(EngineState *state, EngineFrame *frame, ScriptAsset *script); //bne.b
227  void opb6CLAT(EngineState *state, EngineFrame *frame); //call later
228  void opb7CCA(EngineState *state, EngineFrame *frame); //cancel call
229  void opb8CLOW(EngineState *state, EngineFrame *frame); //cancel low priority
230  void opb9CHI(EngineState *state, EngineFrame *frame); //cancel high priority
231  void opbaCRAN(EngineState *state, EngineFrame *frame); //cancel priority range
232  bool opbbFORK(EngineState *state, EngineFrame *frame); //fork
233  bool opbcCALL(EngineState *state, EngineFrame *frame, ScriptAsset &script); //call
234  void opbdFOOB(EngineState *state, EngineFrame *frame); //focus object
235  void opbeSWOB(EngineState *state, EngineFrame *frame); //swap objects
236  void opbfSNOB(EngineState *state, EngineFrame *frame); //snap object
237 
238  void opc0TEXI(EngineState *state, EngineFrame *frame); //toggle exits
239  void opc1PTXT(EngineState *state, EngineFrame *frame); //print text
240  void opc2PNEW(EngineState *state, EngineFrame *frame); //print newline
241  void opc3PTNE(EngineState *state, EngineFrame *frame); //print text+nl
242  void opc4PNTN(EngineState *state, EngineFrame *frame); //print nl+text+nl
243  void opc5PNUM(EngineState *state, EngineFrame *frame); //print number
244  void opc6P2(EngineState *state, EngineFrame *frame); //push 2
245  void opc7PLBG(EngineState *state, EngineFrame *frame); //play sound in background
246  void opc8PLAW(EngineState *state, EngineFrame *frame); //play sound and wait
247  void opc9WAIT(EngineState *state, EngineFrame *frame); //wait for sound to finish?
248  void opcaTIME(EngineState *state, EngineFrame *frame); //get current time
249  void opcbDAY(EngineState *state, EngineFrame *frame); //get current day
250  void opccCHLD(EngineState *state, EngineFrame *frame); //get children
251  void opcdNCHLD(EngineState *state, EngineFrame *frame); //get num children
252  void opceVERS(EngineState *state, EngineFrame *frame); //get engine version
253  void opcfPSCE(EngineState *state, EngineFrame *frame); //push scenario number
254 
255  void opd0P1(EngineState *state, EngineFrame *frame); //push 1
256  void opd1GOBD(EngineState *state, EngineFrame *frame); //get object dimensions
257  void opd2GOVP(EngineState *state, EngineFrame *frame); //get overlap percent
258  void opd3CAPC(EngineState *state, EngineFrame *frame); //capture children
259  void opd4RELC(EngineState *state, EngineFrame *frame); //release children
260  void opd5DLOG(EngineState *state, EngineFrame *frame); //show speech dialog
261  void opd6ACMD(EngineState *state, EngineFrame *frame); //activate command
262  void opd7LOSE(EngineState *state, EngineFrame *frame); //lose game
263  void opd8WIN(EngineState *state, EngineFrame *frame); //win game
264  void opd9SLEEP(EngineState *state, EngineFrame *frame); //sleep
265  void opdaCLICK(EngineState *state, EngineFrame *frame); //click to continue
266  void opdbROBQ(EngineState *state, EngineFrame *frame); //run queue
267  void opdcRSQ(EngineState *state, EngineFrame *frame); //run sound queue
268  void opddRTQ(EngineState *state, EngineFrame *frame); //run text queue
269  void opdeUPSC(EngineState *state, EngineFrame *frame); //update screen
270  void opdfFMAI(EngineState *state, EngineFrame *frame); //flash main window
271 
272  void ope0CHGR(EngineState *state, EngineFrame *frame); //cache graphic and object
273  void ope1CHSO(EngineState *state, EngineFrame *frame); //cache sound
274  void ope2MDIV(EngineState *state, EngineFrame *frame); //muldiv
275  void ope3UPOB(EngineState *state, EngineFrame *frame); //update object
276  void ope4PLEV(EngineState *state, EngineFrame *frame); //currently playing event?
277  void ope5WEV(EngineState *state, EngineFrame *frame); //wait for event to finish
278  void ope6GFIB(EngineState *state, EngineFrame *frame); //get fibonacci (joke)
279  void ope7CFIB(EngineState *state, EngineFrame *frame); //calc fibonacci
280 
281  void op00NOOP(byte op);
282 
283 private:
284  MacVentureEngine *_engine;
285  World *_world;
287  Container *_scripts;
288 };
289 
290 } // End of namespace MacVenture
291 
292 #endif
Definition: script.h:45
Definition: script.h:69
Definition: list.h:44
Definition: world.h:97
Definition: container.h:48
Definition: script.h:129
Definition: macventure.h:185
Definition: rect.h:45
Definition: container.h:38
Definition: script.h:145
Definition: script.h:119