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 KYRA_KYRA_MR_H
24 #define KYRA_KYRA_MR_H
25 
26 #include "kyra/engine/kyra_v2.h"
27 #include "kyra/graphics/screen_mr.h"
28 #include "kyra/script/script.h"
29 #include "kyra/gui/gui_mr.h"
30 
31 #include "common/hashmap.h"
32 #include "common/list.h"
33 
34 namespace Kyra {
35 
36 class SoundDigital_MR;
37 class Screen_MR;
38 class MainMenu;
39 class WSAMovie_v2;
40 class TextDisplayer_MR;
41 struct Button;
42 
43 class KyraEngine_MR : public KyraEngine_v2 {
44 friend class TextDisplayer_MR;
45 friend class GUI_MR;
46 public:
47 	KyraEngine_MR(OSystem *system, const GameFlags &flags);
48 	~KyraEngine_MR();
49 
50 	// Regarding pausing of the engine:
51 	// Idle animation time, item animations and album animations should be taken
52 	// care of, but since those would just produce minor glitches it's not that
53 	// important.
54 
screen()55 	Screen *screen() { return _screen; }
screen_v2()56 	Screen_v2 *screen_v2() const { return _screen; }
gui()57 	GUI *gui() const { return _gui; }
soundDigital()58 	SoundDigital_MR *soundDigital() { return _soundDigital; }
language()59 	int language() const { return _lang; }
heliumMode()60 	bool heliumMode() const { return _configHelium; }
61 
62 	Common::Error go();
63 
64 	void playVQA(const char *name);
65 
66 private:
67 	static const EngineDesc _mrEngineDesc;
68 
69 	// config
70 	bool _configStudio;
71 	bool _configSkip;
72 	bool _configHelium;
73 	int _configVQAQuality;
74 
75 	void registerDefaultSettings();
76 	void writeSettings();
77 	void readSettings();
78 
79 	void initStaticResource();
80 
81 	// --
82 	Screen_MR *_screen;
83 	SoundDigital_MR *_soundDigital;
84 
85 	Common::Error init();
86 
87 	void preinit();
88 	void startup();
89 	void runStartupScript(int script, int unk1);
90 
91 	void setupOpcodeTable();
92 
93 	// input
94 	bool skipFlag() const;
95 	void resetSkipFlag(bool removeEvent = true);
96 
97 	// run
98 	bool _menuDirectlyToLoad;
99 
100 	void runLoop();
101 	void handleInput(int x, int y);
102 	int inputSceneChange(int x, int y, int unk1, int unk2);
103 
104 	void update();
105 	void updateWithText();
106 	void updateMouse();
107 
108 	// sound specific
109 private:
110 	void playMenuAudioFile();
111 
112 	int _musicSoundChannel;
113 	int _fadeOutMusicChannel;
114 	const char *_menuAudioFile;
115 
116 	const char *const *_soundList;
117 	int _soundListSize;
118 
119 	void snd_playWanderScoreViaMap(int track, int force);
120 	void stopMusicTrack();
121 
122 	void fadeOutMusic(int ticks);
123 
124 	void snd_playSoundEffect(int item, int volume);
125 
126 	const uint8 *_sfxFileMap;
127 	int _sfxFileMapSize;
128 	const char *const *_sfxFileList;
129 	int _sfxFileListSize;
130 
131 	int _voiceSoundChannel;
132 
133 	void playVoice(int high, int low);
134 	void snd_playVoiceFile(int file);
135 	bool snd_voiceIsPlaying();
136 	void snd_stopVoice();
137 
138 	int _curStudioSFX;
139 	void playStudioSFX(const char *str);
140 
141 	// gui
142 	GUI_MR *_gui;
143 
144 	Button *_mainButtonData;
145 	Button *_mainButtonList;
146 	bool _mainButtonListInitialized;
147 	void initMainButtonList(bool disable);
148 
149 	bool _enableInventory;
150 	int buttonInventory(Button *button);
151 	int buttonMoodChange(Button *button);
152 	int buttonShowScore(Button *button);
153 	int buttonJesterStaff(Button *button);
154 
155 	void loadButtonShapes();
156 	int callbackButton1(Button *button);
157 	int callbackButton2(Button *button);
158 	int callbackButton3(Button *button);
159 
160 	// -> main menu
161 	void initMainMenu();
162 	void uninitMainMenu();
163 
164 	MainMenu *_menu;
165 	WSAMovie_v2 *_menuAnim;
166 
167 	// timer
168 	void setupTimers();
169 
170 	void setWalkspeed(uint8);
171 	void setCommandLineRestoreTimer(int secs);
172 
173 	void timerRestoreCommandLine(int arg);
174 	void timerRunSceneScript7(int arg);
175 	void timerFleaDeath(int arg);
176 
177 	uint32 _nextIdleAnim;
178 	void setNextIdleAnimTimer();
179 
180 	// pathfinder
181 	bool lineIsPassable(int x, int y);
182 
183 private:
184 	// main menu
185 	const char *const *_mainMenuStrings;
186 	int _mainMenuStringsSize;
187 
188 	static const char *const _mainMenuSpanishFan[];
189 	static const char *const _mainMenuItalianFan[];
190 
191 	// animator
192 	uint8 *_gamePlayBuffer;
193 	void restorePage3();
194 
195 	void clearAnimObjects();
196 
197 	void animSetupPaletteEntry(AnimObj *anim);
198 
199 	void drawAnimObjects();
200 	void drawSceneAnimObject(AnimObj *obj, int x, int y, int drawLayer);
201 	void drawCharacterAnimObject(AnimObj *obj, int x, int y, int drawLayer);
202 
203 	void refreshAnimObjects(int force);
204 
205 	bool _loadingState;
206 	void updateItemAnimations();
207 	void updateCharacterAnim(int charId);
208 
209 	void updateSceneAnim(int anim, int newFrame);
210 	void setupSceneAnimObject(int anim, uint16 flags, int x, int y, int x2, int y2, int w, int h, int unk10, int specialSize, int unk14, int shape, const char *filename);
211 	void removeSceneAnimObject(int anim, int refresh);
212 
213 	int _charBackUpWidth2, _charBackUpHeight2;
214 	int _charBackUpWidth, _charBackUpHeight;
215 
216 	void setCharacterAnimDim(int w, int h);
217 	void resetCharacterAnimDim();
218 
219 	bool _nextIdleType;
220 	void showIdleAnim();
221 
222 	const ItemAnimDefinition *_itemAnimDefinition;
223 	ActiveItemAnim _activeItemAnim[10];
224 	int _nextAnimItem;
225 
226 	// interface
227 	uint8 *_interface;
228 	uint8 *_interfaceCommandLine;
229 
230 	void loadInterfaceShapes();
231 	void loadInterface();
232 
233 	void showMessage(const char *string, uint8 c0, uint8 c1);
234 	void showMessageFromCCode(int string, uint8 c0, int);
235 	void updateItemCommand(Item item, int str, uint8 c0);
236 
237 	void updateCommandLine();
238 	void restoreCommandLine();
239 	void updateCLState();
240 
241 	int _commandLineY;
242 	const char *_shownMessage;
243 	bool _restoreCommandLine;
244 	bool _inventoryState;
245 	int _inventoryScrollSpeed;
246 
247 	void showInventory();
248 	void hideInventory();
249 
250 	void drawMalcolmsMoodText();
251 	void drawMalcolmsMoodPointer(int frame, int page);
252 	void drawJestersStaff(int type, int page);
253 
254 	void drawScore(int page, int x, int y);
255 	void drawScoreCounting(int oldScore, int newScore, int drawOld, const int x);
256 	int getScoreX(const char *str);
257 
258 	static const uint8 _inventoryX[];
259 	static const uint8 _inventoryY[];
260 	void redrawInventory(int page);
261 	void clearInventorySlot(int slot, int page);
262 	void drawInventorySlot(int page, Item item, int slot);
263 
264 	WSAMovie_v2 *_invWsa;
265 	int _invWsaFrame;
266 
267 	// localization
268 	uint8 *_scoreFile;
269 	uint8 *_cCodeFile;
270 	uint8 *_scenesFile;
271 	uint8 *_itemFile;
272 	uint8 *_optionsFile;
273 	uint8 *_actorFile;
274 	uint32 _actorFileSize;
275 	uint8 *_sceneStrings;
276 
277 	uint8 *getTableEntry(uint8 *buffer, int id);
278 	void getTableEntry(Common::SeekableReadStream *stream, int id, char *dst);
279 
280 	// items
281 	int8 *_itemBuffer1;
282 	int8 *_itemBuffer2;
283 
284 	static const Item _trashItemList[];
285 	void removeTrashItems();
286 
287 	void initItems();
288 
289 	int checkItemCollision(int x, int y);
290 
291 	bool dropItem(int unk1, Item item, int x, int y, int unk2);
292 	bool processItemDrop(uint16 sceneId, Item item, int x, int y, int unk1, int unk2);
293 	void itemDropDown(int startX, int startY, int dstX, int dstY, int itemSlot, Item item, int remove);
294 	void exchangeMouseItem(int itemPos, int runScript);
295 	bool pickUpItem(int x, int y, int runScript);
296 
297 	bool isDropable(int x, int y);
298 
299 	const uint8 *_itemMagicTable;
300 	bool itemListMagic(Item handItem, int itemSlot);
301 	bool itemInventoryMagic(Item handItem, int invSlot);
302 
303 	const uint8 *_itemStringMap;
304 	int _itemStringMapSize;
305 	static const uint8 _itemStringPickUp[];
306 	static const uint8 _itemStringDrop[];
307 	static const uint8 _itemStringInv[];
308 
309 	int getItemCommandStringPickUp(uint16 item);
310 	int getItemCommandStringDrop(uint16 item);
311 	int getItemCommandStringInv(uint16 item);
312 
313 	// -> hand item
314 	void setItemMouseCursor();
315 	void setMouseCursor(Item item);
316 
317 	// shapes
318 	void initMouseShapes();
319 
320 	void loadCharacterShapes(int newShapes);
321 	void updateMalcolmShapes();
322 
323 	int _malcolmShapeXOffset, _malcolmShapeYOffset;
324 
325 	struct ShapeDesc {
326 		uint8 width, height;
327 		int8 xOffset, yOffset;
328 	};
329 	static const ShapeDesc _shapeDescs[];
330 	static const int _shapeDescsSize;
331 
332 	// scene animation
333 	uint8 *_sceneShapes[20];
334 
335 	void freeSceneShapes();
336 
337 	// voice
338 	int _currentTalkFile;
339 	void openTalkFile(int file);
340 
341 	// scene
342 	bool _noScriptEnter;
343 	void enterNewScene(uint16 scene, int facing, int unk1, int unk2, int unk3);
344 	void enterNewSceneUnk1(int facing, int unk1, int unk2);
345 	void enterNewSceneUnk2(int unk1);
346 	int _enterNewSceneLock;
347 
348 	void unloadScene();
349 
350 	void loadScenePal();
351 	void loadSceneMsc();
352 	void initSceneScript(int unk1);
353 	void initSceneAnims(int unk1);
354 	void initSceneScreen(int unk1);
355 
356 	int runSceneScript1(int x, int y);
357 	int runSceneScript2();
358 	bool _noStartupChat;
359 	void runSceneScript4(int unk1);
360 	void runSceneScript8();
361 
362 	int _sceneMinX, _sceneMaxX;
363 	int _maskPageMinY, _maskPageMaxY;
364 
365 	int trySceneChange(int *moveTable, int unk1, int unk2);
366 	int checkSceneChange();
367 
368 	int8 _sceneDatPalette[45];
369 	int8 _sceneDatLayerTable[15];
370 	struct SceneShapeDesc {
371 		// the original saves those variables, we don't, since
372 		// they are just needed on scene load
373 		/*int x, y;
374 		int w, h;*/
375 		int drawX, drawY;
376 	};
377 	SceneShapeDesc _sceneShapeDescs[20];
378 
379 	int getDrawLayer(int x, int y);
380 
381 	int getScale(int x, int y);
382 	int _scaleTable[15];
383 
384 	// character
385 	int getCharacterWalkspeed() const;
386 	void updateCharAnimFrame(int *table);
387 	int8 _characterAnimTable[2];
388 	static const uint8 _characterFrameTable[];
389 
390 	void updateCharPal(int unk1);
391 	int _lastCharPalLayer;
392 	bool _charPalUpdate;
393 
394 	bool checkCharCollision(int x, int y);
395 
396 	int _malcolmsMood;
397 
398 	void makeCharFacingMouse();
399 
400 	int findFreeInventorySlot();
401 
402 	// talk object
403 	struct TalkObject {
404 		char filename[13];
405 		int8 sceneAnim;
406 		int8 sceneScript;
407 		int16 x, y;
408 		uint8 color;
409 		uint8 sceneId;
410 	};
411 
412 	TalkObject *_talkObjectList;
413 
414 	bool talkObjectsInCurScene();
415 
416 	// chat
417 	int chatGetType(const char *text);
418 	int chatCalcDuration(const char *text);
419 
420 	void objectChat(const char *text, int object, int vocHigh, int vocLow);
421 	void objectChatInit(const char *text, int object, int vocHigh, int vocLow);
422 	void objectChatPrintText(const char *text, int object);
423 	void objectChatProcess(const char *script);
424 	void objectChatWaitToFinish();
425 
426 	void badConscienceChat(const char *str, int vocHigh, int vocLow);
427 	void badConscienceChatWaitToFinish();
428 
429 	void goodConscienceChat(const char *str, int vocHigh, int vocLow);
430 	void goodConscienceChatWaitToFinish();
431 
432 	bool _albumChatActive;
433 	void albumChat(const char *str, int vocHigh, int vocLow);
434 	void albumChatInit(const char *str, int object, int vocHigh, int vocLow);
435 	void albumChatWaitToFinish();
436 
437 	void malcolmSceneStartupChat();
438 
439 	byte _newSceneDlgState[40];
440 	int8 _conversationState[30][30];
441 	bool _chatAltFlag;
442 	void setDlgIndex(int index);
443 	void updateDlgIndex();
444 
445 	Common::SeekableReadStream *_cnvFile;
446 	Common::SeekableReadStream *_dlgBuffer;
447 	int _curDlgChapter, _curDlgIndex, _curDlgLang;
448 	void updateDlgBuffer();
449 	void loadDlgHeader(int &vocHighBase, int &vocHighIndex, int &index1, int &index2);
450 
451 	static const uint8 _vocHighTable[];
452 	bool _isStartupDialog;
453 	void processDialog(int vocHighIndex, int vocHighBase, int funcNum);
454 
455 	EMCData _dialogScriptData;
456 	EMCState _dialogScriptState;
457 	int _dialogSceneAnim;
458 	int _dialogSceneScript;
459 	int _dialogScriptFuncStart, _dialogScriptFuncProc, _dialogScriptFuncEnd;
460 
461 	void dialogStartScript(int object, int funcNum);
462 	void dialogEndScript(int object);
463 
464 	void npcChatSequence(const char *str, int object, int vocHigh, int vocLow);
465 
466 	Common::Array<const Opcode *> _opcodesDialog;
467 
468 	int o3d_updateAnim(EMCState *script);
469 	int o3d_delay(EMCState *script);
470 
471 	void randomSceneChat();
472 	void doDialog(int dlgIndex, int funcNum);
473 
474 	// conscience
475 	bool _badConscienceShown;
476 	int _badConscienceAnim;
477 	bool _badConsciencePosition;
478 
479 	static const uint8 _badConscienceFrameTable[];
480 
481 	void showBadConscience();
482 	void hideBadConscience();
483 
484 	bool _goodConscienceShown;
485 	int _goodConscienceAnim;
486 	bool _goodConsciencePosition;
487 
488 	static const uint8 _goodConscienceFrameTable[];
489 
490 	void showGoodConscience();
491 	void hideGoodConscience();
492 
493 	// special script code
494 	bool _useFrameTable;
495 
496 	int o3a_setCharacterFrame(EMCState *script);
497 	int o3a_playSoundEffect(EMCState *script);
498 
499 	// special shape code
500 	int initAnimationShapes(uint8 *filedata);
501 	void uninitAnimationShapes(int count, uint8 *filedata);
502 
503 	// unk
504 	uint8 *_costPalBuffer;
505 	uint8 *_paletteOverlay;
506 	bool _useActorBuffer;
507 
508 	int _currentChapter;
509 	void changeChapter(int newChapter, int sceneId, int malcolmShapes, int facing);
510 
511 	static const uint8 _chapterLowestScene[];
512 
513 	void loadCostPal();
514 	void loadShadowShape();
515 	void loadExtrasShapes();
516 
517 	uint8 *_gfxBackUpRect;
518 	void backUpGfxRect32x32(int x, int y);
519 	void restoreGfxRect32x32(int x, int y);
520 
521 	char *_stringBuffer;
522 
523 	int _score;
524 	int _scoreMax;
525 
526 	const uint8 *_scoreTable;
527 	int _scoreTableSize;
528 
529 	int8 _scoreFlagTable[26];
530 	bool updateScore(int scoreId, int strId);
531 	void scoreIncrease(int count, const char *str);
532 
533 	void eelScript();
534 
535 	// Album
536 	struct Album {
537 		uint8 *backUpPage;
538 		uint8 *file;
539 		WSAMovie_v2 *wsa;
540 		uint8 *backUpRect;
541 
542 		struct PageMovie {
543 			WSAMovie_v2 *wsa;
544 			int curFrame;
545 			int maxFrame;
546 			uint32 timer;
547 		};
548 
549 		PageMovie leftPage, rightPage;
550 
551 		int curPage, nextPage;
552 		bool running;
553 		bool isPage14;
554 	} _album;
555 
556 	static const int8 _albumWSAX[];
557 	static const int8 _albumWSAY[];
558 
559 	void showAlbum();
560 
561 	void loadAlbumPage();
562 	void loadAlbumPageWSA();
563 
564 	void printAlbumPageText();
565 	void printAlbumText(int page, const char *str, int x, int y, uint8 c0);
566 
567 	void processAlbum();
568 
569 	void albumNewPage();
570 	void albumUpdateAnims();
571 	void albumAnim1();
572 	void albumAnim2();
573 
574 	void albumBackUpRect();
575 	void albumRestoreRect();
576 	void albumUpdateRect();
577 
578 	void albumSwitchPages(int oldPage, int newPage, int srcPage);
579 
580 	int albumNextPage(Button *caller);
581 	int albumPrevPage(Button *caller);
582 	int albumClose(Button *caller);
583 
584 	// save/load
585 	Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail);
586 	Common::Error loadGameState(int slot);
587 
588 	// opcodes
589 	int o3_getMalcolmShapes(EMCState *script);
590 	int o3_setCharacterPos(EMCState *script);
591 	int o3_defineObject(EMCState *script);
592 	int o3_refreshCharacter(EMCState *script);
593 	int o3_getMalcolmsMood(EMCState *script);
594 	int o3_getCharacterFrameFromFacing(EMCState *script);
595 	int o3_setCharacterFacing(EMCState *script);
596 	int o3_showSceneFileMessage(EMCState *script);
597 	int o3_setCharacterAnimFrameFromFacing(EMCState *script);
598 	int o3_showBadConscience(EMCState *script);
599 	int o3_hideBadConscience(EMCState *script);
600 	int o3_showAlbum(EMCState *script);
601 	int o3_setInventorySlot(EMCState *script);
602 	int o3_getInventorySlot(EMCState *script);
603 	int o3_addItemToInventory(EMCState *script);
604 	int o3_addItemToCurScene(EMCState *script);
605 	int o3_objectChat(EMCState *script);
606 	int o3_resetInventory(EMCState *script);
607 	int o3_removeInventoryItemInstances(EMCState *script);
608 	int o3_countInventoryItemInstances(EMCState *script);
609 	int o3_npcChatSequence(EMCState *script);
610 	int o3_badConscienceChat(EMCState *script);
611 	int o3_wipeDownMouseItem(EMCState *script);
612 	int o3_setMalcolmsMood(EMCState *script);
613 	int o3_updateScore(EMCState *script);
614 	int o3_makeSecondChanceSave(EMCState *script);
615 	int o3_setSceneFilename(EMCState *script);
616 	int o3_removeItemsFromScene(EMCState *script);
617 	int o3_disguiseMalcolm(EMCState *script);
618 	int o3_drawSceneShape(EMCState *script);
619 	int o3_drawSceneShapeOnPage(EMCState *script);
620 	int o3_checkInRect(EMCState *script);
621 	int o3_updateConversations(EMCState *script);
622 	int o3_removeItemSlot(EMCState *script);
623 	int o3_setSceneDim(EMCState *script);
624 	int o3_setSceneAnimPosAndFrame(EMCState *script);
625 	int o3_removeItemInstances(EMCState *script);
626 	int o3_disableInventory(EMCState *script);
627 	int o3_enableInventory(EMCState *script);
628 	int o3_enterNewScene(EMCState *script);
629 	int o3_switchScene(EMCState *script);
630 	int o3_setMalcolmPos(EMCState *script);
631 	int o3_stopMusic(EMCState *script);
632 	int o3_playSoundEffect(EMCState *script);
633 	int o3_getScore(EMCState *script);
634 	int o3_daggerWarning(EMCState *script);
635 	int o3_blockOutWalkableRegion(EMCState *script);
636 	int o3_showSceneStringsMessage(EMCState *script);
637 	int o3_showGoodConscience(EMCState *script);
638 	int o3_goodConscienceChat(EMCState *script);
639 	int o3_hideGoodConscience(EMCState *script);
640 	int o3_defineSceneAnim(EMCState *script);
641 	int o3_updateSceneAnim(EMCState *script);
642 	int o3_runActorScript(EMCState *script);
643 	int o3_doDialog(EMCState *script);
644 	int o3_setConversationState(EMCState *script);
645 	int o3_getConversationState(EMCState *script);
646 	int o3_changeChapter(EMCState *script);
647 	int o3_countItemInstances(EMCState *script);
648 	int o3_dialogStartScript(EMCState *script);
649 	int o3_dialogEndScript(EMCState *script);
650 	int o3_customChat(EMCState *script);
651 	int o3_customChatFinish(EMCState *script);
652 	int o3_setupSceneAnimObject(EMCState *script);
653 	int o3_removeSceneAnimObject(EMCState *script);
654 	int o3_dummy(EMCState *script);
655 
656 	// misc
657 	TextDisplayer_MR *_text;
658 	bool _wasPlayingVQA;
659 
660 	// resource specific
661 private:
662 	static const char *const _languageExtension[];
663 	static const int _languageExtensionSize;
664 
665 	int loadLanguageFile(const char *file, uint8 *&buffer);
666 };
667 
668 } // End of namespace Kyra
669 
670 #endif
671