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