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 "xeen/worldofxeen/clouds_cutscenes.h"
24 #include "xeen/sound.h"
25 
26 namespace Xeen {
27 namespace WorldOfXeen {
28 
29 #define WAIT(TIME) if (_subtitles.wait(TIME)) return false
30 #define ROTATE_BG screen.horizMerge(_mergeX); \
31 	_mergeX = (_mergeX + 1) % SCREEN_WIDTH
32 #define LOAD_VORTEX loadScreen(Common::String::format("vort%02u.frm", cloudsCtr)); \
33 	if (++cloudsCtr > 20) \
34 		cloudsCtr = 1
35 
showCloudsIntro()36 bool CloudsCutscenes::showCloudsIntro() {
37 	EventsManager &events = *g_vm->_events;
38 	FileManager &files = *g_vm->_files;
39 	Screen &screen = *g_vm->_screen;
40 	Sound &sound = *g_vm->_sound;
41 
42 	bool darkCc = files._ccNum;
43 	files.setGameCc(0);
44 	sound._musicSide = 0;
45 	_subtitles.reset();
46 
47 	bool seenIntro = showCloudsTitle() && showCloudsIntroInner();
48 
49 	events.clearEvents();
50 
51 	// Roll up the scroll again
52 	sound.songCommand(50);
53 	doScroll(true, false);
54 
55 	sound.stopAllAudio();
56 	screen.freePages();
57 	files.setGameCc(darkCc ? 1 : 0);
58 
59 	return seenIntro;
60 }
61 
showCloudsTitle()62 bool CloudsCutscenes::showCloudsTitle() {
63 	Screen &screen = *_vm->_screen;
64 	Sound &sound = *_vm->_sound;
65 
66 	// Initial logo display
67 	screen.loadPalette("intro1.pal");
68 	screen.loadBackground("logobak.raw");
69 	screen.saveBackground();
70 	screen.update();
71 	screen.fadeIn(128);
72 
73 	SpriteResource logo[2] = {
74 		SpriteResource("logo.vga"), SpriteResource("logo1.vga")
75 	};
76 	sound.playFX(1);
77 
78 	for (int idx = 0; idx < 80; ++idx) {
79 		screen.restoreBackground();
80 		logo[idx / 65].draw(0, idx % 65);
81 		screen.update();
82 
83 		switch (idx) {
84 		case 37:
85 			sound.playFX(0);
86 			sound.playFX(53);
87 			sound.playSound("fire.voc");
88 			break;
89 		case 52:
90 		case 60:
91 			sound.playFX(3);
92 			break;
93 		case 64:
94 			sound.playFX(2);
95 			break;
96 		case 66:
97 			sound.playFX(52);
98 			sound.playSound("meangro&.voc");
99 			break;
100 		default:
101 			break;
102 		}
103 
104 		WAIT(2);
105 	}
106 
107 	screen.restoreBackground();
108 	screen.update();
109 	WAIT(30);
110 
111 	screen.fadeOut(8);
112 	logo[0].clear();
113 	logo[1].clear();
114 
115 	return true;
116 }
117 
showCloudsIntroInner()118 bool CloudsCutscenes::showCloudsIntroInner() {
119 	EventsManager &events = *_vm->_events;
120 	Screen &screen = *_vm->_screen;
121 	Sound &sound = *_vm->_sound;
122 	Windows &windows = *_vm->_windows;
123 
124 	SpriteResource stars("stars.vga"), intro1("intro1.vga"),
125 		lake("lake.vga"), xeen("xeen.vga"), wizTower("wiztower.vga"),
126 		wizTower2("wiztwer2.vga"), lake2("lake2.vga"), lake3("lake3.vga"),
127 		xeen1("xeen1.vga");
128 
129 	// Show the production splash screen
130 	sound.playSong("mm4theme.m");
131 	screen.loadBackground("jvc.raw");
132 	screen.loadPalette("mm4.pal");
133 	screen.update();
134 	screen.fadeIn();
135 	WAIT(30);
136 	screen.fadeOut(8);
137 
138 	// Clouds of Xeen title with vertically scrolling background
139 	screen.loadPalette("intro.pal");
140 	screen.loadBackground("blank.raw");
141 	screen.saveBackground();
142 	stars.draw(0, 0);
143 	stars.draw(0, 1, Common::Point(160, 0));
144 	screen.loadPage(0);
145 	intro1.draw(0, 0);
146 	screen.loadPage(1);
147 
148 	bool fadeFlag = true;
149 	for (int yCtr = SCREEN_HEIGHT, yScroll = 0, xeenCtr = -1; yCtr > 0; --yCtr, ++yScroll) {
150 		screen.vertMerge(yScroll);
151 		if (yCtr < 160) {
152 			xeen.draw(0, 0);
153 		}
154 		if (yCtr < 100) {
155 			xeen.draw(0, 0);
156 			if (++xeenCtr < 14)
157 				xeen1.draw(0, xeenCtr);
158 		}
159 		screen.update();
160 
161 		if (fadeFlag) {
162 			screen.fadeIn();
163 			fadeFlag = false;
164 		}
165 
166 		WAIT(1);
167 	}
168 
169 	// Remainder of vertical scrolling of background
170 	screen.restoreBackground();
171 	intro1.draw(0, 0);
172 	screen.loadPage(0);
173 	lake.draw(0, 0);
174 	screen.loadPage(1);
175 
176 	bool drawFlag = false;
177 	for (int yCtr = SCREEN_HEIGHT - 1, yScroll = 1, lakeCtr = 0; yCtr > 0; --yCtr, ++yScroll) {
178 		screen.vertMerge(yScroll);
179 
180 		if (yCtr < 95) {
181 			if (++lakeCtr >= 44 || drawFlag) {
182 				lakeCtr = 0;
183 				drawFlag = true;
184 			} else {
185 				lake3.draw(0, lakeCtr, Common::Point(0, yCtr));
186 			}
187 		}
188 
189 		xeen.draw(0, 0);
190 		screen.update();
191 		WAIT(1);
192 	}
193 
194 	screen.freePages();
195 
196 	// Flying creatures moving horizontally
197 	lake.draw(0, 0);
198 	screen.saveBackground();
199 
200 	int frameNum = 0;
201 	events.updateGameCounter();
202 	for (int idx = 0; idx < 100; ++idx) {
203 		frameNum = (frameNum + 1) % 43;
204 		screen.restoreBackground();
205 		lake2.draw(0, frameNum, Common::Point(0, 0), SPRFLAG_800);
206 		WAIT(1);
207 	}
208 
209 	// Zoom in on a closeup of the wizardry tower
210 	const int XLIST1[16] = { 0, 5, 10, 15, 20, 25, 30, 35, 40, 44, 48, 52, 56, 60, 64, 68 };
211 	const int XLIST2[16] = { 160, 155, 150, 145, 140, 135, 130, 125, 120, 114, 108, 102, 96, 90, 84, 78 };
212 	const int YLIST[23] = { 0, 6, 12, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 51 };
213 
214 	for (int idx = 15; idx >= 0; --idx) {
215 		events.updateGameCounter();
216 
217 		screen.restoreBackground();
218 		lake2.draw(0, frameNum, Common::Point(0, 0), SPRFLAG_800);
219 		frameNum = (frameNum + 1) % 43;
220 		wizTower.draw(0, 0, Common::Point(XLIST1[idx], YLIST[idx]), 0, idx);
221 		wizTower.draw(0, 1, Common::Point(XLIST2[idx], YLIST[idx]), 0, idx);
222 		screen.update();
223 		WAIT(1);
224 	}
225 
226 	// Cloaked figure walks horizontally
227 	wizTower.draw(0, 0);
228 	wizTower.draw(0, 1, Common::Point(160, 0));
229 	screen.saveBackground();
230 
231 	for (int idx = 0; idx < 39; ++idx) {
232 		screen.restoreBackground();
233 		wizTower2.draw(0, idx);
234 		screen.update();
235 
236 		WAIT(2);
237 	}
238 
239 	screen.fadeOut();
240 	lake2.clear();
241 	lake3.clear();
242 	xeen1.clear();
243 
244 	// All the lines whilst the scroll is open
245 	SpriteResource groupo("groupo.vga"), group("group.vga"),
246 		crodo("crodo.vga"), box("box.vga");
247 
248 	groupo.draw(0, 0);
249 	groupo.draw(0, 1, Common::Point(160, 0));
250 	crodo.draw(0, 0, Common::Point(0, -5));
251 	windows[0].writeString(Res.CLOUDS_INTRO1);
252 
253 	// Unroll a scroll
254 	if (doScroll(false, true))
255 		return false;
256 
257 	sound.setMusicPercent(60);
258 	screen.restoreBackground();
259 	screen.update();
260 	_subtitles.setLine(0);
261 
262 	// Loop through each spoken line
263 	int ctr1 = 0, ctr2 = 0, ctr3 = 0, ctr4 = 0, ctr5 = 0, totalCtr = 0;
264 	for (int lineCtr = 0; lineCtr < 14; ++lineCtr) {
265 		if (lineCtr != 6 && lineCtr != 7) {
266 			// Set subtitle to display (presuming subtitles are turned on)
267 			switch (lineCtr) {
268 			case 0:
269 				_subtitles.setLine(0);
270 				break;
271 			case 1:
272 				_subtitles.setLine(1);
273 				break;
274 			case 5:
275 				_subtitles.setLine(2);
276 				break;
277 			case 11:
278 				_subtitles.setLine(3);
279 				break;
280 			default:
281 				break;
282 			}
283 
284 			// Play the next sample
285 			sound.playVoice(_INTRO_VOCS[lineCtr]);
286 		}
287 
288 		events.timeMark1();
289 		for (int frameCtr = 0, lookup = 0; sound.isSoundPlaying() ||
290 				(_subtitles.active() && (lineCtr == 0 || lineCtr == 4 || lineCtr == 10 || lineCtr == 13)); ) {
291 			groupo.draw(0, 0);
292 			groupo.draw(0, 1, Common::Point(160, 0));
293 
294 			switch (lineCtr) {
295 			case 2:
296 				ctr1 = (ctr1 + 1) % 5;
297 				group.draw(0, ctr1);
298 				ctr4 = (ctr4 + 1) % 9;
299 				break;
300 
301 			case 4:
302 				ctr4 = (ctr4 + 1) % 9 + 9;
303 				break;
304 
305 			case 8:
306 			case 12:
307 				ctr2 = (ctr2 + 1) % 3;
308 				ctr4 = (ctr4 + 1) % 9;
309 				ctr3 = (ctr3 + 1) % 6 + 3;
310 				break;
311 
312 			case 9:
313 			case 13:
314 				ctr3 = (ctr3 + 1) % 3;
315 				group.draw(0, ctr3 + 43, Common::Point(178, 134));
316 				ctr4 = (ctr4 + 1) % 9;
317 				ctr2 = (ctr2 % 15) + 3;
318 				break;
319 
320 			default:
321 				ctr4 = (ctr4 + 1) % 9;
322 				ctr2 = (ctr2 + 1) % 15 + 3;
323 				ctr3 = (ctr3 + 1) % 6 + 3;
324 				break;
325 			}
326 
327 			group.draw(0, ctr4 + 5, Common::Point(0, 99));
328 			group.draw(0, ctr2 + 24, Common::Point(202, 12));
329 			if ((++totalCtr % 30) == 0)
330 				group.draw(0, 43, Common::Point(178, 134));
331 
332 			switch (lineCtr) {
333 			case 2:
334 			case 4:
335 			case 8:
336 			case 9:
337 			case 12:
338 			case 13: {
339 				crodo.draw(0, 0, Common::Point(0, -5));
340 				windows[0].writeString(Res.CLOUDS_INTRO1);
341 
342 				ctr5 = (ctr5 + 1) % 19;
343 
344 				WAIT(1);
345 				continue;
346 			}
347 
348 			default:
349 				crodo.draw(0, frameCtr, Common::Point(0, -5));
350 				if (lookup > 30)
351 					lookup = 30;
352 				frameCtr = _INTRO_FRAMES_VALS[_INTRO_FRAMES_LOOKUP[lineCtr]][lookup];
353 				windows[0].writeString(Res.CLOUDS_INTRO1);
354 
355 				ctr5 = (ctr5 + 1) % 19;
356 				break;
357 			}
358 
359 			uint expiry = _INTRO_FRAMES_WAIT[_INTRO_FRAMES_LOOKUP[lineCtr]][lookup];
360 			do {
361 				WAIT(1);
362 			} while (events.timeElapsed1() < expiry);
363 
364 			++lookup;
365 			if (!sound._fxOn && lookup > 30)
366 				lookup = 0;
367 		}
368 
369 		if (!sound._fxOn)
370 			lineCtr = 20;
371 
372 		if (lineCtr == 5)
373 			sound.playVoice(_INTRO_VOCS[6]);
374 		else if (lineCtr == 6)
375 			sound.playVoice(_INTRO_VOCS[7]);
376 	}
377 
378 	return true;
379 }
380 
showCloudsEnding(uint finalScore)381 void CloudsCutscenes::showCloudsEnding(uint finalScore) {
382 	EventsManager &events = *g_vm->_events;
383 	FileManager &files = *g_vm->_files;
384 	Sound &sound = *g_vm->_sound;
385 
386 	bool darkCc = files._ccNum;
387 	files.setGameCc(0);
388 	_subtitles.reset();
389 
390 	_mirror.load("mirror.end");
391 	_mirrBack.load("mirrback.end");
392 	_mergeX = 0;
393 	doScroll(true, false);
394 
395 	if (showCloudsEnding1())
396 		if (showCloudsEnding2())
397 			if (showCloudsEnding3())
398 				if (showCloudsEnding4(finalScore))
399 					showCloudsEnding5();
400 
401 	events.clearEvents();
402 	sound.stopAllAudio();
403 	files.setGameCc(darkCc ? 1 : 0);
404 
405 	if (!g_vm->shouldExit())
406 		doScroll(true, false);
407 }
408 
showCloudsEnding1()409 bool CloudsCutscenes::showCloudsEnding1() {
410 	FileManager &files = *_vm->_files;
411 	Screen &screen = *_vm->_screen;
412 	Sound &sound = *_vm->_sound;
413 
414 	files._ccNum = false;
415 	files.setGameCc(0);
416 
417 	// Show the castle with swirling clouds and lightning
418 	SpriteResource prec;
419 	prec.load("prec.end");
420 	screen.loadBackground("blank.raw");
421 	screen.loadPalette("mm4e.pal");
422 
423 	loadScreen(Common::String::format("prec00%02u.frm", 1));
424 	prec.draw(0, 0);
425 	prec.draw(0, 1, Common::Point(160, 0));
426 	screen.fadeIn();
427 	WAIT(15);
428 
429 	sound.playFX(1);
430 	sound.playFX(34);
431 
432 	// Initial animation of vortex & lightning in the sky
433 	for (int idx = 1; idx < 42; ++idx) {
434 		// Load up the background frame of swirling clouds
435 		loadScreen(Common::String::format("prec00%02u.frm", idx));
436 
437 		// Render castle in front of it
438 		prec.draw(0, 0, Common::Point(0, 0));
439 		prec.draw(0, 1, Common::Point(160, 0));
440 		screen.update();
441 
442 		switch (idx) {
443 		case 8:
444 		case 18:
445 		case 21:
446 			sound.playFX(33);
447 			break;
448 
449 		case 19:
450 		case 25:
451 			sound.playFX(34);
452 			break;
453 
454 		default:
455 			break;
456 		}
457 
458 		WAIT(3);
459 	}
460 
461 	prec.clear();
462 
463 	SpriteResource cast1[7], cast2[7], darkLord[3];
464 	for (int idx = 1; idx < 7; ++idx)
465 		cast1[idx - 1].load(Common::String::format("cast%02d.end", idx));
466 	for (int idx = 1; idx < 7; ++idx)
467 		cast2[idx - 1].load(Common::String::format("casb%02d.end", idx));
468 	for (int idx = 1; idx < 4; ++idx)
469 		darkLord[idx - 1].load(Common::String::format("darklrd%d.end", idx));
470 
471 	// Castle close-up
472 	int cloudsCtr = 1;
473 	for (int idx = 1; idx < 16; ++idx) {
474 		LOAD_VORTEX;
475 		cast1[0].draw(0, 0);
476 		cast2[0].draw(0, 0, Common::Point(0, 100));
477 		WAIT(3);
478 	}
479 
480 	screen.loadPalette("mm4.pal");
481 	screen.fadeIn(0x81);
482 
483 	// Castle gets destroyed / sucked into the vortex
484 	const byte COUNTS1[6] = { 9, 3, 2, 2, 3, 15 };
485 	bool flag = false;
486 	for (int idx1 = 1; idx1 < 7; ++idx1) {
487 		for (int idx2 = 0; idx2 < COUNTS1[idx1 - 1]; ++idx2) {
488 			if (flag && !sound.isSoundPlaying()) {
489 				flag = false;
490 				sound.playFX(34);
491 			} else if (!flag && idx1 == 1 && idx2 == 6) {
492 				flag = true;
493 				sound.playVoice("xeenlaff.voc");
494 			}
495 
496 			switch (cloudsCtr) {
497 			case 0:
498 			case 1:
499 			case 5:
500 			case 9:
501 			case 15:
502 				sound.playFX(34);
503 				break;
504 			case 2:
505 			case 7:
506 			case 10:
507 			case 13:
508 				sound.playFX(33);
509 				break;
510 			default:
511 				break;
512 			}
513 
514 			LOAD_VORTEX;
515 			cast1[idx1 - 1].draw(0, idx2, Common::Point(0, 0));
516 			cast2[idx1 - 1].draw(0, idx2, Common::Point(0, 100));
517 			WAIT(3);
518 		}
519 	}
520 
521 	// Fade in of Alamar
522 	for (int idx = 0; idx < 16; ++idx) {
523 		LOAD_VORTEX;
524 
525 		if (idx < 7)
526 			darkLord[0].draw(0, idx);
527 		else if (idx < 11)
528 			darkLord[1].draw(0, idx - 7);
529 		else
530 			darkLord[2].draw(0, idx - 11);
531 
532 		switch (cloudsCtr - 1) {
533 		case 0:
534 		case 4:
535 		case 8:
536 		case 14:
537 			sound.playFX(34);
538 			break;
539 		case 1:
540 		case 6:
541 		case 9:
542 		case 12:
543 			sound.playFX(33);
544 			break;
545 		default:
546 			break;
547 		}
548 
549 		WAIT(3);
550 	}
551 	sound.setMusicPercent(60);
552 	_subtitles.setLine(11);
553 
554 	// Alamar's monologue
555 	for (int idx = 0; idx < (sound._subtitles ? 4 : 3); ++idx) {
556 		switch (idx) {
557 		case 0:
558 			// You have defeated my general, Lord Xeen
559 			sound.playVoice("dark1.voc");
560 			break;
561 		case 1:
562 			// And foiled my plans to conquer this world
563 			sound.playVoice("dark2.voc");
564 			break;
565 		case 2:
566 			// But the Dark Side will always be mine
567 			sound.playVoice("dark3.voc");
568 			break;
569 		default:
570 			// Laugh
571 			sound.playVoice("darklaff.voc");
572 			sound.setMusicPercent(75);
573 			break;
574 		}
575 
576 		do {
577 			LOAD_VORTEX;
578 			darkLord[2].draw(0, getSpeakingFrame(2, 6));
579 
580 			switch (cloudsCtr - 1) {
581 			case 0:
582 			case 4:
583 			case 8:
584 			case 14:
585 				sound.playFX(34);
586 				break;
587 			case 1:
588 			case 6:
589 			case 9:
590 			case 12:
591 				sound.playFX(33);
592 				break;
593 			default:
594 				break;
595 			}
596 
597 			_subtitles.show();
598 			WAIT(3);
599 		} while (sound.isSoundPlaying() || (idx == 3 && _subtitles.active()));
600 	}
601 
602 	if (!sound._subtitles) {
603 		// Laugh
604 		sound.playVoice("darklaff.voc");
605 		sound.setMusicPercent(75);
606 	}
607 
608 	// Alamar fade out
609 	for (int idx = 12; idx >= 0; --idx) {
610 		LOAD_VORTEX;
611 
612 		if (idx < 7)
613 			darkLord[0].draw(0, idx);
614 		else if (idx < 11)
615 			darkLord[1].draw(0, idx - 7);
616 		else
617 			darkLord[2].draw(0, idx - 11);
618 
619 		switch (cloudsCtr - 1) {
620 		case 0:
621 		case 4:
622 		case 8:
623 		case 14:
624 			sound.playFX(34);
625 			break;
626 		case 1:
627 		case 6:
628 		case 9:
629 		case 12:
630 			sound.playFX(33);
631 			break;
632 		default:
633 			break;
634 		}
635 
636 		WAIT(3);
637 	}
638 
639 	sound.stopSound();
640 	sound.playSong("endgame.m");
641 	screen.fadeOut();
642 	return true;
643 }
644 
showCloudsEnding2()645 bool CloudsCutscenes::showCloudsEnding2() {
646 	Screen &screen = *_vm->_screen;
647 	Sound &sound = *_vm->_sound;
648 
649 	SpriteResource king("king.end"), people("people.end"), crodo("crodo.end"),
650 		kingCord("kingcord.end");
651 
652 	// Later at Castle Burlock
653 	screen.loadPalette("endgame.pal");
654 	screen.loadBackground("later.raw");
655 	screen.fadeIn();
656 	WAIT(100);
657 	screen.fadeOut();
658 
659 	// Horizontal pan to the right within throne room
660 	screen.loadBackground("throne1.raw");
661 	screen.loadPage(0);
662 	screen.loadBackground("throne2.raw");
663 	screen.loadPage(1);
664 
665 	int xp2 = SCREEN_WIDTH;
666 	bool fadeFlag = true;
667 	for (int ctr = SCREEN_WIDTH, xp1 = 117, xp3 = 0; ctr > 0; --ctr, xp1 -=   2, ++xp3) {
668 		screen.horizMerge(xp3);
669 		people.draw(0, 0, Common::Point(xp1, 68), SPRFLAG_800);
670 		if (xp3 > 250) {
671 			crodo.draw(0, 0, Common::Point(xp2, 68), SPRFLAG_800);
672 			xp2 -= 2;
673 			if (xp2 < 181)
674 				xp2 = 181;
675 		}
676 
677 		if (ctr % 2) {
678 			WAIT(1);
679 		}
680 		if (fadeFlag) {
681 			screen.fadeIn();
682 			fadeFlag = false;
683 		}
684 	}
685 
686 	screen.horizMerge(SCREEN_WIDTH);
687 	crodo.draw(0, 0, Common::Point(xp2, 68), SPRFLAG_800);
688 	screen.freePages();
689 	WAIT(5);
690 
691 	Graphics::ManagedSurface savedBg;
692 	savedBg.blitFrom(screen);
693 
694 	// Close up of King Roland
695 	const int XLIST1[13] = { 0, -5, -10, -15, -20, -25, -30, -33, -27, -22, -17 };
696 	const int XLIST2[13] = { 160, 145, 130, 115, 100, 85, 70, 57, 53, 48, 42, 39, 34 };
697 	const int YLIST[13] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4 };
698 
699 	for (int idx = 12; idx >= 0; --idx) {
700 		screen.blitFrom(savedBg);
701 		king.draw(0, 0, Common::Point(XLIST1[idx], YLIST[idx]), 0, idx);
702 		king.draw(0, 1, Common::Point(XLIST2[idx], YLIST[idx]), 0, idx);
703 		WAIT(1);
704 	}
705 
706 	// Congratulations adventurers
707 	const char *const VOC_NAMES[3] = { "king1.voc", "king2.voc", "king3.voc" };
708 	_subtitles.setLine(12);
709 	for (int idx = 0; idx < 3; ++idx) {
710 		sound.playVoice(VOC_NAMES[idx]);
711 
712 		do {
713 			king.draw(0, 0, Common::Point(0, 0));
714 			king.draw(0, 1, Common::Point(160, 0));
715 
716 			int frame = getSpeakingFrame(1, 6);
717 			if (frame > 1)
718 				king.draw(0, frame);
719 
720 			_subtitles.show();
721 			WAIT(3);
722 		} while (sound.isSoundPlaying() || (idx == 2 && _subtitles.active()));
723 
724 		king.draw(0, 0, Common::Point(0, 0));
725 		king.draw(0, 1, Common::Point(160, 0));
726 		WAIT(1);
727 	}
728 
729 	screen.fadeOut();
730 	return true;
731 }
732 
733 const byte MONSTER_INDEXES[73] = {
734 	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 76,
735 	23, 16, 17, 80, 19, 20, 83, 22, 24, 25, 26, 27, 28, 29, 30,
736 	31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 42, 43, 44, 45, 84,
737 	47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62,
738 	63, 64, 65, 66, 67, 68, 70, 71, 72, 73, 75, 88, 89
739 };
740 const int8 XARRAY[8] = { -2, -1, 0, 1, 2, 1, 0, -1 };
741 const int8 YARRAY[8] = { -2, 0, 2, 0, -1, 0, 2, 0 };
742 
showCloudsEnding3()743 bool CloudsCutscenes::showCloudsEnding3() {
744 	Map &map = *_vm->_map;
745 	Screen &screen = *_vm->_screen;
746 	Sound &sound = *_vm->_sound;
747 	SpriteResource monSprites, attackSprites;
748 	SpriteResource kingCord("kingcord.end"), room("room.end"), bigSky("bigsky.end");
749 	Graphics::ManagedSurface savedBg;
750 	int counter1 = 0;
751 
752 	// Show the mirror room
753 	screen.loadPalette("mirror.pal");
754 	screen.loadBackground("miror-s.raw");
755 	screen.loadPage(0);
756 	screen.loadPage(1);
757 
758 	room.draw(0, 0, Common::Point(0, 0));
759 	room.draw(0, 1, Common::Point(160, 0));
760 	screen.fadeIn();
761 
762 	for (int idx = 0; idx < 83; ++idx) {
763 		screen.horizMerge(idx);
764 		room.draw(0, 0, Common::Point(0, 0));
765 		room.draw(0, 1, Common::Point(160, 0));
766 		WAIT(1);
767 	}
768 
769 	// Zooming into the mirror
770 	screen.freePages();
771 	savedBg.blitFrom(screen);
772 
773 	const int XLIST3[9] = { 0, -5, -10, -15, -24, -30, -39, -50, -59 };
774 	const int YLIST3[9] = { 0, 12, 25, 37, 46, 52, 59, 64, 68 };
775 	for (int idx = 8; idx >= 0; --idx) {
776 		screen.blitFrom(savedBg);
777 		bigSky.draw(0, 0, Common::Point(XLIST3[idx], YLIST3[idx]), 0, idx);
778 		_mirrBack.draw(0, 0, Common::Point(XLIST3[idx], YLIST3[idx]), 0, idx);
779 		WAIT(1);
780 	}
781 
782 	// Roland and Crodo moving in to look at mirror
783 	const int DELTA = 2;
784 	for (int idx = 0, xc1 = -115, yp = SCREEN_HEIGHT, xc2 = 335;
785 	idx < 115; idx += DELTA, xc1 += DELTA, yp -= DELTA, xc2 -= DELTA) {
786 		ROTATE_BG;
787 
788 		_mirrBack.draw(0, 0);
789 		_mirror.draw(0, 0);
790 		kingCord.draw(0, 0, Common::Point(xc1, yp), SPRFLAG_800);
791 		kingCord.draw(0, 1, Common::Point(xc2, yp), SPRFLAG_800);
792 		WAIT(1);
793 	}
794 
795 	ROTATE_BG;
796 	_mirrBack.draw(0, 0);
797 	_mirror.draw(0, 0);
798 	kingCord.draw(0, 0, Common::Point(0, 85), SPRFLAG_800);
799 	kingCord.draw(0, 1, Common::Point(220, 85), SPRFLAG_800);
800 
801 	// Loop through showing each monster
802 	for (int monsterCtr = 0; monsterCtr < 73; ++monsterCtr) {
803 		MonsterStruct &mon = map._monsterData[MONSTER_INDEXES[monsterCtr]];
804 		monSprites.load(Common::String::format("%03d.mon", mon._imageNumber));
805 		attackSprites.load(Common::String::format("%03d.att", mon._imageNumber));
806 
807 		for (int frameCtr = 0; frameCtr < 8; ++frameCtr) {
808 			ROTATE_BG;
809 			counter1 = (counter1 + 1) % 8;
810 			Common::Point monPos(31, 10);
811 			if (mon._flying) {
812 				monPos.x += XARRAY[counter1];
813 				monPos.y += YARRAY[counter1];
814 			}
815 
816 			_mirrBack.draw(0, 0);
817 			monSprites.draw(0, frameCtr, monPos);
818 			_mirror.draw(0, 0);
819 			kingCord.draw(0, 0, Common::Point(0, 85), SPRFLAG_800);
820 			kingCord.draw(0, 1, Common::Point(220, 85), SPRFLAG_800);
821 			WAIT(1);
822 		}
823 
824 		for (int frameCtr = 0; frameCtr < 3; ++frameCtr) {
825 			if (frameCtr == 2)
826 				sound.playVoice(Common::String::format("%s.voc", mon._attackVoc.c_str()));
827 
828 			ROTATE_BG;
829 			counter1 = (counter1 + 1) % 8;
830 			Common::Point monPos(31, 10);
831 			if (mon._flying) {
832 				monPos.x += XARRAY[counter1];
833 				monPos.y += YARRAY[counter1];
834 			}
835 
836 			_mirrBack.draw(0, 0);
837 			attackSprites.draw(0, frameCtr, monPos);
838 			_mirror.draw(0, 0);
839 			kingCord.draw(0, 0, Common::Point(0, 85), SPRFLAG_800);
840 			kingCord.draw(0, 1, Common::Point(220, 85), SPRFLAG_800);
841 			WAIT(1);
842 		}
843 
844 		for (int idx = 0; idx < 15; ++idx) {
845 			ROTATE_BG;
846 			counter1 = (counter1 + 1) % 8;
847 			Common::Point monPos(31, 10);
848 			if (mon._flying) {
849 				monPos.x += XARRAY[counter1];
850 				monPos.y += YARRAY[counter1];
851 			}
852 
853 			_mirrBack.draw(0, 0);
854 			attackSprites.draw(0, 2, monPos);
855 			_mirror.draw(0, 0);
856 			kingCord.draw(0, 0, Common::Point(0, 85), SPRFLAG_800);
857 			kingCord.draw(0, 1, Common::Point(220, 85), SPRFLAG_800);
858 			WAIT(1);
859 		}
860 
861 		int powNum = getSpeakingFrame(0, 5);
862 		sound.stopSound();
863 		sound.playSound(Common::String::format("pow%d.voc", powNum));
864 
865 		for (int idx = 0; idx < 7; ++idx) {
866 			ROTATE_BG;
867 			counter1 = (counter1 + 1) % 8;
868 			Common::Point monPos(31, 10);
869 			if (mon._flying) {
870 				monPos.x += XARRAY[counter1];
871 				monPos.y += YARRAY[counter1];
872 			}
873 
874 			_mirrBack.draw(0, 0);
875 			attackSprites.draw(0, 2, monPos);
876 			_mirror.draw(0, 0);
877 			kingCord.draw(0, 0, Common::Point(0, 85), SPRFLAG_800);
878 			kingCord.draw(0, 1, Common::Point(220, 85), SPRFLAG_800);
879 			WAIT(1);
880 		}
881 	}
882 
883 	doScroll(true, false);
884 	return true;
885 }
886 
showCloudsEnding4(uint finalScore)887 bool CloudsCutscenes::showCloudsEnding4(uint finalScore) {
888 	EventsManager &events = *_vm->_events;
889 	Screen &screen = *_vm->_screen;
890 	Windows &windows = *_vm->_windows;
891 	SpriteResource endText("endtext.end");
892 
893 	ROTATE_BG;
894 	_mirrBack.draw(0, 0);
895 	_mirror.draw(0, 0);
896 	doScroll(false, false);
897 
898 	// Congratulations your final score
899 	for (int idx = 0; idx < 19; ++idx) {
900 		ROTATE_BG;
901 		_mirrBack.draw(0, 0);
902 		_mirror.draw(0, 0);
903 		endText.draw(0, idx);
904 		WAIT(1);
905 	}
906 
907 	// Random animation of score numbers
908 	int frames[10];
909 	const int FRAMEX[10] = { 64, 83, 102, 121, 140, 159, 178, 197, 216, 235 };
910 	for (int idx1 = 0; idx1 < 30; ++idx1) {
911 		for (int idx2 = 0; idx2 < 10; ++idx2)
912 			frames[idx2] = getSpeakingFrame(20, 29);
913 
914 		ROTATE_BG;
915 		_mirrBack.draw(0, 0);
916 		_mirror.draw(0, 0);
917 		endText.draw(0, 19);
918 		for (int idx2 = 0; idx2 < 10; ++idx2)
919 			endText.draw(0, frames[idx2], Common::Point(FRAMEX[idx2], 73));
920 
921 		WAIT(2);
922 	}
923 
924 	// Animate changing the score digits to the actual final score
925 	Common::String scoreStr = Common::String::format("%.10u", finalScore);
926 	for (int idx1 = 0; idx1 < 10; ++idx1) {
927 		for (int idx2 = 0; idx2 < 10; ++idx2)
928 			frames[idx2] = getSpeakingFrame(20, 29);
929 
930 		for (int idx2 = 0; idx2 <= idx1; ++idx2)
931 			frames[9 - idx2] = (byte)scoreStr[9 - idx2] - 28;
932 
933 		ROTATE_BG;
934 		_mirrBack.draw(0, 0);
935 		_mirror.draw(0, 0);
936 		endText.draw(0, 19);
937 
938 		for (int idx2 = 0; idx2 < 10; ++idx2)
939 			endText.draw(0, frames[idx2], Common::Point(FRAMEX[idx2], 73));
940 
941 		WAIT(2);
942 	}
943 
944 	// Move the score vertically down
945 	for (int idx1 = 0; idx1 < 38; ++idx1) {
946 		ROTATE_BG;
947 		_mirrBack.draw(0, 0);
948 		_mirror.draw(0, 0);
949 		endText.draw(0, 19);
950 
951 		for (int idx2 = 0; idx2 < 10; ++idx2)
952 			endText.draw(0, frames[idx2], Common::Point(FRAMEX[idx2], 73 + idx1));
953 
954 		WAIT(1);
955 	}
956 
957 	// Show two screens worth of text, with prompt to press a key
958 	windows[28].setBounds(Common::Rect(63, 60, 254, 160));
959 
960 	for (int idx = 1; idx <= 2; ++idx) {
961 		events.clearEvents();
962 		do {
963 			ROTATE_BG;
964 			_mirrBack.draw(0, 0);
965 			_mirror.draw(0, 0);
966 			endText.draw(0, 19);
967 
968 			for (int idx2 = 0; idx2 < 10; ++idx2)
969 				endText.draw(0, frames[idx2], Common::Point(FRAMEX[idx2], 110));
970 			windows[28].writeString(idx == 1 ? Res.CLOUDS_CONGRATULATIONS1 :
971 				Res.CLOUDS_CONGRATULATIONS2);
972 
973 			events.updateGameCounter();
974 			events.wait(1, false);
975 		} while (!events.isKeyMousePressed());
976 	}
977 
978 	doScroll(true, false);
979 	screen.fadeOut();
980 
981 	return true;
982 }
983 
showCloudsEnding5()984 bool CloudsCutscenes::showCloudsEnding5() {
985 	Screen &screen = *_vm->_screen;
986 	Sound &sound = *_vm->_sound;
987 	SpriteResource king("king.end");
988 
989 	king.draw(0, 0, Common::Point(0, 0));
990 	king.draw(0, 1, Common::Point(160, 0));
991 	screen.fadeIn();
992 	_subtitles.setLine(13);
993 
994 	sound.playVoice("king4.voc");
995 	do {
996 		king.draw(0, 0, Common::Point(0, 0));
997 		king.draw(0, 1, Common::Point(160, 0));
998 		int frame = getSpeakingFrame(1, 6);
999 		if (frame > 1)
1000 			king.draw(0, frame);
1001 
1002 		WAIT(3);
1003 	} while (sound.isSoundPlaying() || _subtitles.active());
1004 
1005 	king.draw(0, 0, Common::Point(0, 0));
1006 	king.draw(0, 1, Common::Point(160, 0));
1007 	WAIT(1);
1008 	return true;
1009 }
1010 
loadScreen(const Common::String & name)1011 void CloudsCutscenes::loadScreen(const Common::String &name) {
1012 	Screen &screen = *_vm->_screen;
1013 	File fSrc(name);
1014 	byte *destP = (byte *)screen.getPixels();
1015 	byte *destEndP = (byte *)destP + SCREEN_WIDTH * SCREEN_HEIGHT;
1016 
1017 	// Setup reference arrays
1018 	#define ARRAY_SIZE 314
1019 	#define ARRAY_LAST1 ((ARRAY_SIZE - 1) * 2)
1020 	#define ARRAY_LAST2 ((ARRAY_SIZE - 1) * 2 + 1)
1021 	#define BUFFER_SIZE 0x1000
1022 	uint array2[ARRAY_SIZE * 2], array3[ARRAY_SIZE * 2];
1023 	uint array4[ARRAY_SIZE * 3];
1024 	byte buffer[BUFFER_SIZE];
1025 
1026 	for (int idx = 0; idx < ARRAY_SIZE; ++idx) {
1027 		array3[idx] = 1;
1028 		array4[idx + 627] = idx * 2;
1029 		array2[idx] = idx * 2 + (ARRAY_SIZE * 4 - 2);
1030 	}
1031 
1032 	for (int ctr = 0, idx = 0, idx2 = ARRAY_SIZE; ctr < (ARRAY_SIZE - 1); ++ctr, idx += 2, ++idx2) {
1033 		array3[idx2] = array3[idx] + array3[idx + 1];
1034 		array2[idx2] = idx * 2;
1035 		array4[idx] = array4[idx + 1] = idx2 * 2;
1036 	}
1037 	array4[ARRAY_LAST1] = 0;
1038 	array3[ARRAY_LAST2] = (uint)-1;
1039 	array2[ARRAY_LAST2] = 4036;
1040 	uint16 bits = 0x8000;
1041 
1042 	// Get the decompressed size and default buffer contents
1043 	uint16 bytePair;
1044 	fSrc.read((byte *)&bytePair, 2);
1045 	Common::fill((uint16 *)buffer, (uint16 *)(buffer + BUFFER_SIZE),
1046 		bytePair);
1047 
1048 	int count = fSrc.readUint16BE();
1049 	assert(count == (SCREEN_WIDTH * SCREEN_HEIGHT));
1050 
1051 	for (int byteIdx = 0; byteIdx < count; ) {
1052 		assert(fSrc.pos() < fSrc.size());
1053 
1054 		int vMin = array2[(ARRAY_SIZE - 1) * 2];
1055 		int vThreshold = ARRAY_SIZE * 4 - 2;
1056 		while (vMin < vThreshold) {
1057 			bool flag = (bits & 0x8000);
1058 			bits <<= 1;
1059 
1060 			if (!bits) {
1061 				bits = fSrc.readUint16BE();
1062 				flag = (bits & 0x8000);
1063 				bits = (bits << 1) | 1;
1064 			}
1065 
1066 			vMin = array2[vMin / 2 + (flag ? 1 : 0)];
1067 		}
1068 
1069 		vMin -= vThreshold;
1070 
1071 		if (array3[ARRAY_LAST1] == 0x8000) {
1072 			for (int ctr = 0, ctr2 = 0; ctr < (ARRAY_SIZE * 2); ++ctr) {
1073 				if (array2[ctr] >= (ARRAY_SIZE * 4 - 1)) {
1074 					array3[ctr2] = (array3[ctr] + 1) / 2;
1075 					array2[ctr2] = array2[ctr];
1076 					++ctr2;
1077 				}
1078 			}
1079 
1080 			for (int ctr = 0, ctr2 = ARRAY_SIZE; ctr < ARRAY_SIZE; ctr += 2, ++ctr2) {
1081 				int currVal = array3[ctr] + array3[ctr + 1];
1082 				array3[ctr2] = currVal;
1083 				int ctr3 = ctr2;
1084 				do {
1085 					--ctr3;
1086 				} while (array3[ctr3] >= array3[ctr2]);
1087 				++ctr3;
1088 
1089 				int diff = ctr2 - ctr3;
1090 				uint *pDest = &array3[ctr2];
1091 				Common::copy(pDest - 1, pDest - 1 + diff, pDest);
1092 				array3[ctr3] = currVal;
1093 
1094 				pDest = &array2[ctr2];
1095 				Common::copy(pDest - 1, pDest - 1 + diff, pDest);
1096 				array2[ctr3] = ctr * 2;
1097 			}
1098 
1099 			uint *arrEndP = &array4[ARRAY_SIZE * 2 - 1];
1100 			for (int ctr = 0, val = 0; ctr < ARRAY_SIZE * 2; ++ctr, val += 2) {
1101 				uint *arrP = &array4[array2[ctr] / 2];
1102 				if (arrP < arrEndP)
1103 					*arrP = val;
1104 			}
1105 		}
1106 
1107 		int offset = array4[627 + vMin / 2] / 2;
1108 		do {
1109 			int offset2 = offset;
1110 			uint val = ++array3[offset2];
1111 			if (val > array3[offset2 + 1]) {
1112 				while (val > array3[++offset2])
1113 					;
1114 				--offset2;
1115 
1116 				array3[offset] = array3[offset2];
1117 				array3[offset2] = val;
1118 
1119 				int offset3 = array2[offset] / 2;
1120 				array4[offset3] = offset2 * 2;
1121 				if ((offset3 * 2) < (ARRAY_SIZE * 4 - 2))
1122 					array4[offset3 + 1] = offset2 * 2;
1123 
1124 				int offset4 = array2[offset2] / 2;
1125 				array2[offset2] = offset3 * 2;
1126 				array4[offset4] = offset * 2;
1127 				if ((offset4 * 2) < (ARRAY_SIZE * 4 - 2))
1128 					array4[offset4 + 1] = offset * 2;
1129 
1130 				array2[offset] = offset4 * 2;
1131 				offset = offset2;
1132 			}
1133 		} while ((offset = array4[offset] / 2) != 0);
1134 
1135 		vMin /= 2;
1136 		if (vMin < 256) {
1137 			// Single byte write to destination
1138 			*destP++ = (byte)vMin;
1139 			int buffOffset = array2[ARRAY_LAST2];
1140 			array2[ARRAY_LAST2] = (buffOffset + 1) & 0xfff;
1141 			buffer[buffOffset] = (byte)vMin;
1142 			++byteIdx;
1143 			continue;
1144 		}
1145 
1146 		uint16 bitsLow = bits, bitsHigh = 0;
1147 		for (int ctr = 8; ctr > 0; --ctr) {
1148 			bool highBit = bitsLow & 0x8000;
1149 			bitsLow <<= 1;
1150 
1151 			if (bitsLow) {
1152 				bitsHigh = (bitsHigh << 1) | (highBit ? 1 : 0);
1153 			} else {
1154 				bitsLow = fSrc.readUint16BE();
1155 
1156 				byte loBit = 1;
1157 				do {
1158 					bitsHigh = (bitsHigh << 1) | ((bitsLow & 0x8000) ? 1 : 0);
1159 					bitsLow = (bitsLow << 1) | (loBit ? 1 : 0);
1160 					loBit = 0;
1161 				} while (--ctr > 0);
1162 				break;
1163 			}
1164 		}
1165 		bits = bitsLow;
1166 
1167 		int t2Val = _DECODE_TABLE2[bitsHigh] << 6;
1168 		int tCount = _DECODE_TABLE1[bitsHigh] - 2;
1169 
1170 		for (int ctr = 0; ctr < tCount; ++ctr) {
1171 			bool highBit = bits & 0x8000;
1172 			bits <<= 1;
1173 			if (!bits) {
1174 				bits = fSrc.readUint16BE();
1175 				highBit = bits & 0x8000;
1176 				bits = (bits << 1) | 1;
1177 			}
1178 
1179 			bitsHigh = (bitsHigh << 1) | (highBit ? 1 : 0);
1180 		}
1181 
1182 		t2Val |= (bitsHigh & 0x3F);
1183 		uint &last2 = array2[ARRAY_LAST2];
1184 		int buffOffset = last2 - t2Val - 1;
1185 
1186 		for (int ctr = 0; ctr < vMin - 253; ++ctr, ++buffOffset) {
1187 			buffOffset &= 0xfff;
1188 			byte b = buffer[buffOffset];
1189 			*destP++ = b;
1190 
1191 			buffer[last2] = b;
1192 			last2 = (last2 + 1) & 0xfff;
1193 			++byteIdx;
1194 		}
1195 	}
1196 
1197 	assert(destP == destEndP);
1198 	screen.markAllDirty();
1199 }
1200 
1201 const char *const CloudsCutscenes::_INTRO_VOCS[14] = {
1202 	"crodo1.voc", "crodo2.voc", "iamking.voc", "crodo3.voc",
1203 	"ya1.voc", "crodo4a.voc", "crodo4b.voc", "crodo4c.voc",
1204 	"xeenlaff.voc", "tiger2&.voc", "crodo5.voc", "crodo6.voc",
1205 	"xeenlaff.voc", "tiger2&.voc"
1206 };
1207 
1208 const int CloudsCutscenes::_INTRO_FRAMES_LOOKUP[14] = {
1209 	0, 1, 0, 2, 0, 3, 4, 5, 0, 0, 6, 7, 0, 0
1210 };
1211 
1212 const int CloudsCutscenes::_INTRO_FRAMES_VALS[8][32] = {
1213 	{
1214 		4, 2, 3, 0, 2, 3, 2, 0, 1, 1, 3, 4, 3, 2, 4, 2,
1215 		3, 4, 3, 4, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1216 	}, {
1217 		3, 2, 3, 2, 4, 3, 0, 3, 2, 2, 3, 1, 2, 3, 3, 3,
1218 		2, 3, 2, 3, 2, 0, 3, 2, 0, 0, 0, 0, 0, 0, 2, 4
1219 	}, {
1220 		3, 1, 2, 3, 0, 3, 4, 3, 2, 3, 0, 3, 2, 3, 2, 1,
1221 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 3
1222 	}, {
1223 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1224 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 3
1225 	}, {
1226 		4, 2, 2, 3, 2, 3, 3, 4, 2, 4, 2, 0, 3, 2, 3, 2,
1227 		3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 2, 3
1228 	}, {
1229 		2, 0, 2, 3, 2, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1230 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 3, 2, 3, 1
1231 	}, {
1232 		3, 2, 0, 2, 4, 2, 3, 2, 3, 2, 0, 0, 0, 0, 0, 0,
1233 		0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 3, 4, 0, 2
1234 	}, {
1235 		3, 2, 4, 1, 2, 4, 3, 2, 3, 0, 2, 2, 0, 3, 2, 3,
1236 		2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1237 	}
1238 };
1239 
1240 const uint CloudsCutscenes::_INTRO_FRAMES_WAIT[8][32] = {
1241 	{
1242 		 2,  5,  6,  9, 10, 11, 12, 13, 14, 23, 25, 29, 31, 35, 38, 41,
1243 		42, 45, 50, 52, 55, 56, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0
1244 	}, {
1245 		 1,  4,  6,  8,  9, 11, 13, 15, 17, 18, 19, 22, 28, 29, 30, 31,
1246 		 0, 39,  0, 44,  0, 50, 51,  0, 54,  0,  0,  0,  0,  0,  0,  4
1247 	}, {
1248 		 6,  9, 11, 13, 15, 19, 21, 23, 25, 27, 28, 31, 35, 39, 40,  0,
1249 		 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  5,  7
1250 	}, {
1251 		 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1252 		 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  3,  4
1253 	}, {
1254 		 5,  9, 10, 11, 13, 15, 18, 23, 26, 31, 33, 36, 37, 41, 43, 45,
1255 		48,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0, 12
1256 	}, {
1257 		14, 17, 20, 23, 27, 29,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1258 		 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  4,  8, 11, 13
1259 	}, {
1260 		15, 16, 17, 19, 21, 24, 24, 27, 34, 35,  0,  0,  0,  0,  0,  0,
1261 		 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  5,  7, 10, 11, 13
1262 	}, {
1263 		17, 19, 22, 23, 26, 30, 32, 34, 40, 43, 47, 52, 53, 55, 57, 60,
1264 		62,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
1265 	}
1266 };
1267 
1268 const byte CloudsCutscenes::_DECODE_TABLE1[256] = {
1269 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1270 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1271 	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1272 	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1273 	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1274 	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1275 	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1276 	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1277 	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1278 	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1279 	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1280 	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1281 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1282 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1283 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1284 	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
1285 };
1286 
1287 const byte CloudsCutscenes::_DECODE_TABLE2[256] = {
1288 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1289 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1290 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1291 	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1292 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1293 	4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
1294 	6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
1295 	8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
1296 	10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11,
1297 	12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15,
1298 	16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19,
1299 	20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,
1300 	24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
1301 	32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
1302 	40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47,
1303 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
1304 };
1305 
1306 } // End of namespace WorldOfXeen
1307 } // End of namespace Xeen
1308