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
30namespace Kyra {
31
32struct EMCState;
34
35struct 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
47struct 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
70class Resource;
71class KyraEngine_v1;
72
74public:
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
114public:
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);
126protected:
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;
142private:
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: iff_container.h:173
IFFChunkNav _formChunk
The root chunk of the file.
Definition: iff_container.h:226
Definition: stream.h:385
Definition: script.h:113
Definition: script.h:73
Definition: kyra_v1.h:126
Definition: resource.h:48
#define MKTAG(a0, a1, a2, a3)
Definition: endian.h:188
Definition: detection.h:27
Definition: func.h:437
Definition: iff_container.h:160
Definition: script.h:35
Definition: script.h:136
Definition: script.h:47