aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra/script_tim.h
blob: e132ed78c58f4dd428968b609089a764ea00aa99 (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
/* 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 KYRA_SCRIPT_TIM_H
#define KYRA_SCRIPT_TIM_H

#include "kyra/kyra_v1.h"

#include "common/array.h"
#include "common/func.h"
#include "common/str.h"

namespace Kyra {

class WSAMovie_v2;
class Screen_v2;
class Movie;
class LoLEngine;

class TimAnimator {
public:
	struct AnimPart {
		uint16 firstFrame;
		uint16 lastFrame;
		uint16 cycles;
		int16 nextPart;
		int16 partDelay;
		uint16 field_A;
		int16 sfxIndex;
		uint16 sfxFrame;
	};

	struct Animation {
		Movie *wsa;
		int16 x, y;
		uint32 nextFrame;
		uint8 enable;
		uint8 field_D;
		uint8 frameDelay;
		int8 curPart;
		uint8 curFrame;
		uint8 cyclesCompleted;
		uint16 wsaCopyParams;
		int8 lastPart;
		AnimPart *parts;
	};

#ifdef ENABLE_LOL
	TimAnimator(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system, bool useParts);
#else
	TimAnimator(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSystem *system, bool useParts);
#endif
	~TimAnimator();

	void init(int animIndex, Movie *wsa, int x, int y, int wsaCopyParams, int frameDelay);
	void reset(int animIndex, bool clearStruct);

	void displayFrame(int animIndex, int page, int frame, int flags = -1);

	const Movie *getWsaCPtr(int animIndex) { return (animIndex >= 0 && animIndex < 6) ? _animations[animIndex].wsa : 0; }
	int getAnimX(int animIndex) { return (animIndex >= 0 && animIndex < 6) ? _animations[animIndex].x : 0; }
	int getAnimY(int animIndex) { return (animIndex >= 0 && animIndex < 6) ? _animations[animIndex].y : 0; }

#ifdef ENABLE_LOL
	void setupPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame);
	void start(int animIndex, int part);
	void stop(int animIndex);
	void update(int animIndex);
	void playPart(int animIndex, int firstFrame, int lastFrame, int delay);
	int resetLastPart(int animIndex);
#endif

private:
#ifdef ENABLE_LOL
	LoLEngine *_vm;
#else
	KyraEngine_v1 *_vm;
#endif
	Screen_v2 *_screen;
	OSystem *_system;

	Animation *_animations;

	const bool _useParts;
};

struct TIM;
typedef Common::Functor2<const TIM *, const uint16 *, int> TIMOpcode;

struct TIM {
	char filename[13];

	uint16 clickedButton;
	int16 dlgFunc;

	int16 procFunc;
	uint16 procParam;

	enum {
		kCountFuncs = 10
	};

	struct Function {
		uint16 *ip;

		uint32 lastTime;
		uint32 nextTime;

		uint16 *loopIp;

		uint16 *avtl;
	} func[kCountFuncs];

	enum {
		kWSASlots = 6,
		kAnimParts = 10
	};

	struct WSASlot {
		int anim;

		int16 x, y;
		uint16 wsaFlags;
		uint16 offscreen;
	} wsa[kWSASlots];

	uint16 *avtl;
	uint8 *text;

	const Common::Array<const TIMOpcode*> *opcodes;

	// TODO: Get rid of this ugly HACK to allow the
	// Lands of Lore outro to be working properly.
	bool isLoLOutro;
	uint8 lolCharacter;
};

class TIMInterpreter {
public:
	TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSystem *system);
	virtual ~TIMInterpreter();

	TIM *load(const char *filename, const Common::Array<const TIMOpcode*> *opcodes);
	void unload(TIM *&tim) const;

	bool callback(Common::IFFChunk &chunk);

	virtual int initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags);
	virtual int freeAnimStruct(int index);
	TimAnimator *animator() { return _animator; }

	void setLangData(const char *filename);
	void clearLangData() { delete[] _langData; _langData = 0; }

	const char *getCTableEntry(uint idx) const;

	void resetFinishedFlag() { _finished = false; }
	bool finished() const { return _finished; }

	int exec(TIM *tim, bool loop);
	void stopCurFunc() { if (_currentTim) cmd_stopCurFunc(0); }
	void stopAllFuncs(TIM *tim);

	void refreshTimersAfterPause(uint32 elapsedTime);

	void displayText(uint16 textId, int16 flags);
	void displayText(uint16 textId, int16 flags, uint8 color);
	void setupTextPalette(uint index, int fadePalette);

	virtual void resetDialogueState(TIM *tim) {}

	int _drawPage2;

	int _palDelayInc, _palDiff, _palDelayAcc;
	int _abortFlag;

protected:
	KyraEngine_v1 *_vm;
	Screen_v2 *_screen;
	OSystem *_system;

	TIM *_currentTim;
	int _currentFunc;

	TimAnimator *_animator;

	bool _finished;

	// used when loading
	int _avtlChunkSize;
	const char *_filename;
	TIM *_tim;

	Common::String _vocFiles[120];

	virtual void update() {}
	virtual void checkSpeechProgress() {}

	char _audioFilename[32];

	uint8 *_langData;
	char *getTableEntry(uint idx);
	bool _textDisplayed;
	uint8 *_textAreaBuffer;

	virtual int execCommand(int cmd, const uint16 *param);

	typedef int (TIMInterpreter::*CommandProc)(const uint16 *);
	struct CommandEntry {
		CommandProc proc;
		const char *desc;
	};

	const CommandEntry *_commands;
	int _commandsSize;

	int cmd_initFunc0(const uint16 *param);
	int cmd_stopCurFunc(const uint16 *param);
	int cmd_initWSA(const uint16 *param);
	int cmd_uninitWSA(const uint16 *param);
	int cmd_initFunc(const uint16 *param);
	int cmd_stopFunc(const uint16 *param);
	int cmd_wsaDisplayFrame(const uint16 *param);
	int cmd_displayText(const uint16 *param);
	int cmd_loadVocFile(const uint16 *param);
	int cmd_unloadVocFile(const uint16 *param);
	int cmd_playVocFile(const uint16 *param);
	int cmd_loadSoundFile(const uint16 *param);
	int cmd_playMusicTrack(const uint16 *param);
	virtual int cmd_setLoopIp(const uint16 *param);
	virtual int cmd_continueLoop(const uint16 *param);
	int cmd_resetLoopIp(const uint16 *param);
	int cmd_resetAllRuntimes(const uint16 *param);
	int cmd_execOpcode(const uint16 *param);
	int cmd_initFuncNow(const uint16 *param);
	int cmd_stopFuncNow(const uint16 *param);
#define cmd_return(n, v) \
	int cmd_return_##n(const uint16 *){ return v; }
	cmd_return( 1,  1)
	cmd_return(n1, -1)
#undef cmd_return
};

#ifdef ENABLE_LOL
class LoLEngine;
class Screen_LoL;
class TIMInterpreter_LoL : public TIMInterpreter {
public:
	TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system);

	int initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaCopyParams);
	int freeAnimStruct(int index);

	void resetDialogueState(TIM *tim);

private:
	void update();
	void checkSpeechProgress();

	char *getTableString(int id);
	void advanceToOpcode(int opcode);

	LoLEngine *_vm;
	Screen_LoL *_screen;

	virtual int execCommand(int cmd, const uint16 *param);

	typedef int (TIMInterpreter_LoL::*CommandProc)(const uint16 *);
	struct CommandEntry {
		CommandProc proc;
		const char *desc;
	};

	const CommandEntry *_commands;
	int _commandsSize;

	int cmd_stopAllFuncs(const uint16 *param);
	int cmd_setLoopIp(const uint16 *param);
	int cmd_continueLoop(const uint16 *param);
	int cmd_processDialogue(const uint16 *param);
	int cmd_dialogueBox(const uint16 *param);
};
#endif // ENABLE_LOL

} // End of namespace Kyra

#endif