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 
24 #include "common/endian.h"
25 #include "common/util.h"
26 #include "common/events.h"
27 #include "common/system.h"
28 #include "common/textconsole.h"
29 
30 #include "sky/disk.h"
31 #include "sky/intro.h"
32 #include "sky/music/musicbase.h"
33 #include "sky/screen.h"
34 #include "sky/sky.h"
35 #include "sky/sound.h"
36 #include "sky/struc.h"
37 #include "sky/text.h"
38 
39 #include "audio/audiostream.h"
40 #include "audio/decoders/raw.h"
41 
42 namespace Sky {
43 
44 #define SHOWSCREEN		 0
45 #define COMMANDEND		 0 // end of COMMANDFLIRT block
46 #define FADEUP			 1 // fade up palette
47 #define FADEDOWN		 2
48 #define DELAY			 3
49 #define DOFLIRT			 4 // start flirt sequence (and wait for it to finish)
50 #define SCROLLFLIRT		 5 // start special floppy intro flirt sequence (and wait for it)
51 #define COMMANDFLIRT	 6 // start flirt sequence and wait for it, while processing command block
52 #define BGFLIRT			 7 // start flirt sequence without waiting for it
53 #define WAITFLIRT		 8 // wait for sequence started by BGFLIRT
54 #define STOPFLIRT		 9
55 #define STARTMUSIC		10
56 #define WAITMUSIC		11
57 #define PLAYVOICE		12
58 #define WAITVOICE		13
59 #define LOADBG			14 // load new background sound
60 #define PLAYBG			15 // play background sound
61 #define LOOPBG			16 // loop background sound
62 #define STOPBG			17 // stop background sound
63 #define CLEARBOTTOM		18 // clear the screen
64 #define SEQEND		 65535 // end of intro sequence
65 
66 // Modifier flag for SHOWSCREEN when we want the image to cover the entire
67 // screen.
68 #define FULLSCREEN		0x8000
69 
70 #define IC_PREPARE_TEXT 20 // commands used in COMMANDFLIRT block
71 #define IC_SHOW_TEXT    21
72 #define IC_REMOVE_TEXT  22
73 #define IC_MAKE_SOUND   23
74 #define IC_FX_VOLUME    24
75 
76 #define FRAME_SIZE (GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT)
77 #define INTRO_TEXT_WIDTH 128
78 //CD intro file defines
79 #define CDV_00	59500
80 #define CD_PAL	59501
81 #define CD_1_LOG	59502
82 #define CD_1	59503
83 #define CDV_01	59504
84 #define CDV_02	59505
85 #define CD_2	59506
86 #define CDV_03	59507
87 #define CDV_04	59508
88 #define CD_3	59509
89 #define CDV_05	59510
90 #define CDV_06	59511
91 #define CD_5	59512
92 #define CDV_07	59513
93 #define CDV_08	59514
94 #define CDV_09	59515
95 #define CD_7	59516
96 #define CDV_10	59518
97 #define CD_11	59519
98 #define CDV_11	59520
99 #define CD_11_PAL	59521
100 #define CD_11_LOG	59522
101 #define CDV_12	59523
102 #define CD_13	59524
103 #define CDV_13	59525
104 #define CDV_14	59527
105 #define CDV_15	59528
106 #define CD_15_PAL	59529
107 #define CD_15_LOG	59530
108 #define CDV_16	59531
109 #define CD_17_LOG	59532
110 #define CD_17	59533
111 #define CDV_17	59534
112 #define CDV_18	59535
113 #define CDV_19	59536
114 #define CD_19_PAL	59537
115 #define CD_19_LOG	59538
116 #define CDV_20	59539
117 #define CD_20_LOG	59540
118 #define CDV_21	59541
119 #define CD_21_LOG	59542
120 #define CDV_22	59545
121 #define CDV_23	59546
122 #define CD_23_PAL	59547
123 #define CD_24_LOG	59550
124 #define CDV_24	59551
125 #define CDV_25	59554
126 #define CDV_26	59556
127 #define CD_27	59557
128 #define CDV_27	59558
129 #define CD_27_PAL	59559
130 #define CD_27_LOG	59560
131 #define CDV_28	59561
132 #define CDV_29	59562
133 #define CDV_30	59563
134 #define CDV_31	59565
135 #define CDV_32	59566
136 #define CDV_33	59567
137 #define CDV_34	59568
138 #define CD_35	59569
139 #define CDV_35	59570
140 #define CD_35_PAL	59571
141 #define CD_35_LOG	59572
142 #define CDV_36	59574
143 #define CD_37	59575
144 #define CDV_37	59576
145 #define CD_37_PAL	59577
146 #define CD_37_LOG	59578
147 #define CDV_38	59579
148 #define CDV_39	59581
149 #define CDV_40	59583
150 #define CD_40_PAL	59584
151 #define CD_40_LOG	59585
152 #define CDV_41	59587
153 #define CDV_42	59588
154 #define CD_43	59589
155 #define CDV_43	59590
156 #define CD_43_PAL	59591
157 #define CD_43_LOG	59592
158 #define CDV_44	59594
159 #define CD_45	59595
160 #define CDV_45	59596
161 #define CD_45_PAL	59597
162 #define CD_45_LOG	59598
163 #define CDV_46	59600
164 #define CDV_47	59602
165 #define CD_47_PAL	59603
166 #define CD_47_LOG	59604
167 #define CD_48	59605
168 #define CDV_48	59606
169 #define CD_48_PAL	59607
170 #define CD_48_LOG	59608
171 #define CD_49	59609
172 #define CDV_49	59610
173 #define CD_50	59611
174 #define CDV_50	59612
175 #define CDV_51	59613
176 #define CDV_52	59614
177 #define CDV_53	59615
178 #define CDV_54	59616
179 #define CDV_55	59618
180 #define CD_55_PAL	59619
181 #define CD_55_LOG	59620
182 #define CDV_56	59621
183 #define CDV_57	59622
184 #define CD_58	59623
185 #define CDV_58	59624
186 #define CD_58_PAL	59625
187 #define CD_58_LOG	59626
188 #define CDV_59	59627
189 #define CDV_60	59628
190 #define CDV_61	59629
191 #define CDV_62	59630
192 #define CDV_63	59631
193 #define CDV_64	59632
194 #define CDV_65	59633
195 #define CDV_66	59635
196 #define CD_66_PAL	59636
197 #define CD_66_LOG	59637
198 #define CDV_67	59639
199 #define CD_67_PAL	59640
200 #define CD_67_LOG	59641
201 #define CDV_68	59642
202 #define CD_69	59643
203 #define CDV_69	59644
204 #define CD_69_PAL	59645
205 #define CD_69_LOG	59646
206 #define CDV_70	59647
207 #define CDV_71	59648
208 #define CDV_72	59649
209 #define CD_72_PAL	59650
210 #define CD_72_LOG	59651
211 #define CD_73_PAL	59652
212 #define CD_73_LOG	59653
213 #define CDV_73	59654
214 #define CDV_74	59655
215 #define CDV_75	59656
216 #define CD_76_PAL	59657
217 #define CD_76_LOG	59658
218 #define CDV_76	59659
219 #define CDV_77	59660
220 #define CD_78_PAL	59661
221 #define CD_78_LOG	59662
222 #define CDV_78	59663
223 #define CDV_79	59664
224 #define CDV_80	59665
225 #define CDV_81	59666
226 #define CDV_82	59667
227 #define CDV_83	59668
228 #define CDV_84	59669
229 #define CDV_85	59670
230 #define CDV_86	59671
231 #define CDV_87	59672
232 #define CD_100	60087
233 #define CD_101_LOG	60088
234 #define CD_101	60099
235 #define CD_102_LOG	60090
236 #define CD_102	60091
237 #define CD_103_PAL	60092
238 #define CD_103_LOG	60093
239 #define CD_103	60094
240 #define CD_104_PAL	60095
241 #define CD_104_LOG	60096
242 #define CD_104	60097
243 #define CD_105	60098
244 
245 
246 uint16 Intro::_mainIntroSeq[] = {
247 	DELAY,       3000, // keep virgin screen up
248 	FADEDOWN,
249 	SHOWSCREEN, 60112, // revo screen + palette
250 	FADEUP,     60113,
251 	DELAY,       8000,
252 	FADEDOWN,
253 	SHOWSCREEN, 60114, // gibbo screen + palette
254 	FADEUP,     60115,
255 	DELAY,       2000,
256 	FADEDOWN,
257 	SEQEND
258 };
259 
260 uint16 Intro::_cdIntroSeq[] = {
261 	/* black screen */
262 	PLAYVOICE,	CDV_00,	// Foster: "The old man was trying to tell the future. Looking for pictures in the campfire..."
263 	LOADBG,		59499,	// Fire crackle
264 	LOOPBG,
265 	WAITVOICE,
266 	PLAYVOICE,	CDV_01,	// Shaman: "ohhh, I see evil..."
267 	/* Fade up shaman image while he says his line... */
268 	SHOWSCREEN,	CD_1_LOG,
269 	FADEUP,		CD_PAL,
270 	/* And then play the animation showing the shadows of the fire on his face */
271 	BGFLIRT,	CD_1,
272 		WAITVOICE,
273 		PLAYVOICE,	CDV_02,	// Shaman: "Evil born deep beneath the city... far from the light of day."
274 		WAITVOICE,
275 	STOPFLIRT,
276 	BGFLIRT,	CD_2,
277 		PLAYVOICE,	CDV_03, // Shaman: "I see it growing, safe beneath a sky of steel..."
278 		WAITVOICE,
279 		PLAYVOICE,	CDV_04, // Shaman: "Scheming in the dark... gathering strength."
280 	WAITFLIRT,
281 	WAITVOICE,
282 	PLAYVOICE,	CDV_05,		// Shaman: "And now... ohhh.... now the evil spreads..."
283 	DELAY,		2000,
284 	BGFLIRT,	CD_3,
285 		WAITVOICE,
286 		PLAYVOICE,	CDV_06,	// Shaman: "It sends deadly feelers over the land above..."
287 	WAITFLIRT,
288 	WAITVOICE,
289 	PLAYVOICE,	CDV_07,		// Shaman: "Across the gap... reaching towards this very place!"
290 	BGFLIRT,	CD_5,
291 		WAITVOICE,
292 		PLAYVOICE,	CDV_08,	// Foster: "I'd seen him do this a hundred times, but I humoured him."
293 		WAITVOICE,
294 		PLAYVOICE,	CDV_09,	// Foster: "After all, he'd been like a father to me."
295 	WAITFLIRT,
296 	WAITVOICE,
297 	PLAYVOICE,	CDV_10,		// Foster: "And what does this evil want here?"
298 	BGFLIRT,	CD_7,
299 		WAITVOICE,
300 		PLAYVOICE,	CDV_11, // Shaman: "Oh, my son. I fear..."
301 	WAITFLIRT,
302 	FADEDOWN,
303 	SHOWSCREEN,	CD_11_LOG,
304 	FADEUP,		CD_11_PAL,
305 	WAITVOICE,
306 	PLAYVOICE,	CDV_12,		// Shaman: "I fear the evil wants you!"
307 	DELAY,		1600,
308 	BGFLIRT,	CD_11,
309 		WAITVOICE,
310 		PLAYVOICE,	CDV_13,	// Foster: "That was when Joey piped up..."
311 		WAITVOICE,
312 	WAITFLIRT,
313 	WAITVOICE,
314 	PLAYVOICE,	CDV_14,		// Joey: "Foster! Sensors detect incoming audio source!"
315 	LOADBG,		59498, // fire crackle to heli start
316 	PLAYBG,
317 	DOFLIRT,	CD_13,
318 	WAITVOICE,
319 	PLAYVOICE,	CDV_15,		// Shaman: "The evil! The evil is nearly here...!"
320 	FADEDOWN,
321 	SHOWSCREEN,	CD_15_LOG,
322 	FADEUP,		CD_15_PAL,
323 	WAITVOICE,
324 	LOADBG,		59496, // quiet heli
325 	LOOPBG,
326 	PLAYVOICE,	CDV_16,		// Foster: "It sounded more like a 'copter than a demon."
327 	WAITVOICE,
328 	PLAYVOICE,	CDV_17,		// Foster: "But next thing, all hell let loose anyway..."
329 	DELAY,		2000,
330 	SHOWSCREEN,	CD_17_LOG,
331 	WAITVOICE,
332 	BGFLIRT,	CD_17,
333 		PLAYVOICE,	CDV_18,	// Shaman: "Run, Foster! Run! Hide from the evil!"
334 	LOADBG,		59497, // loud heli
335 	LOOPBG,
336 	WAITFLIRT,
337 	WAITVOICE,
338 	FADEDOWN,
339 	SHOWSCREEN | FULLSCREEN,	CD_19_LOG,
340 	FADEUP,		CD_19_PAL,
341 	PLAYVOICE,	CDV_19,		// Joey: "Foster! (zzzt) H-Help!"
342 	WAITVOICE,
343 	PLAYVOICE,	CDV_20,		// Joey: "Better make my next body move faster, Foster..."
344 	FADEDOWN,
345 	SHOWSCREEN | FULLSCREEN,	CD_20_LOG,
346 	FADEUP,		CD_19_PAL,
347 	WAITVOICE,
348 	LOADBG,		59496, // quiet heli
349 	LOOPBG,
350 	PLAYVOICE,	CDV_21,		// Foster: "He was only a robot, but, well, I loved the little guy."
351 	FADEDOWN,
352 	SHOWSCREEN | FULLSCREEN,	CD_21_LOG,
353 	FADEUP,		CD_19_PAL,
354 	WAITVOICE,
355 	PLAYVOICE,	CDV_22,		// Foster: "Then, as suddenly as it started, the shooting stopped."
356 	LOADBG,		59494, // heli whine
357 	PLAYBG,
358 	WAITVOICE,
359 	PLAYVOICE,	CDV_23,		// Foster: "There was a moment's silence as the copter cut its rotors, then..."
360 	/* fade down while Foster's saying his line */
361 	FADEDOWN,
362 	WAITVOICE,
363 	SHOWSCREEN | FULLSCREEN,	CD_24_LOG,
364 	FADEUP,		CD_23_PAL,
365 	PLAYVOICE,	CDV_24,		// Reich: "Whoever is in charge here, come forward..."
366 	WAITVOICE,
367 	PLAYVOICE,	CDV_25,		// Reich: "Now!!"
368 	WAITVOICE,
369 	PLAYVOICE,	CDV_26,		// Foster: "Only a fool would have argued with that firepower."
370 	WAITVOICE,
371 	FADEDOWN,
372 	SHOWSCREEN | FULLSCREEN,	CD_27_LOG,
373 	FADEUP,		CD_27_PAL,
374 	PLAYVOICE,	CDV_27,		// Shaman: "... I am the leader of these people... We are peaceful..."
375 	WAITVOICE,
376 	PLAYVOICE,	CDV_29,		// Reich: "Bring him here."
377 	WAITVOICE,
378 	PLAYVOICE,	CDV_30,		// Guard: "At once, Commander Reich."
379 	WAITVOICE,
380 	BGFLIRT,	CD_27,
381 		PLAYVOICE,	CDV_31,	// Reich: "We're looking for someone..."
382 		WAITFLIRT,
383 		CLEARBOTTOM,
384 		WAITVOICE,
385 		PLAYVOICE,	CDV_32,	// Reich: "Someone who doesn't belong here..."
386 		WAITVOICE,
387 		PLAYVOICE,	CDV_33,	// Reich: "Who wasn't born in this garbage dump..."
388 		WAITVOICE,
389 		PLAYVOICE,	CDV_34,	// Reich: "Who came from the city as a child..."
390 	WAITVOICE,
391 	PLAYVOICE,	CDV_35,		// Reich: "We want to take him home again."
392 	WAITVOICE,
393 	PLAYVOICE,	CDV_36,		// Foster: "My mind racing, I remembered where I'd seen that symbol before..."
394 		FADEDOWN,
395 		SHOWSCREEN | FULLSCREEN,	CD_35_LOG,
396 		FADEUP,		CD_35_PAL,
397 	WAITVOICE,
398 	PLAYVOICE,	CDV_37,		// Foster: "It was the day the tribe found me..."
399 		DOFLIRT,	CD_35,
400 	CLEARBOTTOM,
401 	WAITVOICE,
402 	PLAYVOICE,	CDV_38,		// Foster: "The day of the crash..."
403 		DOFLIRT,	CD_37,
404 	WAITVOICE,
405 	PLAYVOICE,	CDV_39,		// Foster: "The day my mother died."
406 	WAITVOICE,
407 	FADEDOWN,
408 	SHOWSCREEN | FULLSCREEN,	CD_40_LOG,
409 	FADEUP,		CD_40_PAL,
410 	PLAYVOICE,	CDV_40,		// Shaman: "You alright, city boy?"
411 	WAITVOICE,
412 	PLAYVOICE,	CDV_41,		// Shaman: "Got a name, son?"
413 	WAITVOICE,
414 	PLAYVOICE,	CDV_42,		// Foster: "R-Robert."
415 	WAITVOICE,
416 	FADEDOWN,
417 	SHOWSCREEN | FULLSCREEN,	CD_43_LOG,
418 	FADEUP,		CD_43_PAL,
419 	PLAYVOICE,	CDV_43,		// Shaman: "Hah! Welcome to the Gap, Robert!"
420 	WAITVOICE,
421 	DOFLIRT,	CD_43,
422 	PLAYVOICE,	CDV_45,		// Foster: "As he patched me up, the old man had gently explained that there was no way back into the City..."
423 	FADEDOWN,
424 	SHOWSCREEN,	CD_45_LOG,
425 	FADEUP,		CD_45_PAL,
426 	WAITVOICE,
427 	PLAYVOICE,	CDV_46,		// Foster: "And I already knew there was nothing he could do for mother."
428 	DOFLIRT,	CD_45,
429 	WAITVOICE,
430 	FADEDOWN,
431 	SHOWSCREEN | FULLSCREEN,	CD_47_LOG,
432 	FADEUP,		CD_47_PAL,
433 	PLAYVOICE,	CDV_47,		// Foster: "His tribe was poor, but they treated me like one of their own..."
434 	WAITVOICE,
435 	PLAYVOICE,	CDV_48,		// Foster: "I learned how to survive in the wasteland they called the Gap..."
436 	FADEDOWN,
437 	SHOWSCREEN | FULLSCREEN,	CD_48_LOG,
438 	FADEUP,		CD_48_PAL,
439 	WAITVOICE,
440 	BGFLIRT,	CD_48,
441 		PLAYVOICE,	CDV_49,	// Foster: "And scavenging from the City dumps."
442 		WAITVOICE,
443 		PLAYVOICE,	CDV_50,	// Foster: "As the years passed, I forgot my life in the City."
444 	WAITFLIRT,
445 	WAITVOICE,
446 	PLAYVOICE,	CDV_51,		// Foster: "Discovered new talents..."
447 	BGFLIRT,	CD_49,
448 		WAITVOICE,
449 		PLAYVOICE,	CDV_52,	// Foster: "Hah!"
450 		WAITVOICE,
451 		PLAYVOICE,	CDV_53,	// Joey: "I'm your (zzzt) friend... call me (zzzt) Joey."
452 		WAITVOICE,
453 	WAITFLIRT,
454 	PLAYVOICE,	CDV_54,		// Foster: "And got a second name."
455 	DOFLIRT,	CD_50,
456 	WAITVOICE,
457 	PLAYVOICE,	CDV_55,		// Shaman: "This is what we'll call you now you've come of age, son."
458 	WAITVOICE,
459 	PLAYVOICE,	CDV_56,		// Shaman: "We found you... we fostered you..."
460 		FADEDOWN,
461 		SHOWSCREEN,	CD_55_LOG,
462 		FADEUP,		CD_55_PAL,
463 	WAITVOICE,
464 	PLAYVOICE,	CDV_57,		// Shaman: "So that makes you Robert Foster."
465 	WAITVOICE,
466 	FADEDOWN,
467 	SHOWSCREEN,	CD_58_LOG,
468 	FADEUP,		CD_58_PAL,
469 	PLAYVOICE,	CDV_58,		// Reich: "...Wasted enough time!"
470 	WAITVOICE,
471 	PLAYVOICE,	CDV_59,		// Reich: "Give us the runaway or we'll shoot everyone..."
472 	WAITVOICE,
473 	PLAYVOICE,	CDV_60,		// Reich: "Starting with you, grandad!"
474 	WAITVOICE,
475 	PLAYVOICE,	CDV_61,		// Foster: "The old man had been right, for once..."
476 	WAITVOICE,
477 	PLAYVOICE,	CDV_62,		// Foster: "It was me they wanted."
478 	BGFLIRT,	CD_58,
479 		WAITVOICE,
480 		PLAYVOICE,	CDV_63,	// Shaman: "No, my son! Don't let the evil take you! Run!"
481 		WAITVOICE,
482 		PLAYVOICE,	CDV_64,	// Guard: "DNA scan confirms it's him, sir."
483 	WAITFLIRT,
484 	WAITVOICE,
485 	PLAYVOICE,	CDV_65,		// Foster: "Evil had come to the Gap, just as he said."
486 	FADEDOWN,
487 	WAITVOICE,
488 	SHOWSCREEN,	CD_66_LOG,
489 	FADEUP,		CD_66_PAL,
490 	PLAYVOICE,	CDV_66,		// Reich: "Take him."
491 	WAITVOICE,
492 	PLAYVOICE,	CDV_67,		// Foster: "But had the old man seen why it wanted me?"
493 		FADEDOWN,
494 		SHOWSCREEN,	CD_67_LOG,
495 		FADEUP,		CD_67_PAL,
496 	WAITVOICE,
497 	PLAYVOICE,	CDV_68,		// Foster: "Or what it would do next?"
498 	WAITVOICE,
499 	PLAYVOICE,	CDV_69,		// Foster: "It was too late to ask him now."
500 		FADEDOWN,
501 		SHOWSCREEN,	CD_69_LOG,
502 		FADEUP,		CD_69_PAL,
503 	WAITVOICE,
504 	PLAYVOICE,	CDV_70,		// Guard: "Leaving destruction zone, Commander Reich."
505 	DOFLIRT,	CD_69,
506 	WAITVOICE,
507 	FADEDOWN,
508 	PLAYVOICE,	CDV_71,		// Reich: "Good. Detonate."
509 	WAITVOICE,
510 	SHOWSCREEN | FULLSCREEN,	CD_72_LOG,
511 	FADEUP,		CD_72_PAL,
512 	PLAYVOICE,	CDV_72,		// Foster: "Much too late."
513 	WAITVOICE,
514 	FADEDOWN,
515 	SHOWSCREEN | FULLSCREEN,	CD_73_LOG,
516 	FADEUP,		CD_73_PAL,
517 	PLAYVOICE,	CDV_73,		// Foster: "Why, you murdering..."
518 	WAITVOICE,
519 	PLAYVOICE,	CDV_74,		// Reich: "Keep him quiet."
520 	WAITVOICE,
521 	PLAYVOICE,	CDV_75,		// Foster: "All I could do was wait."
522 	FADEDOWN,
523 	SHOWSCREEN | FULLSCREEN,	CD_76_LOG,
524 	FADEUP,		CD_76_PAL,
525 	WAITVOICE,
526 	PLAYVOICE,	CDV_76,		// Foster: "Just like on a hunt. Just like the old man taught me."
527 	WAITVOICE,
528 	PLAYVOICE,	CDV_77,		// Foster: "Wait... and be ready."
529 	WAITVOICE,
530 	FADEDOWN,
531 	CLEARBOTTOM,
532 	SHOWSCREEN,	CD_78_LOG,
533 	FADEUP,		CD_78_PAL,
534 	PLAYVOICE,	CDV_78,		// Foster: "It was dawn when we reached the City."
535 	WAITVOICE,
536 	PLAYVOICE,	CDV_79,		// Reich: "Land in the central Security compound."
537 	WAITVOICE,
538 	PLAYVOICE,	CDV_80,		// Foster: "A dawn my tribe would never see."
539 	BGFLIRT,	CD_100,
540 		WAITVOICE,
541 		PLAYVOICE,	CDV_81,	// Foster: "They were no more than a note in Reich's book now."
542 		WAITVOICE,
543 		PLAYVOICE,	CDV_82,	// Guard: "Yes, sir. Locking on automatic landing beacon."
544 		WAITVOICE,
545 	WAITFLIRT,
546 	SHOWSCREEN,	CD_101_LOG,
547 	BGFLIRT,	CD_101,
548 		PLAYVOICE,	CDV_83,	// Foster: "But what was I? Why did..."
549 		WAITVOICE,
550 		PLAYVOICE,	CDV_84,	// Guard: "Sir! The guidance system! It's gone crazy!"
551 		WAITVOICE,
552 		PLAYVOICE,	CDV_85,	// Guard: "We're going to HIT!"
553 		WAITVOICE,
554 	WAITFLIRT,
555 	CLEARBOTTOM,
556 	SHOWSCREEN,	CD_102_LOG,
557 	PLAYVOICE,	CDV_86,		// Foster: "Maybe I'd get some answers now."
558 	DOFLIRT,	CD_102,
559 	FADEDOWN,
560 	// This one could be fullscreen, but that causes animation glitches.
561 	SHOWSCREEN,	CD_103_LOG,
562 	FADEUP,		CD_103_PAL,
563 	BGFLIRT,	CD_103,
564 	WAITVOICE,
565 	PLAYVOICE,	CDV_87,		// Foster: "If I survived another 'copter crash."
566 	WAITFLIRT,
567 	WAITVOICE,
568 	STARTMUSIC,	2,
569 	FADEDOWN,
570 	SHOWSCREEN | FULLSCREEN,	CD_104_LOG,
571 	FADEUP,		CD_104_PAL,
572 	DOFLIRT,	CD_104,
573 	DOFLIRT,	CD_105,
574 	SEQEND
575 };
576 
577 uint16 Intro::_floppyIntroSeq[] = {
578 	// This one could be fullscreen, but that causes animation glitches.
579 	SHOWSCREEN,   60081,
580 	FADEUP,       60080,
581 	DOFLIRT,      60082,
582 	DOFLIRT,      60083,
583 	DOFLIRT,      60084, // Beneath a Steel Sky
584 	DOFLIRT,      60085,
585 	DOFLIRT,      60086,
586 	SCROLLFLIRT,
587 	COMMANDFLIRT, 60087, // => command list 4a
588 		136, IC_MAKE_SOUND,  1, 70,
589 		 90, IC_FX_VOLUME,  80,
590 		 50, IC_FX_VOLUME,  90,
591 		  5, IC_FX_VOLUME, 100,
592 	COMMANDEND,
593 	SHOWSCREEN,   60088,
594 	COMMANDFLIRT, 60089, // => command list 4b (cockpit)
595 		1000, IC_PREPARE_TEXT,  77,
596 		 220, IC_SHOW_TEXT,     20, 160, // radar detects jamming signal
597 		 105, IC_REMOVE_TEXT,
598 		 105, IC_PREPARE_TEXT,  81,
599 		 105, IC_SHOW_TEXT,    170,  86, // well switch to override you fool
600 		  35, IC_REMOVE_TEXT,
601 		  35, IC_PREPARE_TEXT, 477,
602 		  35, IC_SHOW_TEXT,     30, 160,
603 		   3, IC_REMOVE_TEXT,
604 	COMMANDEND,
605 	CLEARBOTTOM,
606 	SHOWSCREEN,   60090,
607 	COMMANDFLIRT, 60091, // => command list 4c
608 		1000, IC_FX_VOLUME, 100,
609 		  25, IC_FX_VOLUME, 110,
610 		  15, IC_FX_VOLUME, 120,
611 		   4, IC_FX_VOLUME, 127,
612 	COMMANDEND,
613 	FADEDOWN,
614 	// This one could be fullscreen, but that causes animation glitches.
615 	SHOWSCREEN,  60093,
616 	FADEUP,       60092,
617 	COMMANDFLIRT, 60094, // => command list 5
618 		31, IC_MAKE_SOUND, 2, 127,
619 	COMMANDEND,
620 	WAITMUSIC,
621 	FADEDOWN,
622 	SHOWSCREEN | FULLSCREEN,   60096,
623 	STARTMUSIC,       2,
624 	FADEUP,       60095,
625 	COMMANDFLIRT, 60097, // => command list 6a
626 		1000, IC_PREPARE_TEXT, 478,
627 		  13, IC_SHOW_TEXT,    175, 155,
628 	COMMANDEND,
629 	COMMANDFLIRT, 60098, // => command list 6b
630 		131, IC_REMOVE_TEXT,
631 		131, IC_PREPARE_TEXT, 479,
632 		 74, IC_SHOW_TEXT,    175, 155,
633 		 45, IC_REMOVE_TEXT,
634 		 45, IC_PREPARE_TEXT, 162,
635 		 44, IC_SHOW_TEXT,    175, 155,
636 		  4, IC_REMOVE_TEXT,
637 	COMMANDEND,
638 	SEQEND
639 };
640 
Intro(Disk * disk,Screen * screen,MusicBase * music,Sound * sound,Text * text,Audio::Mixer * mixer,OSystem * system)641 Intro::Intro(Disk *disk, Screen *screen, MusicBase *music, Sound *sound, Text *text, Audio::Mixer *mixer, OSystem *system) {
642 	_skyDisk = disk;
643 	_skyScreen = screen;
644 	_skyMusic = music;
645 	_skySound = sound;
646 	_skyText = text;
647 	_mixer = mixer;
648 	_system = system;
649 	_textBuf = (uint8 *)malloc(10000);
650 	_saveBuf = (uint8 *)malloc(10000);
651 	_bgBuf = NULL;
652 	_relDelay = 0;
653 }
654 
~Intro()655 Intro::~Intro() {
656 	if (_skyScreen->sequenceRunning())
657 		_skyScreen->stopSequence();
658 
659 	free(_textBuf);
660 	free(_saveBuf);
661 	_mixer->stopID(SOUND_BG);
662 	free(_bgBuf);
663 }
664 
doIntro(bool floppyIntro)665 bool Intro::doIntro(bool floppyIntro) {
666 	if (!SkyEngine::isCDVersion())
667 		floppyIntro = true;
668 
669 	_skyMusic->loadSection(0);
670 	_skySound->loadSection(0);
671 
672 	if (!escDelay(3000))
673 		return false;
674 
675 	if (floppyIntro)
676 		_skyMusic->startMusic(1);
677 
678 	uint16 *seqData = _mainIntroSeq;
679 	while (*seqData != SEQEND) {
680 		if (!nextPart(seqData))
681 			return false;
682 	}
683 	if (floppyIntro)
684 		seqData = _floppyIntroSeq;
685 	else
686 		seqData = _cdIntroSeq;
687 
688 	while (*seqData != SEQEND) {
689 		if (!nextPart(seqData))
690 			return false;
691 	}
692 	return true;
693 }
694 
nextPart(uint16 * & data)695 bool Intro::nextPart(uint16 *&data) {
696 	uint8 *vData = NULL;
697 	Audio::RewindableAudioStream *stream = 0;
698 
699 	// return false means cancel intro
700 	uint16 command = *data++;
701 	switch (command & 0x7fff) {
702 	case SHOWSCREEN:
703 		_skyScreen->showScreen(*data++, (command & FULLSCREEN) ? true : false);
704 		return true;
705 	case FADEUP:
706 		_skyScreen->paletteFadeUp(*data++);
707 		_relDelay += 32 * 20; // hack: the screen uses a seperate delay function for the
708 							  // blocking fadeups. So add 32*20 msecs to out delay counter.
709 		return true;
710 	case FADEDOWN:
711 		_skyScreen->fnFadeDown(0);
712 		_relDelay += 32 * 20; // hack: see above.
713 		return true;
714 	case DELAY:
715 		if (!escDelay(*data++))
716 			return false;
717 		return true;
718 	case DOFLIRT:
719 		_skyScreen->startSequence(*data++);
720 		while (_skyScreen->sequenceRunning())
721 			if (!escDelay(50))
722 				return false;
723 		return true;
724 	case SCROLLFLIRT:
725 		return floppyScrollFlirt();
726 	case COMMANDFLIRT:
727 		return commandFlirt(data);
728 	case STOPFLIRT:
729 		_skyScreen->stopSequence();
730 		return true;
731 	case STARTMUSIC:
732 		_skyMusic->startMusic(*data++);
733 		return true;
734 	case WAITMUSIC:
735 		while (_skyMusic->musicIsPlaying())
736 			if (!escDelay(50))
737 				return false;
738 		return true;
739 	case BGFLIRT:
740 		_skyScreen->startSequence(*data++);
741 		return true;
742 	case WAITFLIRT:
743 		while (_skyScreen->sequenceRunning())
744 			if (!escDelay(50))
745 				return false;
746 		return true;
747 	case PLAYVOICE:
748 		if (!escDelay(200))
749 			return false;
750 		vData = _skyDisk->loadFile(*data++);
751 		// HACK: Fill the header with silence. We should
752 		// probably use _skySound instead of calling playStream()
753 		// directly, but this will have to do for now.
754 		memset(vData, 127, sizeof(DataFileHeader));
755 
756 		stream = Audio::makeRawStream(vData, _skyDisk->_lastLoadedFileSize, 11025, Audio::FLAG_UNSIGNED);
757 		_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_voice, stream, SOUND_VOICE);
758 		return true;
759 	case WAITVOICE:
760 		while (_mixer->isSoundHandleActive(_voice))
761 			if (!escDelay(50))
762 				return false;
763 		return true;
764 	case LOADBG:
765 		_mixer->stopID(SOUND_BG);
766 		free(_bgBuf);
767 		_bgBuf = _skyDisk->loadFile(*data++);
768 		_bgSize = _skyDisk->_lastLoadedFileSize;
769 		return true;
770 	case LOOPBG:
771 		_mixer->stopID(SOUND_BG);
772 		stream = Audio::makeRawStream(_bgBuf + 256, _bgSize - 768, 11025, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO);
773 		_mixer->playStream(Audio::Mixer::kSFXSoundType, &_bgSfx, Audio::makeLoopingAudioStream(stream, 0), SOUND_BG);
774 		return true;
775 	case PLAYBG:
776 		_mixer->stopID(SOUND_BG);
777 		stream = Audio::makeRawStream(_bgBuf + 256, _bgSize - 768, 11025, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO);
778 		_mixer->playStream(Audio::Mixer::kSFXSoundType, &_bgSfx, stream, SOUND_BG);
779 		return true;
780 	case STOPBG:
781 		_mixer->stopID(SOUND_BG);
782 		return true;
783 	case CLEARBOTTOM:
784 		{
785 			byte *screenBuf = _skyScreen->giveCurrent() + GAME_SCREEN_HEIGHT * GAME_SCREEN_WIDTH;
786 			memset(screenBuf, 0, GAME_SCREEN_WIDTH * (FULL_SCREEN_HEIGHT - GAME_SCREEN_HEIGHT));
787 			_system->copyRectToScreen(screenBuf, GAME_SCREEN_WIDTH, 0, GAME_SCREEN_HEIGHT, GAME_SCREEN_WIDTH, FULL_SCREEN_HEIGHT - GAME_SCREEN_HEIGHT);
788 			_system->updateScreen();
789 		}
790 		return true;
791 	default:
792 		error("Unknown intro command %X", command);
793 	}
794 	return true;
795 }
796 
floppyScrollFlirt()797 bool Intro::floppyScrollFlirt() {
798 	uint8 *scrollScreen = (uint8 *)malloc(FRAME_SIZE * 2);
799 	memset(scrollScreen, 0, FRAME_SIZE);
800 	memcpy(scrollScreen + FRAME_SIZE, _skyScreen->giveCurrent(), FRAME_SIZE);
801 	uint8 *scrollPos = scrollScreen + FRAME_SIZE;
802 	uint8 *vgaData = _skyDisk->loadFile(60100);
803 	uint8 *diffData = _skyDisk->loadFile(60101);
804 	uint16 frameNum = READ_LE_UINT16(diffData);
805 	uint8 *diffPtr = diffData + 2;
806 	uint8 *vgaPtr = vgaData;
807 	bool doContinue = true;
808 
809 	for (uint16 frameCnt = 1; (frameCnt < frameNum) && doContinue; frameCnt++) {
810 		uint8 scrollVal = *diffPtr++;
811 		if (scrollVal)
812 			scrollPos -= scrollVal * GAME_SCREEN_WIDTH;
813 
814 		uint16 scrPos = 0;
815 		while (scrPos < FRAME_SIZE) {
816 			uint8 nrToDo, nrToSkip;
817 			do {
818 				nrToSkip = *diffPtr++;
819 				scrPos += nrToSkip;
820 			} while (nrToSkip == 255);
821 			do {
822 				nrToDo = *diffPtr++;
823 				memcpy(scrollPos + scrPos, vgaPtr, nrToDo);
824 				scrPos += nrToDo;
825 				vgaPtr += nrToDo;
826 			} while (nrToDo == 255);
827 		}
828 		_system->copyRectToScreen(scrollPos, GAME_SCREEN_WIDTH, 0, 0, GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT);
829 		_system->updateScreen();
830 		if (!escDelay(60))
831 			doContinue = false;
832 	}
833 	memcpy(_skyScreen->giveCurrent(), scrollPos, FRAME_SIZE);
834 	free(diffData);
835 	free(vgaData);
836 	free(scrollScreen);
837 	return doContinue;
838 }
839 
commandFlirt(uint16 * & data)840 bool Intro::commandFlirt(uint16 *&data) {
841 	_skyScreen->startSequence(*data++);
842 
843 	while ((*data != COMMANDEND) || _skyScreen->sequenceRunning()) {
844 		while ((_skyScreen->seqFramesLeft() < *data)) {
845 			data++;
846 			uint16 command = *data++;
847 			switch (command) {
848 			case IC_PREPARE_TEXT:
849 				_skyText->displayText(*data++, _textBuf, true, INTRO_TEXT_WIDTH, 255);
850 				break;
851 			case IC_SHOW_TEXT:
852 				((DataFileHeader *)_textBuf)->s_x = *data++;
853 				((DataFileHeader *)_textBuf)->s_y = *data++;
854 				showTextBuf();
855 				break;
856 			case IC_REMOVE_TEXT:
857 				restoreScreen();
858 				break;
859 			case IC_MAKE_SOUND:
860 				_skySound->playSound(data[0], data[1], 0);
861 				data += 2;
862 				break;
863 			case IC_FX_VOLUME:
864 				_skySound->playSound(1, *data++, 0);
865 				break;
866 			default:
867 				error("Unknown FLIRT command %X", command);
868 			}
869 		}
870 
871 		if (!escDelay(50)) {
872 			_skyScreen->stopSequence();
873 			return false;
874 		}
875 	}
876 
877 	data++; // move pointer over "COMMANDEND"
878 	return true;
879 }
880 
showTextBuf()881 void Intro::showTextBuf() {
882 	uint16 x = ((DataFileHeader *)_textBuf)->s_x;
883 	uint16 y = ((DataFileHeader *)_textBuf)->s_y;
884 	uint16 width = ((DataFileHeader *)_textBuf)->s_width;
885 	uint16 height = ((DataFileHeader *)_textBuf)->s_height;
886 	uint8 *screenBuf = _skyScreen->giveCurrent() + y * GAME_SCREEN_WIDTH + x;
887 	memcpy(_saveBuf, _textBuf, sizeof(DataFileHeader));
888 	uint8 *saveBuf = _saveBuf + sizeof(DataFileHeader);
889 	uint8 *textBuf = _textBuf + sizeof(DataFileHeader);
890 	for (uint16 cnty = 0; cnty < height; cnty++) {
891 		memcpy(saveBuf, screenBuf, width);
892 		for (uint16 cntx = 0; cntx < width; cntx++)
893 			if (textBuf[cntx])
894 				screenBuf[cntx] = textBuf[cntx];
895 		screenBuf += GAME_SCREEN_WIDTH;
896 		textBuf += width;
897 		saveBuf += width;
898 	}
899 	screenBuf = _skyScreen->giveCurrent() + y * GAME_SCREEN_WIDTH + x;
900 	_system->copyRectToScreen(screenBuf, GAME_SCREEN_WIDTH, x, y, width, height);
901 }
902 
restoreScreen()903 void Intro::restoreScreen() {
904 	uint16 x = ((DataFileHeader *)_saveBuf)->s_x;
905 	uint16 y = ((DataFileHeader *)_saveBuf)->s_y;
906 	uint16 width = ((DataFileHeader *)_saveBuf)->s_width;
907 	uint16 height = ((DataFileHeader *)_saveBuf)->s_height;
908 	uint8 *screenBuf = _skyScreen->giveCurrent() + y * GAME_SCREEN_WIDTH + x;
909 	uint8 *saveBuf = _saveBuf + sizeof(DataFileHeader);
910 	for (uint16 cnt = 0; cnt < height; cnt++) {
911 		memcpy(screenBuf, saveBuf, width);
912 		screenBuf += GAME_SCREEN_WIDTH;
913 		saveBuf += width;
914 	}
915 	_system->copyRectToScreen(_saveBuf + sizeof(DataFileHeader), width, x, y, width, height);
916 }
917 
escDelay(uint32 msecs)918 bool Intro::escDelay(uint32 msecs) {
919 	Common::EventManager *eventMan = _system->getEventManager();
920 	Common::Event event;
921 
922 	if (_relDelay == 0) // first call, init with system time
923 		_relDelay = (int32)_system->getMillis();
924 
925 	_relDelay += msecs; // now wait until _system->getMillis() >= _relDelay
926 
927 	int32 nDelay = 0;
928 	do {
929 		while (eventMan->pollEvent(event)) {
930 			if (event.type == Common::EVENT_KEYDOWN) {
931 				if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
932 					return false;
933 			} else if (event.type == Common::EVENT_QUIT || event.type == Common::EVENT_RTL) {
934 				return false;
935 			}
936 		}
937 		nDelay = _relDelay - _system->getMillis();
938 		if (nDelay < 0)
939 			nDelay = 0;
940 		else if (nDelay > 20)
941 			nDelay = 20;
942 
943 		_system->delayMillis(nDelay);
944 
945 		_skyScreen->processSequence();
946 		_system->updateScreen();
947 	} while (nDelay == 20);
948 
949 	return true;
950 }
951 
952 } // End of namespace Sky
953