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