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