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
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (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, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef PRINCE_SCRIPT_H
24 #define PRINCE_SCRIPT_H
25 
26 #include "common/random.h"
27 #include "common/endian.h"
28 #include "common/array.h"
29 #include "common/stream.h"
30 
31 #include "prince/flags.h"
32 
33 namespace Prince {
34 
35 class PrinceEngine;
36 class Animation;
37 class Object;
38 struct Anim;
39 struct BackgroundAnim;
40 struct Mask;
41 
42 class Room {
43 public:
44 	Room();
45 	int _mobs; // mob flag offset
46 	int _backAnim; // offset to array of animation numbers
47 	int _obj; // offset to array of object numbers
48 	int _nak; // offset to array of masks
49 	int _itemUse;
50 	int _itemGive;
51 	int _walkTo; // offset to array of WALKTO events or 0
52 	int _examine; // offset to array of EXAMINE events or 0
53 	int _pickup;
54 	int _use;
55 	int _pushOpen;
56 	int _pullClose;
57 	int _talk;
58 	int _give;
59 
60 	bool loadStream(Common::SeekableReadStream &stream);
61 	bool loadRoom(byte *roomData);
62 	int getOptionOffset(int option);
63 
64 private:
65 
66 	typedef void (Room::*LoadingStep)(Common::SeekableReadStream &stream);
67 
68 	void nextLoadStep(Common::SeekableReadStream &stream, LoadingStep step);
69 
70 	void loadMobs(Common::SeekableReadStream &stream);
71 	void loadBackAnim(Common::SeekableReadStream &stream);
72 	void loadObj(Common::SeekableReadStream &stream);
73 	void loadNak(Common::SeekableReadStream &stream);
74 	void loadItemUse(Common::SeekableReadStream &stream);
75 	void loadItemGive(Common::SeekableReadStream &stream);
76 	void loadWalkTo(Common::SeekableReadStream &stream);
77 	void loadExamine(Common::SeekableReadStream &stream);
78 	void loadPickup(Common::SeekableReadStream &stream);
79 	void loadUse(Common::SeekableReadStream &stream);
80 	void loadPushOpen(Common::SeekableReadStream &stream);
81 	void loadPullClose(Common::SeekableReadStream &stream);
82 	void loadTalk(Common::SeekableReadStream &stream);
83 	void loadGive(Common::SeekableReadStream &stream);
84 };
85 
86 
87 class Script {
88 public:
89 	static const int16 kMaxRooms = 60;
90 
91 	Script(PrinceEngine *vm);
92 	~Script();
93 
94 	struct ScriptInfo {
95 		int rooms;
96 		int startGame;
97 		int restoreGame;
98 		int stdExamine;
99 		int stdPickup;
100 		int stdUse;
101 		int stdOpen;
102 		int stdClose;
103 		int stdTalk;
104 		int stdGive;
105 		int usdCode;
106 		int invObjExam;
107 		int invObjUse;
108 		int invObjUU;
109 		int stdUseItem;
110 		int lightSources;
111 		int specRout;
112 		int invObjGive;
113 		int stdGiveItem;
114 		int goTester;
115 	};
116 
117 	ScriptInfo _scriptInfo;
118 
119 	bool loadStream(Common::SeekableReadStream &stream);
120 
121 	uint16 readScript16(uint32 address);
122 	uint32 readScript32(uint32 address);
123 
124 	uint32 getStartGameOffset();
125 	uint32 getLocationInitScript(int initRoomTableOffset, int roomNr);
126 	int16 getLightX(int locationNr);
127 	int16 getLightY(int locationNr);
128 	int32 getShadowScale(int locationNr);
129 	uint8 *getRoomOffset(int locationNr);
130 	int32 getOptionStandardOffset(int option);
131 	uint8 *getHeroAnimName(int offset);
132 
133 	void installBackAnims(Common::Array<BackgroundAnim> &backAnimList, int roomBackAnimOffset);
134 	void installSingleBackAnim(Common::Array<BackgroundAnim> &backAnimList, int slot, int roomBackAnimOffset);
135 	void installObjects(int offset);
136 	bool loadAllMasks(Common::Array<Mask> &maskList, int offset);
137 
138 	int scanMobEvents(int mobMask, int dataEventOffset);
139 	int scanMobEventsWithItem(int mobMask, int dataEventOffset, int itemMask);
140 
141 	byte getMobVisible(int roomMobOffset, uint16 mob);
142 	void setMobVisible(int roomMobOffset, uint16 mob, byte value);
143 
144 	uint32 getBackAnimId(int roomBackAnimOffset, int slot);
145 	void setBackAnimId(int roomBackAnimOffset, int slot, int animId);
146 
147 	byte getObjId(int roomObjOffset, int slot);
148 	void setObjId(int roomObjOffset, int slot, byte objectId);
149 
getString(uint32 offset)150 	const char *getString(uint32 offset) {
151 		return (const char *)(&_data[offset]);
152 	}
153 
154 private:
155 	PrinceEngine *_vm;
156 	uint8 *_data;
157 	uint32 _dataSize;
158 	Common::Array<Room> _roomList;
159 };
160 
161 class InterpreterFlags {
162 public:
163 	InterpreterFlags();
164 
165 	void setFlagValue(Flags::Id flag, int32 value);
166 	int32 getFlagValue(Flags::Id flag);
167 
168 	void resetAllFlags();
169 
170 	static const uint16 kFlagMask = 0x8000;
171 	static const uint16 kMaxFlags = 2000;
172 private:
173 	int32 _flags[kMaxFlags];
174 };
175 
176 class Interpreter {
177 public:
178 	Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags);
179 
stopBg()180 	void stopBg() { _bgOpcodePC = 0; }
181 
182 	void stepBg();
183 	void stepFg();
184 	void storeNewPC(int opcodePC);
185 	int getLastOPCode();
186 	int getFgOpcodePC();
187 
188 	void setBgOpcodePC(uint32 value);
189 	void setFgOpcodePC(uint32 value);
190 
191 	uint32 getCurrentString();
192 	void setCurrentString(uint32 value);
193 
194 	byte *getString();
195 	void setString(byte *newString);
196 	void increaseString();
197 
198 	void setResult(byte value);
199 
200 private:
201 	PrinceEngine *_vm;
202 	Script *_script;
203 	InterpreterFlags *_flags;
204 
205 	uint32 _currentInstruction;
206 
207 	uint32 _bgOpcodePC;
208 	uint32 _fgOpcodePC;
209 
210 	uint16 _lastOpcode;
211 	uint32 _lastInstruction;
212 	byte _result;
213 
214 	bool _opcodeNF; // break interpreter loop
215 	bool _opcodeEnd; // end of a game flag
216 
217 	static const uint32 _STACK_SIZE = 500;
218 	uint32 _stack[_STACK_SIZE];
219 	struct stringStack {
220 		byte *string;
221 		byte *dialogData;
222 		uint32 currentString;
223 	} _stringStack;
224 	uint8 _stacktop;
225 	uint32 _waitFlag;
226 
227 	byte *_string;
228 	uint32 _currentString;
229 	const char *_mode;
230 
231 	// Helper functions
232 	uint32 step(uint32 opcodePC);
233 	uint16 readScript16();
234 	uint32 readScript32();
235 	int32 readScriptFlagValue();
236 	Flags::Id readScriptFlagId();
237 	int checkSeq(byte *string);
238 
239 	void debugInterpreter(const char *s, ...);
240 
241 	typedef void (Interpreter::*OpcodeFunc)();
242 	static OpcodeFunc _opcodes[];
243 
244 	static const uint kGiveLetterScriptFix = 79002;
245 	static const uint kSecondBirdAnimationScriptFix = 45658;
246 
247 	// Keep opcode handlers names as they are in original code
248 	// making it easier to switch back and forth
249 	void O_WAITFOREVER();
250 	void O_BLACKPALETTE();
251 	void O_SETUPPALETTE();
252 	void O_INITROOM();
253 	void O_SETSAMPLE();
254 	void O_FREESAMPLE();
255 	void O_PLAYSAMPLE();
256 	void O_PUTOBJECT();
257 	void O_REMOBJECT();
258 	void O_SHOWANIM();
259 	void O_CHECKANIMEND();
260 	void O_FREEANIM();
261 	void O_CHECKANIMFRAME();
262 	void O_PUTBACKANIM();
263 	void O_REMBACKANIM();
264 	void O_CHECKBACKANIMFRAME();
265 	void O_FREEALLSAMPLES();
266 	void O_SETMUSIC();
267 	void O_STOPMUSIC();
268 	void O__WAIT();
269 	void O_UPDATEOFF();
270 	void O_UPDATEON();
271 	void O_UPDATE ();
272 	void O_CLS();
273 	void O__CALL();
274 	void O_RETURN();
275 	void O_GO();
276 	void O_BACKANIMUPDATEOFF();
277 	void O_BACKANIMUPDATEON();
278 	void O_CHANGECURSOR();
279 	void O_CHANGEANIMTYPE();
280 	void O__SETFLAG();
281 	void O_COMPARE();
282 	void O_JUMPZ();
283 	void O_JUMPNZ();
284 	void O_EXIT();
285 	void O_ADDFLAG();
286 	void O_TALKANIM();
287 	void O_SUBFLAG();
288 	void O_SETSTRING();
289 	void O_ANDFLAG();
290 	void O_GETMOBDATA();
291 	void O_ORFLAG();
292 	void O_SETMOBDATA();
293 	void O_XORFLAG();
294 	void O_GETMOBTEXT();
295 	void O_MOVEHERO();
296 	void O_WALKHERO();
297 	void O_SETHERO();
298 	void O_HEROOFF();
299 	void O_HEROON();
300 	void O_CLSTEXT();
301 	void O_CALLTABLE();
302 	void O_CHANGEMOB();
303 	void O_ADDINV();
304 	void O_REMINV();
305 	void O_REPINV();
306 	void O_OBSOLETE_GETACTION();
307 	void O_ADDWALKAREA();
308 	void O_REMWALKAREA();
309 	void O_RESTOREWALKAREA();
310 	void O_WAITFRAME();
311 	void O_SETFRAME();
312 	void O_RUNACTION();
313 	void O_COMPAREHI();
314 	void O_COMPARELO();
315 	void O_PRELOADSET();
316 	void O_FREEPRELOAD();
317 	void O_CHECKINV();
318 	void O_TALKHERO();
319 	void O_WAITTEXT();
320 	void O_SETHEROANIM();
321 	void O_WAITHEROANIM();
322 	void O_GETHERODATA();
323 	void O_GETMOUSEBUTTON();
324 	void O_CHANGEFRAMES();
325 	void O_CHANGEBACKFRAMES();
326 	void O_GETBACKANIMDATA();
327 	void O_GETANIMDATA();
328 	void O_SETBGCODE();
329 	void O_SETBACKFRAME();
330 	void O_GETRND();
331 	void O_TALKBACKANIM();
332 	void O_LOADPATH();
333 	void O_GETCHAR();
334 	void O_SETDFLAG();
335 	void O_CALLDFLAG();
336 	void O_PRINTAT();
337 	void O_ZOOMIN();
338 	void O_ZOOMOUT();
339 	void O_SETSTRINGOFFSET();
340 	void O_GETOBJDATA();
341 	void O_SETOBJDATA();
342 	void O_SWAPOBJECTS();
343 	void O_CHANGEHEROSET();
344 	void O_ADDSTRING();
345 	void O_SUBSTRING();
346 	void O_INITDIALOG();
347 	void O_ENABLEDIALOGOPT();
348 	void O_DISABLEDIALOGOPT();
349 	void O_SHOWDIALOGBOX();
350 	void O_STOPSAMPLE();
351 	void O_BACKANIMRANGE();
352 	void O_CLEARPATH();
353 	void O_SETPATH();
354 	void O_GETHEROX();
355 	void O_GETHEROY();
356 	void O_GETHEROD();
357 	void O_PUSHSTRING();
358 	void O_POPSTRING();
359 	void O_SETFGCODE();
360 	void O_STOPHERO();
361 	void O_ANIMUPDATEOFF();
362 	void O_ANIMUPDATEON();
363 	void O_FREECURSOR();
364 	void O_ADDINVQUIET();
365 	void O_RUNHERO();
366 	void O_SETBACKANIMDATA();
367 	void O_VIEWFLC();
368 	void O_CHECKFLCFRAME();
369 	void O_CHECKFLCEND();
370 	void O_FREEFLC();
371 	void O_TALKHEROSTOP();
372 	void O_HEROCOLOR();
373 	void O_GRABMAPA();
374 	void O_ENABLENAK();
375 	void O_DISABLENAK();
376 	void O_GETMOBNAME();
377 	void O_SWAPINVENTORY();
378 	void O_CLEARINVENTORY();
379 	void O_SKIPTEXT();
380 	void O_SETVOICEH();
381 	void O_SETVOICEA();
382 	void O_SETVOICEB();
383 	void O_SETVOICEC();
384 	void O_VIEWFLCLOOP();
385 	void O_FLCSPEED();
386 	void O_OPENINVENTORY();
387 	void O_KRZYWA();
388 	void O_GETKRZYWA();
389 	void O_GETMOB();
390 	void O_INPUTLINE();
391 	void O_SETVOICED();
392 	void O_BREAK_POINT();
393 
394 };
395 
396 } // End of namespace Prince
397 
398 #endif
399