aboutsummaryrefslogtreecommitdiff
path: root/engines/cine/script.h
blob: ec8278065f0251aa1f0446d0409a3cf6a64d16c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#ifndef CINE_SCRIPT_H
#define CINE_SCRIPT_H

#include "common/savefile.h"
#include "common/array.h"
#include "common/list.h"
#include "common/ptr.h"

namespace Cine {

#define SCRIPT_STACK_SIZE 50
#define LOCAL_VARS_SIZE 50

/**
 * Fixed size array of script variables.
 *
 * Array size can be set in constructors, once the instance is created,
 * it cannot be changed directly.
 */

class FWScript;

typedef int (FWScript::*OpFunc)();

struct Opcode {
	OpFunc proc;
	const char *args;
};

/**
 *  Fixed size array for script variables
 */
class ScriptVars {
private:
	unsigned int _size; ///< Size of array
	int16 *_vars; ///< Variable values

public:
	// Explicit to prevent var=0 instead of var[i]=0 typos.
	explicit ScriptVars(unsigned int len = 50);
	ScriptVars(Common::SeekableReadStream &fHandle, unsigned int len = 50);
	ScriptVars(const ScriptVars &src);
	~ScriptVars();

	void reinit(unsigned int len);
	ScriptVars &operator=(const ScriptVars &src);
	int16 &operator[](unsigned int idx);
	int16 operator[](unsigned int idx) const;

	void save(Common::OutSaveFile &fHandle) const;
	void save(Common::OutSaveFile &fHandle, unsigned int len) const;
	void load(Common::SeekableReadStream &fHandle);
	void load(Common::SeekableReadStream &fHandle, unsigned int len);
	void reset();
};

class FWScriptInfo;

/**
 *  Script bytecode and initial labels, ScriptStruct replacement.
 *
 * _data is one byte longer to make sure strings in bytecode are properly
 * terminated
 */
class RawScript {
private:
	byte *_data; ///< Script bytecode
	ScriptVars _labels; ///< Initial script labels

protected:
	void computeLabels(const FWScriptInfo &info);
	int getNextLabel(const FWScriptInfo &info, int offset) const;

public:
	uint16 _size; ///< Bytecode length

	explicit RawScript(uint16 size);
	RawScript(const FWScriptInfo &info, const byte *data, uint16 size);
	RawScript(const RawScript &src);
	~RawScript();

	RawScript &operator=(const RawScript &src);

	void setData(const FWScriptInfo &info, const byte *data);
	const ScriptVars &labels() const;
	byte getByte(unsigned int pos) const;
	uint16 getWord(unsigned int pos) const;
	const char *getString(unsigned int pos) const;
	uint16 getLabel(const FWScriptInfo &info, byte index, uint16 offset) const;
};

/**
 * Object script class, RelObjectScript replacement
 *
 * Script parameters are not used, this class is required by different
 * script initialization of object scripts
 */
class RawObjectScript : public RawScript {
public:
	int16 _runCount; ///< How many times the script was used
	uint16 _param1; ///< Additional parameter not used at the moment
	uint16 _param2; ///< Additional parameter not used at the moment
	uint16 _param3; ///< Additional parameter not used at the moment

	RawObjectScript(uint16 size, uint16 p1, uint16 p2, uint16 p3);
	RawObjectScript(const FWScriptInfo &info, const byte *data, uint16 size, uint16 p1, uint16 p2, uint16 p3);

	/**
	 * Run the script one more time.
	 * @return Run count before incrementation
	 */
	int16 run() { return _runCount++; }
};

/**
 * Future Wars script, prcLinkedListStruct replacement.
 * @todo Rewrite _globalVars initialization
 */
class FWScript {
private:
	const RawScript &_script; ///< Script bytecode reference
	uint16 _pos; ///< Current position in script
	uint16 _line; ///< Current opcode index in bytecode for debugging
	uint16 _compare; ///< Last compare result
	ScriptVars _labels; ///< Current script labels
	ScriptVars _localVars; ///< Local script variables
	ScriptVars &_globalVars; ///< Global variables reference
	FWScriptInfo *_info; ///< Script info

protected:
	static const Opcode *_opcodeTable;
	static unsigned int _numOpcodes;

	int o1_modifyObjectParam();
	int o1_getObjectParam();
	int o1_addObjectParam();
	int o1_subObjectParam();
	int o1_mulObjectParam();
	int o1_divObjectParam();
	int o1_compareObjectParam();
	int o1_setupObject();
	int o1_checkCollision();
	int o1_loadVar();
	int o1_addVar();
	int o1_subVar();
	int o1_mulVar();
	int o1_divVar();
	int o1_compareVar();
	int o1_modifyObjectParam2();
	int o1_loadMask0();
	int o1_unloadMask0();
	int o1_addToBgList();
	int o1_loadMask1();
	int o1_unloadMask1();
	int o1_loadMask4();
	int o1_unloadMask4();
	int o1_addSpriteFilledToBgList();
	int o1_op1B();
	int o1_label();
	int o1_goto();
	int o1_gotoIfSup();
	int o1_gotoIfSupEqu();
	int o1_gotoIfInf();
	int o1_gotoIfInfEqu();
	int o1_gotoIfEqu();
	int o1_gotoIfDiff();
	int o1_removeLabel();
	int o1_loop();
	int o1_startGlobalScript();
	int o1_endGlobalScript();
	int o1_loadAnim();
	int o1_loadBg();
	int o1_loadCt();
	int o1_loadPart();
	int o1_closePart();
	int o1_loadNewPrcName();
	int o1_requestCheckPendingDataLoad();
	int o1_blitAndFade();
	int o1_fadeToBlack();
	int o1_transformPaletteRange();
	int o1_setDefaultMenuBgColor();
	int o1_palRotate();
	int o1_break();
	int o1_endScript();
	int o1_message();
	int o1_loadGlobalVar();
	int o1_compareGlobalVar();
	int o1_declareFunctionName();
	int o1_freePartRange();
	int o1_unloadAllMasks();
	int o1_setScreenDimensions();
	int o1_displayBackground();
	int o1_initializeZoneData();
	int o1_setZoneDataEntry();
	int o1_getZoneDataEntry();
	int o1_setPlayerCommandPosY();
	int o1_allowPlayerInput();
	int o1_disallowPlayerInput();
	int o1_changeDataDisk();
	int o1_loadMusic();
	int o1_playMusic();
	int o1_fadeOutMusic();
	int o1_stopSample();
	int o1_op71();
	int o1_op72();
	int o1_op73();
	int o1_playSample();
	int o1_playSampleSwapped();
	int o1_disableSystemMenu();
	int o1_loadMask5();
	int o1_unloadMask5();

	// pointers to member functions in C++ suck...
	int o2_loadCt();
	int o2_loadPart();
	int o2_addSeqListElement();
	int o2_removeSeq();
	int o2_playSample();
	int o2_playSampleAlt();
	int o2_op81();
	int o2_modifySeqListElement();
	int o2_isSeqRunning();
	int o2_gotoIfSupNearest();
	int o2_gotoIfSupEquNearest();
	int o2_gotoIfInfNearest();
	int o2_gotoIfInfEquNearest();
	int o2_gotoIfEquNearest();
	int o2_gotoIfDiffNearest();
	int o2_startObjectScript();
	int o2_stopObjectScript();
	int o2_op8D();
	int o2_addBackground();
	int o2_removeBackground();
	int o2_loadAbs();
	int o2_loadBg();
	int o2_wasZoneChecked();
	int o2_op9B();
	int o2_op9C();
	int o2_useBgScroll();
	int o2_setAdditionalBgVScroll();
	int o2_op9F();
	int o2_addGfxElementType20();
	int o2_removeGfxElementType20();
	int o2_addGfxElementType21();
	int o2_removeGfxElementType21();
	int o2_loadMask22();
	int o2_unloadMask22();

	byte getNextByte();
	uint16 getNextWord();
	const char *getNextString();

	void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos);

	FWScript(const RawScript &script, int16 index, FWScriptInfo *info);
	FWScript(RawObjectScript &script, int16 index, FWScriptInfo *info);
	FWScript(const FWScript &src, FWScriptInfo *info);

public:
	int16 _index; ///< Index in script table

	static void setupTable();

	FWScript(const RawScript &script, int16 index);
//	FWScript(const RawObjectScript &script, int16 index);
	FWScript(const FWScript &src);
	~FWScript();

	int execute();
	void save(Common::OutSaveFile &fHandle) const;

	friend class FWScriptInfo;

	// workaround for bug in g++ which prevents protected member functions
	// of FWScript from being used in OSScript::_opcodeTable[]
	// initialization ("error: protected within this context")
	friend class OSScript;
};

/**
 * Operation Stealth script, prcLinkedListStruct replacement
 */
class OSScript : public FWScript {
private:
	static const Opcode *_opcodeTable;
	static unsigned int _numOpcodes;

protected:
	void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos);

public:
	static void setupTable();

	OSScript(const RawScript &script, int16 index);
	OSScript(RawObjectScript &script, int16 index);
	OSScript(const OSScript &src);

	friend class OSScriptInfo;
};

/**
 * Future Wars script factory and info
 */
class FWScriptInfo {
protected:
	virtual OpFunc opcodeHandler(byte opcode) const;

public:
	virtual ~FWScriptInfo() {}

	virtual const char *opcodeInfo(byte opcode) const;
	virtual FWScript *create(const RawScript &script, int16 index) const;
	virtual FWScript *create(const RawObjectScript &script, int16 index) const;
	virtual FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
	virtual FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;

	friend class FWScript;
};

/**
 * Operation Stealth script factory and info
 */
class OSScriptInfo : public FWScriptInfo {
protected:
	virtual OpFunc opcodeHandler(byte opcode) const;

public:
	virtual ~OSScriptInfo() {}

	virtual const char *opcodeInfo(byte opcode) const;
	virtual FWScript *create(const RawScript &script, int16 index) const;
	virtual FWScript *create(const RawObjectScript &script, int16 index) const;
	virtual FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
	virtual FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;

	friend class FWScript;
};

typedef Common::SharedPtr<FWScript> ScriptPtr;
typedef Common::SharedPtr<RawScript> RawScriptPtr;
typedef Common::SharedPtr<RawObjectScript> RawObjectScriptPtr;
typedef Common::List<ScriptPtr> ScriptList;
typedef Common::Array<RawScriptPtr> RawScriptArray;
typedef Common::Array<RawObjectScriptPtr> RawObjectScriptArray;

#define NUM_MAX_SCRIPT 50

extern FWScriptInfo *scriptInfo;

void setupOpcodes();

void decompileScript(const byte *scriptPtr, uint16 scriptSize, uint16 scriptIdx);
void dumpScript(char *dumpName);

#define OP_loadPart                     0x3F
#define OP_loadNewPrcName               0x41
#define OP_requestCheckPendingDataLoad  0x42
#define OP_endScript                    0x50

void addScriptToGlobalScripts(uint16 idx);
int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx);

void runObjectScript(int16 entryIdx);

void executeObjectScripts();
void executeGlobalScripts();

void purgeObjectScripts();
void purgeGlobalScripts();

} // End of namespace Cine

#endif