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 #include "hopkins/hopkins.h"
24 #include "hopkins/graphics.h"
25 #include "hopkins/files.h"
26 #include "hopkins/saveload.h"
27 #include "hopkins/sound.h"
28 #include "hopkins/talk.h"
29 
30 #include "common/scummsys.h"
31 #include "common/config-manager.h"
32 #include "common/debug-channels.h"
33 #include "common/events.h"
34 #include "common/file.h"
35 
36 namespace Hopkins {
37 
HopkinsEngine(OSystem * syst,const HopkinsGameDescription * gameDesc)38 HopkinsEngine::HopkinsEngine(OSystem *syst, const HopkinsGameDescription *gameDesc) : Engine(syst),
39 		_gameDescription(gameDesc), _randomSource("Hopkins") {
40 	_animMan = new AnimationManager(this);
41 	_computer = new ComputerManager(this);
42 	_dialog = new DialogsManager(this);
43 	setDebugger(new Debugger(this));
44 	_events = new EventsManager(this);
45 	_fileIO = new FileManager(this);
46 	_fontMan = new FontManager(this);
47 	_globals = new Globals(this);
48 	_graphicsMan = new GraphicsManager(this);
49 	_linesMan = new LinesManager(this);
50 	_menuMan = new MenuManager(this);
51 	_objectsMan = new ObjectsManager(this);
52 	_saveLoad = new SaveLoadManager(this);
53 	_script = new ScriptManager(this);
54 	_soundMan = new SoundManager(this);
55 	_talkMan = new TalkManager(this);
56 
57 	_startGameSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
58 }
59 
~HopkinsEngine()60 HopkinsEngine::~HopkinsEngine() {
61 	delete _talkMan;
62 	delete _soundMan;
63 	delete _script;
64 	delete _saveLoad;
65 	delete _objectsMan;
66 	delete _menuMan;
67 	delete _linesMan;
68 	delete _graphicsMan;
69 	delete _globals;
70 	delete _fontMan;
71 	delete _fileIO;
72 	delete _events;
73 	delete _dialog;
74 	delete _computer;
75 	delete _animMan;
76 }
77 
78 /**
79  * Returns true if it is currently okay to restore a game
80  */
canLoadGameStateCurrently()81 bool HopkinsEngine::canLoadGameStateCurrently() {
82 	return !_globals->_exitId && !_globals->_cityMapEnabledFl && _events->_mouseFl && _globals->_curRoomNum != 0;
83 }
84 
85 /**
86  * Returns true if it is currently okay to save the game
87  */
canSaveGameStateCurrently()88 bool HopkinsEngine::canSaveGameStateCurrently() {
89 	return !_globals->_exitId && !_globals->_cityMapEnabledFl && _events->_mouseFl
90 		&& _globals->_curRoomNum != 0 && !isUnderwaterSubScene();
91 }
92 
93 /**
94  * Load the savegame at the specified slot index
95  */
loadGameState(int slot)96 Common::Error HopkinsEngine::loadGameState(int slot) {
97 	return _saveLoad->loadGame(slot);
98 }
99 
100 /**
101  * Save the game to the given slot index, and with the given name
102  */
saveGameState(int slot,const Common::String & desc,bool isAutosave)103 Common::Error HopkinsEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
104 	return _saveLoad->saveGame(slot, desc);
105 }
106 
run()107 Common::Error HopkinsEngine::run() {
108 	_globals->setConfig();
109 	_fileIO->initCensorship();
110 	initializeSystem();
111 
112 	if (!getIsDemo())
113 		runFull();
114 	else if (getPlatform() == Common::kPlatformLinux)
115 		runLinuxDemo();
116 	else if (getPlatform() == Common::kPlatformWindows)
117 		runWin95Demo();
118 	else {
119 		warning("Unhandled version, switching to Linux demo. Please report this version to ScummVM developers");
120 		runLinuxDemo();
121 	}
122 
123 	return Common::kNoError;
124 }
125 
runWin95Demo()126 bool HopkinsEngine::runWin95Demo() {
127 	_objectsMan->loadObjects();
128 	_objectsMan->changeObject(14);
129 	_objectsMan->addObject(14);
130 	_objectsMan->_helicopterFl = false;
131 
132 	_globals->_eventMode = EVENTMODE_IGNORE;
133 
134 	_graphicsMan->clearScreen();
135 	_graphicsMan->clearPalette();
136 
137 	if (_startGameSlot == -1) {
138 		_graphicsMan->loadImage("H2");
139 		_graphicsMan->fadeInLong();
140 
141 		if (!_events->_escKeyFl)
142 			playIntro();
143 	}
144 
145 	_events->_rateCounter = 0;
146 	_globals->_eventMode = EVENTMODE_IGNORE;
147 	_globals->_speed = 1;
148 	_events->delay(500);
149 	_globals->_eventMode = EVENTMODE_DEFAULT;
150 	if (_events->_rateCounter > 475)
151 		_globals->_speed = 2;
152 	if (_events->_rateCounter > 700)
153 		_globals->_speed = 3;
154 
155 	if (_startGameSlot == -1)
156 		_graphicsMan->fadeOutShort();
157 
158 	_globals->_eventMode = EVENTMODE_IGNORE;
159 	_globals->_characterSpriteBuf = _fileIO->loadFile("PERSO.SPR");
160 
161 	_globals->_characterType = CHARACTER_HOPKINS;
162 	_objectsMan->_mapCarPosX = _objectsMan->_mapCarPosY = 0;
163 	_globals->_saveData->reset();
164 	_globals->_exitId = 0;
165 
166 	if (getLanguage() != Common::PL_POL)
167 		if (!displayAdultDisclaimer())
168 			return Common::kNoError;
169 
170 	if (_startGameSlot != -1)
171 		_saveLoad->loadGame(_startGameSlot);
172 
173 	for (;;) {
174 		if (_globals->_exitId == 300)
175 			_globals->_exitId = 0;
176 
177 		if (!_globals->_exitId) {
178 			_globals->_exitId = _menuMan->menu();
179 			if (_globals->_exitId == -1) {
180 				_globals->_characterSpriteBuf = _globals->freeMemory(_globals->_characterSpriteBuf);
181 				restoreSystem();
182 				return false;
183 			}
184 		}
185 
186 		if (shouldQuit())
187 			return false;
188 
189 		_globals->_curRoomNum = _globals->_exitId;
190 
191 		switch (_globals->_exitId) {
192 		case 1:
193 			// Handles room: Apartment
194 			_linesMan->setMaxLineIdx(40);
195 			_globals->_characterMaxPosY = 435;
196 			_objectsMan->sceneControl2("IM01", "IM01", "ANIM01", "IM01", 2, true);
197 			break;
198 
199 		case 3:
200 			// - Displays bank attack when leaving the apartment
201 			// - Handles room: bottom of the apartment
202 			if (!_globals->_saveData->_data[svBankAttackAnimPlayedFl]) {
203 				_soundMan->playSound(3);
204 				if (getPlatform() == Common::kPlatformOS2 || getPlatform() == Common::kPlatformBeOS)
205 					_graphicsMan->loadImage("fond");
206 				else {
207 					switch (_globals->_language) {
208 					case LANG_FR:
209 						_graphicsMan->loadImage("fondfr");
210 						break;
211 					case LANG_EN:
212 						_graphicsMan->loadImage("fondan");
213 						break;
214 					case LANG_SP:
215 						_graphicsMan->loadImage("fondes");
216 						break;
217 					default:
218 						break;
219 					}
220 				}
221 				_graphicsMan->fadeInLong();
222 				_events->delay(500);
223 				_graphicsMan->fadeOutLong();
224 				_globals->_eventMode = EVENTMODE_IGNORE;
225 				_soundMan->_specialSoundNum = 2;
226 				_graphicsMan->clearScreen();
227 				_graphicsMan->clearPalette();
228 				if (!_globals->_censorshipFl)
229 					_animMan->playAnim("BANQUE.ANM", "BANKUK.ANM", 200, 28, 200);
230 				else
231 					_animMan->playAnim("BANKUK.ANM", "BANQUE.ANM", 200, 28, 200);
232 				_soundMan->_specialSoundNum = 0;
233 				_soundMan->removeSample(1);
234 				_soundMan->removeSample(2);
235 				_soundMan->removeSample(3);
236 				_soundMan->removeSample(4);
237 				_graphicsMan->fadeOutShort();
238 				_globals->_saveData->_data[svBankAttackAnimPlayedFl] = 1;
239 			}
240 			_linesMan->setMaxLineIdx(5);
241 			_globals->_characterMaxPosY = 450;
242 			_objectsMan->sceneControl2("IM03", "IM03", "ANIM03", "IM03", 2, false);
243 			break;
244 
245 		case 4:
246 			// Handle room: City map
247 			_globals->_disableInventFl = true;
248 			_objectsMan->handleCityMap();
249 			_globals->_disableInventFl = false;
250 			break;
251 
252 		case 5:
253 			// Handle room: Outside the bank
254 			_linesMan->setMaxLineIdx(5);
255 			_globals->_characterMaxPosY = 455;
256 
257 			if (_globals->_saveData->_data[svFreedHostageFl]) {
258 				if (_globals->_saveData->_data[svFreedHostageFl] == 1)
259 					_objectsMan->sceneControl2("IM05", "IM05A", "ANIM05B", "IM05", 3, false);
260 			} else {
261 				_objectsMan->sceneControl2("IM05", "IM05", "ANIM05", "IM05", 3, false);
262 			}
263 			break;
264 
265 		case 6:
266 			_linesMan->setMaxLineIdx(20);
267 			_globals->_characterMaxPosY = 460;
268 			_objectsMan->sceneControl2("IM06", "IM06", "ANIM06", "IM06", 2, true);
269 			break;
270 
271 		case 7:
272 			if (_globals->_saveData->_data[svBombBoxOpenedFl])
273 				_objectsMan->sceneControl("BOMBEB", "BOMBE", "BOMBE", "BOMBE", 2, true);
274 			else
275 				_objectsMan->sceneControl("BOMBEA", "BOMBE", "BOMBE", "BOMBE", 2, true);
276 			break;
277 
278 		case 8:
279 			_linesMan->setMaxLineIdx(15);
280 			_globals->_characterMaxPosY = 450;
281 			_objectsMan->sceneControl2("IM08", "IM08", "ANIM08", "IM08", 2, true);
282 			break;
283 
284 		case 9:
285 			_globals->_characterMaxPosY = 440;
286 			_linesMan->setMaxLineIdx(20);
287 			if (_globals->_saveData->_data[svBombDisarmedFl])
288 			  _objectsMan->sceneControl2("IM09", "IM09", "ANIM09", "IM09", 10, true);
289 			else
290 			  bombExplosion();
291 			break;
292 
293 		case 10:
294 			_objectsMan->sceneControl("IM10", "IM10", "ANIM10", "IM10", 9, false);
295 			break;
296 
297 		case 11:
298 			_linesMan->setMaxLineIdx(20);
299 			_globals->_characterMaxPosY = 450;
300 			_objectsMan->sceneControl2("IM11", "IM11", "ANIM11", "IM11", 2, false);
301 			break;
302 
303 		case 12:
304 			_globals->_characterMaxPosY = 450;
305 			_linesMan->setMaxLineIdx(20);
306 			if (_globals->_saveData->_data[svBombDisarmedFl]) {
307 				if (_globals->_language == LANG_FR)
308 					_graphicsMan->loadImage("ENDFR");
309 				else
310 					_graphicsMan->loadImage("ENDUK");
311 				_graphicsMan->fadeInLong();
312 				_events->mouseOn();
313 				do {
314 					_events->refreshScreenAndEvents();
315 				} while (_events->getMouseButton() != 1);
316 				_graphicsMan->fadeOutLong();
317 				restoreSystem();
318 			} else
319 				bombExplosion();
320 			break;
321 
322 		case 13:
323 		case 14:
324 		case 15:
325 			handleNotAvailable(11);
326 			break;
327 
328 		case 16:
329 		case 24:
330 		case 25:
331 		case 26:
332 		case 27:
333 		case 28:
334 		case 29:
335 		case 30:
336 		case 31:
337 		case 33:
338 		case 32:
339 		case 34:
340 			handleNotAvailable(4);
341 			break;
342 
343 		case 17:
344 			handleNotAvailable(1);
345 			break;
346 
347 		case 111:
348 			_objectsMan->sceneControl("IM111", "IM111", "ANIM111", "IM111", 10, false);
349 			break;
350 
351 		case 112:
352 			_objectsMan->sceneControl("IM112", "IM112", "ANIM112", "IM112", 10, false);
353 			break;
354 
355 		case 113:
356 			_globals->_exitId = 0;
357 			_globals->_prevScreenId = _globals->_screenId;
358 			_globals->_saveData->_data[svLastPrevScreenId] = _globals->_screenId;
359 			_globals->_screenId = 113;
360 			_globals->_saveData->_data[svLastScreenId] = _globals->_screenId;
361 			_computer->showComputer(COMPUTER_HOPKINS);
362 			_graphicsMan->clearScreen();
363 			_graphicsMan->updateScreen();
364 			memset(_graphicsMan->_frontBuffer, 0, 307200);
365 			memset(_graphicsMan->_backBuffer, 0, 307200);
366 			_graphicsMan->clearPalette();
367 			_graphicsMan->resetDirtyRects();
368 			break;
369 
370 		case 114:
371 			_globals->_prevScreenId = _globals->_screenId;
372 			_globals->_saveData->_data[svLastPrevScreenId] = _globals->_screenId;
373 			_globals->_screenId = 114;
374 			_globals->_saveData->_data[svLastScreenId] = _globals->_screenId;
375 			_globals->_exitId = 0;
376 			_computer->showComputer(COMPUTER_SAMANTHA);
377 			_graphicsMan->clearScreen();
378 			break;
379 
380 		case 115:
381 			_globals->_exitId = 0;
382 			_globals->_prevScreenId = _globals->_screenId;
383 			_globals->_saveData->_data[svLastPrevScreenId] = _globals->_screenId;
384 			_globals->_screenId = 115;
385 			_globals->_saveData->_data[svLastScreenId] = _globals->_screenId;
386 			_computer->showComputer(COMPUTER_PUBLIC);
387 			_graphicsMan->clearScreen();
388 			break;
389 
390 		case 150:
391 			_soundMan->playSound(28);
392 			_globals->_eventMode = EVENTMODE_ALT; // CHECKME!
393 			_graphicsMan->clearScreen();
394 			_graphicsMan->clearPalette();
395 			_animMan->playAnim("JOUR1A.ANM", "JOUR1A.ANM", 12, 12, 2000);
396 			_globals->_eventMode = EVENTMODE_DEFAULT;
397 			_globals->_exitId = 300;
398 			break;
399 
400 		case 151:
401 			if (_fileIO->fileExists("JOUR3A.ANM")) {
402 				// The Polish demo uses the animation file than the complete versions
403 				_soundMan->playSound(16);
404 				_globals->_eventMode = EVENTMODE_IGNORE;
405 
406 				_graphicsMan->clearScreen();
407 				_graphicsMan->clearPalette();
408 				_graphicsMan->_fadingFl = true;
409 				_animMan->playAnim("JOUR3A.ANM", "JOUR3A.ANM", 12, 12, 2000);
410 			} else {
411 				// The other demos only display a nag screen
412 				_soundMan->playSound(28);
413 				_globals->_eventMode = EVENTMODE_ALT; // CHECKME!
414 				_graphicsMan->clearScreen();
415 				_graphicsMan->clearPalette();
416 				_graphicsMan->loadImage("njour3a");
417 				_graphicsMan->fadeInLong();
418 				_events->delay(5000);
419 				_graphicsMan->fadeOutLong();
420 			}
421 
422 			_globals->_exitId = 300;
423 			_globals->_eventMode = EVENTMODE_DEFAULT;
424 			break;
425 
426 		case 152:
427 			_soundMan->playSound(28);
428 			_globals->_eventMode = EVENTMODE_ALT; // CHECKME!
429 			_graphicsMan->clearScreen();
430 			_graphicsMan->clearPalette();
431 			_animMan->playAnim("JOUR4A.ANM", "JOUR4A.ANM", 12, 12, 2000);
432 			_globals->_eventMode = EVENTMODE_DEFAULT;
433 			_globals->_exitId = 300;
434 			break;
435 
436 		default:
437 			break;
438 		}
439 	}
440 	return true;
441 }
442 
runLinuxDemo()443 bool HopkinsEngine::runLinuxDemo() {
444 	_objectsMan->loadObjects();
445 	_objectsMan->changeObject(14);
446 	_objectsMan->addObject(14);
447 	_objectsMan->_helicopterFl = false;
448 
449 	_events->mouseOff();
450 
451 	_graphicsMan->clearScreen();
452 
453 	if (_startGameSlot == -1) {
454 		_graphicsMan->loadImage("LINUX");
455 		_graphicsMan->fadeInLong();
456 		_events->delay(1500);
457 		_graphicsMan->fadeOutLong();
458 
459 		_graphicsMan->loadImage("H2");
460 		_graphicsMan->fadeInLong();
461 		_events->delay(500);
462 		_graphicsMan->fadeOutLong();
463 
464 		if (!_events->_escKeyFl)
465 			playIntro();
466 	}
467 
468 	_globals->_eventMode = EVENTMODE_DEFAULT;
469 	_globals->_characterSpriteBuf = _fileIO->loadFile("PERSO.SPR");
470 	_globals->_characterType = CHARACTER_HOPKINS;
471 	_objectsMan->_mapCarPosX = _objectsMan->_mapCarPosY = 0;
472 	_globals->_saveData->reset();
473 	_globals->_exitId = 0;
474 
475 	if (_startGameSlot != -1)
476 		_saveLoad->loadGame(_startGameSlot);
477 
478 	for (;;) {
479 		if (_globals->_exitId == 300)
480 			_globals->_exitId = 0;
481 
482 		if (!_globals->_exitId) {
483 			_globals->_exitId = _menuMan->menu();
484 			if (_globals->_exitId == -1) {
485 				if (!shouldQuit())
486 					endLinuxDemo();
487 				_globals->_characterSpriteBuf = _globals->freeMemory(_globals->_characterSpriteBuf);
488 				restoreSystem();
489 			}
490 		}
491 
492 		if (shouldQuit())
493 			return false;
494 
495 		_globals->_curRoomNum = _globals->_exitId;
496 
497 		switch (_globals->_exitId) {
498 		case 17:
499 		case 18:
500 		case 19:
501 		case 20:
502 		case 22:
503 		case 23:
504 		case 24:
505 		case 27:
506 		case 28:
507 		case 29:
508 		case 30:
509 		case 31:
510 		case 32:
511 		case 34:
512 		case 38:
513 			displayNotAvailable();
514 			break;
515 
516 		case 1:
517 			_linesMan->setMaxLineIdx(40);
518 			_globals->_characterMaxPosY = 435;
519 			_objectsMan->sceneControl2("IM01", "IM01", "ANIM01", "IM01", 1, true);
520 			break;
521 
522 		case 3:
523 			if (!_globals->_saveData->_data[svBankAttackAnimPlayedFl]) {
524 				_soundMan->playSound(3);
525 				if (getPlatform() == Common::kPlatformOS2 || getPlatform() == Common::kPlatformBeOS)
526 					_graphicsMan->loadImage("fond");
527 				else {
528 					switch (_globals->_language) {
529 					case LANG_FR:
530 						_graphicsMan->loadImage("fondfr");
531 						break;
532 					case LANG_EN:
533 						_graphicsMan->loadImage("fondan");
534 						break;
535 					case LANG_SP:
536 						_graphicsMan->loadImage("fondes");
537 						break;
538 					default:
539 						break;
540 					}
541 				}
542 				_graphicsMan->fadeInLong();
543 				_events->delay(500);
544 				_graphicsMan->fadeOutLong();
545 				_globals->_eventMode = EVENTMODE_IGNORE;
546 				_soundMan->_specialSoundNum = 2;
547 
548 				_graphicsMan->clearScreen();
549 				_graphicsMan->clearPalette();
550 				_graphicsMan->_fadingFl = true;
551 
552 				if (!_globals->_censorshipFl)
553 					_animMan->playAnim("BANQUE.ANM", "BANKUK.ANM", 200, 28, 200);
554 				else
555 					_animMan->playAnim("BANKUK.ANM", "BANQUE.ANM", 200, 28, 200);
556 				_soundMan->_specialSoundNum = 0;
557 				_soundMan->removeSample(1);
558 				_soundMan->removeSample(2);
559 				_soundMan->removeSample(3);
560 				_soundMan->removeSample(4);
561 				_globals->_saveData->_data[svBankAttackAnimPlayedFl] = 1;
562 			}
563 
564 			_linesMan->setMaxLineIdx(5);
565 			_globals->_characterMaxPosY = 450;
566 			_objectsMan->sceneControl2("IM03", "IM03", "ANIM03", "IM03", 2, false);
567 			break;
568 
569 		case 4:
570 			_globals->_disableInventFl = true;
571 			_objectsMan->handleCityMap();
572 			_globals->_disableInventFl = false;
573 			break;
574 
575 		case 5:
576 			_linesMan->setMaxLineIdx(5);
577 			_globals->_characterMaxPosY = 455;
578 			if (_globals->_saveData->_data[svFreedHostageFl] == 1)
579 					_objectsMan->sceneControl2("IM05", "IM05A", "ANIM05B", "IM05", 3, false);
580 			else
581 				_objectsMan->sceneControl2("IM05", "IM05", "ANIM05", "IM05", 3, false);
582 			break;
583 
584 		case 6:
585 			_linesMan->setMaxLineIdx(20);
586 			_globals->_characterMaxPosY = 460;
587 			_objectsMan->sceneControl2("IM06", "IM06", "ANIM06", "IM06", 2, true);
588 			break;
589 
590 		case 7:
591 			if (_globals->_saveData->_data[svBombBoxOpenedFl])
592 				_objectsMan->sceneControl("BOMBEB", "BOMBE", "BOMBE", "BOMBE", 2, true);
593 			else
594 				_objectsMan->sceneControl("BOMBEA", "BOMBE", "BOMBE", "BOMBE", 2, true);
595 			break;
596 
597 		case 8:
598 			_linesMan->setMaxLineIdx(15);
599 			_globals->_characterMaxPosY = 450;
600 			_objectsMan->sceneControl2("IM08", "IM08", "ANIM08", "IM08", 2, true);
601 			break;
602 
603 		case 9:
604 			_linesMan->setMaxLineIdx(20);
605 			_globals->_characterMaxPosY = 440;
606 
607 			if (!_globals->_saveData->_data[svBombDisarmedFl])
608 				bombExplosion();
609 			else
610 				_objectsMan->sceneControl2("IM09", "IM09", "ANIM09", "IM09", 10, true);
611 			break;
612 
613 		case 10:
614 			_objectsMan->sceneControl("IM10", "IM10", "ANIM10", "IM10", 9, false);
615 			break;
616 
617 		case 11:
618 			_linesMan->setMaxLineIdx(20);
619 			_globals->_characterMaxPosY = 450;
620 			_objectsMan->sceneControl2("IM11", "IM11", "ANIM11", "IM11", 2, false);
621 			break;
622 
623 		case 12:
624 			_linesMan->setMaxLineIdx(20);
625 			_globals->_characterMaxPosY = 450;
626 			if (_globals->_saveData->_data[svBombDisarmedFl])
627 				_objectsMan->sceneControl2("IM12", "IM12", "ANIM12", "IM12", 1, false);
628 			else
629 				bombExplosion();
630 			break;
631 
632 		case 13:
633 			_linesMan->setMaxLineIdx(40);
634 			_globals->_characterMaxPosY = 440;
635 			_objectsMan->sceneControl2("IM13", "IM13", "ANIM13", "IM13", 1, true);
636 			break;
637 
638 		case 14:
639 			_linesMan->setMaxLineIdx(40);
640 			_globals->_characterMaxPosY = 440;
641 			_objectsMan->sceneControl2("IM14", "IM14", "ANIM14", "IM14", 1, true);
642 			break;
643 
644 		case 15:
645 			_objectsMan->sceneControl("IM15", "IM15", "ANIM15", "IM15", 29, false);
646 			break;
647 
648 		case 16:
649 			_linesMan->setMaxLineIdx(5);
650 			_globals->_characterMaxPosY = 450;
651 
652 			if (_globals->_saveData->_data[svForestAvailableFl] == 1) {
653 				_objectsMan->sceneControl2("IM16", "IM16A", "ANIM16", "IM16", 7, true);
654 			} else if (!_globals->_saveData->_data[svForestAvailableFl]) {
655 				_objectsMan->sceneControl2("IM16", "IM16", "ANIM16", "IM16", 7, true);
656 			}
657 			break;
658 
659 		case 25:
660 			_linesMan->setMaxLineIdx(20);
661 			_globals->_characterMaxPosY = 445;
662 			_objectsMan->sceneControl2("IM25", "IM25", "ANIM25", "IM25", 30, true);
663 			break;
664 
665 		case 26:
666 			_linesMan->setMaxLineIdx(40);
667 			_globals->_characterMaxPosY = 435;
668 			_objectsMan->sceneControl2("IM26", "IM26", "ANIM26", "IM26", 30, true);
669 			break;
670 
671 		case 33:
672 			_objectsMan->sceneControl("IM33", "IM33", "ANIM33", "IM33", 8, false);
673 			break;
674 
675 		case 35:
676 			displayEndDemo();
677 			break;
678 
679 		case 111:
680 			_objectsMan->sceneControl("IM111", "IM111", "ANIM111", "IM111", 10, false);
681 			break;
682 
683 		case 112:
684 			_objectsMan->sceneControl("IM112", "IM112", "ANIM112", "IM112", 10, false);
685 			break;
686 
687 		case 113:
688 			_globals->_exitId = 0;
689 			_globals->_prevScreenId = _globals->_screenId;
690 			_globals->_saveData->_data[svLastPrevScreenId] = _globals->_screenId;
691 			_globals->_screenId = 113;
692 			_globals->_saveData->_data[svLastScreenId] = 113;
693 			_computer->showComputer(COMPUTER_HOPKINS);
694 
695 			_graphicsMan->clearScreen();
696 			_graphicsMan->updateScreen();
697 			memset(_graphicsMan->_frontBuffer, 0, 307200);
698 			memset(_graphicsMan->_backBuffer, 0, 307200);
699 			_graphicsMan->clearPalette();
700 			_graphicsMan->resetDirtyRects();
701 			break;
702 
703 		case 114:
704 			_globals->_exitId = 0;
705 			_globals->_prevScreenId = _globals->_screenId;
706 			_globals->_saveData->_data[svLastPrevScreenId] = _globals->_screenId;
707 			_globals->_screenId = 114;
708 			_globals->_saveData->_data[svLastScreenId] = 114;
709 			_computer->showComputer(COMPUTER_SAMANTHA);
710 			_graphicsMan->clearScreen();
711 			break;
712 
713 		case 115:
714 			_globals->_exitId = 0;
715 			_globals->_prevScreenId = _globals->_screenId;
716 			_globals->_saveData->_data[svLastPrevScreenId] = _globals->_screenId;
717 			_globals->_screenId = 115;
718 			_globals->_saveData->_data[svLastScreenId] = 115;
719 			_computer->showComputer(COMPUTER_PUBLIC);
720 			_graphicsMan->clearScreen();
721 			break;
722 
723 		case 150:
724 			_soundMan->playSound(16);
725 			_globals->_eventMode = EVENTMODE_IGNORE;
726 
727 			_graphicsMan->clearScreen();
728 			_graphicsMan->clearPalette();
729 			_graphicsMan->_fadingFl = true;
730 			_animMan->playAnim("JOUR1A.ANM", "JOUR1A.ANM", 12, 12, 2000);
731 			_globals->_eventMode = EVENTMODE_DEFAULT;
732 			_globals->_exitId = 300;
733 			break;
734 
735 		case 151:
736 			_soundMan->playSound(16);
737 			_globals->_eventMode = EVENTMODE_IGNORE;
738 
739 			_graphicsMan->clearScreen();
740 			_graphicsMan->clearPalette();
741 			_graphicsMan->_fadingFl = true;
742 			_animMan->playAnim("JOUR3A.ANM", "JOUR3A.ANM", 12, 12, 2000);
743 			_globals->_eventMode = EVENTMODE_DEFAULT;
744 			_globals->_exitId = 300;
745 			break;
746 
747 		case 152:
748 			_soundMan->playSound(16);
749 			_globals->_eventMode = EVENTMODE_IGNORE;
750 
751 			_graphicsMan->clearScreen();
752 			_graphicsMan->clearPalette();
753 			_graphicsMan->_fadingFl = true;
754 			_animMan->playAnim("JOUR4A.ANM", "JOUR4A.ANM", 12, 12, 2000);
755 			_globals->_eventMode = EVENTMODE_DEFAULT;
756 			_globals->_exitId = 300;
757 			break;
758 
759 		default:
760 			break;
761 		}
762 	}
763 	return true;
764 }
765 
runFull()766 bool HopkinsEngine::runFull() {
767 	if (_startGameSlot == -1 && getPlatform() == Common::kPlatformLinux)
768 		_soundMan->playSound(16);
769 
770 	_objectsMan->loadObjects();
771 	_objectsMan->changeObject(14);
772 	_objectsMan->addObject(14);
773 
774 	if (getPlatform() == Common::kPlatformLinux) {
775 		_objectsMan->_helicopterFl = false;
776 		_events->mouseOff();
777 		// No code has been added to display the version as it's wrong
778 		// in my copy: it mentions a Win95 version v4 using DirectDraw (Strangerke)
779 	} else if (getPlatform() == Common::kPlatformWindows) {
780 		_objectsMan->_helicopterFl = false;
781 		_globals->_eventMode = EVENTMODE_IGNORE;
782 		// This code displays the game version.
783 		// It wasn't present in the original and could be put in the debugger
784 		// It has been added there for debug purposes
785 		if (_startGameSlot == -1) {
786 			_graphicsMan->loadImage("VERSW");
787 			_graphicsMan->fadeInLong();
788 			_events->delay(500);
789 			_graphicsMan->fadeOutLong();
790 		}
791 		_graphicsMan->clearVesaScreen();
792 	} else {
793 		// This piece of code, though named "display_version" in the original,
794 		// displays a "loading please wait" screen.
795 		if (_startGameSlot == -1) {
796 			_graphicsMan->loadImage("VERSW");
797 			_graphicsMan->fadeInLong();
798 			_events->delay(500);
799 			_graphicsMan->fadeOutLong();
800 		}
801 		_graphicsMan->clearVesaScreen();
802 
803 		_globals->_eventMode = EVENTMODE_IGNORE;
804 	}
805 
806 	_graphicsMan->clearScreen();
807 	_graphicsMan->clearPalette();
808 
809 	if (_startGameSlot == -1) {
810 		if (getPlatform() == Common::kPlatformLinux) {
811 			_graphicsMan->loadImage("H2");
812 			_graphicsMan->fadeInLong();
813 			_events->delay(500);
814 			_graphicsMan->fadeOutLong();
815 			_globals->_speed = 2;
816 			_globals->_eventMode = EVENTMODE_IGNORE;
817 			_graphicsMan->_fadingFl = true;
818 			_animMan->playAnim("MP.ANM", "MP.ANM", 10, 16, 200);
819 		} else {
820 			_animMan->playAnim("MP.ANM", "MP.ANM", 10, 16, 200);
821 			_graphicsMan->fadeOutLong();
822 		}
823 	}
824 
825 	_events->mouseOff();
826 
827 	if (!_events->_escKeyFl && _startGameSlot == -1) {
828 		playIntro();
829 		if (shouldQuit())
830 			return false;
831 	}
832 
833 	if (getPlatform() != Common::kPlatformLinux && _startGameSlot == -1) {
834 		_graphicsMan->fadeOutShort();
835 		_graphicsMan->loadImage("H2");
836 		_graphicsMan->fadeInLong();
837 		_events->delay(500);
838 		_graphicsMan->fadeOutLong();
839 	}
840 	_globals->_eventMode = EVENTMODE_DEFAULT;
841 	_globals->_characterSpriteBuf = _fileIO->loadFile("PERSO.SPR");
842 	_globals->_characterType = CHARACTER_HOPKINS;
843 	_objectsMan->_mapCarPosX = _objectsMan->_mapCarPosY = 0;
844 	_globals->_saveData->reset();
845 
846 	_globals->_exitId = 0;
847 
848 
849 	if (_startGameSlot != -1) {
850 		_soundMan->playSound(28);
851 		_saveLoad->loadGame(_startGameSlot);
852 	}
853 
854 	for (;;) {
855 		if (_globals->_exitId == 300)
856 			_globals->_exitId = 0;
857 		if (!_globals->_exitId) {
858 			_globals->_exitId = _menuMan->menu();
859 			if (_globals->_exitId == -1) {
860 				_globals->_characterSpriteBuf = _globals->freeMemory(_globals->_characterSpriteBuf);
861 				restoreSystem();
862 				return false;
863 			}
864 		}
865 
866 		if (shouldQuit())
867 			return false;
868 
869 		_globals->_curRoomNum = _globals->_exitId;
870 
871 		switch (_globals->_exitId) {
872 		case 1:
873 			_linesMan->setMaxLineIdx(40);
874 			_globals->_characterMaxPosY = 435;
875 			_objectsMan->sceneControl2("IM01", "IM01", "ANIM01", "IM01", 1, true);
876 			break;
877 
878 		case 3:
879 			if (!_globals->_saveData->_data[svBankAttackAnimPlayedFl]) {
880 				// Play the bank attack animation
881 				_soundMan->playSound(3);
882 				if (getPlatform() == Common::kPlatformOS2 || getPlatform() == Common::kPlatformBeOS)
883 					_graphicsMan->loadImage("fond");
884 				else {
885 					switch (_globals->_language) {
886 					case LANG_FR:
887 						_graphicsMan->loadImage("fondfr");
888 						break;
889 					case LANG_EN:
890 						_graphicsMan->loadImage("fondan");
891 						break;
892 					case LANG_SP:
893 						_graphicsMan->loadImage("fondes");
894 						break;
895 					default:
896 						break;
897 					}
898 				}
899 				_graphicsMan->fadeInLong();
900 				_events->delay(500);
901 				_graphicsMan->fadeOutLong();
902 				_globals->_eventMode = EVENTMODE_IGNORE;
903 				_soundMan->_specialSoundNum = 2;
904 				_graphicsMan->clearScreen();
905 				_graphicsMan->clearPalette();
906 				if (getPlatform() == Common::kPlatformLinux || getPlatform() == Common::kPlatformWindows) {
907 					if (getPlatform() == Common::kPlatformLinux)
908 						_graphicsMan->_fadingFl = true;
909 
910 					if (!_globals->_censorshipFl)
911 						_animMan->playAnim("BANQUE.ANM", "BANKUK.ANM", 200, 28, 200);
912 					else
913 						_animMan->playAnim("BANKUK.ANM", "BANQUE.ANM", 200, 28, 200);
914 				} else {
915 					_animMan->playAnim("BANQUE.ANM", "BANKUK.ANM", 200, 28, 200);
916 				}
917 
918 				_soundMan->_specialSoundNum = 0;
919 				_soundMan->removeSample(1);
920 				_soundMan->removeSample(2);
921 				_soundMan->removeSample(3);
922 				_soundMan->removeSample(4);
923 
924 				if (getPlatform() != Common::kPlatformLinux) {
925 					// Copy the end of the animation into the secondary buffer and fade out the screen
926 					Common::fill(_graphicsMan->_frontBuffer, _graphicsMan->_frontBuffer +
927 						SCREEN_WIDTH * 2 * SCREEN_HEIGHT, 0);
928 					_graphicsMan->fadeOutLong();
929 				}
930 
931 				_globals->_saveData->_data[svBankAttackAnimPlayedFl] = 1;
932 			}
933 			_linesMan->setMaxLineIdx(5);
934 			_globals->_characterMaxPosY = 450;
935 			_objectsMan->sceneControl2("IM03", "IM03", "ANIM03", "IM03", 2, false);
936 			break;
937 
938 		case 4:
939 			_globals->_disableInventFl = true;
940 			_objectsMan->handleCityMap();
941 			_globals->_disableInventFl = false;
942 			break;
943 
944 		case 5:
945 			_linesMan->setMaxLineIdx(5);
946 			_globals->_characterMaxPosY = 455;
947 			if (_globals->_saveData->_data[svFreedHostageFl] == 1)
948 				_objectsMan->sceneControl2("IM05", "IM05A", "ANIM05B", "IM05", 3, false);
949 			else
950 				_objectsMan->sceneControl2("IM05", "IM05", "ANIM05", "IM05", 3, false);
951 			break;
952 
953 		case 6:
954 			_linesMan->setMaxLineIdx(20);
955 			_globals->_characterMaxPosY = 460;
956 			_objectsMan->sceneControl2("IM06", "IM06", "ANIM06", "IM06", 2, true);
957 			break;
958 
959 		case 7:
960 			if (_globals->_saveData->_data[svBombBoxOpenedFl])
961 				_objectsMan->sceneControl("BOMBEB", "BOMBE", "BOMBE", "BOMBE", 2, true);
962 			else
963 				_objectsMan->sceneControl("BOMBEA", "BOMBE", "BOMBE", "BOMBE", 2, true);
964 			break;
965 
966 		case 8:
967 			_linesMan->setMaxLineIdx(15);
968 			_globals->_characterMaxPosY = 450;
969 			_objectsMan->sceneControl2("IM08", "IM08", "ANIM08", "IM08", 2, true);
970 			break;
971 
972 		case 9:
973 			_linesMan->setMaxLineIdx(20);
974 			_globals->_characterMaxPosY = 440;
975 			if (_globals->_saveData->_data[svBombDisarmedFl])
976 				_objectsMan->sceneControl2("IM09", "IM09", "ANIM09", "IM09", 10, true);
977 			else
978 				bombExplosion();
979 			break;
980 
981 		case 10:
982 			_objectsMan->sceneControl("IM10", "IM10", "ANIM10", "IM10", 9, false);
983 			break;
984 
985 		case 11:
986 			_linesMan->setMaxLineIdx(20);
987 			_globals->_characterMaxPosY = 450;
988 			_objectsMan->sceneControl2("IM11", "IM11", "ANIM11", "IM11", 2, false);
989 			break;
990 
991 		case 12:
992 			_linesMan->setMaxLineIdx(20);
993 			_globals->_characterMaxPosY = 450;
994 			if (_globals->_saveData->_data[svBombDisarmedFl])
995 				_objectsMan->sceneControl2("IM12", "IM12", "ANIM12", "IM12", 1, false);
996 			else
997 				bombExplosion();
998 			break;
999 
1000 		case 13:
1001 			_linesMan->setMaxLineIdx(40);
1002 			_globals->_characterMaxPosY = 440;
1003 			_objectsMan->sceneControl2("IM13", "IM13", "ANIM13", "IM13", 1, true);
1004 			break;
1005 
1006 		case 14:
1007 			_linesMan->setMaxLineIdx(40);
1008 			_globals->_characterMaxPosY = 440;
1009 			_objectsMan->sceneControl2("IM14", "IM14", "ANIM14", "IM14", 1, true);
1010 			break;
1011 
1012 		case 15:
1013 			if (getPlatform() == Common::kPlatformLinux || getPlatform() == Common::kPlatformWindows)
1014 				_objectsMan->sceneControl("IM15", "IM15", "ANIM15", "IM15", 29, false);
1015 			else
1016 				_objectsMan->sceneControl("IM15", "IM15", "ANIM15", "IM15", 18, false);
1017 			break;
1018 
1019 		case 16:
1020 			_linesMan->setMaxLineIdx(5);
1021 			_globals->_characterMaxPosY = 450;
1022 			if (_globals->_saveData->_data[svForestAvailableFl] == 1)
1023 				_objectsMan->sceneControl2("IM16", "IM16A", "ANIM16", "IM16", 7, true);
1024 			else
1025 				_objectsMan->sceneControl2("IM16", "IM16", "ANIM16", "IM16", 7, true);
1026 			break;
1027 
1028 		case 17:
1029 			_linesMan->setMaxLineIdx(40);
1030 			_globals->_characterMaxPosY = 440;
1031 			if (_globals->_saveData->_data[svHutBurningFl] == 1)
1032 				_objectsMan->sceneControl2("IM17", "IM17A", "ANIM17", "IM17", 11, true);
1033 			else if (!_globals->_saveData->_data[svHutBurningFl])
1034 				_objectsMan->sceneControl2("IM17", "IM17", "ANIM17", "IM17", 11, true);
1035 			if (_globals->_exitId == 18) {
1036 				_globals->_eventMode = EVENTMODE_IGNORE;
1037 				_graphicsMan->clearScreen();
1038 				_graphicsMan->clearPalette();
1039 				_soundMan->stopSound();
1040 				if (getPlatform() == Common::kPlatformLinux) {
1041 					_soundMan->playSound(29);
1042 					_graphicsMan->_fadingFl = true;
1043 					_animMan->playAnim("PURG1A.ANM", "PURG1.ANM", 12, 18, 50);
1044 				} else if (getPlatform() == Common::kPlatformWindows) {
1045 					_soundMan->playSound(29);
1046 					_animMan->playAnim("PURG1A.ANM", "PURG1.ANM", 12, 18, 50);
1047 					_graphicsMan->fadeOutShort();
1048 				} else {
1049 					_soundMan->playSound(6);
1050 					_animMan->playAnim("PURG1A.ANM", "PURG1.ANM", 12, 18, 50);
1051 					_graphicsMan->fadeOutShort();
1052 				}
1053 				_globals->_eventMode = EVENTMODE_DEFAULT;
1054 			}
1055 			break;
1056 
1057 		case 18:
1058 			_linesMan->setMaxLineIdx(5);
1059 			_globals->_characterMaxPosY = 450;
1060 			if (getPlatform() == Common::kPlatformLinux || getPlatform() == Common::kPlatformWindows)
1061 				_objectsMan->sceneControl2("IM18", "IM18", "ANIM18", "IM18", 29, false);
1062 			else
1063 				_objectsMan->sceneControl2("IM18", "IM18", "ANIM18", "IM18", 6, false);
1064 			break;
1065 
1066 		case 19:
1067 			_linesMan->setMaxLineIdx(40);
1068 			_globals->_characterMaxPosY = 440;
1069 			if (_globals->_saveData->_data[svHeavenGuardGoneFl])
1070 				_objectsMan->sceneControl2("IM19", "IM19A", "ANIM19", "IM19", 6, true);
1071 			else
1072 				_objectsMan->sceneControl2("IM19", "IM19", "ANIM19", "IM19", 6, true);
1073 			break;
1074 
1075 		case 20:
1076 			_linesMan->setMaxLineIdx(10);
1077 			_globals->_characterMaxPosY = 440;
1078 			_objectsMan->sceneControl2("IM20", "IM20", "ANIM20", "IM20", 6, true);
1079 			if (_globals->_exitId == 17) {
1080 				_globals->_eventMode = EVENTMODE_IGNORE;
1081 				_soundMan->stopSound();
1082 				_graphicsMan->clearScreen();
1083 				_graphicsMan->clearPalette();
1084 				_soundMan->playSound(6);
1085 				if (getPlatform() == Common::kPlatformLinux)
1086 					_graphicsMan->_fadingFl = true;
1087 				_animMan->playAnim("PURG2A.ANM", "PURG2.ANM", 12, 18, 50);
1088 				if (getPlatform() != Common::kPlatformLinux)
1089 					_graphicsMan->fadeOutShort();
1090 				_globals->_eventMode = EVENTMODE_DEFAULT;
1091 			}
1092 			break;
1093 
1094 		case 22:
1095 			_linesMan->setMaxLineIdx(20);
1096 			_globals->_characterMaxPosY = 445;
1097 			_objectsMan->sceneControl2("IM22", "IM22", "ANIM22", "IM22", 6, true);
1098 			break;
1099 
1100 		case 23:
1101 			_linesMan->setMaxLineIdx(20);
1102 			_globals->_characterMaxPosY = 440;
1103 			_objectsMan->sceneControl2("IM23", "IM23", "ANIM23", "IM23", 6, true);
1104 			break;
1105 
1106 		case 24:
1107 			_linesMan->setMaxLineIdx(5);
1108 			_globals->_characterMaxPosY = 450;
1109 			if (_globals->_saveData->_data[svCinemaDogGoneFl] == 1)
1110 				_objectsMan->sceneControl2("IM24", "IM24A", "ANIM24", "IM24", 1, true);
1111 			else
1112 				_objectsMan->sceneControl2("IM24", "IM24", "ANIM24", "IM24", 1, true);
1113 			break;
1114 
1115 		case 25:
1116 			_linesMan->setMaxLineIdx(20);
1117 			_globals->_characterMaxPosY = 445;
1118 			if (getPlatform() == Common::kPlatformLinux || getPlatform() == Common::kPlatformWindows)
1119 				_objectsMan->sceneControl2("IM25", "IM25", "ANIM25", "IM25", 30, true);
1120 			else
1121 				_objectsMan->sceneControl2("IM25", "IM25", "ANIM25", "IM25", 8, true);
1122 			break;
1123 
1124 		case 26:
1125 			_linesMan->setMaxLineIdx(40);
1126 			_globals->_characterMaxPosY = 435;
1127 			if (getPlatform() == Common::kPlatformLinux || getPlatform() == Common::kPlatformWindows)
1128 				_objectsMan->sceneControl2("IM26", "IM26", "ANIM26", "IM26", 30, true);
1129 			else
1130 				_objectsMan->sceneControl2("IM26", "IM26", "ANIM26", "IM26", 8, true);
1131 			break;
1132 
1133 		case 27:
1134 			_linesMan->setMaxLineIdx(15);
1135 			_globals->_characterMaxPosY = 440;
1136 			if (_globals->_saveData->_data[svPoolDogGoneFl] == 1)
1137 				_objectsMan->sceneControl2("IM27", "IM27A", "ANIM27", "IM27", 27, true);
1138 			else
1139 				_objectsMan->sceneControl2("IM27", "IM27", "ANIM27", "IM27", 27, true);
1140 			break;
1141 
1142 		case 28:
1143 			_linesMan->setMaxLineIdx(5);
1144 			_globals->_characterMaxPosY = 450;
1145 			if (_globals->_saveData->_data[svCinemaCurtainCond1] != 1 || _globals->_saveData->_data[svCinemaCurtainCond2] != 1)
1146 				_objectsMan->sceneControl2("IM28", "IM28", "ANIM28", "IM28", 1, false);
1147 			else
1148 				_objectsMan->sceneControl2("IM28A", "IM28", "ANIM28", "IM28", 1, false);
1149 			break;
1150 
1151 		case 29:
1152 			_linesMan->setMaxLineIdx(50);
1153 			_globals->_characterMaxPosY = 445;
1154 			_objectsMan->sceneControl2("IM29", "IM29", "ANIM29", "IM29", 1, true);
1155 			break;
1156 
1157 		case 30:
1158 			// Shooting
1159 			_linesMan->setMaxLineIdx(15);
1160 			_globals->_characterMaxPosY = 440;
1161 			_objectsMan->sceneControl2("IM30", "IM30", "ANIM30", "IM30", 24, false);
1162 			break;
1163 
1164 		case 31:
1165 			// Shooting target
1166 			_objectsMan->sceneControl("IM31", "IM31", "ANIM31", "IM31", 10, true);
1167 			break;
1168 
1169 		case 32:
1170 			_linesMan->setMaxLineIdx(20);
1171 			_globals->_characterMaxPosY = 445;
1172 			_objectsMan->sceneControl2("IM32", "IM32", "ANIM32", "IM32", 2, true);
1173 			break;
1174 
1175 		case 33:
1176 			_objectsMan->sceneControl("IM33", "IM33", "ANIM33", "IM33", 8, false);
1177 			break;
1178 
1179 		case 34:
1180 			// In the airport, before the flight cut-scene
1181 			_objectsMan->sceneControl("IM34", "IM34", "ANIM34", "IM34", 2, false);
1182 			break;
1183 
1184 		case 35:
1185 		case 36:
1186 		case 37:
1187 		case 38:
1188 		case 39:
1189 		case 40:
1190 		case 41: {
1191 			_linesMan->setMaxLineIdx(40);
1192 			_globals->_characterMaxPosY = 435;
1193 			_globals->_disableInventFl = false;
1194 			_objectsMan->_forestFl = true;
1195 			Common::String im = Common::String::format("IM%d", _globals->_exitId);
1196 			_soundMan->playSound(13);
1197 			if (_objectsMan->_forestSprite == NULL) {
1198 				_objectsMan->_forestSprite = _objectsMan->loadSprite("HOPDEG.SPR");
1199 				_soundMan->loadSample(1, "SOUND41.WAV");
1200 			}
1201 			_objectsMan->sceneControl2(im, im, "BANDIT", im, 13, false);
1202 			if (_globals->_exitId < 35 || _globals->_exitId > 49) {
1203 				_objectsMan->_forestSprite = _globals->freeMemory(_objectsMan->_forestSprite);
1204 				_objectsMan->_forestFl = false;
1205 				_soundMan->removeSample(1);
1206 			}
1207 			break;
1208 			}
1209 
1210 		case 50:
1211 			// Flight cut scene
1212 			playPlaneCutscene();
1213 			_globals->_exitId = 51;
1214 			break;
1215 
1216 		case 51:
1217 			_linesMan->setMaxLineIdx(10);
1218 			_globals->_characterMaxPosY = 440;
1219 			_objectsMan->sceneControl2("IM51", "IM51", "ANIM51", "IM51", 14, true);
1220 			break;
1221 
1222 		case 52:
1223 			_linesMan->setMaxLineIdx(15);
1224 			_globals->_characterMaxPosY = 445;
1225 			_objectsMan->sceneControl2("IM52", "IM52", "ANIM52", "IM52", 14, true);
1226 			break;
1227 
1228 		case 54:
1229 			_linesMan->setMaxLineIdx(30);
1230 			_globals->_characterMaxPosY = 440;
1231 			_objectsMan->sceneControl2("IM54", "IM54", "ANIM54", "IM54", 14, true);
1232 			break;
1233 
1234 		case 55:
1235 			_linesMan->setMaxLineIdx(30);
1236 			_globals->_characterMaxPosY = 460;
1237 			_objectsMan->sceneControl2("IM55", "IM55", "ANIM55", "IM55", 14, false);
1238 			break;
1239 
1240 		case 56:
1241 			_linesMan->setMaxLineIdx(30);
1242 			_globals->_characterMaxPosY = 440;
1243 			_objectsMan->sceneControl2("IM56", "IM56", "ANIM56", "IM56", 14, false);
1244 			break;
1245 
1246 		case 57:
1247 			_linesMan->setMaxLineIdx(30);
1248 			_globals->_characterMaxPosY = 440;
1249 			_objectsMan->sceneControl2("IM57", "IM57", "ANIM57", "IM57", 14, true);
1250 			break;
1251 
1252 		case 58:
1253 			_linesMan->setMaxLineIdx(30);
1254 			_globals->_characterMaxPosY = 440;
1255 			_objectsMan->sceneControl2("IM58", "IM58", "ANIM58", "IM58", 14, false);
1256 			break;
1257 
1258 		case 59:
1259 			_linesMan->setMaxLineIdx(5);
1260 			_globals->_characterMaxPosY = 445;
1261 			_objectsMan->sceneControl2("IM59", "IM59", "ANIM59", "IM59", 21, false);
1262 			break;
1263 
1264 		case 60:
1265 			_linesMan->setMaxLineIdx(30);
1266 			_globals->_characterMaxPosY = 440;
1267 			_objectsMan->sceneControl2("IM60", "IM60", "ANIM60", "IM60", 21, false);
1268 			break;
1269 
1270 		case 61:
1271 			if (_globals->_saveData->_data[svBaseElevatorCond1] == 1 && !_globals->_saveData->_data[svBaseFireFl])
1272 				handleConflagration();
1273 			_objectsMan->sceneControl("IM61", "IM61", "ANIM61", "IM61", 21, false);
1274 			break;
1275 
1276 		case 62:
1277 			_linesMan->setMaxLineIdx(8);
1278 			_globals->_characterMaxPosY = 435;
1279 			_objectsMan->sceneControl2("IM62", "IM62", NULL, "IM62", 21, false);
1280 			break;
1281 
1282 		case 63:
1283 			_linesMan->setMaxLineIdx(30);
1284 			_globals->_characterMaxPosY = 435;
1285 			_objectsMan->sceneControl2("IM63", "IM63", "ANIM63", "IM63", 21, false);
1286 			break;
1287 
1288 		case 64:
1289 			_linesMan->setMaxLineIdx(30);
1290 			_globals->_characterMaxPosY = 435;
1291 			_objectsMan->sceneControl2("IM64", "IM64", "ANIM64", "IM64", 21, true);
1292 			break;
1293 
1294 		case 65:
1295 			_linesMan->setMaxLineIdx(30);
1296 			_globals->_characterMaxPosY = 435;
1297 			_objectsMan->sceneControl2("IM65", "IM65", "ANIM65", "IM65", 21, false);
1298 			break;
1299 
1300 		case 66:
1301 			_linesMan->setMaxLineIdx(5);
1302 			_globals->_characterMaxPosY = 445;
1303 			_objectsMan->sceneControl2("IM66", "IM66", "ANIM66", "IM66", 21, false);
1304 			break;
1305 
1306 		case 67:
1307 			_linesMan->setMaxLineIdx(8);
1308 			_globals->_characterMaxPosY = 435;
1309 			_objectsMan->sceneControl2("IM67", "IM67", NULL, "IM67", 21, false);
1310 			break;
1311 
1312 		case 68:
1313 			_linesMan->setMaxLineIdx(8);
1314 			_globals->_characterMaxPosY = 435;
1315 			_objectsMan->sceneControl2("IM68", "IM68", "ANIM68", "IM68", 21, true);
1316 			break;
1317 
1318 		case 69:
1319 			_linesMan->setMaxLineIdx(5);
1320 			_globals->_characterMaxPosY = 445;
1321 			_objectsMan->sceneControl2("IM69", "IM69", "ANIM69", "IM69", 21, false);
1322 			break;
1323 
1324 		case 70:
1325 			_linesMan->setMaxLineIdx(8);
1326 			_globals->_characterMaxPosY = 435;
1327 			_objectsMan->sceneControl2("IM70", "IM70", NULL, "IM70", 21, false);
1328 			break;
1329 
1330 		case 71:
1331 			_linesMan->setMaxLineIdx(5);
1332 			_globals->_characterMaxPosY = 445;
1333 			_objectsMan->sceneControl2("IM71", "IM71", "ANIM71", "IM71", 21, false);
1334 			break;
1335 
1336 		case 73:
1337 			_linesMan->setMaxLineIdx(15);
1338 			_globals->_characterMaxPosY = 445;
1339 			if (_globals->_saveData->_data[svSecondElevatorAvailableFl] == 1)
1340 				_objectsMan->sceneControl2("IM73", "IM73A", "ANIM73", "IM73", 21, true);
1341 			else
1342 				_objectsMan->sceneControl2("IM73", "IM73", "ANIM73", "IM73", 21, true);
1343 			break;
1344 
1345 		case 75:
1346 			playSubmarineCutscene();
1347 			break;
1348 
1349 		case 77:
1350 			handleOceanMaze(77, "OCEAN01", DIR_RIGHT, 0, 84, 0, 0, 25);
1351 			break;
1352 
1353 		case 78:
1354 			handleOceanMaze(78, "OCEAN02", DIR_UP, 0, 91, 84, 0, 25);
1355 			break;
1356 
1357 		case 79:
1358 			handleOceanMaze(79, "OCEAN03", DIR_LEFT, 87, 0, 0, 83, 25);
1359 			break;
1360 
1361 		case 80:
1362 			handleOceanMaze(80, "OCEAN04", DIR_UP, 86, 88, 0, 81, 25);
1363 			break;
1364 
1365 		case 81:
1366 			handleOceanMaze(81, "OCEAN05", DIR_UP, 91, 82, 80, 85, 25);
1367 			break;
1368 
1369 		case 82:
1370 			handleOceanMaze(82, "OCEAN06", DIR_LEFT, 81, 0, 88, 0, 25);
1371 			break;
1372 
1373 		case 83:
1374 			handleOceanMaze(83, "OCEAN07", DIR_UP, 89, 0, 79, 88, 25);
1375 			break;
1376 
1377 		case 84:
1378 			handleOceanMaze(84, "OCEAN08", DIR_UP, 77, 0, 0, 78, 25);
1379 			break;
1380 
1381 		case 85:
1382 			handleOceanMaze(85, "OCEAN09", DIR_UP, 0, 0, 81, 0, 25);
1383 			break;
1384 
1385 		case 86:
1386 			handleOceanMaze(86, "OCEAN10", DIR_UP, 0, 80, 0, 91, 25);
1387 			break;
1388 
1389 		case 87:
1390 			handleOceanMaze(87, "OCEAN11", DIR_RIGHT, 0, 79, 90, 0, 25);
1391 			break;
1392 
1393 		case 88:
1394 			handleOceanMaze(88, "OCEAN12", DIR_UP, 80, 0, 83, 82, 25);
1395 			break;
1396 
1397 		case 89:
1398 			handleOceanMaze(89, "OCEAN13", DIR_RIGHT, 0, 83, 0, 0, 25);
1399 			break;
1400 
1401 		case 90:
1402 			playUnderwaterBaseCutscene();
1403 			break;
1404 
1405 		case 91:
1406 			handleOceanMaze(91, "OCEAN15", DIR_RIGHT, 78, 81, 86, 0, 25);
1407 			break;
1408 
1409 		case 93:
1410 			_linesMan->setMaxLineIdx(5);
1411 			_globals->_characterMaxPosY = 445;
1412 			if (_globals->_saveData->_data[svEscapeLeftJailFl]) {
1413 				if (getPlatform() == Common::kPlatformLinux || getPlatform() == Common::kPlatformWindows)
1414 					_objectsMan->sceneControl2("IM93", "IM93C", "ANIM93", "IM93", 29, true);
1415 				else
1416 					_objectsMan->sceneControl2("IM93", "IM93C", "ANIM93", "IM93", 26, true);
1417 			} else {
1418 				if (getPlatform() == Common::kPlatformLinux || getPlatform() == Common::kPlatformWindows)
1419 					_objectsMan->sceneControl2("IM93", "IM93", "ANIM93", "IM93", 29, true);
1420 				else
1421 					_objectsMan->sceneControl2("IM93", "IM93", "ANIM93", "IM93", 26, true);
1422 			}
1423 			break;
1424 
1425 		case 94:
1426 			_linesMan->setMaxLineIdx(5);
1427 			_globals->_characterMaxPosY = 440;
1428 			_objectsMan->sceneControl2("IM94", "IM94", "ANIM94", "IM94", 19, true);
1429 			break;
1430 
1431 		case 95:
1432 			_linesMan->setMaxLineIdx(5);
1433 			_globals->_characterMaxPosY = 435;
1434 			_objectsMan->sceneControl2("IM95", "IM95", "ANIM95", "IM95", 19, false);
1435 			break;
1436 
1437 		case 96:
1438 			_linesMan->setMaxLineIdx(5);
1439 			_globals->_characterMaxPosY = 435;
1440 			_objectsMan->sceneControl2("IM96", "IM96", "ANIM96", "IM96", 19, false);
1441 			break;
1442 
1443 		case 97:
1444 			_linesMan->setMaxLineIdx(5);
1445 			_globals->_characterMaxPosY = 435;
1446 			_objectsMan->sceneControl2("IM97", "IM97", "ANIM97", "IM97", 19, false);
1447 			if (_globals->_exitId == 18) {
1448 				_globals->_eventMode = EVENTMODE_IGNORE;
1449 				_soundMan->stopSound();
1450 				_graphicsMan->clearScreen();
1451 				_graphicsMan->clearPalette();
1452 				_soundMan->playSound(6);
1453 				_animMan->playAnim("PURG1A.ANM", "PURG1.ANM", 12, 18, 50);
1454 				_graphicsMan->fadeOutShort();
1455 				_globals->_eventMode = EVENTMODE_DEFAULT;
1456 			}
1457 			break;
1458 
1459 		case 98:
1460 			_linesMan->setMaxLineIdx(5);
1461 			_globals->_characterMaxPosY = 435;
1462 			_objectsMan->sceneControl2("IM98", "IM98", "ANIM98", "IM98", 19, true);
1463 			break;
1464 
1465 		case 99:
1466 			_linesMan->setMaxLineIdx(5);
1467 			_globals->_characterMaxPosY = 435;
1468 			_objectsMan->sceneControl2("IM99", "IM99", "ANIM99", "IM99", 19, true);
1469 			break;
1470 
1471 		case 100:
1472 			playEnding();
1473 			break;
1474 
1475 		case 111:
1476 			_objectsMan->sceneControl("IM111", "IM111", "ANIM111", "IM111", 10, false);
1477 			break;
1478 
1479 		case 112:
1480 			_objectsMan->sceneControl("IM112", "IM112", "ANIM112", "IM112", 10, false);
1481 			break;
1482 
1483 		case 113:
1484 			_globals->_prevScreenId = _globals->_screenId;
1485 			_globals->_screenId = 113;
1486 			_globals->_saveData->_data[svLastPrevScreenId] = _globals->_prevScreenId;
1487 			_globals->_saveData->_data[svLastScreenId] = _globals->_screenId;
1488 			_globals->_exitId = 0;
1489 			_computer->showComputer(COMPUTER_HOPKINS);
1490 			_graphicsMan->clearScreen();
1491 			_graphicsMan->updateScreen();
1492 			memset(_graphicsMan->_frontBuffer, 0, 307200);
1493 			memset(_graphicsMan->_backBuffer, 0, 307200);
1494 			_graphicsMan->clearPalette();
1495 			_graphicsMan->resetDirtyRects();
1496 			break;
1497 
1498 		case 114:
1499 			_globals->_exitId = 0;
1500 			_globals->_prevScreenId = _globals->_screenId;
1501 			_globals->_screenId = 114;
1502 			_globals->_saveData->_data[svLastPrevScreenId] = _globals->_prevScreenId;
1503 			_globals->_saveData->_data[svLastScreenId] = _globals->_screenId;
1504 			_computer->showComputer(COMPUTER_SAMANTHA);
1505 			_graphicsMan->clearScreen();
1506 			break;
1507 
1508 		case 115:
1509 			_globals->_prevScreenId = _globals->_screenId;
1510 			_globals->_screenId = 115;
1511 			_globals->_saveData->_data[svLastPrevScreenId] = _globals->_prevScreenId;
1512 			_globals->_saveData->_data[svLastScreenId] = _globals->_screenId;
1513 			_globals->_exitId = 0;
1514 			_computer->showComputer(COMPUTER_PUBLIC);
1515 			_graphicsMan->clearScreen();
1516 			break;
1517 
1518 		case 150:
1519 			_soundMan->playSound(16);
1520 			_globals->_eventMode = EVENTMODE_IGNORE;
1521 			_graphicsMan->clearScreen();
1522 			_graphicsMan->clearPalette();
1523 			if (getPlatform() == Common::kPlatformLinux)
1524 				_graphicsMan->_fadingFl = true;
1525 			_animMan->playAnim("JOUR1A.ANM", "JOUR1A.ANM", 12, 12, 2000);
1526 			_globals->_eventMode = EVENTMODE_DEFAULT;
1527 			_globals->_exitId = 300;
1528 			break;
1529 
1530 		case 151:
1531 			_soundMan->playSound(16);
1532 			_globals->_eventMode = EVENTMODE_IGNORE;
1533 			_graphicsMan->clearScreen();
1534 			_graphicsMan->clearPalette();
1535 			if (getPlatform() == Common::kPlatformLinux)
1536 				_graphicsMan->_fadingFl = true;
1537 			_animMan->playAnim("JOUR3A.ANM", "JOUR3A.ANM", 12, 12, 2000);
1538 			_globals->_eventMode = EVENTMODE_DEFAULT;
1539 			_globals->_exitId = 300;
1540 			break;
1541 
1542 		case 152:
1543 			_soundMan->playSound(16);
1544 			_globals->_eventMode = EVENTMODE_IGNORE;
1545 			_graphicsMan->clearScreen();
1546 			_graphicsMan->clearPalette();
1547 			if (getPlatform() == Common::kPlatformLinux)
1548 				_graphicsMan->_fadingFl = true;
1549 			_animMan->playAnim("JOUR4A.ANM", "JOUR4A.ANM", 12, 12, 2000);
1550 			_globals->_eventMode = EVENTMODE_DEFAULT;
1551 			_globals->_exitId = 300;
1552 			break;
1553 
1554 		case 194:
1555 		case 195:
1556 		case 196:
1557 		case 197:
1558 		case 198:
1559 		case 199:
1560 			_globals->_characterSpriteBuf = _globals->freeMemory(_globals->_characterSpriteBuf);
1561 			_globals->_eventMode = EVENTMODE_IGNORE;
1562 			_soundMan->stopSound();
1563 			_soundMan->playSound(23);
1564 			_globals->_exitId = handleBaseMap();	// Handles the base map (non-Windows)
1565 			//_globals->_exitId = WBASE();	// Handles the 3D Doom level (Windows)
1566 			_soundMan->stopSound();
1567 			_globals->_characterSpriteBuf = _fileIO->loadFile("PERSO.SPR");
1568 			_globals->_characterType = CHARACTER_HOPKINS;
1569 			_globals->_eventMode = EVENTMODE_DEFAULT;
1570 			_graphicsMan->_lineNbr = SCREEN_WIDTH;
1571 			break;
1572 
1573 		default:
1574 			break;
1575 		}
1576 	}
1577 	_globals->_characterSpriteBuf = _globals->freeMemory(_globals->_characterSpriteBuf);
1578 	restoreSystem();
1579 	return true;
1580 }
1581 
getRandomNumber(int maxNumber)1582 int HopkinsEngine::getRandomNumber(int maxNumber) {
1583 	return _randomSource.getRandomNumber(maxNumber);
1584 }
1585 
initializeSystem()1586 void HopkinsEngine::initializeSystem() {
1587 	// Set graphics mode
1588 	_graphicsMan->setGraphicalMode(SCREEN_WIDTH, SCREEN_HEIGHT);
1589 
1590 	// Synchronize the sound settings from ScummVM
1591 	_soundMan->syncSoundSettings();
1592 
1593 	const Common::FSNode gameDataDir(ConfMan.get("path"));
1594 	SearchMan.addSubDirectoryMatching(gameDataDir, "SYSTEM");
1595 	SearchMan.addSubDirectoryMatching(gameDataDir, "LINK");
1596 	SearchMan.addSubDirectoryMatching(gameDataDir, "BUFFER");
1597 	SearchMan.addSubDirectoryMatching(gameDataDir, "ANIM");
1598 	SearchMan.addSubDirectoryMatching(gameDataDir, "ANM");
1599 	SearchMan.addSubDirectoryMatching(gameDataDir, "BASE");
1600 	SearchMan.addSubDirectoryMatching(gameDataDir, "MUSIC");
1601 	SearchMan.addSubDirectoryMatching(gameDataDir, "SEQ");
1602 	SearchMan.addSubDirectoryMatching(gameDataDir, "SAVE");
1603 	SearchMan.addSubDirectoryMatching(gameDataDir, "SOUND");
1604 	SearchMan.addSubDirectoryMatching(gameDataDir, "SVGA");
1605 	SearchMan.addSubDirectoryMatching(gameDataDir, "VOICE");
1606 	SearchMan.addSubDirectoryMatching(gameDataDir, "TSVGA");
1607 
1608 	_globals->clearAll();
1609 
1610 	_events->initMouseData();
1611 	_fontMan->initData();
1612 
1613 	_dialog->loadIcons();
1614 	_objectsMan->_headSprites = _fileIO->loadFile("TETE.SPR");
1615 
1616 	_events->setMouseOn();
1617 	_events->_mouseFl = false;
1618 
1619 	_globals->loadCharacterData();
1620 
1621 	_events->_mouseOffset.x = 0;
1622 	_events->_mouseOffset.y = 0;
1623 }
1624 
1625 /**
1626  * Play the intro of the game
1627  */
playIntro()1628 void HopkinsEngine::playIntro() {
1629 	// Win95 EN demo doesn't include the intro
1630 	if ((getLanguage() == Common::EN_ANY) && (getPlatform() == Common::kPlatformWindows) && (getIsDemo()))
1631 		return;
1632 
1633 	byte paletteData[PALETTE_EXT_BLOCK_SIZE];
1634 	byte paletteData2[PALETTE_EXT_BLOCK_SIZE];
1635 
1636 	memset(&paletteData, 0, PALETTE_EXT_BLOCK_SIZE);
1637 	_events->refreshScreenAndEvents();
1638 	_events->_mouseFl = false;
1639 	_globals->_eventMode = EVENTMODE_IGNORE;
1640 	_events->refreshScreenAndEvents();
1641 	_soundMan->playSound(16);
1642 	_animMan->setClearAnimFlag();
1643 
1644 	_animMan->playAnim("J1.ANM", "J1.ANM", 12, 12, 50);
1645 	if (shouldQuit() || _events->_escKeyFl)
1646 		return;
1647 	_events->mouseOff();
1648 	_soundMan->mixVoice(1, 3);
1649 	_animMan->playAnim("J2.ANM", "J2.ANM", 12, 12, 50);
1650 
1651 	if (shouldQuit() || _events->_escKeyFl)
1652 		return;
1653 
1654 	_events->mouseOff();
1655 	_soundMan->mixVoice(2, 3);
1656 	_animMan->playAnim("J3.ANM", "J3.ANM", 12, 12, 50);
1657 
1658 	if (shouldQuit() || _events->_escKeyFl)
1659 		return;
1660 
1661 	_events->mouseOff();
1662 	_soundMan->mixVoice(3, 3);
1663 	_graphicsMan->clearScreen();
1664 	_graphicsMan->clearPalette();
1665 	_graphicsMan->updateScreen();
1666 	_soundMan->playSound(11);
1667 	_graphicsMan->loadImage("intro1");
1668 	_graphicsMan->scrollScreen(0);
1669 	_graphicsMan->_scrollOffset = 0;
1670 	_graphicsMan->setColorPercentage(252, 100, 100, 100);
1671 	_graphicsMan->setColorPercentage(253, 100, 100, 100);
1672 	_graphicsMan->setColorPercentage(251, 100, 100, 100);
1673 	_graphicsMan->setColorPercentage(254, 0, 0, 0);
1674 
1675 	_events->delay(500);
1676 
1677 	_globals->_eventMode = EVENTMODE_IGNORE;
1678 	_graphicsMan->fadeInLong();
1679 	if (_graphicsMan->_largeScreenFl) {
1680 		_graphicsMan->_scrollStatus = 2;
1681 		_graphicsMan->_scrollPosX = 0;
1682 
1683 		bool loopCond = false;
1684 		do {
1685 			_graphicsMan->_scrollPosX += 2;
1686 			if (_graphicsMan->_scrollPosX > (SCREEN_WIDTH - 2)) {
1687 				_graphicsMan->_scrollPosX = SCREEN_WIDTH;
1688 				loopCond = true;
1689 			}
1690 
1691 			if (_events->getMouseX() < _graphicsMan->_scrollPosX + 10)
1692 				_events->setMouseXY(_events->_mousePos.x + 4, _events->getMouseY());
1693 			_events->refreshScreenAndEvents();
1694 		} while (!shouldQuit() && !loopCond && _graphicsMan->_scrollPosX != SCREEN_WIDTH);
1695 
1696 		_events->refreshScreenAndEvents();
1697 		_graphicsMan->_scrollStatus = 0;
1698 
1699 		if (shouldQuit())
1700 			return;
1701 	}
1702 
1703 	_soundMan->mixVoice(4, 3);
1704 	_graphicsMan->fadeOutLong();
1705 	_graphicsMan->_scrollStatus = 0;
1706 	_graphicsMan->loadImage("intro2");
1707 	_graphicsMan->scrollScreen(0);
1708 	_animMan->loadAnim("INTRO2");
1709 	_graphicsMan->displayAllBob();
1710 	_soundMan->playSound(23);
1711 	_objectsMan->stopBobAnimation(3);
1712 	_objectsMan->stopBobAnimation(5);
1713 	_graphicsMan->_scrollOffset = 0;
1714 	_graphicsMan->setColorPercentage(252, 100, 100, 100);
1715 	_graphicsMan->setColorPercentage(253, 100, 100, 100);
1716 	_graphicsMan->setColorPercentage(251, 100, 100, 100);
1717 	_graphicsMan->setColorPercentage(254, 0, 0, 0);
1718 
1719 	for (int i = 0; i <= 4; i++)
1720 		_events->refreshScreenAndEvents();
1721 
1722 	_globals->_eventMode = EVENTMODE_IGNORE;
1723 	_graphicsMan->fadeInLong();
1724 	for (uint i = 0; i < 200 / _globals->_speed; ++i)
1725 		_events->refreshScreenAndEvents();
1726 
1727 	_objectsMan->setBobAnimation(3);
1728 	_soundMan->mixVoice(5, 3);
1729 	_objectsMan->stopBobAnimation(3);
1730 	_events->refreshScreenAndEvents();
1731 	memcpy(&paletteData2, _graphicsMan->_palette, 796);
1732 
1733 	_graphicsMan->setPaletteVGA256WithRefresh(paletteData, _graphicsMan->_frontBuffer);
1734 	_graphicsMan->endDisplayBob();
1735 
1736 	if (shouldQuit() || _events->_escKeyFl)
1737 		return;
1738 
1739 	_soundMan->_specialSoundNum = 5;
1740 	_graphicsMan->_fadingFl = true;
1741 	_animMan->playAnim("ELEC.ANM", "ELEC.ANM", 10, 26, 200);
1742 	_soundMan->_specialSoundNum = 0;
1743 
1744 	if (shouldQuit() || _events->_escKeyFl)
1745 		return;
1746 
1747 	_graphicsMan->loadImage("intro2");
1748 	_graphicsMan->scrollScreen(0);
1749 	_animMan->loadAnim("INTRO2");
1750 	_graphicsMan->displayAllBob();
1751 	_soundMan->playSound(23);
1752 	_objectsMan->stopBobAnimation(3);
1753 	_objectsMan->stopBobAnimation(5);
1754 	_objectsMan->stopBobAnimation(1);
1755 	_graphicsMan->_scrollOffset = 0;
1756 	_graphicsMan->setColorPercentage(252, 100, 100, 100);
1757 	_graphicsMan->setColorPercentage(253, 100, 100, 100);
1758 	_graphicsMan->setColorPercentage(251, 100, 100, 100);
1759 	_graphicsMan->setColorPercentage(254, 0, 0, 0);
1760 
1761 	for (int i = 0; i <= 3; i++)
1762 		_events->refreshScreenAndEvents();
1763 
1764 	_globals->_eventMode = EVENTMODE_IGNORE;
1765 	_graphicsMan->setPaletteVGA256WithRefresh(paletteData2, _graphicsMan->_frontBuffer);
1766 
1767 	int introIndex = 0;
1768 	while (!shouldQuit() && !_events->_escKeyFl) {
1769 		if (introIndex == 12) {
1770 			_objectsMan->setBobAnimation(3);
1771 			_events->refreshScreenAndEvents();
1772 			_soundMan->mixVoice(6, 3);
1773 			_events->refreshScreenAndEvents();
1774 			_objectsMan->stopBobAnimation(3);
1775 		}
1776 
1777 		Common::copy(&paletteData2[0], &paletteData2[PALETTE_BLOCK_SIZE], &_graphicsMan->_palette[0]);
1778 
1779 		for (int i = 1, maxPalVal = 4 * introIndex; i <= PALETTE_BLOCK_SIZE; i++) {
1780 			if (_graphicsMan->_palette[i] > maxPalVal)
1781 				_graphicsMan->_palette[i] -= maxPalVal;
1782 		}
1783 
1784 		_graphicsMan->setPaletteVGA256WithRefresh(_graphicsMan->_palette, _graphicsMan->_frontBuffer);
1785 
1786 		for (int i = 1; i < 2 * introIndex; i++)
1787 			_events->refreshScreenAndEvents();
1788 
1789 		_graphicsMan->setPaletteVGA256WithRefresh(paletteData2, _graphicsMan->_frontBuffer);
1790 
1791 		for (int i = 1; i < 20 - introIndex; i++)
1792 			_events->refreshScreenAndEvents();
1793 
1794 		introIndex += 2;
1795 		if (introIndex > 15) {
1796 			_graphicsMan->setPaletteVGA256WithRefresh(paletteData, _graphicsMan->_frontBuffer);
1797 			for (uint j = 1; j < 100 / _globals->_speed; ++j)
1798 				_events->refreshScreenAndEvents();
1799 
1800 			_objectsMan->setBobAnimation(3);
1801 			_soundMan->mixVoice(7, 3);
1802 			_objectsMan->stopBobAnimation(3);
1803 
1804 			for (uint k = 1; k < 60 / _globals->_speed; ++k)
1805 				_events->refreshScreenAndEvents();
1806 			_objectsMan->setBobAnimation(5);
1807 			for (uint l = 0; l < 20 / _globals->_speed; ++l)
1808 				_events->refreshScreenAndEvents();
1809 
1810 			Common::copy(&paletteData2[0], &paletteData2[PALETTE_BLOCK_SIZE], &_graphicsMan->_palette[0]);
1811 			_graphicsMan->setPaletteVGA256WithRefresh(_graphicsMan->_palette, _graphicsMan->_frontBuffer);
1812 
1813 			for (uint m = 0; m < 50 / _globals->_speed; ++m) {
1814 				if (m == 30 / _globals->_speed) {
1815 					_objectsMan->setBobAnimation(3);
1816 					_soundMan->mixVoice(8, 3);
1817 					_objectsMan->stopBobAnimation(3);
1818 				}
1819 
1820 				_events->refreshScreenAndEvents();
1821 			}
1822 
1823 			_graphicsMan->fadeOutLong();
1824 			_graphicsMan->endDisplayBob();
1825 			_soundMan->playSound(3);
1826 			_soundMan->_specialSoundNum = 1;
1827 			_animMan->setClearAnimFlag();
1828 			_animMan->playAnim("INTRO1.ANM", "INTRO1.ANM", 10, 24, 18);
1829 			_soundMan->_specialSoundNum = 0;
1830 			if (shouldQuit() || _events->_escKeyFl)
1831 				return;
1832 
1833 			_animMan->playAnim("INTRO2.ANM", "INTRO2.ANM", 10, 24, 18);
1834 			if (shouldQuit() || _events->_escKeyFl)
1835 				return;
1836 
1837 			_animMan->playAnim("INTRO3.ANM", "INTRO3.ANM", 10, 24, 200);
1838 			if (shouldQuit() || _events->_escKeyFl)
1839 				return;
1840 
1841 			_graphicsMan->_fadingFl = true;
1842 			_animMan->unsetClearAnimFlag();
1843 			_animMan->playAnim("J4.ANM", "J4.ANM", 12, 12, 1000);
1844 			break;
1845 		}
1846 	}
1847 
1848 	_events->_escKeyFl = false;
1849 }
1850 
1851 /**
1852  * If in demo, displays a 'not available' screen and returns to the city map
1853  */
displayNotAvailable()1854 void HopkinsEngine::displayNotAvailable() {
1855 	if (!getIsDemo())
1856 		return;
1857 
1858 	if (_globals->_language == LANG_FR)
1859 		_graphicsMan->loadImage("ndfr");
1860 	else
1861 		_graphicsMan->loadImage("nduk");
1862 
1863 	_graphicsMan->fadeInLong();
1864 	if (_soundMan->_voiceOffFl)
1865 		_events->delay(500);
1866 	else
1867 		_soundMan->mixVoice(628, 4);
1868 
1869 	_graphicsMan->fadeOutLong();
1870 	_globals->_exitId = 4;
1871 }
1872 
handleNotAvailable(int nextScreen)1873 void HopkinsEngine::handleNotAvailable(int nextScreen) {
1874 	// Use the code of the Linux demo instead of the code of the Windows demo.
1875 	// The behavior is somewhat better, and common code is easier to maintain.
1876 	displayNotAvailable();
1877 	_globals->_exitId = nextScreen;
1878 }
1879 
displayEndDemo()1880 void HopkinsEngine::displayEndDemo() {
1881 	_soundMan->playSound(28);
1882 	if (_globals->_language == LANG_FR)
1883 		_graphicsMan->loadImage("endfr");
1884 	else
1885 		_graphicsMan->loadImage("enduk");
1886 
1887 	_graphicsMan->fadeInLong();
1888 	_events->delay(1500);
1889 	_graphicsMan->fadeOutLong();
1890 	_globals->_exitId = 0;
1891 }
1892 
bombExplosion()1893 void HopkinsEngine::bombExplosion() {
1894 	_graphicsMan->_lineNbr = SCREEN_WIDTH;
1895 	_graphicsMan->setScreenWidth(SCREEN_WIDTH);
1896 	_graphicsMan->clearScreen();
1897 	_graphicsMan->clearPalette();
1898 
1899 	_globals->_eventMode = EVENTMODE_IGNORE;
1900 	_soundMan->_specialSoundNum = 199;
1901 	_graphicsMan->_fadingFl = true;
1902 	_animMan->playAnim("BOMBE2A.ANM", "BOMBE2.ANM", 50, 14, 500);
1903 	_soundMan->_specialSoundNum = 0;
1904 	_graphicsMan->loadImage("IM15");
1905 	_animMan->loadAnim("ANIM15");
1906 	_graphicsMan->displayAllBob();
1907 	_objectsMan->stopBobAnimation(7);
1908 
1909 	for (int idx = 0; idx < 5; ++idx) {
1910 		_events->refreshScreenAndEvents();
1911 	}
1912 
1913 	_graphicsMan->fadeInLong();
1914 	_events->mouseOff();
1915 
1916 	for (int idx = 0; idx < 20; ++idx) {
1917 		_events->refreshScreenAndEvents();
1918 	}
1919 
1920 	_globals->_introSpeechOffFl = true;
1921 	_talkMan->startStaticCharacterDialogue("vire.pe2");
1922 	_globals->_introSpeechOffFl = false;
1923 	_objectsMan->setBobAnimation(7);
1924 
1925 	for (int idx = 0; idx < 100; ++idx) {
1926 		_events->refreshScreenAndEvents();
1927 	}
1928 
1929 	_graphicsMan->fadeOutLong();
1930 	_graphicsMan->endDisplayBob();
1931 	_globals->_eventMode = EVENTMODE_DEFAULT;
1932 	_globals->_exitId = 151;
1933 }
1934 
restoreSystem()1935 void HopkinsEngine::restoreSystem() {
1936 	_events->refreshEvents();
1937 }
1938 
endLinuxDemo()1939 void HopkinsEngine::endLinuxDemo() {
1940 	_globals->_linuxEndDemoFl = true;
1941 	_graphicsMan->resetDirtyRects();
1942 	_objectsMan->_forestFl = false;
1943 	_events->_breakoutFl = false;
1944 	_globals->_disableInventFl = true;
1945 	_graphicsMan->loadImage("BOX");
1946 	_soundMan->playSound(28);
1947 	_graphicsMan->fadeInLong();
1948 	_events->mouseOn();
1949 	_events->changeMouseCursor(0);
1950 	_events->_mouseCursorId = 0;
1951 	_events->_mouseSpriteId = 0;
1952 
1953 	bool mouseClicked = false;
1954 
1955 	do {
1956 		_events->refreshScreenAndEvents();
1957 
1958 		if (_events->getMouseButton() == 1)
1959 			mouseClicked = true;
1960 	} while (!mouseClicked && !shouldQuit());
1961 
1962 	// Original tried to open a web browser link here. Since ScummVM doesn't support
1963 	// that, it's being skipped in favor of simply exiting
1964 
1965 	_graphicsMan->fadeOutLong();
1966 }
1967 
handleConflagration()1968 void HopkinsEngine::handleConflagration() {
1969 	_globals->_disableInventFl = true;
1970 	_globals->_eventMode = EVENTMODE_IGNORE;
1971 	_graphicsMan->loadImage("IM71");
1972 	_animMan->loadAnim("ANIM71");
1973 	_graphicsMan->setColorPercentage(252, 100, 100, 100);
1974 	_graphicsMan->setColorPercentage(253, 100, 100, 100);
1975 	_graphicsMan->setColorPercentage(251, 100, 100, 100);
1976 	_graphicsMan->setColorPercentage(254, 0, 0, 0);
1977 	_graphicsMan->displayAllBob();
1978 
1979 	for (int cpt = 0; cpt <= 4; cpt++)
1980 		_events->refreshScreenAndEvents();
1981 
1982 	_graphicsMan->fadeInLong();
1983 	_globals->_eventMode = EVENTMODE_IGNORE;
1984 
1985 	for (int cpt = 0; cpt <= 249; cpt++)
1986 		_events->refreshScreenAndEvents();
1987 
1988 	_globals->_introSpeechOffFl = true;
1989 	_talkMan->startAnimatedCharacterDialogue("SVGARD1.pe2");
1990 	_globals->_introSpeechOffFl = false;
1991 
1992 	for (int cpt = 0; cpt <= 49; cpt++)
1993 		_events->refreshScreenAndEvents();
1994 
1995 	_graphicsMan->fadeOutLong();
1996 	_graphicsMan->endDisplayBob();
1997 	_globals->_saveData->_data[svBaseFireFl] = 1;
1998 	_globals->_disableInventFl = false;
1999 }
2000 
playSubmarineCutscene()2001 void HopkinsEngine::playSubmarineCutscene() {
2002 	_globals->_eventMode = EVENTMODE_IGNORE;
2003 	_graphicsMan->_lineNbr = SCREEN_WIDTH;
2004 	_graphicsMan->clearScreen();
2005 	_graphicsMan->clearPalette();
2006 	_soundMan->playSound(25);
2007 	_animMan->setClearAnimFlag();
2008 	_animMan->playAnim("BASE00A.ANM", "BASE00.ANM", 10, 18, 18);
2009 	if (!_events->_escKeyFl)
2010 		_animMan->playAnim("BASE05A.ANM", "BASE05.ANM", 10, 18, 18);
2011 	if (!_events->_escKeyFl)
2012 		_animMan->playAnim("BASE10A.ANM", "BASE10.ANM", 10, 18, 18);
2013 	if (!_events->_escKeyFl)
2014 		_animMan->playAnim("BASE20A.ANM", "BASE20.ANM", 10, 18, 18);
2015 	// CHECKME: The original code was doing the opposite test, which was a bug.
2016 	if (!_events->_escKeyFl)
2017 		_animMan->playAnim("BASE30A.ANM", "BASE30.ANM", 10, 18, 18);
2018 	if (!_events->_escKeyFl)
2019 		_animMan->playAnim("BASE40A.ANM", "BASE40.ANM", 10, 18, 18);
2020 	if (!_events->_escKeyFl)
2021 		_animMan->playAnim("BASE50A.ANM", "BASE50.ANM", 10, 18, 18);
2022 	if (!_events->_escKeyFl)
2023 		_animMan->playAnim("OC00A.ANM", "OC00.ANM", 10, 18, 18);
2024 	if (!_events->_escKeyFl)
2025 		_animMan->playAnim("OC05A.ANM", "OC05.ANM", 10, 18, 18);
2026 	if (!_events->_escKeyFl)
2027 		_animMan->playAnim("OC10A.ANM", "OC10.ANM", 10, 18, 18);
2028 	if (!_events->_escKeyFl)
2029 		_animMan->playAnim("OC20A.ANM", "OC20.ANM", 10, 18, 18);
2030 	if (!_events->_escKeyFl) {
2031 		_graphicsMan->_fadingFl = true;
2032 		_animMan->playAnim("OC30A.ANM", "OC30.ANM", 10, 18, 18);
2033 	}
2034 
2035 	_events->_escKeyFl = false;
2036 	_animMan->unsetClearAnimFlag();
2037 	_globals->_exitId = 85;
2038 }
2039 
playUnderwaterBaseCutscene()2040 void HopkinsEngine::playUnderwaterBaseCutscene() {
2041 	_graphicsMan->clearScreen();
2042 	_graphicsMan->clearPalette();
2043 	_soundMan->playSound(26);
2044 	_globals->_eventMode = EVENTMODE_IGNORE;
2045 	_globals->_disableInventFl = true;
2046 	_graphicsMan->_fadingFl = true;
2047 	_animMan->playSequence("abase.seq", 50, 15, 50, false, false, true);
2048 	_graphicsMan->loadImage("IM92");
2049 	_animMan->loadAnim("ANIM92");
2050 	_graphicsMan->displayAllBob();
2051 	_objectsMan->loadLinkFile("IM92");
2052 /*
2053 	for (int cpt = 0; cpt <= 4 && !shouldQuit(); cpt++)
2054 		_eventsManager->refreshScreenAndEvents();
2055 */
2056 	_graphicsMan->fadeInLong();
2057 	_objectsMan->enableHidingBehavior();
2058 
2059 	do {
2060 		_events->refreshScreenAndEvents();
2061 	} while (!shouldQuit() && _objectsMan->getBobAnimDataIdx(8) != 22);
2062 
2063 	if (!shouldQuit()) {
2064 		_graphicsMan->fadeOutLong();
2065 		_graphicsMan->endDisplayBob();
2066 		_objectsMan->resetHidingItems();
2067 		_globals->_disableInventFl = false;
2068 		_globals->_exitId = 93;
2069 		_globals->_eventMode = EVENTMODE_DEFAULT;
2070 	}
2071 }
2072 
playEnding()2073 void HopkinsEngine::playEnding() {
2074 	_globals->_characterSpriteBuf = _globals->freeMemory(_globals->_characterSpriteBuf);
2075 	_dialog->disableInvent();
2076 	_globals->_disableInventFl = true;
2077 	_graphicsMan->_scrollOffset = 0;
2078 	_globals->_cityMapEnabledFl = false;
2079 	_globals->_eventMode = EVENTMODE_IGNORE;
2080 	_soundMan->playSound(26);
2081 	_linesMan->_route = NULL;
2082 	_globals->_freezeCharacterFl = true;
2083 	_globals->_exitId = 0;
2084 	_soundMan->loadSample(1, "SOUND90.WAV");
2085 	_graphicsMan->loadImage("IM100");
2086 	_animMan->loadAnim("ANIM100");
2087 	_graphicsMan->displayAllBob();
2088 	_events->mouseOn();
2089 	_objectsMan->stopBobAnimation(7);
2090 	_objectsMan->stopBobAnimation(8);
2091 	_objectsMan->stopBobAnimation(9);
2092 	_graphicsMan->setColorPercentage(252, 100, 100, 100);
2093 	_graphicsMan->setColorPercentage(253, 100, 100, 100);
2094 	_graphicsMan->setColorPercentage(251, 100, 100, 100);
2095 	_graphicsMan->setColorPercentage(254, 0, 0, 0);
2096 	_events->changeMouseCursor(0);
2097 
2098 	for (int cpt = 0; cpt <= 4; cpt++)
2099 		_events->refreshScreenAndEvents();
2100 
2101 	_graphicsMan->fadeInLong();
2102 	_globals->_eventMode = EVENTMODE_IGNORE;
2103 
2104 	do {
2105 		_events->refreshScreenAndEvents();
2106 	} while (_objectsMan->getBobAnimDataIdx(6) != 54);
2107 
2108 	_globals->_introSpeechOffFl = true;
2109 	_talkMan->startAnimatedCharacterDialogue("GM4.PE2");
2110 	_globals->_disableInventFl = true;
2111 	_objectsMan->stopBobAnimation(6);
2112 	_objectsMan->stopBobAnimation(10);
2113 	_objectsMan->setBobAnimation(9);
2114 	_objectsMan->setBobAnimation(7);
2115 
2116 	do {
2117 		_events->refreshScreenAndEvents();
2118 	} while (_objectsMan->getBobAnimDataIdx(7) != 54);
2119 
2120 	_soundMan->playSample(1);
2121 
2122 	do {
2123 		_events->refreshScreenAndEvents();
2124 	} while (_objectsMan->getBobAnimDataIdx(7) != 65);
2125 
2126 	_globals->_introSpeechOffFl = true;
2127 	_talkMan->startAnimatedCharacterDialogue("DUELB4.PE2");
2128 	_events->mouseOff();
2129 	_globals->_disableInventFl = true;
2130 
2131 	do {
2132 		_events->refreshScreenAndEvents();
2133 	} while (_objectsMan->getBobAnimDataIdx(7) != 72);
2134 
2135 	_globals->_introSpeechOffFl = true;
2136 	_talkMan->startAnimatedCharacterDialogue("DUELH1.PE2");
2137 
2138 	do {
2139 		_events->refreshScreenAndEvents();
2140 	} while (_objectsMan->getBobAnimDataIdx(7) != 81);
2141 
2142 	_globals->_introSpeechOffFl = true;
2143 	_talkMan->startAnimatedCharacterDialogue("DUELB5.PE2");
2144 
2145 	do {
2146 		_events->refreshScreenAndEvents();
2147 	} while (_objectsMan->getBobAnimDataIdx(7) != 120);
2148 
2149 	_objectsMan->stopBobAnimation(7);
2150 	if (_globals->_saveData->_data[svGameWonFl] == 1) {
2151 		_soundMan->_specialSoundNum = 200;
2152 		_soundMan->_skipRefreshFl = true;
2153 		_graphicsMan->_fadingFl = true;
2154 		_animMan->playAnim("BERM.ANM", "BERM.ANM", 100, 24, 300);
2155 		_graphicsMan->endDisplayBob();
2156 		_soundMan->removeSample(1);
2157 		_graphicsMan->loadImage("PLAN3");
2158 		_graphicsMan->fadeInLong();
2159 
2160 		_events->_rateCounter = 0;
2161 		if (!_events->_escKeyFl) {
2162 			do {
2163 				_events->refreshEvents();
2164 			} while (_events->_rateCounter < 2000 / _globals->_speed && !_events->_escKeyFl);
2165 		}
2166 		_events->_escKeyFl = false;
2167 		_graphicsMan->fadeOutLong();
2168 		_globals->_eventMode = EVENTMODE_IGNORE;
2169 		_soundMan->_specialSoundNum = 0;
2170 		_graphicsMan->_fadingFl = true;
2171 		_animMan->playAnim("JOUR2A.anm", "JOUR2A.anm", 12, 12, 1000);
2172 		_soundMan->playSound(11);
2173 		_graphicsMan->clearScreen();
2174 		_graphicsMan->clearPalette();
2175 		_animMan->playAnim("FF1a.anm", "FF1.anm", 18, 18, 9);
2176 		_animMan->playAnim("FF1a.anm", "FF1.anm", 9, 18, 9);
2177 		_animMan->playAnim("FF1a.anm", "FF1.anm", 9, 18, 18);
2178 		_animMan->playAnim("FF1a.anm", "FF1.anm", 9, 18, 9);
2179 		_animMan->playAnim("FF2a.anm", "FF2.anm", 24, 24, 100);
2180 		_events->mouseOff();
2181 		displayCredits();
2182 		_globals->_eventMode = EVENTMODE_DEFAULT;
2183 		_globals->_exitId = 300;
2184 		_dialog->enableInvent();
2185 		_globals->_disableInventFl = false;
2186 	} else {
2187 		_soundMan->_specialSoundNum = 200;
2188 		_soundMan->_skipRefreshFl = true;
2189 		_animMan->playAnim2("BERM.ANM", "BERM.ANM", 100, 24, 300);
2190 		_objectsMan->stopBobAnimation(7);
2191 		_objectsMan->setBobAnimation(8);
2192 		_globals->_introSpeechOffFl = true;
2193 		_talkMan->startAnimatedCharacterDialogue("GM5.PE2");
2194 		_globals->_disableInventFl = true;
2195 
2196 		do {
2197 			_events->refreshScreenAndEvents();
2198 		} while (_objectsMan->getBobAnimDataIdx(8) != 5);
2199 
2200 		_soundMan->directPlayWav("SOUND41.WAV");
2201 
2202 		do {
2203 			_events->refreshScreenAndEvents();
2204 		} while (_objectsMan->getBobAnimDataIdx(8) != 21);
2205 
2206 		_graphicsMan->fadeOutLong();
2207 		_graphicsMan->endDisplayBob();
2208 		_soundMan->removeSample(1);
2209 		_soundMan->playSound(16);
2210 		_globals->_eventMode = EVENTMODE_IGNORE;
2211 		_soundMan->_specialSoundNum = 0;
2212 		_dialog->enableInvent();
2213 		_globals->_disableInventFl = false;
2214 		_animMan->playAnim("JOUR4A.ANM", "JOUR4A.ANM", 12, 12, 1000);
2215 		_globals->_eventMode = EVENTMODE_DEFAULT;
2216 		_globals->_exitId = 300;
2217 	}
2218 	_globals->_characterSpriteBuf = _fileIO->loadFile("PERSO.SPR");
2219 	_globals->_characterType = CHARACTER_HOPKINS;
2220 	_globals->_eventMode = EVENTMODE_DEFAULT;
2221 }
2222 
playPlaneCutscene()2223 void HopkinsEngine::playPlaneCutscene() {
2224 	_soundMan->playSound(28);
2225 	_globals->_eventMode = EVENTMODE_IGNORE;
2226 	_graphicsMan->clearScreen();
2227 	_graphicsMan->clearPalette();
2228 
2229 	_animMan->unsetClearAnimFlag();
2230 	_animMan->playAnim("AEROP00A.ANM", "AEROP00.ANM", 10, 18, 18);
2231 	if (!_events->_escKeyFl)
2232 		_animMan->playAnim("SEROP10A.ANM", "SEROP10A.ANM", 10, 18, 18);
2233 	if (!_events->_escKeyFl)
2234 		_animMan->playAnim("AEROP20A.ANM", "AEROP20.ANM", 10, 18, 18);
2235 	if (!_events->_escKeyFl)
2236 		_animMan->playAnim("AEROP30A.ANM", "AEROP30.ANM", 10, 18, 18);
2237 	if (!_events->_escKeyFl)
2238 		_animMan->playAnim("AEROP40A.ANM", "AEROP40.ANM", 10, 18, 18);
2239 	if (!_events->_escKeyFl)
2240 		_animMan->playAnim("AEROP50A.ANM", "AEROP50.ANM", 10, 18, 18);
2241 	if (!_events->_escKeyFl)
2242 		_animMan->playAnim("AEROP60A.ANM", "AEROP60.ANM", 10, 18, 18);
2243 	if (!_events->_escKeyFl)
2244 		_animMan->playAnim("AEROP70A.ANM", "AEROP70.ANM", 10, 18, 18);
2245 	if (!_events->_escKeyFl)
2246 		_animMan->playAnim("TRANS00A.ANM", "TRANS00.ANM", 10, 18, 18);
2247 	if (!_events->_escKeyFl)
2248 		_animMan->playAnim("TRANS10A.ANM", "TRANS10.ANM", 10, 18, 18);
2249 	if (!_events->_escKeyFl)
2250 		_animMan->playAnim("TRANS15A.ANM", "TRANS15.ANM", 10, 18, 18);
2251 	if (!_events->_escKeyFl)
2252 		_animMan->playAnim("TRANS20A.ANM", "TRANS20.ANM", 10, 18, 18);
2253 	if (!_events->_escKeyFl)
2254 		_animMan->playAnim("TRANS30A.ANM", "TRANS30.ANM", 10, 18, 18);
2255 	if (!_events->_escKeyFl)
2256 		_animMan->playAnim("TRANS40A.ANM", "TRANS40.ANM", 10, 18, 18);
2257 	if (!_events->_escKeyFl) {
2258 		_graphicsMan->_fadingFl = true;
2259 		_animMan->playAnim("PARA00A.ANM", "PARA00.ANM", 9, 9, 9);
2260 	} else {
2261 		_graphicsMan->fadeOutShort();
2262 	}
2263 
2264 	_events->_escKeyFl = false;
2265 	_animMan->unsetClearAnimFlag();
2266 }
2267 
loadBaseMap()2268 void HopkinsEngine::loadBaseMap() {
2269 	Common::String filename	= Common::String::format("%s.PCX", "PBASE");
2270 	Common::File f;
2271 
2272 	if (f.exists(filename)) {
2273 		// PBASE file exists, so go ahead and load it
2274 		_graphicsMan->loadImage("PBASE");
2275 	} else {
2276 		// PBASE file doesn't exist, so draw a substitute screen
2277 		drawBaseMap();
2278 	}
2279 }
2280 
drawBaseMap()2281 void HopkinsEngine::drawBaseMap() {
2282 	memset(_graphicsMan->_backBuffer, 0, SCREEN_WIDTH * 2 * SCREEN_HEIGHT);
2283 
2284 	// List of rectangle areas to draw for exit points
2285 	const int rects[] = {
2286 		181, 66, 181 + 16, 66 + 22,
2287 		353, 116, 353 + 22, 116 + 16,
2288 		483, 250, 483 + 20, 250 + 25,
2289 		471, 326, 471 + 27, 326 + 20,
2290 		162, 365, 162 + 21, 365 + 23,
2291 		106, 267, 106 + 20, 267 + 26
2292 	};
2293 
2294 	// Loop through displaying
2295 	const int *rectP = &rects[0];
2296 	for (int rectIndex = 0; rectIndex < 6; ++rectIndex, rectP += 4) {
2297 		Common::Rect r(rectP[0], rectP[1], rectP[2], rectP[3]);
2298 
2299 		for (int yp = r.top; yp <= r.bottom; ++yp) {
2300 			byte *pDest = _graphicsMan->_backBuffer + yp * SCREEN_WIDTH + r.left;
2301 			Common::fill(pDest, pDest + r.width(), 0xff);
2302 		}
2303 	}
2304 
2305 	// Copy the calculated screen
2306 	memcpy(_graphicsMan->_frontBuffer, _graphicsMan->_backBuffer, SCREEN_WIDTH * 2 * SCREEN_HEIGHT);
2307 
2308 	// Write some explanatory text
2309 	_fontMan->displayText(40, 200, "ScummVM base map - select a square for different rooms", 255);
2310 }
2311 
handleBaseMap()2312 int HopkinsEngine::handleBaseMap() {
2313 	_globals->_disableInventFl = true;
2314 
2315 	// Load the map image
2316 	loadBaseMap();
2317 
2318 	// Set needed colors
2319 	_graphicsMan->setColorPercentage(252, 100, 100, 100);
2320 	_graphicsMan->setColorPercentage(253, 100, 100, 100);
2321 	_graphicsMan->setColorPercentage(251, 100, 100, 100);
2322 	_graphicsMan->setColorPercentage(254, 0, 0, 0);
2323 	_events->changeMouseCursor(0);
2324 	_graphicsMan->fadeInLong();
2325 	bool loopCond = false;
2326 	int zone;
2327 	do {
2328 		if (shouldQuit())
2329 			return 0;
2330 
2331 		int mouseButton = _events->getMouseButton();
2332 		int posX = _events->getMouseX();
2333 		int posY = _events->getMouseY();
2334 		zone = 0;
2335 		if ((posX - 181 <= 16) && (posY - 66 <= 22) &&
2336 		    (posX - 181 >= 0) && (posY - 66 >= 0))
2337 			zone = 1;
2338 		if ((posX - 353 <= 22) && (posY - 116 <= 19) &&
2339 		    (posX - 353 >= 0) && (posY - 116 >= 0))
2340 			zone = 2;
2341 		if ((posX - 483 <= 20) && (posY - 250 <= 25) &&
2342 		    (posX - 483 >= 0) && (posY - 250 >= 0))
2343 			zone = 3;
2344 		if ((posX - 471 <= 27) && (posY - 326 <= 20) &&
2345 		    (posX - 471 >= 0) && (posY - 326 >= 0))
2346 			zone = 4;
2347 		if ((posX - 162 <= 21) && (posY - 365 <= 23) &&
2348 		    (posX - 162 >= 0) && (posY - 365 >= 0))
2349 			zone = 5;
2350 		if ((posX - 106 <= 20) && (posY - 267 <= 26) &&
2351 		    (posX - 106 >= 0) && (posY - 267 >= 0))
2352 			zone = 6;
2353 		if (zone) {
2354 			_events->changeMouseCursor(4);
2355 			_globals->_baseMapColor += 25;
2356 			if (_globals->_baseMapColor > 100)
2357 				_globals->_baseMapColor = 0;
2358 			_graphicsMan->setColorPercentage2(251, _globals->_baseMapColor, _globals->_baseMapColor, _globals->_baseMapColor);
2359 		} else {
2360 			_events->changeMouseCursor(0);
2361 			_graphicsMan->setColorPercentage2(251, 100, 100, 100);
2362 		}
2363 		_events->refreshScreenAndEvents();
2364 		if ((mouseButton == 1) && zone)
2365 			loopCond = true;
2366 	} while (!loopCond);
2367 
2368 	_globals->_disableInventFl = false;
2369 	_graphicsMan->fadeOutLong();
2370 
2371 	int result;
2372 	switch (zone) {
2373 	case 1:
2374 		result = 94;
2375 		break;
2376 	case 2:
2377 		result = 95;
2378 		break;
2379 	case 3:
2380 		result = 96;
2381 		break;
2382 	case 4:
2383 		result = 97;
2384 		break;
2385 	case 5:
2386 		result = 98;
2387 		break;
2388 	case 6:
2389 		result = 99;
2390 		break;
2391 	default:
2392 		result = 0;
2393 		break;
2394 	}
2395 	return result;
2396 }
2397 
loadCredits()2398 void HopkinsEngine::loadCredits() {
2399 	_globals->_creditsPosY = 440;
2400 	_globals->_creditsStep = 45;
2401 	byte *bufPtr;
2402 	Common::String filename;
2403 	switch (_globals->_language) {
2404 	case LANG_EN:
2405 		filename = "CREAN.TXT";
2406 		break;
2407 	case LANG_FR:
2408 		filename = "CREFR.TXT";
2409 		break;
2410 	case LANG_SP:
2411 		filename = "CREES.TXT";
2412 		break;
2413 	default:
2414 		error("Unhandled language");
2415 		break;
2416 	}
2417 
2418 	if (!_fileIO->fileExists(filename)) {
2419 		_globals->_creditsLineNumb = 1;
2420 		_globals->_creditsItem[0]._color = '1';
2421 		_globals->_creditsItem[0]._actvFl = true;
2422 		_globals->_creditsItem[0]._linePosY = _globals->_creditsPosY;
2423 		strcpy((char *)_globals->_creditsItem[0]._line, "The End");
2424 		_globals->_creditsItem[0]._lineSize = 7;
2425 		return;
2426 	}
2427 
2428 	bufPtr = _fileIO->loadFile(filename);
2429 
2430 	byte *curPtr = bufPtr;
2431 	int idxLines = 0;
2432 	bool loopCond = false;
2433 	do {
2434 		if (*curPtr == '%') {
2435 			if (curPtr[1] == '%') {
2436 				loopCond = true;
2437 				break;
2438 			}
2439 			_globals->_creditsItem[idxLines]._color = curPtr[1];
2440 			_globals->_creditsItem[idxLines]._actvFl = true;
2441 			_globals->_creditsItem[idxLines]._linePosY = _globals->_creditsPosY + idxLines * _globals->_creditsStep;
2442 
2443 			int idxBuf = 0;
2444 			for(; idxBuf < 49; idxBuf++) {
2445 				byte curChar = curPtr[idxBuf + 3];
2446 				if (curChar == '%' || curChar == 10)
2447 					break;
2448 				_globals->_creditsItem[idxLines]._line[idxBuf] = curChar;
2449 			}
2450 			_globals->_creditsItem[idxLines]._line[idxBuf] = 0;
2451 			_globals->_creditsItem[idxLines]._lineSize = idxBuf - 1;
2452 			curPtr = curPtr + idxBuf + 2;
2453 			++idxLines;
2454 		} else {
2455 			curPtr++;
2456 		}
2457 		_globals->_creditsLineNumb = idxLines;
2458 	} while (!loopCond);
2459 
2460 	_globals->freeMemory(bufPtr);
2461 }
2462 
displayCredits(int startPosY,byte * buffer,char color)2463 void HopkinsEngine::displayCredits(int startPosY, byte *buffer, char color) {
2464 	byte *bufPtr = buffer;
2465 	int strWidth = 0;
2466 	byte curChar;
2467 	for (;;) {
2468 		curChar = *bufPtr++;
2469 		if (!curChar)
2470 			break;
2471 		if (curChar > 31)
2472 			strWidth += _objectsMan->getWidth(_fontMan->_font, curChar - 32);
2473 	}
2474 	int startPosX = 320 - strWidth / 2;
2475 	int endPosX = strWidth + startPosX;
2476 	int endPosY = startPosY + 12;
2477 	if ((_globals->_creditsStartX == -1) && (_globals->_creditsEndX == -1) && (_globals->_creditsStartY == -1) && (_globals->_creditsEndY == -1)) {
2478 		_globals->_creditsStartX = startPosX;
2479 		_globals->_creditsEndX = endPosX;
2480 		_globals->_creditsStartY = startPosY;
2481 		_globals->_creditsEndY = endPosY;
2482 	}
2483 
2484 	_globals->_creditsStartX = MIN(_globals->_creditsStartX, startPosX);
2485 	_globals->_creditsEndX = MAX(_globals->_creditsEndX, endPosX);
2486 	_globals->_creditsStartY = MIN(_globals->_creditsStartY, startPosY);
2487 	_globals->_creditsEndY = MAX(_globals->_creditsEndY, endPosY);
2488 
2489 	Common::String message = Common::String((char *)buffer);
2490 	_fontMan->displayText(startPosX, startPosY, message, color);
2491 }
2492 
displayCredits()2493 void HopkinsEngine::displayCredits() {
2494 	loadCredits();
2495 	_globals->_creditsPosY = 436;
2496 	_graphicsMan->loadImage("GENERIC");
2497 	_graphicsMan->fadeInLong();
2498 	_soundMan->playSound(28);
2499 	_events->_mouseFl = false;
2500 	_globals->_eventMode = EVENTMODE_CREDITS;
2501 	_globals->_creditsStartX = _globals->_creditsEndX = _globals->_creditsStartY = _globals->_creditsEndY = -1;
2502 	int soundId = 28;
2503 
2504 	do {
2505 		for (int i = 0; i < _globals->_creditsLineNumb; ++i) {
2506 			if (_globals->_creditsItem[i]._actvFl) {
2507 				int nextY = _globals->_creditsPosY + i * _globals->_creditsStep;
2508 				_globals->_creditsItem[i]._linePosY = nextY;
2509 
2510 				if ((nextY >= 51) && (nextY <= 460)) {
2511 					int col = 0;
2512 					switch (_globals->_creditsItem[i]._color) {
2513 					case '1':
2514 						col = 163;
2515 						break;
2516 					case '2':
2517 						col = 161;
2518 						break;
2519 					case '3':
2520 						col = 162;
2521 						break;
2522 					default:
2523 						warning("Unknown color, default to col #1");
2524 						col = 163;
2525 						break;
2526 					}
2527 					if (_globals->_creditsItem[i]._lineSize != -1)
2528 						displayCredits(nextY, _globals->_creditsItem[i]._line, col);
2529 				}
2530 			}
2531 		}
2532 		--_globals->_creditsPosY;
2533 		if (_globals->_creditsStartX != -1 || _globals->_creditsEndX != -1 || _globals->_creditsStartY != -1 || _globals->_creditsEndY != -1) {
2534 			_events->refreshScreenAndEvents();
2535 			_graphicsMan->copySurface(_graphicsMan->_backBuffer, 60, 50, 520, 430, _graphicsMan->_frontBuffer, 60, 50);
2536 		} else {
2537 			_events->refreshScreenAndEvents();
2538 		}
2539 		if (_globals->_creditsItem[_globals->_creditsLineNumb - 1]._linePosY <= 39) {
2540 			_globals->_creditsPosY = 440;
2541 			++soundId;
2542 			if (soundId > 31)
2543 				soundId = 28;
2544 			_soundMan->playSound(soundId);
2545 		}
2546 		_globals->_creditsStartX = -1;
2547 		_globals->_creditsEndX = -1;
2548 		_globals->_creditsStartY = -1;
2549 		_globals->_creditsEndY = -1;
2550 	} while ((_events->getMouseButton() != 1) && (!shouldQuit()));
2551 	_graphicsMan->fadeOutLong();
2552 	_globals->_eventMode = EVENTMODE_IGNORE;
2553 	_events->_mouseFl = true;
2554 }
2555 
handleOceanMouseEvents()2556 void HopkinsEngine::handleOceanMouseEvents() {
2557 	_fontMan->hideText(9);
2558 	if (_events->_mouseCursorId != 16)
2559 		return;
2560 
2561 	_events->getMouseX();
2562 	if (_objectsMan->_zoneNum <= 0)
2563 		return;
2564 
2565 	int oldPosX = _events->getMouseX();
2566 	int oldPosY = _events->getMouseY();
2567 	bool displAnim = false;
2568 	int oldX;
2569 	switch (_objectsMan->_zoneNum) {
2570 	case 1:
2571 		switch (_globals->_oceanDirection) {
2572 		case DIR_UP:
2573 			_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "27,26,25,24,23,22,21,20,19,18,-1,", 6, false);
2574 			break;
2575 		case DIR_RIGHT:
2576 			_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,-1,", 6, false);
2577 			break;
2578 		case DIR_DOWN:
2579 			_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "9,10,11,12,13,14,15,16,17,18,-1,", 6, false);
2580 			break;
2581 		default:
2582 			break;
2583 		}
2584 
2585 		_globals->_oceanDirection = DIR_LEFT;
2586 		_globals->_exitId = 1;
2587 		oldX = _objectsMan->getSpriteX(0);
2588 		for (;;) {
2589 			if (_globals->_speed == 1)
2590 				oldX -= 2;
2591 			else if (_globals->_speed == 2)
2592 				oldX -= 4;
2593 			else if (_globals->_speed == 3)
2594 				oldX -= 6;
2595 			_objectsMan->setSpriteX(0, oldX);
2596 			setSubmarineSprites();
2597 			_events->refreshScreenAndEvents();
2598 			if (_events->getMouseButton() == 1 && oldPosX == _events->getMouseX() && _events->getMouseY() == oldPosY) {
2599 				displAnim = true;
2600 				break;
2601 			}
2602 
2603 			if (oldX <= -100)
2604 				break;
2605 		}
2606 		break;
2607 	case 2:
2608 		switch (_globals->_oceanDirection) {
2609 		case DIR_UP:
2610 			_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "27,28,29,30,31,32,33,34,35,36,-1,", 6, false);
2611 			break;
2612 		case DIR_DOWN:
2613 			_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "9,8,7,6,5,4,3,2,1,0,-1,", 6, false);
2614 			break;
2615 		case DIR_LEFT:
2616 			_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,-1,", 6, false);
2617 			break;
2618 		default:
2619 			break;
2620 		}
2621 		_globals->_oceanDirection = DIR_RIGHT;
2622 		_globals->_exitId = 2;
2623 		oldX = _objectsMan->getSpriteX(0);
2624 		for (;;) {
2625 			if (_globals->_speed == 1)
2626 				oldX += 2;
2627 			else if (_globals->_speed == 2)
2628 				oldX += 4;
2629 			else if (_globals->_speed == 3)
2630 				oldX += 6;
2631 			_objectsMan->setSpriteX(0, oldX);
2632 			setSubmarineSprites();
2633 			_events->refreshScreenAndEvents();
2634 			if (_events->getMouseButton() == 1 && oldPosX == _events->getMouseX() && _events->getMouseY() == oldPosY) {
2635 				displAnim = true;
2636 				break;
2637 			}
2638 			if (oldX > 499)
2639 				break;
2640 		}
2641 		break;
2642 	case 3:
2643 		switch (_globals->_oceanDirection) {
2644 		case DIR_RIGHT:
2645 			oldX = _objectsMan->getSpriteX(0);
2646 			do {
2647 				if (_globals->_speed == 1)
2648 					oldX += 2;
2649 				else if (_globals->_speed == 2)
2650 					oldX += 4;
2651 				else if (_globals->_speed == 3)
2652 					oldX += 6;
2653 				_objectsMan->setSpriteX(0, oldX);
2654 				setSubmarineSprites();
2655 				_events->refreshScreenAndEvents();
2656 				if (_events->getMouseButton() == 1 && oldPosX == _events->getMouseX() && _events->getMouseY() == oldPosY) {
2657 					displAnim = true;
2658 					break;
2659 				}
2660 			} while (oldX <= 235);
2661 			if (!displAnim)
2662 				_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "36,35,34,33,32,31,30,29,28,27,-1,", 6, false);
2663 			break;
2664 		case DIR_DOWN:
2665 			_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,-1,", 6, false);
2666 			break;
2667 		case DIR_LEFT:
2668 			oldX = _objectsMan->getSpriteX(0);
2669 			do {
2670 				if (_globals->_speed == 1)
2671 					oldX -= 2;
2672 				else if (_globals->_speed == 2)
2673 					oldX -= 4;
2674 				else if (_globals->_speed == 3)
2675 					oldX -= 6;
2676 				_objectsMan->setSpriteX(0, oldX);
2677 				setSubmarineSprites();
2678 				_events->refreshScreenAndEvents();
2679 				if (_events->getMouseButton() == 1 && oldPosX == _events->getMouseX() && _events->getMouseY() == oldPosY) {
2680 					displAnim = true;
2681 					break;
2682 				}
2683 			} while (oldX > 236);
2684 			if (!displAnim)
2685 				_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "18,19,20,21,22,23,24,25,26,27,-1,", 6, false);
2686 			break;
2687 		default:
2688 			break;
2689 		}
2690 		_globals->_oceanDirection = DIR_UP;
2691 		_globals->_exitId = 3;
2692 		break;
2693 	case 4:
2694 		switch (_globals->_oceanDirection) {
2695 		case DIR_UP:
2696 			_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,-1,", 6, false);
2697 			break;
2698 		case DIR_RIGHT:
2699 			oldX = _objectsMan->getSpriteX(0);
2700 			do {
2701 				if (_globals->_speed == 1)
2702 					oldX += 2;
2703 				else if (_globals->_speed == 2)
2704 					oldX += 4;
2705 				else if (_globals->_speed == 3)
2706 					oldX += 6;
2707 				_objectsMan->setSpriteX(0, oldX);
2708 				setSubmarineSprites();
2709 				_events->refreshScreenAndEvents();
2710 				if (_events->getMouseButton() == 1 && oldPosX == _events->getMouseX() && _events->getMouseY() == oldPosY) {
2711 					displAnim = true;
2712 					break;
2713 				}
2714 			} while (oldX <= 235);
2715 			if (!displAnim)
2716 				_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "0,1,2,3,4,5,6,7,8,9,-1,", 6, false);
2717 			break;
2718 		case DIR_LEFT:
2719 			oldX = _objectsMan->getSpriteX(0);
2720 			for (;;) {
2721 				if (_globals->_speed == 1)
2722 					oldX -= 2;
2723 				else if (_globals->_speed == 2)
2724 					oldX -= 4;
2725 				else if (_globals->_speed == 3)
2726 					oldX -= 6;
2727 				_objectsMan->setSpriteX(0, oldX);
2728 				setSubmarineSprites();
2729 				_events->refreshScreenAndEvents();
2730 				if (_events->getMouseButton() == 1 && oldPosX == _events->getMouseX() && _events->getMouseY() == oldPosY)
2731 					break;
2732 
2733 				if (oldX <= 236) {
2734 					if (!displAnim)
2735 						_objectsMan->showSpecialActionAnimationWithFlip(_globals->_characterSpriteBuf, "18,17,16,15,14,13,12,11,10,9,-1,", 6, false);
2736 					break;
2737 				}
2738 			}
2739 			break;
2740 		default:
2741 			break;
2742 		}
2743 		_globals->_oceanDirection = DIR_DOWN;
2744 		_globals->_exitId = 4;
2745 		break;
2746 	default:
2747 		break;
2748 	}
2749 }
2750 
setSubmarineSprites()2751 void HopkinsEngine::setSubmarineSprites() {
2752 	switch (_globals->_oceanDirection) {
2753 	case DIR_UP:
2754 		_objectsMan->setSpriteIndex(0, 27);
2755 		break;
2756 	case DIR_RIGHT:
2757 		_objectsMan->setSpriteIndex(0, 0);
2758 		break;
2759 	case DIR_DOWN:
2760 		_objectsMan->setSpriteIndex(0, 9);
2761 		break;
2762 	case DIR_LEFT:
2763 		_objectsMan->setSpriteIndex(0, 18);
2764 		break;
2765 	default:
2766 		break;
2767 	}
2768 }
2769 
handleOceanMaze(int16 curExitId,Common::String backgroundFilename,Directions defaultDirection,int16 exit1,int16 exit2,int16 exit3,int16 exit4,int16 soundId)2770 void HopkinsEngine::handleOceanMaze(int16 curExitId, Common::String backgroundFilename, Directions defaultDirection, int16 exit1, int16 exit2, int16 exit3, int16 exit4, int16 soundId) {
2771 	_globals->_cityMapEnabledFl = false;
2772 	_graphicsMan->_noFadingFl = false;
2773 	_globals->_freezeCharacterFl = false;
2774 	_globals->_exitId = 0;
2775 	_globals->_disableInventFl = true;
2776 	_soundMan->playSound(soundId);
2777 	_globals->_characterSpriteBuf = _fileIO->loadFile("VAISSEAU.SPR");
2778 	if (backgroundFilename.size())
2779 		_graphicsMan->loadImage(backgroundFilename);
2780 
2781 	if (curExitId == 77)
2782 		_objectsMan->loadLinkFile("IM77");
2783 	else if (curExitId == 84)
2784 		_objectsMan->loadLinkFile("IM84");
2785 	else if (curExitId == 91)
2786 		_objectsMan->loadLinkFile("IM91");
2787 	else
2788 		_objectsMan->loadLinkFile("ocean");
2789 
2790 	if (!exit1)
2791 		_linesMan->disableZone(1);
2792 	if (!exit2)
2793 		_linesMan->disableZone(2);
2794 	if (!exit3)
2795 		_linesMan->disableZone(3);
2796 	if (!exit4)
2797 		_linesMan->disableZone(4);
2798 
2799 	if (_globals->_oceanDirection == DIR_NONE)
2800 		_globals->_oceanDirection = defaultDirection;
2801 
2802 	switch (_globals->_oceanDirection) {
2803 	case DIR_UP:
2804 		_objectsMan->_characterPos.x = 236;
2805 		_objectsMan->_startSpriteIndex = 27;
2806 		break;
2807 	case DIR_RIGHT:
2808 		_objectsMan->_characterPos.x = -20;
2809 		_objectsMan->_startSpriteIndex = 0;
2810 		break;
2811 	case DIR_DOWN:
2812 		_objectsMan->_characterPos.x = 236;
2813 		_objectsMan->_startSpriteIndex = 9;
2814 		break;
2815 	case DIR_LEFT:
2816 		_objectsMan->_characterPos.x = 415;
2817 		_objectsMan->_startSpriteIndex = 18;
2818 		break;
2819 	default:
2820 		break;
2821 	}
2822 
2823 	_objectsMan->addStaticSprite(_globals->_characterSpriteBuf, Common::Point(_objectsMan->_characterPos.x, 110), 0, _objectsMan->_startSpriteIndex, 0, false, 0, 0);
2824 	_graphicsMan->setColorPercentage(252, 100, 100, 100);
2825 	_graphicsMan->setColorPercentage(253, 100, 100, 100);
2826 	_graphicsMan->setColorPercentage(251, 100, 100, 100);
2827 	_graphicsMan->setColorPercentage(254, 0, 0, 0);
2828 	_objectsMan->animateSprite(0);
2829 	_linesMan->_route = NULL;
2830 	_events->mouseOn();
2831 	_events->changeMouseCursor(4);
2832 
2833 	for (int cpt = 0; cpt <= 4; cpt++)
2834 		_events->refreshScreenAndEvents();
2835 
2836 	if (!_graphicsMan->_noFadingFl)
2837 		_graphicsMan->fadeInLong();
2838 	_graphicsMan->_noFadingFl = false;
2839 	_globals->_eventMode = EVENTMODE_IGNORE;
2840 
2841 	for (;;) {
2842 		int mouseButton = _events->getMouseButton();
2843 		if (mouseButton && mouseButton == 1)
2844 			handleOceanMouseEvents();
2845 		_linesMan->checkZone();
2846 		setSubmarineSprites();
2847 
2848 		_events->refreshScreenAndEvents();
2849 		if (_globals->_exitId || shouldQuit())
2850 			break;
2851 	}
2852 
2853 	if (_globals->_exitId == 1)
2854 		_globals->_exitId = exit1;
2855 	else if (_globals->_exitId == 2)
2856 		_globals->_exitId = exit2;
2857 	else if (_globals->_exitId == 3)
2858 		_globals->_exitId = exit3;
2859 	else if (_globals->_exitId == 4)
2860 		_globals->_exitId = exit4;
2861 	_graphicsMan->fadeOutLong();
2862 	_objectsMan->removeSprite(0);
2863 	_objectsMan->clearScreen();
2864 	_globals->_characterSpriteBuf = _fileIO->loadFile("PERSO.SPR");
2865 	_globals->_characterType = CHARACTER_HOPKINS;
2866 }
2867 
syncSoundSettings()2868 void HopkinsEngine::syncSoundSettings() {
2869 	Engine::syncSoundSettings();
2870 
2871 	_soundMan->syncSoundSettings();
2872 }
2873 
displayAdultDisclaimer()2874 bool HopkinsEngine::displayAdultDisclaimer() {
2875 	int buttonIndex;
2876 
2877 	_graphicsMan->_minX = 0;
2878 	_graphicsMan->_minY = 0;
2879 	_graphicsMan->_maxX = SCREEN_WIDTH;
2880 	_graphicsMan->_maxY = SCREEN_HEIGHT - 1;
2881 	_events->_breakoutFl = false;
2882 	_objectsMan->_forestFl = false;
2883 	_globals->_disableInventFl = true;
2884 	_globals->_exitId = 0;
2885 
2886 	_graphicsMan->loadImage("ADULT");
2887 	_graphicsMan->fadeInLong();
2888 	_events->mouseOn();
2889 	_events->changeMouseCursor(0);
2890 	_events->_mouseCursorId = 0;
2891 	_events->_mouseSpriteId = 0;
2892 
2893 	do {
2894 		int xp = _events->getMouseX();
2895 		int yp = _events->getMouseY();
2896 
2897 		buttonIndex = 0;
2898 		if (xp >= 37 && xp <= 169 && yp >= 406 && yp <= 445)
2899 			buttonIndex = 2;
2900 		else if (xp >= 424 && xp <= 602 && yp >= 406 && yp <= 445)
2901 			buttonIndex = 1;
2902 
2903 		_events->refreshScreenAndEvents();
2904 	} while (!shouldQuit() && (buttonIndex == 0 || _events->getMouseButton() != 1));
2905 
2906 	_globals->_disableInventFl = false;
2907 	_graphicsMan->fadeOutLong();
2908 
2909 	if (buttonIndex != 2) {
2910 		// Quit game
2911 		return false;
2912 	} else {
2913 		// Continue
2914 		_graphicsMan->_minX = 0;
2915 		_graphicsMan->_maxY = 20;
2916 		_graphicsMan->_maxX = SCREEN_WIDTH;
2917 		_graphicsMan->_maxY = SCREEN_HEIGHT - 20;
2918 		return true;
2919 	}
2920 }
2921 
isUnderwaterSubScene()2922 bool HopkinsEngine::isUnderwaterSubScene() {
2923 	return (_globals->_curRoomNum >= 77) && (_globals->_curRoomNum <= 89);
2924 }
2925 
2926 } // End of namespace Hopkins
2927