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