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 #ifndef KYRA_SCRIPT_H
23 #define KYRA_SCRIPT_H
24 
25 #include "common/stream.h"
26 #include "common/array.h"
27 #include "common/func.h"
28 #include "common/formats/iff_container.h"
29 
30 namespace Kyra {
31 
32 struct EMCState;
34 
35 struct EMCData {
36  char filename[13];
37 
38  byte *text;
39  uint16 *data;
40  uint32 ordrSize;
41  uint16 *ordr;
42  uint32 dataSize;
43 
44  const Common::Array<const Opcode *> *sysFuncs;
45 };
46 
47 struct EMCState {
48  enum {
49  kStackSize = 100,
50  kStackLastEntry = kStackSize - 1
51  };
52 
53  const uint16 *ip;
54  const EMCData *dataPtr;
55  int16 retValue;
56  uint16 bp;
57  uint16 sp;
58  int16 regs[30]; // VM registers
59  int16 stack[kStackSize]; // VM stack
60 };
61 
62 #ifdef RELEASE_BUILD
63 #define stackPos(x) (script->stack[script->sp+x])
64 #else
65 #define stackPos(x) emcSafeReadStack(script, x, __LINE__, __FILE__)
66 #endif
67 #define safeStackPos(x) (script->sp+x < EMCState::kStackSize ? stackPos(x) : 0)
68 #define stackPosString(x) ((const char *)&script->dataPtr->text[READ_BE_UINT16(&script->dataPtr->text[stackPos(x)<<1])])
69 
70 class Resource;
71 class KyraEngine_v1;
72 
73 class IFFParser : public Common::IFFParser {
74 public:
76  // It seems Westwood missunderstood the 'size' field of the FORM chunk.
77  //
78  // For EMC scripts (type EMC2) it's filesize instead of filesize - 8,
79  // means accidentally including the 8 bytes used by the chunk header for the FORM
80  // chunk.
81  //
82  // For TIM scripts (type AVFS) it's filesize - 12 instead of filesize - 8,
83  // means it will not include the size of the 'type' field in the FORM chunk,
84  // instead of only not including the chunk header size.
85  //
86  // Both lead to some problems in our IFF parser, either reading after the end
87  // of file or producing a "Chunk overread" error message. To work around this
88  // we need to adjust the size field properly.
89 
90  // Fix for certain Russian fan translations:
91  // Westwood's original code completely ignores the FORM chunk and its size
92  // setting. After opening a TIM or EMC file they just check whether the FORM
93  // chunk exists (as a kind of file type verification) and then immediately seek
94  // behind the FORM chunk.
95  // This means that their parser is immune to weird fan translation scripts
96  // where the file size doesn't match the form chunk size. In our implemetation
97  // this would produce "Chunk overread" errors.
98  // Westwood also always pads all chunk sizes to 2 byte alignment after reading
99  // them from the file (not with FORM though, since they completely ignore it).
100  // This seems to do the trick for our FORM chunk size issue with the Russian
101  // fan translations. Another method which I have tried and which seems to work
102  // well would be simply setting _formChunk.size to the file size (-12 for TIM).
103 
104  _formChunk.size = (_formChunk.size + 1) & ~1;
105 
106  if (_formType == MKTAG('E','M','C','2'))
107  _formChunk.size -= 8;
108  else if (_formType == MKTAG('A','V','F','S'))
109  _formChunk.size += 4;
110  }
111 };
112 
114 public:
116 
117  bool load(const char *filename, EMCData *data, const Common::Array<const Opcode *> *opcodes);
118  void unload(EMCData *data);
119 
120  void init(EMCState *scriptState, const EMCData *data);
121  bool start(EMCState *script, int function);
122 
123  bool isValid(EMCState *script);
124 
125  bool run(EMCState *script);
126 protected:
127  KyraEngine_v1 *_vm;
128  int16 _parameter;
129 
130  const char *_filename;
131  EMCData *_scriptData;
132 
133  bool callback(Common::IFFChunk &chunk);
134 
135  typedef void (EMCInterpreter::*OpcodeProc)(EMCState *);
136  struct OpcodeEntry {
137  OpcodeProc proc;
138  const char *desc;
139  };
140 
141  const OpcodeEntry *_opcodes;
142 private:
143  void op_jmp(EMCState *);
144  void op_setRetValue(EMCState *);
145  void op_pushRetOrPos(EMCState *);
146  void op_push(EMCState *);
147  void op_pushReg(EMCState *);
148  void op_pushBPNeg(EMCState *);
149  void op_pushBPAdd(EMCState *);
150  void op_popRetOrPos(EMCState *);
151  void op_popReg(EMCState *);
152  void op_popBPNeg(EMCState *);
153  void op_popBPAdd(EMCState *);
154  void op_addSP(EMCState *);
155  void op_subSP(EMCState *);
156  void op_sysCall(EMCState *);
157  void op_ifNotJmp(EMCState *);
158  void op_negate(EMCState *);
159  void op_eval(EMCState *);
160  void op_setRetAndJmp(EMCState *);
161 };
162 } // End of namespace Kyra
163 
164 #endif
Definition: script.h:113
Definition: resource.h:48
Definition: kyra_v1.h:126
Definition: script.h:73
Definition: script.h:136
Definition: script.h:47
Definition: iff_container.h:173
Definition: func.h:437
Definition: detection.h:27
#define MKTAG(a0, a1, a2, a3)
Definition: endian.h:188
Definition: stream.h:385
Definition: script.h:35
Definition: iff_container.h:160