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 #ifdef ENABLE_EOB
24 
25 #include "kyra/engine/darkmoon.h"
26 #include "kyra/graphics/screen_eob.h"
27 #include "kyra/resource/resource.h"
28 #include "kyra/sound/sound.h"
29 
30 #include "common/system.h"
31 
32 #include "base/version.h"
33 
34 namespace Kyra {
35 
36 class DarkmoonSequenceHelper {
37 friend class DarkMoonEngine;
38 public:
39 	enum Mode {
40 		kIntro,
41 		kFinale
42 	};
43 
44 	DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine *vm, Screen_EoB *screen, Mode mode);
45 	~DarkmoonSequenceHelper();
46 
47 	void loadScene(int index, int pageNum, bool ignorePalette = false);
48 	void animCommand(int index, int del = -1);
49 	void setPlatformAnimIndexOffset(int offset);
50 
51 	void printText(int index, int color);
52 	void fadeText();
53 
54 	void update(int srcPage);
55 
56 	void setPalette(int index);
57 	void fadePalette(int index, int del);
58 	void copyPalette(int srcIndex, int destIndex);
59 
60 	void initDelayedPaletteFade(int palIndex, int rate);
61 	bool processDelayedPaletteFade();
62 
63 	void delay(uint32 ticks);
64 	void waitForSongNotifier(int index, bool introUpdateAnim = false);
65 	void updateAmigaSound();
66 
67 private:
68 	void init(Mode mode);
69 	void setPaletteWithoutTextColor(int index);
70 
71 	OSystem *_system;
72 	DarkMoonEngine *_vm;
73 	Screen_EoB *_screen;
74 
75 	struct Config {
ConfigKyra::DarkmoonSequenceHelper::Config76 		Config(const char *const *str, const char *const *cpsfiles, const uint8 **cpsdata, const char *const *pal, const DarkMoonShapeDef **shp, const DarkMoonAnimCommand **anim, bool loadScenePalette, bool paletteFading, bool animCmdRestorePalette, bool shapeBackgroundFading, int animPalOffset, int animType1ShapeDim, bool animCmd5SetPalette, int animCmd5ExtraPage) : strings(str), cpsFiles(cpsfiles), cpsData(cpsdata), palFiles(pal), shapeDefs(shp), animData(anim), loadScenePal(loadScenePalette), palFading(paletteFading), animCmdRestorePal(animCmdRestorePalette), shpBackgroundFading(shapeBackgroundFading), animPalOffs(animPalOffset), animCmd1ShapeFrame(animType1ShapeDim), animCmd5SetPal(animCmd5SetPalette), animCmd5AltPage(animCmd5ExtraPage) {}
77 		const char *const *strings;
78 		const char *const *cpsFiles;
79 		const uint8 **cpsData;
80 		const char *const *palFiles;
81 		const DarkMoonShapeDef **shapeDefs;
82 		const DarkMoonAnimCommand **animData;
83 		bool loadScenePal;
84 		bool palFading;
85 		bool animCmdRestorePal;
86 		bool shpBackgroundFading;
87 		int animPalOffs;
88 		int animCmd1ShapeFrame;
89 		bool animCmd5SetPal;
90 		int animCmd5AltPage;
91 	};
92 
93 	const Config *_config;
94 
95 	Palette *_palettes[13];
96 	uint8 *_fadingTables[7];
97 
98 	const uint8 **_shapes;
99 
100 	uint32 _fadePalTimer;
101 	int _fadePalRate;
102 	int _fadePalIndex;
103 
104 	uint8 _sndNextTrack;
105 	uint16 _sndNextTrackMarker;
106 	const uint16 *_sndMarkersFMTowns;
107 
108 	uint8 _textColor[3];
109 
110 	int _platformAnimOffset;
111 
112 	Screen::FontId _prevFont;
113 
114 	static const char *const _palFilesIntroVGA[];
115 	static const char *const _palFilesIntroEGA[];
116 	static const char *const _palFilesFinaleVGA[];
117 	static const char *const _palFilesFinaleEGA[];
118 	static const char *const _palFilesFinaleAmiga[];
119 };
120 
mainMenu()121 int DarkMoonEngine::mainMenu() {
122 	int menuChoice = _menuChoiceInit;
123 	_menuChoiceInit = 0;
124 
125 	_sound->selectAudioResourceSet(kMusicIntro);
126 	_sound->loadSoundFile(0);
127 
128 	Screen::FontId of = _screen->_currentFont;
129 	int op = 0;
130 	Common::SeekableReadStream *s = 0;
131 
132 	while (menuChoice >= 0 && !shouldQuit()) {
133 		switch (menuChoice) {
134 		case 0: {
135 			if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformAmiga) {
136 				_screen->loadPalette("MENU.PAL", _screen->getPalette(0));
137 				_screen->setScreenPalette(_screen->getPalette(0));
138 				_screen->loadEoBBitmap("MENU", 0, 3, 3, 2);
139 			} else {
140 				s = _res->createReadStream("XENU.CPS");
141 				if (s) {
142 					s->read(_screen->getPalette(0).getData(), 768);
143 					_screen->loadFileDataToPage(s, 3, 64000);
144 					delete s;
145 				} else {
146 					_screen->loadBitmap("MENU.CPS", 3, 3, &_screen->getPalette(0));
147 				}
148 
149 				if (_configRenderMode == Common::kRenderEGA)
150 					_screen->loadPalette("MENU.EGA", _screen->getPalette(0));
151 			}
152 
153 			_screen->setScreenPalette(_screen->getPalette(0));
154 			_screen->convertPage(3, 2, 0);
155 
156 			of = _screen->setFont(Screen::FID_6_FNT);
157 			op = _screen->setCurPage(2);
158 			Common::String versionString(Common::String::format("ScummVM %s", gScummVMVersion));
159 			_screen->printText(versionString.c_str(), 267 - versionString.size() * 6, _flags.platform == Common::kPlatformFMTowns ? 152 : 160, _flags.platform == Common::kPlatformAmiga ? 18 : 13, 0);
160 			_screen->setFont(of);
161 			_screen->_curPage = op;
162 			_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
163 			_screen->shadeRect(78, 99, 249, 141, 4);
164 			_screen->showMouse();
165 			_screen->updateScreen();
166 			_allowImport = true;
167 			menuChoice = mainMenuLoop();
168 			_allowImport = false;
169 		} break;
170 
171 		case 1:
172 			// load game in progress
173 			menuChoice = -1;
174 			break;
175 
176 		case 2:
177 			// create new party
178 			menuChoice = -2;
179 			break;
180 
181 		case 3:
182 			// transfer party
183 			menuChoice = -3;
184 			break;
185 
186 		case 4:
187 			// play intro
188 			seq_playIntro();
189 			menuChoice = 0;
190 			break;
191 
192 		case 5:
193 			// quit
194 			menuChoice = -5;
195 			break;
196 
197 		default:
198 			break;
199 		}
200 	}
201 
202 	return shouldQuit() ? -5 : menuChoice;
203 }
204 
mainMenuLoop()205 int DarkMoonEngine::mainMenuLoop() {
206 	int sel = -1;
207 	do {
208 		_screen->setScreenDim(6);
209 		_gui->simpleMenu_setup(6, 0, _mainMenuStrings, -1, 0, 0, _configRenderMode == Common::kRenderCGA ? 1 : guiSettings()->colors.guiColorWhite, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.guiColorBlack);
210 		_screen->updateScreen();
211 
212 		while (sel == -1 && !shouldQuit())
213 			sel = _gui->simpleMenu_process(6, _mainMenuStrings, 0, -1, 0);
214 	} while ((sel < 0 || sel > 5) && !shouldQuit());
215 
216 	if (_flags.platform == Common::kPlatformFMTowns && sel == 2) {
217 		townsUtilitiesMenu();
218 		sel = -1;
219 	}
220 
221 	return sel + 1;
222 }
223 
townsUtilitiesMenu()224 void DarkMoonEngine::townsUtilitiesMenu() {
225 	_screen->copyRegion(78, 99, 78, 99, 172, 43, 2, 0, Screen::CR_NO_P_CHECK);
226 	int sel = -1;
227 	do {
228 		_gui->simpleMenu_setup(8, 0, _utilMenuStrings, -1, 0, 0, _configRenderMode == Common::kRenderCGA ? 1 : guiSettings()->colors.guiColorWhite, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.guiColorBlack);
229 		_screen->updateScreen();
230 		while (sel == -1 && !shouldQuit())
231 			sel = _gui->simpleMenu_process(8, _utilMenuStrings, 0, -1, 0);
232 		if (sel == 0) {
233 			_config2431 ^= true;
234 			sel = -1;
235 		}
236 	} while ((sel < 0 || sel > 1) && !shouldQuit());
237 }
238 
seq_playIntro()239 void DarkMoonEngine::seq_playIntro() {
240 	DarkmoonSequenceHelper sq(_system, this, _screen, DarkmoonSequenceHelper::kIntro);
241 
242 	_screen->setCurPage(0);
243 	_screen->clearCurPage();
244 
245 	snd_stopSound();
246 
247 	sq.loadScene(4, 2);
248 
249 	uint8 textColor1 = 16;
250 	uint8 textColor2 = 15;
251 
252 	if (_flags.platform == Common::kPlatformAmiga) {
253 		textColor1 = textColor2 = 31;
254 		sq.loadScene(13, 2);
255 		sq.loadScene(14, 2);
256 		sq.loadScene(15, 2);
257 	} else if (_configRenderMode == Common::kRenderEGA) {
258 		textColor1 = 15;
259 	}
260 
261 	sq.loadScene(0, 2);
262 	sq.delay(1);
263 
264 	if (!skipFlag() && !shouldQuit())
265 		snd_playSong(12);
266 
267 	_screen->copyRegion(0, 0, 8, 8, 304, 128, 2, 0, Screen::CR_NO_P_CHECK);
268 	sq.setPalette(9);
269 	sq.fadePalette(0, 3);
270 
271 	_screen->setCurPage(2);
272 	_screen->setClearScreenDim(17);
273 	_screen->setCurPage(0);
274 
275 	removeInputTop();
276 	sq.delay(18);
277 
278 	sq.animCommand(3, 18);
279 	sq.animCommand(6, 18);
280 	sq.animCommand(0);
281 
282 	sq.waitForSongNotifier(1);
283 
284 	sq.animCommand(_configRenderMode == Common::kRenderEGA ? 12 : 11);
285 	sq.animCommand(7, 6);
286 	sq.animCommand(2, 6);
287 
288 	sq.waitForSongNotifier(2);
289 
290 	sq.animCommand(_flags.platform == Common::kPlatformAmiga ? 37 : (_configRenderMode == Common::kRenderEGA ? 39 : 38));
291 	sq.animCommand(3);
292 	sq.animCommand(8);
293 	sq.animCommand(1, 10);
294 	sq.animCommand(0, 6);
295 	sq.animCommand(2);
296 
297 	sq.waitForSongNotifier(3);
298 
299 	_screen->setClearScreenDim(17);
300 	_screen->setCurPage(2);
301 	_screen->setClearScreenDim(17);
302 	_screen->setCurPage(0);
303 
304 	sq.animCommand(_flags.platform == Common::kPlatformAmiga ? 38 : (_configRenderMode == Common::kRenderEGA ? 41 : 40));
305 	sq.animCommand(7, 18);
306 
307 	if (_flags.platform == Common::kPlatformAmiga)
308 		sq.fadeText();
309 
310 	sq.printText(0, textColor1);    // You were settling...
311 	sq.animCommand(7, 90);
312 	sq.fadeText();
313 
314 	sq.printText(1, textColor1);    // Then a note was slipped to you
315 	sq.animCommand(8);
316 	sq.animCommand(2, 72);
317 	sq.fadeText();
318 
319 	sq.printText(2, textColor1);    // It was from your friend Khelben Blackstaff...
320 	sq.animCommand(2);
321 	sq.animCommand(6, 36);
322 	sq.animCommand(3);
323 	sq.fadeText();
324 
325 	sq.printText(3, textColor1);    // The message was urgent.
326 
327 	sq.loadScene(1, 2);
328 	sq.waitForSongNotifier(4);
329 
330 	// intro scroll
331 	if (!skipFlag() && !shouldQuit()) {
332 		if (_configRenderMode == Common::kRenderEGA) {
333 			for (int i = 0; i < 35; i++) {
334 				uint32 endtime = _system->getMillis() + 2 * _tickLength;
335 				_screen->copyRegion(16, 8, 8, 8, 296, 128, 0, 0, Screen::CR_NO_P_CHECK);
336 				_screen->copyRegion(i << 3, 0, 304, 8, 8, 128, 2, 0, Screen::CR_NO_P_CHECK);
337 				_screen->updateScreen();
338 				if (i == 12)
339 					sq.animCommand(42);
340 				else if (i == 25)
341 					snd_playSoundEffect(11);
342 				delayUntil(endtime);
343 			}
344 		} else {
345 			for (int i = 0; i < 280; i += 3) {
346 				uint32 endtime = _system->getMillis() + _tickLength;
347 				_screen->copyRegion(11, 8, 8, 8, 301, 128, 0, 0, Screen::CR_NO_P_CHECK);
348 				_screen->copyRegion(i, 0, 309, 8, 3, 128, 2, 0, Screen::CR_NO_P_CHECK);
349 				_screen->updateScreen();
350 				if (_flags.platform == Common::kPlatformAmiga) {
351 					if (i == 4 || i == 24 || i == 36)
352 						sq.animCommand(39);
353 				} else if (i == 96) {
354 					sq.animCommand(42);
355 				}
356 				delayUntil(endtime);
357 			}
358 		}
359 	}
360 
361 	_screen->copyRegion(8, 8, 0, 0, 304, 128, 0, 2, Screen::CR_NO_P_CHECK);
362 	sq.animCommand(4);
363 	sq.fadeText();
364 	sq.delay(10);
365 
366 	sq.loadScene(2, 2);
367 	sq.update(2);
368 	sq.delay(10);
369 
370 	sq.printText(4, textColor1);    // What could Khelben want?
371 	sq.delay(25);
372 
373 	sq.loadScene(3, 2);
374 	sq.delay(54);
375 	sq.animCommand(_flags.platform == Common::kPlatformAmiga ? 12 : 13);
376 	_screen->copyRegion(104, 16, 96, 8, 120, 100, 0, 2, Screen::CR_NO_P_CHECK);
377 	sq.fadeText();
378 
379 	if (_flags.platform == Common::kPlatformAmiga)
380 		sq.animCommand(9);
381 
382 	sq.printText(5, textColor2);    // Welcome, please come in
383 	sq.animCommand(10);
384 	sq.animCommand(10);
385 	sq.animCommand(9);
386 	sq.animCommand(9);
387 	sq.fadeText();
388 
389 	sq.printText(6, textColor2);    // Khelben awaits you in his study
390 	for (int i = 0; i < 3; i++)
391 		sq.animCommand(10);
392 	sq.animCommand(9);
393 
394 	if (_flags.platform == Common::kPlatformAmiga)
395 		sq.setPlatformAnimIndexOffset(-1);
396 
397 	sq.animCommand(14);
398 
399 	if (_flags.platform == Common::kPlatformAmiga)
400 		_sound->beginFadeOut();
401 
402 	sq.loadScene(5, 2);
403 
404 	if (!skipFlag() && !shouldQuit()) {
405 		if (_flags.platform == Common::kPlatformAmiga) {
406 			_screen->fadeToBlack(5);
407 			_screen->clearCurPage();
408 			_screen->fadeFromBlack(1);
409 			sq.fadeText();
410 			snd_playSong(14);
411 		} else {
412 			sq.waitForSongNotifier(5);
413 			sq.fadeText();
414 			_screen->clearCurPage();
415 			_screen->updateScreen();
416 		}
417 	}
418 
419 	for (int i = 0; i < 6; i++)
420 		sq.animCommand(15);
421 
422 	if (_configRenderMode == Common::kRenderEGA && !skipFlag() && !shouldQuit()) {
423 		_screen->loadPalette("INTRO.EGA", _screen->getPalette(0));
424 		_screen->setScreenPalette(_screen->getPalette(0));
425 	}
426 
427 	sq.loadScene(6, 2);
428 	sq.loadScene(7, 2);
429 	_screen->clearCurPage();
430 	sq.update(2);
431 
432 	if (_flags.platform == Common::kPlatformAmiga && !skipFlag() && !shouldQuit())
433 		snd_playSong(15);
434 
435 	sq.animCommand(16);
436 	sq.printText(7, textColor2);    // Thank you for coming so quickly
437 	sq.animCommand(16);
438 	sq.animCommand(17);
439 	for (int i = 0; i < 3; i++)
440 		sq.animCommand(16);
441 	sq.fadeText();
442 	sq.animCommand(16);
443 
444 	sq.loadScene(8, 2, true);
445 	sq.update(2);
446 	sq.animCommand(32);
447 	sq.printText(8, textColor2);    // I am troubled my friend
448 	sq.animCommand(33);
449 	sq.animCommand(33);
450 	for (int i = 0; i < 4; i++)
451 		sq.animCommand(32);
452 	sq.fadeText();
453 
454 	sq.printText(9, textColor2);    // Ancient evil stirs in the Temple Darkmoon
455 	sq.animCommand(33);
456 	sq.animCommand(_flags.platform == Common::kPlatformAmiga ? 41 : 43);
457 	sq.animCommand(33);
458 	for (int i = 0; i < 3; i++)
459 		sq.animCommand(32);
460 	sq.fadeText();
461 
462 	sq.printText(10, textColor2);   // I fear for the safety of our city
463 	for (int i = 0; i < 4; i++)
464 		sq.animCommand(33);
465 	sq.animCommand(32);
466 	sq.animCommand(32);
467 
468 	sq.fadeText();
469 	sq.loadScene(9, 2);
470 
471 	sq.waitForSongNotifier(6);
472 
473 	sq.update(2);
474 	sq.animCommand(34);
475 
476 	sq.printText(11, textColor2);   // I need your help
477 	for (int i = 0; i < 3; i++)
478 		sq.animCommand(34);
479 	sq.animCommand(35);
480 	for (int i = 0; i < 4; i++)
481 		sq.animCommand(34);
482 	sq.fadeText();
483 
484 	sq.loadScene(12, 2);
485 	sq.update(2);
486 	sq.loadScene(6, 2, true);
487 	sq.animCommand(18);
488 
489 	sq.printText(12, textColor2);   // Three nights ago I sent forth a scout
490 	sq.animCommand(19);
491 	sq.animCommand(20);
492 	sq.animCommand(22);
493 	sq.animCommand(19);
494 	sq.animCommand(20);
495 	sq.animCommand(18);
496 	sq.fadeText();
497 
498 	sq.printText(13, textColor2);   // She has not yet returned
499 	sq.animCommand(20);
500 	sq.animCommand(19);
501 	sq.animCommand(23);
502 	sq.animCommand(24);
503 	sq.animCommand(20);
504 	sq.animCommand(19);
505 	sq.animCommand(17);
506 	sq.animCommand(18);
507 	sq.fadeText();
508 
509 	sq.printText(14, textColor2);   // I fear for her safety
510 	sq.animCommand(19);
511 	sq.animCommand(20);
512 	sq.animCommand(20);
513 	sq.animCommand(18);
514 	sq.animCommand(25);
515 	sq.animCommand(18);
516 	sq.animCommand(18);
517 	sq.fadeText();
518 	sq.animCommand(18);
519 	sq.animCommand(18);
520 
521 	sq.printText(15, textColor2);   // Take this coin
522 	sq.animCommand(28);
523 	sq.animCommand(19);
524 	sq.animCommand(20);
525 	sq.animCommand(18);
526 	sq.animCommand(18);
527 	sq.fadeText();
528 
529 	sq.loadScene(10, 2);
530 
531 	if (_flags.platform == Common::kPlatformAmiga)
532 		_screen->fadeToBlack(10);
533 
534 	_screen->clearCurPage();
535 	if (_flags.platform == Common::kPlatformAmiga)
536 		sq.setPalette(0);
537 	_screen->updateScreen();
538 
539 	sq.animCommand(37, 18);
540 	sq.animCommand(36, 36);
541 
542 	sq.loadScene(12, 2);
543 	_screen->clearCurPage();
544 	sq.update(2);
545 
546 	sq.loadScene(11, 2, true);
547 	sq.printText(16, textColor2);   // I will use it to contact you
548 	sq.animCommand(19);
549 	sq.animCommand(20);
550 	sq.animCommand(20);
551 	sq.animCommand(18);
552 	sq.animCommand(18);
553 	sq.fadeText();
554 
555 	sq.printText(17, textColor2);   // You must act quickly
556 	sq.animCommand(19);
557 	sq.animCommand(20);
558 	sq.animCommand(19);
559 	sq.animCommand(18);
560 	sq.animCommand(18);
561 	sq.fadeText();
562 	sq.animCommand(18);
563 
564 	sq.printText(18, textColor2);   // I will teleport you near Darkmoon
565 	sq.animCommand(20);
566 	sq.animCommand(27);
567 	sq.animCommand(20);
568 	sq.animCommand(19);
569 	sq.animCommand(18);
570 	sq.animCommand(18);
571 	sq.fadeText();
572 	sq.animCommand(18);
573 
574 	sq.printText(19, textColor2);   // May luck be with you my friend
575 	sq.animCommand(19);
576 	sq.animCommand(19);
577 	sq.animCommand(20);
578 	sq.animCommand(18);
579 	sq.fadeText();
580 	sq.animCommand(29);
581 
582 	sq.waitForSongNotifier(7);
583 
584 	sq.animCommand(30);
585 	sq.animCommand(31);
586 
587 	sq.waitForSongNotifier(8, true);
588 
589 	if (_flags.platform == Common::kPlatformAmiga && !skipFlag() && !shouldQuit()) {
590 		static const uint8 magicHandsCol[] = { 0x15, 0x1D, 0x3A, 0x32, 0x32, 0x3F };
591 		snd_fadeOut();
592 		_screen->getPalette(0).copy(magicHandsCol, 0, 1, 31);
593 		_screen->fadePalette(_screen->getPalette(0), 32);
594 		_screen->getPalette(0).copy(magicHandsCol, 1, 1, 31);
595 		_screen->fadePalette(_screen->getPalette(0), 32);
596 	}
597 
598 	if (skipFlag() || shouldQuit())
599 		snd_fadeOut();
600 	else {
601 		_screen->setScreenDim(17);
602 		_screen->clearCurDim();
603 		snd_playSoundEffect(14);
604 
605 		if (_configRenderMode != Common::kRenderEGA)
606 			sq.fadePalette(10, 1);
607 		_screen->setClearScreenDim(18);
608 		sq.delay(6);
609 		if (_configRenderMode != Common::kRenderEGA)
610 			sq.fadePalette(9, 1);
611 		_screen->clearCurPage();
612 	}
613 	sq.fadePalette(9, 10);
614 }
615 
seq_playFinale()616 void DarkMoonEngine::seq_playFinale() {
617 	_screen->fadeToBlack();
618 	_screen->clearCurPage();
619 	_screen->clearPage(2);
620 
621 	DarkmoonSequenceHelper sq(_system, this, _screen, DarkmoonSequenceHelper::kFinale);
622 
623 	_screen->setCurPage(0);
624 
625 	_sound->loadSoundFile(0);
626 	snd_stopSound();
627 	sq.delay(3);
628 	_screen->updateScreen();
629 
630 	uint8 textColor1 = 10;
631 	uint8 textColor2 = 15;
632 
633 	if (_flags.platform == Common::kPlatformAmiga) {
634 		textColor1 = 29;
635 		textColor2 = 31;
636 	} else if (_configRenderMode == Common::kRenderEGA) {
637 		textColor1 = 15;
638 	}
639 
640 	sq.loadScene(0, 2);
641 	sq.delay(18);
642 
643 	if (!skipFlag() && !shouldQuit() && _flags.platform != Common::kPlatformAmiga)
644 		snd_playSong(1);
645 	sq.update(2);
646 
647 	sq.loadScene(1, 2);
648 
649 	sq.animCommand(0);
650 	sq.animCommand(0);
651 	for (int i = 0; i < 3; i++)
652 		sq.animCommand(2);
653 	sq.animCommand(1);
654 	sq.animCommand(2);
655 	sq.animCommand(2);
656 
657 	sq.printText(0, textColor1);            // Finally, Dran has been defeated
658 	for (int i = 0; i < 7; i++)
659 		sq.animCommand(2);
660 	sq.fadeText();
661 	sq.animCommand(2);
662 
663 	sq.waitForSongNotifier(1);
664 
665 	sq.printText(1, textColor1);            // Suddenly, your friend Khelben appears
666 	sq.animCommand(4);
667 	for (int i = 0; i < 3; i++)
668 		sq.animCommand(2);
669 	sq.fadeText();
670 
671 	sq.printText(2, textColor2);            // Greetings, my victorious friends
672 	for (int i = 0; i < 4; i++)
673 		sq.animCommand(5);
674 	sq.animCommand(2);
675 	sq.animCommand(2);
676 	sq.fadeText();
677 	sq.animCommand(6);
678 
679 	sq.printText(3, textColor2);            // You have defeated Dran
680 	for (int i = 0; i < 5; i++)
681 		sq.animCommand(5);
682 	sq.animCommand(2);
683 	sq.animCommand(2);
684 	sq.fadeText();
685 
686 	sq.printText(4, textColor2);            // I did not know Dran was a dragon
687 	for (int i = 0; i < 4; i++)
688 		sq.animCommand(5);
689 	sq.animCommand(2);
690 	sq.animCommand(2);
691 	sq.fadeText();
692 
693 	sq.printText(5, textColor2);            // He must have been over 300 years old
694 	for (int i = 0; i < 4; i++)
695 		sq.animCommand(5);
696 	sq.animCommand(2);
697 	sq.animCommand(2);
698 	sq.fadeText();
699 
700 	sq.printText(6, textColor2);            // His power is gone
701 	for (int i = 0; i < 3; i++)
702 		sq.animCommand(5);
703 	sq.animCommand(2);
704 	sq.animCommand(2);
705 	sq.fadeText();
706 
707 	sq.printText(7, textColor2);            // But Darkmoon is still a source of great evil
708 	for (int i = 0; i < 4; i++)
709 		sq.animCommand(5);
710 	sq.animCommand(2);
711 	sq.animCommand(2);
712 	sq.fadeText();
713 
714 	sq.printText(8, textColor2);            // And many of his minions remain
715 	for (int i = 0; i < 4; i++)
716 		sq.animCommand(5);
717 	sq.animCommand(2);
718 	sq.animCommand(2);
719 	sq.fadeText();
720 
721 	sq.loadScene(2, 2);
722 	sq.update(2);
723 	sq.loadScene(3, 2);
724 	_screen->copyRegion(8, 8, 0, 0, 304, 128, 0, 2, Screen::CR_NO_P_CHECK);
725 
726 	sq.printText(9, textColor2);            // Now we must leave this place
727 	sq.animCommand(7);
728 	sq.animCommand(8);
729 	sq.animCommand(7);
730 	sq.animCommand(7, 36);
731 	sq.fadeText();
732 
733 	sq.printText(10, textColor2);           // So my forces can destroy it..
734 	for (int i = 0; i < 3; i++)
735 		sq.animCommand(7);
736 	sq.animCommand(8);
737 	sq.animCommand(7);
738 	sq.animCommand(7, 36);
739 	sq.animCommand(8, 18);
740 	sq.fadeText();
741 
742 	sq.printText(11, textColor2);           // Follow me
743 	sq.animCommand(7, 18);
744 	sq.animCommand(9, 18);
745 	sq.animCommand(8, 18);
746 	sq.fadeText();
747 
748 	sq.loadScene(7, 2);
749 
750 	sq.copyPalette(3, 0);
751 
752 	sq.loadScene(4, 2);
753 
754 	sq.waitForSongNotifier(2);
755 
756 	_screen->clearCurPage();
757 	sq.update(2);
758 
759 	sq.loadScene(8, 2);
760 	sq.loadScene(6, 6);
761 	sq.delay(10);
762 
763 	sq.printText(12, textColor1);           // Powerful mages stand ready for the final assault...
764 	sq.delay(90);
765 	sq.fadeText();
766 
767 	sq.waitForSongNotifier(3);
768 
769 	if (!skipFlag() && !shouldQuit())
770 		snd_playSoundEffect(7);
771 	sq.delay(8);
772 
773 	sq.animCommand(10);
774 	sq.animCommand(13);
775 	if (_flags.platform != Common::kPlatformAmiga)
776 		sq.initDelayedPaletteFade(4, 1);
777 
778 	sq.animCommand(14);
779 	sq.animCommand(13);
780 	sq.animCommand(14);
781 	sq.animCommand(14);
782 	sq.animCommand(13);
783 	if (_flags.platform != Common::kPlatformAmiga)
784 		sq.initDelayedPaletteFade(2, 1);
785 
786 	sq.animCommand(15);
787 	sq.animCommand(14);
788 	sq.animCommand(13);
789 	sq.animCommand(15);
790 	sq.animCommand(15);
791 	sq.animCommand(11);
792 
793 	sq.printText(13, textColor1);           // The temple's evil is very strong
794 	sq.delay(72);
795 	sq.fadeText();
796 
797 	sq.printText(14, textColor1);           // It must not be allowed...
798 	sq.delay(72);
799 	sq.fadeText();
800 
801 	sq.waitForSongNotifier(4);
802 
803 	if (!skipFlag() && !shouldQuit())
804 		snd_playSoundEffect(7);
805 	sq.delay(8);
806 
807 	sq.animCommand(10);
808 	if (_flags.platform != Common::kPlatformAmiga)
809 		sq.initDelayedPaletteFade(5, 1);
810 	sq.animCommand(13);
811 	sq.animCommand(14);
812 	sq.animCommand(13);
813 	sq.animCommand(14);
814 	sq.animCommand(13);
815 	sq.animCommand(13);
816 	sq.animCommand(14);
817 	sq.animCommand(14);
818 	sq.animCommand(13);
819 	sq.animCommand(12);
820 	if (_flags.platform == Common::kPlatformAmiga)
821 		sq.fadePalette(2, 3);
822 	for (int i = 0; i < 4; i++)
823 		sq.animCommand(16);
824 	if (_flags.platform == Common::kPlatformAmiga)
825 		sq.fadePalette(4, 3);
826 	sq.animCommand(17);
827 	sq.animCommand(18);
828 
829 	sq.printText(15, textColor1);           // The temple ceases to exist
830 	if (_flags.platform != Common::kPlatformAmiga) {
831 		sq.initDelayedPaletteFade(6, 1);
832 	} else if (skipFlag()) {
833 		_screen->fadeToBlack();
834 	} else {
835 		_screen->fadePalette(_screen->getPalette(5), 127);
836 		sq.copyPalette(5, 0);
837 	}
838 	sq.delay(36);
839 
840 	if (!skipFlag() && !shouldQuit())
841 		snd_playSoundEffect(11);
842 
843 	sq.delay(54);
844 	sq.fadeText();
845 	sq.loadScene(12, 2);
846 
847 	sq.waitForSongNotifier(5);
848 
849 	if (!skipFlag() && !shouldQuit())
850 		snd_playSoundEffect(6);
851 
852 	if (_flags.platform == Common::kPlatformAmiga)
853 		sq.copyPalette(6, 0);
854 
855 	if (!skipFlag() && !shouldQuit()) {
856 		if (_configRenderMode != Common::kRenderEGA)
857 			sq.setPaletteWithoutTextColor(0);
858 		_screen->crossFadeRegion(0, 0, 8, 8, 304, 128, 2, 0);
859 	}
860 	sq.delay(18);
861 
862 	sq.printText(16, textColor2);           // My friends, our work is done
863 	sq.animCommand(20);
864 	sq.animCommand(19);
865 	sq.animCommand(19, 36);
866 	if (!skipFlag() && !shouldQuit())
867 		snd_playSoundEffect(12);
868 	sq.fadeText();
869 
870 	sq.printText(17, textColor2);           // Thank you
871 	sq.animCommand(19);
872 	sq.animCommand(20, 36);
873 	sq.fadeText();
874 
875 	sq.printText(18, textColor2);           // You have earned my deepest respect
876 	if (!skipFlag() && !shouldQuit())
877 		snd_playSoundEffect(11);
878 	sq.animCommand(20);
879 	sq.animCommand(19);
880 	sq.animCommand(19);
881 	if (!skipFlag() && !shouldQuit())
882 		snd_playSoundEffect(11);
883 	sq.delay(36);
884 	sq.fadeText();
885 
886 	sq.printText(19, textColor2);           // We will remember you always
887 	sq.animCommand(19);
888 	sq.animCommand(19, 18);
889 	if (!skipFlag() && !shouldQuit())
890 		snd_playSoundEffect(11);
891 	sq.animCommand(20, 18);
892 	sq.fadeText();
893 
894 	sq.delay(28);
895 	if (!skipFlag() && !shouldQuit())
896 		snd_playSoundEffect(12);
897 	sq.delay(3);
898 
899 	sq.loadScene(5, 2);
900 	if (skipFlag() || shouldQuit()) {
901 		_screen->copyRegion(0, 0, 8, 8, 304, 128, 2, 0, Screen::CR_NO_P_CHECK);
902 	} else {
903 		sq.updateAmigaSound();
904 		snd_playSoundEffect(6);
905 		if (_configRenderMode != Common::kRenderEGA)
906 			sq.setPaletteWithoutTextColor(0);
907 		_screen->crossFadeRegion(0, 0, 8, 8, 304, 128, 2, 0);
908 	}
909 
910 	if (!skipFlag() && !shouldQuit())
911 		snd_playSoundEffect(12);
912 	sq.delay(5);
913 	if (!skipFlag() && !shouldQuit())
914 		snd_playSoundEffect(11);
915 	sq.delay(11);
916 	if (!skipFlag() && !shouldQuit())
917 		snd_playSoundEffect(12);
918 	sq.delay(7);
919 	if (!skipFlag() && !shouldQuit())
920 		snd_playSoundEffect(11);
921 	sq.delay(12);
922 	if (!skipFlag() && !shouldQuit())
923 		snd_playSoundEffect(12);
924 	sq.updateAmigaSound();
925 
926 	removeInputTop();
927 	resetSkipFlag(true);
928 
929 	sq.loadScene(10, 2);
930 	sq.loadScene(9, 2);
931 
932 	if (_flags.platform == Common::kPlatformAmiga) {
933 		sq.setPalette(7);
934 		sq.delay(3);
935 	} else {
936 		snd_stopSound();
937 		sq.delay(3);
938 		_sound->loadSoundFile(1);
939 	}
940 
941 	sq.delay(18);
942 	if (!skipFlag() && !shouldQuit() && _flags.platform != Common::kPlatformAmiga)
943 		snd_playSong(_flags.platform == Common::kPlatformFMTowns ? 16 : 1);
944 
945 	int temp = 0;
946 	const uint8 *creditsData = (_flags.platform != Common::kPlatformDOS) ? _res->fileData("CREDITS.TXT", 0) : _staticres->loadRawData(kEoB2CreditsData, temp);
947 
948 	seq_playCredits(&sq, creditsData, 18, 2, 6, 2);
949 
950 	if (_flags.platform != Common::kPlatformDOS)
951 		delete[] creditsData;
952 
953 	sq.delay(90);
954 
955 	removeInputTop();
956 	resetSkipFlag(true);
957 
958 	if (_configRenderMode != Common::kRenderEGA) {
959 		if (_flags.platform != Common::kPlatformAmiga)
960 			sq.setPalette(11);
961 		sq.fadePalette(9, 10);
962 	}
963 
964 	_screen->clearCurPage();
965 	sq.loadScene(11, 2);
966 
967 	static const uint8 finPortraitPos[] = { 0x50, 0x50, 0xD0, 0x50, 0x50, 0x90, 0xD0, 0x90, 0x90, 0x50, 0x90, 0x90 };
968 
969 	for (int i = 0; i < 6; i++) {
970 		if (!testCharacter(i, 1))
971 			continue;
972 		if (i > 3)
973 			_screen->drawShape(2, sq._shapes[6 + i], finPortraitPos[i << 1] - 16, finPortraitPos[(i << 1) + 1] - 16, 0);
974 		_screen->drawShape(2, _characters[i].faceShape, finPortraitPos[i << 1], finPortraitPos[(i << 1) + 1], 0);
975 	}
976 
977 	_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
978 
979 	if (_flags.platform == Common::kPlatformFMTowns)
980 		sq.copyPalette(12, 0);
981 
982 	if (_flags.platform != Common::kPlatformAmiga)
983 		sq.setPalette(9);
984 	sq.fadePalette(0, 18);
985 
986 	while (!skipFlag() && !shouldQuit()) {
987 		sq.updateAmigaSound();
988 		delay(_tickLength);
989 	}
990 
991 	snd_stopSound();
992 	removeInputTop();
993 	resetSkipFlag(true);
994 
995 	sq.fadePalette(9, 10);
996 }
997 
seq_playCredits(DarkmoonSequenceHelper * sq,const uint8 * data,int sd,int backupPage,int tempPage,int speed)998 void DarkMoonEngine::seq_playCredits(DarkmoonSequenceHelper *sq, const uint8 *data, int sd, int backupPage, int tempPage, int speed) {
999 	if (!data)
1000 		return;
1001 
1002 	_screen->setFont(Screen::FID_8_FNT);
1003 	_screen->setScreenDim(sd);
1004 
1005 	const ScreenDim *dm = _screen->_curDim;
1006 	const uint8 col1 = _flags.platform == Common::kPlatformAmiga ? 19 : 12;
1007 	const uint8 col2 = _flags.platform == Common::kPlatformAmiga ? 29 : 240;
1008 
1009 	_screen->copyRegion(dm->sx << 3, dm->sy, dm->sx << 3, dm->sy, dm->w << 3, dm->h, 0, backupPage, Screen::CR_NO_P_CHECK);
1010 
1011 	struct CreditsDataItem {
1012 		int16 x;
1013 		int16 y;
1014 		const void *data;
1015 		char *str;
1016 		uint8 crlf;
1017 		uint8 size;
1018 		uint8 dataType;
1019 	} items[36];
1020 	memset(items, 0, sizeof(items));
1021 
1022 	const char *pos = (const char *)data;
1023 	uint32 end = _system->getMillis();
1024 	uint32 cur = 0;
1025 	int i = 0;
1026 
1027 	do {
1028 		for (bool loop = true; loop;) {
1029 			sq->processDelayedPaletteFade();
1030 			cur = _system->getMillis();
1031 			if (end <= cur)
1032 				break;
1033 			delay(MIN<uint32>(_tickLength, end - cur));
1034 		}
1035 
1036 		end = _system->getMillis() + ((speed * _tickLength) >> 1);
1037 
1038 		for (; i < 35 && *pos; i++) {
1039 			int16 nextY = i ? items[i].y + items[i].size + (items[i].size >> 2) : dm->h;
1040 
1041 			const char *posOld = pos;
1042 			pos = strchr(pos, 0x0D);
1043 			if (!pos)
1044 				pos = strchr(posOld, 0x00);
1045 
1046 			items[i + 1].crlf = *pos++;
1047 
1048 			if (*posOld == 2) {
1049 				const uint8 *shp = sq->_shapes[(*++posOld) - 1];
1050 				items[i + 1].data = shp;
1051 				items[i + 1].size = shp[1];
1052 				items[i + 1].x = (dm->w - shp[2]) << 2;
1053 				items[i + 1].dataType = 1;
1054 				delete[] items[i + 1].str;
1055 				items[i + 1].str = 0;
1056 
1057 			} else {
1058 				if (*posOld == 1) {
1059 					posOld++;
1060 					items[i + 1].size = 6;
1061 				} else {
1062 					items[i + 1].size = _screen->getFontWidth();
1063 				}
1064 
1065 				items[i + 1].dataType = 0;
1066 
1067 				int l = pos - posOld;
1068 				if (items[i + 1].crlf != 0x0D)
1069 					l++;
1070 
1071 				delete[] items[i + 1].str;
1072 				items[i + 1].str = new char[l];
1073 				memcpy(items[i + 1].str, posOld, l);
1074 				items[i + 1].str[l - 1] = 0;
1075 				items[i + 1].data = 0;
1076 				items[i + 1].x = (((dm->w << 3) - (strlen(items[i + 1].str) * items[i + 1].size)) >> 1) + 1;
1077 			}
1078 
1079 			items[i + 1].y = nextY;
1080 		}
1081 
1082 		_screen->copyRegion(dm->sx << 3, dm->sy, dm->sx << 3, dm->sy, dm->w << 3, dm->h, backupPage, tempPage, Screen::CR_NO_P_CHECK);
1083 		sq->updateAmigaSound();
1084 
1085 		for (int h = 0; h < i; h++) {
1086 			if (items[h + 1].y < dm->h) {
1087 				if (items[h + 1].dataType == 1) {
1088 					_screen->drawShape(tempPage, (const uint8 *)items[h + 1].data, items[h + 1].x, items[h + 1].y, sd);
1089 				} else {
1090 					_screen->setCurPage(tempPage);
1091 
1092 					if (items[h + 1].size == 6)
1093 						_screen->setFont(Screen::FID_6_FNT);
1094 
1095 					_screen->printText(items[h + 1].str, (dm->sx << 3) + items[h + 1].x - 1, dm->sy + items[h + 1].y + 1, col1, 0);
1096 					_screen->printText(items[h + 1].str, (dm->sx << 3) + items[h + 1].x, dm->sy + items[h + 1].y, col2, 0);
1097 
1098 					if (items[h + 1].size == 6)
1099 						_screen->setFont(Screen::FID_8_FNT);
1100 
1101 					_screen->setCurPage(0);
1102 				}
1103 			}
1104 
1105 			items[h + 1].y -= MAX<int>(1, speed >> 1);
1106 		}
1107 
1108 		_screen->copyRegion(dm->sx << 3, dm->sy, dm->sx << 3, dm->sy, dm->w << 3, dm->h, tempPage, 0, Screen::CR_NO_P_CHECK);
1109 		_screen->updateScreen();
1110 
1111 		if (-items[1].size > items[1].y) {
1112 			delete[] items[1].str;
1113 			--i;
1114 			for (int t = 1; t <= i; t++)
1115 				memcpy(&items[t], &items[t + 1], sizeof(CreditsDataItem));
1116 			items[i + 1].str = 0;
1117 		}
1118 
1119 		if (i < 35 && ((items[i].y + items[i].size) < (dm->sy + dm->h))) {
1120 			resetSkipFlag(true);
1121 			break;
1122 		}
1123 
1124 		sq->processDelayedPaletteFade();
1125 	} while (!skipFlag() && i && !shouldQuit());
1126 
1127 	for (i = 0; i < 35; i++)
1128 		delete[] items[i].str;
1129 }
1130 
DarkmoonSequenceHelper(OSystem * system,DarkMoonEngine * vm,Screen_EoB * screen,DarkmoonSequenceHelper::Mode mode)1131 DarkmoonSequenceHelper::DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine *vm, Screen_EoB *screen, DarkmoonSequenceHelper::Mode mode) : _system(system), _vm(vm), _screen(screen) {
1132 	init(mode);
1133 }
1134 
~DarkmoonSequenceHelper()1135 DarkmoonSequenceHelper::~DarkmoonSequenceHelper() {
1136 	if (_vm->_flags.platform != Common::kPlatformAmiga) {
1137 		for (int i = 4; _config->palFiles[i]; i++)
1138 			delete _palettes[i];
1139 		for (int i = 9; i < 13; ++i)
1140 			delete _palettes[i];
1141 	}
1142 
1143 	for (int i = 0; i < 7; i++)
1144 		delete[] _fadingTables[i];
1145 
1146 	for (int i = 0; i < 54; i++)
1147 		delete[] _shapes[i];
1148 	delete[] _shapes;
1149 
1150 	delete[] _config->animData;
1151 	delete[] _config->shapeDefs;
1152 	delete[] _config->cpsData;
1153 	delete _config;
1154 
1155 	_screen->enableHiColorMode(true);
1156 	_screen->clearCurPage();
1157 	_screen->setFont(_prevFont);
1158 	_screen->updateScreen();
1159 
1160 	_system->delayMillis(150);
1161 	_vm->resetSkipFlag(true);
1162 	_vm->_allowSkip = false;
1163 }
1164 
loadScene(int index,int pageNum,bool ignorePalette)1165 void DarkmoonSequenceHelper::loadScene(int index, int pageNum, bool ignorePalette) {
1166 	Common::String file;
1167 	Common::SeekableReadStream *s = 0;
1168 	uint32 chunkID = 0;
1169 	bool isRawData = false;
1170 
1171 	if (_config->cpsFiles) {
1172 		file = _config->cpsFiles[index];
1173 		s = _vm->resource()->createReadStream(file);
1174 	}
1175 
1176 	if (s) {
1177 		chunkID = s->readUint32LE();
1178 		s->seek(0);
1179 	}
1180 
1181 	if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
1182 		// Tolerance for diffenrences up to 2 bytes is needed in some cases
1183 		if ((((int32)(chunkID & 0xFFFF) + 5) & ~3) != (((s->size()) + 3) & ~3))
1184 			isRawData = true;
1185 	} else if (file.firstChar() == 'X' && _vm->gameFlags().lang == Common::DE_DEU) {
1186 		isRawData = true;
1187 	}
1188 
1189 	if (_config->cpsData[index]) {
1190 		_screen->decodeSHP(_config->cpsData[index], pageNum);
1191 	} else if (s && chunkID == MKTAG('F', 'O', 'R', 'M')) {
1192 		// The original code also handles files with FORM chunks and ILBM and PBM sub chunks.
1193 		// Up until now I haven't found any need for these (Amiga versions included).
1194 		// We error out here theoretically, but this should never happen.
1195 		error("DarkmoonSequenceHelper::loadScene(): CPS file loading failure in scene %d - unhandled FORM chunk encountered", index);
1196 
1197 	} else if (s && !isRawData) {
1198 		delete s;
1199 		_screen->loadBitmap(_config->cpsFiles[index], pageNum | 1, pageNum | 1, ignorePalette ? 0 : _palettes[0]);
1200 
1201 	} else if (s && _vm->gameFlags().platform == Common::kPlatformAmiga) {
1202 		delete s;
1203 		_screen->loadSpecialAmigaCPS(_config->cpsFiles[index], pageNum | 1, true);
1204 
1205 	} else {
1206 		if (!s) {
1207 			file.setChar('X', 0);
1208 			s = _vm->resource()->createReadStream(file);
1209 		}
1210 
1211 		if (!s)
1212 			error("DarkmoonSequenceHelper::loadScene(): CPS file loading failure in scene %d", index);
1213 
1214 		if (_config->loadScenePal)
1215 			s->read(_palettes[0]->getData(), 768);
1216 		else
1217 			s->seek(768);
1218 		_screen->loadFileDataToPage(s, 3, 64000);
1219 		delete s;
1220 	}
1221 
1222 	int cp = _screen->setCurPage(pageNum);
1223 
1224 	if (_config->shapeDefs[index]) {
1225 		for (const DarkMoonShapeDef *df = _config->shapeDefs[index]; df->w; df++) {
1226 			uint16 shapeIndex = (df->index < 0) ? df->index * -1 : df->index;
1227 			if (_shapes[shapeIndex])
1228 				delete[] _shapes[shapeIndex];
1229 			_shapes[shapeIndex] = _screen->encodeShape(df->x, df->y, df->w, df->h, (df->index >> 8) != 0);
1230 		}
1231 	}
1232 
1233 	_screen->setCurPage(cp);
1234 
1235 	if (_vm->_configRenderMode == Common::kRenderEGA)
1236 		setPalette(0);
1237 
1238 	_screen->convertPage(pageNum | 1, pageNum, 0);
1239 
1240 	if ((pageNum == 0 || pageNum == 1) && !_vm->skipFlag() && !_vm->shouldQuit())
1241 		_screen->updateScreen();
1242 }
1243 
animCommand(int index,int del)1244 void DarkmoonSequenceHelper::animCommand(int index, int del) {
1245 	if (_vm->skipFlag() || _vm->shouldQuit())
1246 		return;
1247 
1248 	index += _platformAnimOffset;
1249 	uint32 end = 0;
1250 
1251 	for (const DarkMoonAnimCommand *s = _config->animData[index]; s->command != 0xFF && !_vm->skipFlag() && !_vm->shouldQuit(); s++) {
1252 		updateAmigaSound();
1253 
1254 		int palIndex = s->pal + _config->animPalOffs;
1255 
1256 		int x = s->x1;
1257 		if (x >= Screen::SCREEN_W)
1258 			x >>= 1;
1259 		int y = s->y1;
1260 		int x2 = 0;
1261 		uint16 shapeW = 0;
1262 		uint16 shapeH = 0;
1263 
1264 		switch (s->command) {
1265 		case 0:
1266 			// flash palette
1267 			if (_vm->_configRenderMode != Common::kRenderEGA && s->pal)
1268 				setPaletteWithoutTextColor(palIndex);
1269 			delay(s->delay);
1270 			if (_vm->_configRenderMode != Common::kRenderEGA && _config->animCmdRestorePal && s->pal)
1271 				setPaletteWithoutTextColor(0);
1272 			break;
1273 
1274 		case 1:
1275 			// draw shape, then restore background
1276 			shapeW = _shapes[s->obj][2];
1277 			shapeH = _shapes[s->obj][3];
1278 
1279 			if (_config->animCmd1ShapeFrame == 18) {
1280 				_screen->setScreenDim(18);
1281 				x -= (_screen->_curDim->sx << 3);
1282 				y -= _screen->_curDim->sy;
1283 				if (x < 0)
1284 					shapeW -= ((-x >> 3) + 1);
1285 				else
1286 					x2 = x;
1287 			}
1288 
1289 			_screen->drawShape(0, _shapes[s->obj], x, y, _config->animCmd1ShapeFrame);
1290 
1291 			if (_vm->_configRenderMode != Common::kRenderEGA && s->pal)
1292 				setPaletteWithoutTextColor(palIndex);
1293 			else
1294 				_screen->updateScreen();
1295 
1296 			delay(s->delay);
1297 
1298 			if (_config->animCmd1ShapeFrame == 0) {
1299 				if (_vm->_configRenderMode != Common::kRenderEGA && s->pal)
1300 					setPaletteWithoutTextColor(0);
1301 				_screen->copyRegion(x - 8, y - 8, x, y, (shapeW + 1) << 3, shapeH, 2, 0, Screen::CR_NO_P_CHECK);
1302 			} else {
1303 				_screen->copyRegion(x2, y, x2 + (_screen->_curDim->sx << 3), y + _screen->_curDim->sy, (shapeW + 1) << 3, shapeH, 2, 0, Screen::CR_NO_P_CHECK);
1304 			}
1305 
1306 			_screen->updateScreen();
1307 			break;
1308 
1309 		case 2:
1310 			// draw shape
1311 			_screen->drawShape(_screen->_curPage, _shapes[s->obj], x, y, 0);
1312 
1313 			if (_vm->_configRenderMode != Common::kRenderEGA && s->pal)
1314 				setPaletteWithoutTextColor(palIndex);
1315 			else if (!_screen->_curPage)
1316 				_screen->updateScreen();
1317 
1318 			delay(s->delay);
1319 
1320 			if (_vm->_configRenderMode != Common::kRenderEGA && _config->animCmdRestorePal && s->pal)
1321 				setPaletteWithoutTextColor(0);
1322 			break;
1323 
1324 		case 3:
1325 		case 4:
1326 			// fade shape in or out or restore background
1327 			if (!_config->shpBackgroundFading)
1328 				break;
1329 
1330 			if (_vm->_configRenderMode == Common::kRenderEGA) {
1331 				if (palIndex)
1332 					_screen->drawShape(0, _shapes[s->obj], s->x1, y, 0);
1333 				else
1334 					_screen->copyRegion(s->x1 - 8, s->y1 - 8, s->x1, s->y1, (_shapes[s->obj][2] + 1) << 3, _shapes[s->obj][3], 2, 0, Screen::CR_NO_P_CHECK);
1335 				_screen->updateScreen();
1336 				delay(s->delay /** 7*/);
1337 			} else if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
1338 				end = _system->getMillis() + s->delay * _vm->tickLength();
1339 
1340 				if (--palIndex) {
1341 					uint8 obj = (palIndex - 1) * 10 + s->obj;
1342 					_screen->copyRegion(s->x1 - 8, s->y1 - 8, 0, 0, (_shapes[obj][2] + 1) << 3, _shapes[obj][3], 2, 4, Screen::CR_NO_P_CHECK);
1343 					_screen->drawShape(4, _shapes[obj], s->x1 & 7, 0, 0);
1344 					_screen->copyRegion(0, 0, s->x1, s->y1, (_shapes[obj][2] + 1) << 3, _shapes[obj][3], 4, 0, Screen::CR_NO_P_CHECK);
1345 				} else {
1346 					_screen->copyRegion(s->x1 - 8, s->y1 - 8, s->x1, s->y1, (_shapes[s->obj][2] + 1) << 3, _shapes[s->obj][3], 2, 0, Screen::CR_NO_P_CHECK);
1347 				}
1348 				_screen->updateScreen();
1349 
1350 				_vm->delayUntil(end);
1351 			} else {
1352 				_screen->enableShapeBackgroundFading(true);
1353 				_screen->setShapeFadingLevel(1);
1354 
1355 				end = _system->getMillis() + s->delay * _vm->tickLength();
1356 
1357 				if (palIndex) {
1358 					_screen->setFadeTable(_fadingTables[palIndex - 1]);
1359 
1360 					_screen->copyRegion(s->x1 - 8, s->y1 - 8, 0, 0, (_shapes[s->obj][2] + 1) << 3, _shapes[s->obj][3], 2, 4, Screen::CR_NO_P_CHECK);
1361 					_screen->drawShape(4, _shapes[s->obj], s->x1 & 7, 0, 0);
1362 					_screen->copyRegion(0, 0, s->x1, s->y1, (_shapes[s->obj][2] + 1) << 3, _shapes[s->obj][3], 4, 0, Screen::CR_NO_P_CHECK);
1363 				} else {
1364 					_screen->copyRegion(s->x1 - 8, s->y1 - 8, s->x1, s->y1, (_shapes[s->obj][2] + 1) << 3, _shapes[s->obj][3], 2, 0, Screen::CR_NO_P_CHECK);
1365 				}
1366 				_screen->updateScreen();
1367 
1368 				_vm->delayUntil(end);
1369 				_screen->enableShapeBackgroundFading(false);
1370 				_screen->setShapeFadingLevel(0);
1371 			}
1372 			break;
1373 
1374 		case 5:
1375 			// copy region
1376 			if (_config->animCmd5SetPal && s->pal)
1377 				setPaletteWithoutTextColor(palIndex);
1378 
1379 			_screen->copyRegion(s->x2 << 3, s->y2, s->x1, s->y1, s->w << 3, s->h, s->obj ? _config->animCmd5AltPage : 2, 0, Screen::CR_NO_P_CHECK);
1380 			_screen->updateScreen();
1381 			delay(s->delay);
1382 			break;
1383 
1384 		case 6:
1385 			// play sound effect
1386 			if (s->obj != 0xFF)
1387 				_vm->snd_playSoundEffect(s->obj);
1388 			break;
1389 
1390 		case 7:
1391 			// restore background (only used in EGA mode)
1392 			delay(s->delay);
1393 			_screen->copyRegion(s->x1 - 8, s->y1 - 8, s->x1, s->y1, (_shapes[s->obj][2] + 1) << 3, _shapes[s->obj][3], 2, 0, Screen::CR_NO_P_CHECK);
1394 			_screen->updateScreen();
1395 			break;
1396 
1397 		default:
1398 			error("DarkmoonSequenceHelper::animCommand(): Unknown animation opcode encountered.");
1399 			break;
1400 		}
1401 	}
1402 
1403 	if (del > 0)
1404 		delay(del);
1405 }
1406 
setPlatformAnimIndexOffset(int offset)1407 void DarkmoonSequenceHelper::setPlatformAnimIndexOffset(int offset) {
1408 	_platformAnimOffset = offset;
1409 }
1410 
printText(int index,int color)1411 void DarkmoonSequenceHelper::printText(int index, int color) {
1412 	if (_vm->skipFlag() || _vm->shouldQuit())
1413 		return;
1414 
1415 	_screen->setClearScreenDim(17);
1416 
1417 	if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
1418 		memset(_textColor, 58, 3);
1419 		_palettes[0]->copy(_textColor, 0, 1, 31);
1420 		color = 31;
1421 	} else if (_vm->_configRenderMode != Common::kRenderEGA) {
1422 		_palettes[0]->copy(*_palettes[0], color, 1, 255);
1423 		setPalette(0);
1424 		color = 255;
1425 	}
1426 
1427 	char *temp = new char[strlen(_config->strings[index]) + 1];
1428 	char *str = temp;
1429 	strcpy(str, _config->strings[index]);
1430 
1431 	const ScreenDim *dm = _screen->_curDim;
1432 	int fontHeight = _screen->getFontHeight() + 1;
1433 
1434 	for (int yOffs = 0; *str; yOffs += fontHeight) {
1435 		char *cr = strchr(str, 13);
1436 
1437 		if (cr)
1438 			*cr = 0;
1439 
1440 		uint32 len = strlen(str);
1441 		_screen->printText(str, (dm->sx + ((dm->w - len) >> 1)) << 3, dm->sy + yOffs, color, dm->unkA);
1442 
1443 		if (cr) {
1444 			*cr = 13;
1445 			str = cr + 1;
1446 		} else {
1447 			str += len;
1448 		}
1449 	}
1450 
1451 	delete[] temp;
1452 
1453 	if (_vm->gameFlags().platform == Common::kPlatformAmiga)
1454 		_screen->fadePalette(*_palettes[0], 20);
1455 	else
1456 		_screen->updateScreen();
1457 }
1458 
fadeText()1459 void DarkmoonSequenceHelper::fadeText() {
1460 	uint8 col = _vm->gameFlags().platform == Common::kPlatformAmiga ? 31 : 255;
1461 
1462 	if (_vm->skipFlag() || _vm->shouldQuit()) {
1463 		_screen->clearCurDim();
1464 		_screen->setPaletteIndex(col, 0, 0, 0);
1465 		return;
1466 	}
1467 
1468 	if (_vm->_configRenderMode != Common::kRenderEGA)
1469 		_screen->fadeTextColor(_palettes[0], col, 8);
1470 
1471 	memset(_textColor, 0, 3);
1472 	_screen->clearCurDim();
1473 }
1474 
update(int srcPage)1475 void DarkmoonSequenceHelper::update(int srcPage) {
1476 	if (_vm->skipFlag() || _vm->shouldQuit())
1477 		return;
1478 
1479 	if (_vm->gameFlags().platform == Common::kPlatformAmiga)
1480 		_screen->fadeToBlack(5);
1481 
1482 	_screen->copyRegion(0, 0, 8, 8, 304, 128, srcPage, 0, Screen::CR_NO_P_CHECK);
1483 
1484 	if (_vm->_configRenderMode != Common::kRenderEGA)
1485 		setPaletteWithoutTextColor(0);
1486 
1487 	_screen->updateScreen();
1488 }
1489 
init(DarkmoonSequenceHelper::Mode mode)1490 void DarkmoonSequenceHelper::init(DarkmoonSequenceHelper::Mode mode) {
1491 	assert(mode == kIntro || mode == kFinale);
1492 
1493 	static const uint16 soundMarkersFMTowns[2][8] = {
1494 		{  229,  447,  670, 1380, 2037, 3000, 4475, 4825 },
1495 		{  475, 2030, 2200, 2752, 3475,    0,    0,    0 }
1496 	};
1497 
1498 	int size = 0;
1499 	_platformAnimOffset = 0;
1500 	_sndNextTrack = 1;
1501 	_sndNextTrackMarker = 0;
1502 	_sndMarkersFMTowns = soundMarkersFMTowns[mode];
1503 
1504 	if (mode == kIntro) {
1505 		_config = new Config(
1506 			_vm->staticres()->loadStrings(kEoB2IntroStrings, size),
1507 			_vm->staticres()->loadStrings(kEoB2IntroCPSFiles, size),
1508 			new const uint8*[16],
1509 			_vm->_flags.platform == Common::kPlatformAmiga ? 0 : (_vm->_configRenderMode == Common::kRenderEGA ? _palFilesIntroEGA : _palFilesIntroVGA),
1510 			new const DarkMoonShapeDef*[16],
1511 			new const DarkMoonAnimCommand *[44],
1512 			false,
1513 			false,
1514 			true,
1515 			true,
1516 			_vm->_flags.platform == Common::kPlatformAmiga ? 1 : 0,
1517 			0,
1518 			false,
1519 			2
1520 		);
1521 
1522 		for (int i = 0; i < 44; i++)
1523 			_config->animData[i] = _vm->staticres()->loadEoB2SeqData(kEoB2IntroAnimData00 + i, size);
1524 
1525 		for (int i = 0; i < 16; i++)
1526 			_config->cpsData[i] = _vm->staticres()->loadRawData(kEoB2IntroCpsDataStreet1 + i, size);
1527 
1528 		memset(_config->shapeDefs, 0, 16 * sizeof(DarkMoonShapeDef*));
1529 		_config->shapeDefs[0] = _vm->staticres()->loadEoB2ShapeData(kEoB2IntroShapes00, size);
1530 		_config->shapeDefs[1] = _vm->staticres()->loadEoB2ShapeData(kEoB2IntroShapes01, size);
1531 		_config->shapeDefs[4] = _vm->staticres()->loadEoB2ShapeData(kEoB2IntroShapes04, size);
1532 		_config->shapeDefs[7] = _vm->staticres()->loadEoB2ShapeData(kEoB2IntroShapes07, size);
1533 		_config->shapeDefs[13] = _vm->staticres()->loadEoB2ShapeData(kEoB2IntroShapes13, size);
1534 		_config->shapeDefs[14] = _vm->staticres()->loadEoB2ShapeData(kEoB2IntroShapes14, size);
1535 		_config->shapeDefs[15] = _vm->staticres()->loadEoB2ShapeData(kEoB2IntroShapes15, size);
1536 
1537 	} else {
1538 		_config = new Config(
1539 			_vm->staticres()->loadStrings(kEoB2FinaleStrings, size),
1540 			_vm->staticres()->loadStrings(kEoB2FinaleCPSFiles, size),
1541 			new const uint8*[13],
1542 			_vm->_flags.platform == Common::kPlatformAmiga ? _palFilesFinaleAmiga : (_vm->_configRenderMode == Common::kRenderEGA ? _palFilesFinaleEGA : _palFilesFinaleVGA),
1543 			new const DarkMoonShapeDef*[13],
1544 			new const DarkMoonAnimCommand *[21],
1545 			true,
1546 			true,
1547 			false,
1548 			false,
1549 			_vm->_flags.platform == Common::kPlatformAmiga ? 2 : 1,
1550 			18,
1551 			true,
1552 			6
1553 		);
1554 
1555 		for (int i = 0; i < 21; i++)
1556 			_config->animData[i] = _vm->staticres()->loadEoB2SeqData(kEoB2FinaleAnimData00 + i, size);
1557 
1558 		for (int i = 0; i < 13; i++)
1559 			_config->cpsData[i] = _vm->staticres()->loadRawData(kEoB2FinaleCpsDataDragon1 + i, size);
1560 
1561 		memset(_config->shapeDefs, 0, 13 * sizeof(DarkMoonShapeDef*));
1562 		_config->shapeDefs[0] = _vm->staticres()->loadEoB2ShapeData(kEoB2FinaleShapes00, size);
1563 		_config->shapeDefs[3] = _vm->staticres()->loadEoB2ShapeData(kEoB2FinaleShapes03, size);
1564 		_config->shapeDefs[7] = _vm->staticres()->loadEoB2ShapeData(kEoB2FinaleShapes07, size);
1565 		_config->shapeDefs[9] = _vm->staticres()->loadEoB2ShapeData(kEoB2FinaleShapes09, size);
1566 		_config->shapeDefs[10] = _vm->staticres()->loadEoB2ShapeData(kEoB2FinaleShapes10, size);
1567 	}
1568 
1569 	_screen->enableHiColorMode(false);
1570 	_screen->disableDualPaletteMode();
1571 	int numColors = 256;
1572 
1573 	if (_vm->_flags.platform == Common::kPlatformAmiga) {
1574 		static const int8 palIndex[13] = { -1, -1, 3, 2, 4, 5, 6, 7, -1, -1, -1, -1, -1 };
1575 		for (int i = 0; i < 13; ++i)
1576 			_palettes[i] = &_screen->getPalette(i);
1577 		Common::SeekableReadStream *s = _config->palFiles ? _vm->resource()->createReadStream(_config->palFiles[0]) : 0;
1578 		numColors = 32;
1579 		for (int i = 0; i < 13; ++i) {
1580 			if (s && palIndex[i] != -1)
1581 				_palettes[palIndex[i]]->loadAmigaPalette(*s, 0, 32);
1582 		}
1583 		delete s;
1584 	} else {
1585 		for (int i = 0; _config->palFiles[i]; i++) {
1586 			if (i < 4)
1587 				_palettes[i] = &_screen->getPalette(i);
1588 			else
1589 				_palettes[i] = new Palette(256);
1590 			_screen->loadPalette(_config->palFiles[i], *_palettes[i]);
1591 		}
1592 
1593 		for (int i = 9; i < 13; ++i)
1594 			_palettes[i] = new Palette(256);
1595 	}
1596 
1597 	_palettes[9]->fill(0, numColors, 0);
1598 	_palettes[10]->fill(0, numColors, 63);
1599 	_palettes[11]->fill(0, numColors, 0);
1600 
1601 
1602 	if (_vm->gameFlags().platform == Common::kPlatformFMTowns)
1603 		_screen->loadPalette("PALETTE.COL", *_palettes[12]);
1604 
1605 	for (int i = 0; i < 7; i++)
1606 		_fadingTables[i] = 0;
1607 
1608 	uint8 *fadeData = (_vm->_configRenderMode != Common::kRenderCGA && _vm->_configRenderMode != Common::kRenderEGA) ? _vm->resource()->fileData("FADING.DAT", 0) : 0;
1609 
1610 	if (fadeData) {
1611 		for (int i = 0; i < 7; i++) {
1612 			_fadingTables[i] = new uint8[256];
1613 			memcpy(_fadingTables[i], fadeData + (i << 8), 256);
1614 		}
1615 	} else {
1616 		if (_vm->_flags.platform != Common::kPlatformAmiga && _vm->_configRenderMode != Common::kRenderCGA && _vm->_configRenderMode != Common::kRenderEGA) {
1617 			uint8 *pal = _vm->resource()->fileData("PALETTE1.PAL", 0);
1618 			for (int i = 0; i < 7; i++)
1619 				_screen->createFadeTable(pal, _fadingTables[i], 18, (i + 1) * 36);
1620 			delete[] pal;
1621 		}
1622 	}
1623 
1624 	delete[] fadeData;
1625 
1626 	_shapes = new const uint8*[54];
1627 	memset(_shapes, 0, 54 * sizeof(uint8*));
1628 
1629 	_fadePalTimer = 0;
1630 	_fadePalRate = 0;
1631 
1632 	memset(_textColor, 0, 3);
1633 
1634 	_screen->setScreenPalette(*_palettes[0]);
1635 	_prevFont = _screen->setFont(_vm->gameFlags().platform == Common::kPlatformFMTowns ? Screen::FID_SJIS_LARGE_FNT : Screen::FID_8_FNT);
1636 	_screen->hideMouse();
1637 
1638 	_vm->delay(150);
1639 	_vm->_eventList.clear();
1640 	_vm->_allowSkip = true;
1641 }
1642 
setPaletteWithoutTextColor(int index)1643 void DarkmoonSequenceHelper::setPaletteWithoutTextColor(int index) {
1644 	if (_vm->_configRenderMode == Common::kRenderEGA || _vm->skipFlag() || _vm->shouldQuit())
1645 		return;
1646 
1647 	int numCol = (_vm->gameFlags().platform == Common::kPlatformAmiga) ? 31 : 255;
1648 
1649 	if (_vm->gameFlags().platform != Common::kPlatformAmiga) {
1650 		if (!memcmp(_palettes[11]->getData(), _palettes[index]->getData(), numCol * 3))
1651 			return;
1652 	}
1653 
1654 	_palettes[11]->copy(*_palettes[index], 0, numCol);
1655 	if (_vm->gameFlags().platform == Common::kPlatformAmiga)
1656 		_palettes[11]->copy(_textColor, 0, 1, numCol);
1657 	else
1658 		_palettes[11]->copy(*_palettes[0], numCol, 1, numCol);
1659 	setPalette(11);
1660 
1661 	_screen->updateScreen();
1662 	_system->delayMillis(10);
1663 }
1664 
setPalette(int index)1665 void DarkmoonSequenceHelper::setPalette(int index) {
1666 	_screen->setScreenPalette(*_palettes[index]);
1667 }
1668 
fadePalette(int index,int del)1669 void DarkmoonSequenceHelper::fadePalette(int index, int del) {
1670 	if (_vm->skipFlag() || _vm->shouldQuit())
1671 		return;
1672 	if (_vm->_configRenderMode == Common::kRenderEGA) {
1673 		setPalette(index);
1674 		_screen->updateScreen();
1675 	} else {
1676 		_screen->fadePalette(*_palettes[index], del * _vm->tickLength());
1677 	}
1678 }
1679 
copyPalette(int srcIndex,int destIndex)1680 void DarkmoonSequenceHelper::copyPalette(int srcIndex, int destIndex) {
1681 	_palettes[destIndex]->copy(*_palettes[srcIndex]);
1682 }
1683 
initDelayedPaletteFade(int palIndex,int rate)1684 void DarkmoonSequenceHelper::initDelayedPaletteFade(int palIndex, int rate) {
1685 	_palettes[11]->copy(*_palettes[0]);
1686 
1687 	_fadePalIndex = palIndex;
1688 	_fadePalRate = rate;
1689 	_fadePalTimer = _system->getMillis() + 2 * _vm->_tickLength;
1690 }
1691 
processDelayedPaletteFade()1692 bool DarkmoonSequenceHelper::processDelayedPaletteFade() {
1693 	if (_vm->skipFlag() || _vm->shouldQuit())
1694 		return true;
1695 
1696 	if (_vm->_configRenderMode == Common::kRenderEGA || !_fadePalRate || (_system->getMillis() <= _fadePalTimer))
1697 		return false;
1698 
1699 	if (_screen->delayedFadePalStep(_palettes[_fadePalIndex], _palettes[0], _fadePalRate)) {
1700 		setPaletteWithoutTextColor(0);
1701 		_fadePalTimer = _system->getMillis() + 3 * _vm->_tickLength;
1702 	} else {
1703 		_fadePalRate = 0;
1704 	}
1705 
1706 	return false;
1707 }
1708 
delay(uint32 ticks)1709 void DarkmoonSequenceHelper::delay(uint32 ticks) {
1710 	if (_vm->skipFlag() || _vm->shouldQuit())
1711 		return;
1712 
1713 	uint32 end = _system->getMillis() + ticks * _vm->_tickLength;
1714 
1715 	if (_config->palFading) {
1716 		do {
1717 			if (processDelayedPaletteFade())
1718 				break;
1719 			_vm->updateInput();
1720 		} while (end > _system->getMillis());
1721 		processDelayedPaletteFade();
1722 
1723 	} else {
1724 		_vm->delayUntil(end);
1725 	}
1726 }
1727 
waitForSongNotifier(int index,bool introUpdateAnim)1728 void DarkmoonSequenceHelper::waitForSongNotifier(int index, bool introUpdateAnim) {
1729 	if (_vm->gameFlags().platform == Common::kPlatformFMTowns)
1730 		index = _sndMarkersFMTowns[index - 1];
1731 	else if (_vm->sound()->getMusicType() != Sound::kAdLib)
1732 		return;
1733 
1734 	int seq = 0;
1735 
1736 	while (_vm->sound()->musicEnabled() && _vm->sound()->checkTrigger() < index && !(_vm->skipFlag() || _vm->shouldQuit())) {
1737 		if (introUpdateAnim) {
1738 			animCommand(30 | seq);
1739 			seq ^= 1;
1740 		}
1741 
1742 		if (_config->palFading)
1743 			processDelayedPaletteFade();
1744 
1745 		_vm->updateInput();
1746 	}
1747 }
1748 
updateAmigaSound()1749 void DarkmoonSequenceHelper::updateAmigaSound() {
1750 	if (_vm->gameFlags().platform != Common::kPlatformAmiga || !_vm->sound()->musicEnabled())
1751 		return;
1752 
1753 	int ct = _vm->sound()->checkTrigger();
1754 	if (ct < _sndNextTrackMarker)
1755 		return;
1756 
1757 	_vm->snd_playSong(_sndNextTrack++);
1758 	if (_sndNextTrack == 4)
1759 		_sndNextTrack = 1;
1760 
1761 	static const uint16 interval[4] = { 0, 1015, 4461, 1770 };
1762 	_sndNextTrackMarker = interval[_sndNextTrack];
1763 }
1764 
1765 const char *const DarkmoonSequenceHelper::_palFilesIntroVGA[] = {
1766 	"PALETTE1.PAL",
1767 	"PALETTE3.PAL",
1768 	"PALETTE2.PAL",
1769 	"PALETTE4.PAL",
1770 	0
1771 };
1772 
1773 const char *const DarkmoonSequenceHelper::_palFilesIntroEGA[] = {
1774 	"PALETTE0.PAL",
1775 	"PALETTE3.PAL",
1776 	"PALETTE2.PAL",
1777 	"PALETTE4.PAL",
1778 	0
1779 };
1780 
1781 const char *const DarkmoonSequenceHelper::_palFilesFinaleVGA[] = {
1782 	"FINALE_0.PAL",
1783 	"FINALE_0.PAL",
1784 	"FINALE_1.PAL",
1785 	"FINALE_2.PAL",
1786 	"FINALE_3.PAL",
1787 	"FINALE_4.PAL",
1788 	"FINALE_5.PAL",
1789 	"FINALE_6.PAL",
1790 	"FINALE_7.PAL",
1791 	0
1792 };
1793 
1794 const char *const DarkmoonSequenceHelper::_palFilesFinaleEGA[] = {
1795 	"FINALE_6.PAL",
1796 	"FINALE_0.PAL",
1797 	"FINALE_1.PAL",
1798 	"FINALE_7.PAL",
1799 	"FINALE_3.PAL",
1800 	"FINALE_4.PAL",
1801 	"FINALE_5.PAL",
1802 	"FINALE_0.PAL",
1803 	"FINALE_0.PAL",
1804 	0
1805 };
1806 
1807 const char *const DarkmoonSequenceHelper::_palFilesFinaleAmiga[] = {
1808 	"FINALE.PAL",
1809 	0
1810 };
1811 
seq_nightmare()1812 void DarkMoonEngine::seq_nightmare() {
1813 	Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
1814 	_screen->clearCurDimOvl(0);
1815 	_screen->copyRegion(0, 0, 0, 120, 176, 24, 12, 2, Screen::CR_NO_P_CHECK);
1816 	initDialogueSequence();
1817 	gui_drawDialogueBox();
1818 
1819 	_txt->printDialogueText(99, 0);
1820 	snd_playSoundEffect(54);
1821 
1822 	static const uint8 seqX[] = { 0, 20, 0, 20 };
1823 	static const uint8 seqY[] = { 0, 0, 96, 96 };
1824 	static const uint8 seqDelay[] = { 12, 7, 7, 12 };
1825 
1826 	for (const int8 *i = _dreamSteps; *i != -1; ++i) {
1827 		drawSequenceBitmap("DREAM", 0, seqX[*i], seqY[*i], 0);
1828 		delay(seqDelay[*i] * _tickLength);
1829 	}
1830 
1831 	_txt->printDialogueText(20, _okStrings[0]);
1832 
1833 	restoreAfterDialogueSequence();
1834 
1835 	_screen->setFont(of);
1836 }
1837 
seq_kheldran()1838 void DarkMoonEngine::seq_kheldran() {
1839 	Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
1840 
1841 	initDialogueSequence();
1842 	gui_drawDialogueBox();
1843 
1844 	static const char file[] = "KHELDRAN";
1845 	_screen->set16bitShadingLevel(4);
1846 	_txt->printDialogueText(_kheldranStrings[0]);
1847 	drawSequenceBitmap(file, 0, 0, 0, 0);
1848 	_txt->printDialogueText(20, _moreStrings[0]);
1849 	snd_playSoundEffect(56);
1850 	drawSequenceBitmap(file, 0, 20, 0, 0);
1851 	delay(10 * _tickLength);
1852 	drawSequenceBitmap(file, 0, 0, 96, 0);
1853 	delay(10 * _tickLength);
1854 	drawSequenceBitmap(file, 0, 20, 96, 0);
1855 	delay(7 * _tickLength);
1856 	_txt->printDialogueText(76, _okStrings[0]);
1857 
1858 	restoreAfterDialogueSequence();
1859 
1860 	_screen->setFont(of);
1861 }
1862 
seq_dranDragonTransformation()1863 void DarkMoonEngine::seq_dranDragonTransformation() {
1864 	Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
1865 
1866 	initDialogueSequence();
1867 	gui_drawDialogueBox();
1868 
1869 	static const char file[] = "DRANX";
1870 	drawSequenceBitmap(file, 0, 0, 0, 0);
1871 	_txt->printDialogueText(120, _moreStrings[0]);
1872 	snd_playSoundEffect(56);
1873 	drawSequenceBitmap(file, 0, 20, 0, 0);
1874 	delay(7 * _tickLength);
1875 	drawSequenceBitmap(file, 0, 0, 96, 0);
1876 	delay(7 * _tickLength);
1877 	drawSequenceBitmap(file, 0, 20, 96, 0);
1878 	delay(18 * _tickLength);
1879 
1880 	restoreAfterDialogueSequence();
1881 
1882 	_screen->setFont(of);
1883 }
1884 
1885 } // End of namespace Kyra
1886 
1887 #endif // ENABLE_EOB
1888