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