1 /*
2 BStone: A Source port of
3 Blake Stone: Aliens of Gold and Blake Stone: Planet Strike
4
5 Copyright (c) 1992-2013 Apogee Entertainment, LLC
6 Copyright (c) 2013-2015 Boris I. Bendovsky (bibendovsky@hotmail.com)
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the
20 Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24
25 //
26 // Warning!
27 //
28 // All functions in this source file are designated usable by the memory
29 // manager after program initialization.
30 //
31
32
33 #include "3d_def.h"
34
35
36 extern SpanStart spanstart;
37 extern StepScale stepscale;
38 extern BaseDist basedist;
39 extern PlaneYLookup planeylookup;
40 extern MirrorOfs mirrorofs;
41
42
43 void CA_CannotOpen(
44 const std::string& string);
45
46 void CAL_GetGrChunkLength(
47 int16_t chunk);
48
49 void CA_CacheScreen(
50 int16_t chunk);
51
52 void VH_UpdateScreen();
53 void IN_StartAck();
54 bool IN_CheckAck();
55 void OpenMapFile();
56 void CloseMapFile();
57 void ClearMemory();
58 void ShutdownId();
59 void InitRedShifts();
60
61 void CAL_OptimizeNodes(
62 huffnode* table);
63
64 void OpenAudioFile();
65 void ReadConfig();
66 void read_high_scores();
67
68 void initialize_sprites();
69 void initialize_states();
70 void initialize_audio_constants();
71 void initialize_songs();
72 void initialize_gfxv_contants();
73 void initialize_tp_shape_table();
74 void initialize_tp_animation_table();
75 void initialize_static_info_constants();
76 void initialize_weapon_constants();
77 void initialize_grenade_shape_constants();
78 void initialize_static_health_table();
79 void initialize_boss_constants();
80 void initialize_messages();
81 void initialize_ca_constants();
82
83 void SDL_SetupDigi();
84
85
86 static uint8_t wolfdigimap[] = {
87 // These first sounds are in the upload version
88
89 ATKIONCANNONSND, 0,
90 ATKCHARGEDSND, 1,
91 ATKBURSTRIFLESND, 2,
92 ATKGRENADESND, 46,
93
94 OPENDOORSND, 3,
95 CLOSEDOORSND, 4,
96 HTECHDOOROPENSND, 5,
97 HTECHDOORCLOSESND, 6,
98
99 INFORMANTDEATHSND, 7,
100 SCIENTISTHALTSND, 19,
101 SCIENTISTDEATHSND, 20,
102
103 GOLDSTERNHALTSND, 8,
104 GOLDSTERNLAUGHSND, 24,
105
106 HALTSND, 9, // Rent-A-Cop 1st sighting
107 RENTDEATH1SND, 10, // Rent-A-Cop Death
108
109 EXPLODE1SND, 11,
110
111 GGUARDHALTSND, 12,
112 GGUARDDEATHSND, 17,
113
114 PROHALTSND, 16,
115 PROGUARDDEATHSND, 13,
116
117 BLUEBOYDEATHSND, 18,
118 BLUEBOYHALTSND, 51,
119
120 SWATHALTSND, 22,
121 SWATDIESND, 47,
122
123 SCANHALTSND, 15,
124 SCANDEATHSND, 23,
125
126 PODHATCHSND, 26,
127 PODHALTSND, 50,
128 PODDEATHSND, 49,
129
130 ELECTSHOTSND, 27,
131
132 DOGBOYHALTSND, 14,
133 DOGBOYDEATHSND, 21,
134 ELECARCDAMAGESND, 25,
135 ELECAPPEARSND, 28,
136 ELECDIESND, 29,
137
138 INFORMDEATH2SND, 39, // Informant Death #2
139 RENTDEATH2SND, 34, // Rent-A-Cop Death #2
140 PRODEATH2SND, 42, // PRO Death #2
141 SWATDEATH2SND, 48, // SWAT Death #2
142 SCIDEATH2SND, 53, // Gen. Sci Death #2
143
144 LIQUIDDIESND, 30,
145
146 GURNEYSND, 31,
147 GURNEYDEATHSND, 41,
148
149 WARPINSND, 32,
150 WARPOUTSND, 33,
151
152 EXPLODE2SND, 35,
153
154 LCANHALTSND, 36,
155 LCANDEATHSND, 37,
156
157 // RENTDEATH3SND, 38, // Rent-A-Cop Death #3
158 INFORMDEATH3SND, 40, // Informant Death #3
159 PRODEATH3SND, 43, // PRO Death #3
160 SWATDEATH3SND, 52, // Swat Guard #3
161 SCIDEATH3SND, 54, // Gen. Sci Death #3
162
163 LCANBREAKSND, 44,
164 SCANBREAKSND, 45,
165 CLAWATTACKSND, 56,
166 SPITATTACKSND, 55,
167 PUNCHATTACKSND, 57,
168
169 LASTSOUND,
170 };
171
172
173 extern const uint8_t colormap[16896];
174 const uint8_t* lightsource;
175
176
177 // ------------------ ID Software 'startup' functions ---------------------
178
179
180 /*
181 ==================
182 =
183 = BuildTables
184 =
185 = Calculates:
186 =
187 = scale projection constant
188 = sintable/costable overlapping fractional tables
189 =
190 ==================
191 */
192
193 const float radtoint = static_cast<float>(FINEANGLES / 2 / PI);
194
195
BuildTables()196 void BuildTables()
197 {
198 int16_t i;
199 float angle, anglestep;
200 double tang;
201 fixed value;
202
203
204 //
205 // calculate fine tangents
206 //
207
208 for (i = 0; i < FINEANGLES / 8; i++) {
209 tang = tan((i + 0.5) / radtoint);
210 finetangent[i] = static_cast<int32_t>(tang * TILEGLOBAL);
211 finetangent[FINEANGLES / 4 - 1 - i] = static_cast<int32_t>(1 / tang * TILEGLOBAL);
212 }
213
214 //
215 // costable overlays sintable with a quarter phase shift
216 // ANGLES is assumed to be divisable by four
217 //
218 // The low word of the value is the fraction, the high bit is the sign bit,
219 // bits 16-30 should be 0
220 //
221
222 angle = 0.0F;
223 anglestep = static_cast<float>(PI / 2 / ANGLEQUAD);
224 for (i = 0; i <= ANGLEQUAD; i++) {
225 value = static_cast<fixed>(GLOBAL1 * sin(static_cast<double>(angle)));
226 sintable[i] =
227 sintable[i + ANGLES] =
228 sintable[ANGLES / 2 - i] = value;
229 sintable[ANGLES - i] =
230 sintable[ANGLES / 2 + i] = value | 0x80000000l;
231 angle += anglestep;
232 }
233
234 lightsource = colormap;
235 }
236
237 // Map tile values to scaled pics
SetupWalls()238 void SetupWalls()
239 {
240 //
241 // Hey! Yea You! This is where you can VERY easly setup to use a
242 // specific 'BANK' of wall graphics.... JTR
243 //
244
245 for (int i = 1; i < MAXWALLTILES; ++i)
246 {
247 ::horizwall[i] = (i - 1) * 2;
248 ::vertwall[i] = ::horizwall[i] + 1;
249 }
250
251 WallHeight().swap(wallheight);
252 wallheight.resize(::vga_width);
253
254
255 const int k_half_height = ::vga_height / 2;
256
257 SpanStart().swap(spanstart);
258 spanstart.resize(k_half_height);
259
260 StepScale().swap(stepscale);
261 stepscale.resize(k_half_height);
262
263 BaseDist().swap(basedist);
264 basedist.resize(k_half_height);
265
266 PlaneYLookup().swap(planeylookup);
267 planeylookup.resize(k_half_height);
268
269 MirrorOfs().swap(mirrorofs);
270 mirrorofs.resize(k_half_height);
271 }
272
InitDigiMap()273 void InitDigiMap()
274 {
275 char* map;
276
277 for (map = reinterpret_cast<char*>(wolfdigimap); *map != LASTSOUND; map += 2) {
278 DigiMap[static_cast<int>(map[0])] = map[1];
279 }
280 }
281
CAL_SetupAudioFile()282 void CAL_SetupAudioFile()
283 {
284 bstone::FileStream handle;
285 int32_t length;
286 std::string fname;
287
288 //
289 // load maphead.ext (offsets and tileinfo for map file)
290 //
291 #ifndef AUDIOHEADERLINKED
292 fname = ::data_dir + ::aheadname + ::extension;
293
294 handle.open(fname);
295 if (!handle.is_open()) {
296 ::CA_CannotOpen(fname);
297 }
298
299 length = static_cast<int32_t>(handle.get_size());
300 ::audiostarts = new int32_t[length / 4];
301 handle.read(::audiostarts, length);
302 handle.close();
303 #else
304 audiohuffman = (huffnode*)&audiodict;
305 CAL_OptimizeNodes(audiohuffman);
306 audiostarts = (int32_t*)FP_SEG(&audiohead);
307 #endif
308
309 //
310 // open the data file
311 //
312 ::OpenAudioFile();
313 }
314
CAL_SetupGrFile()315 void CAL_SetupGrFile()
316 {
317 std::string fname;
318 bstone::FileStream handle;
319 uint8_t* compseg;
320
321 //
322 // load ???dict.ext (huffman dictionary for graphics files)
323 //
324
325 fname = ::data_dir + ::gdictname + ::extension;
326
327 handle.open(fname);
328
329 if (!handle.is_open()) {
330 ::CA_CannotOpen(fname);
331 }
332
333 handle.read(&::grhuffman, sizeof(::grhuffman));
334
335 //
336 // load the data offsets from ???head.ext
337 //
338 int grstarts_size = (NUMCHUNKS + 1) * FILEPOSSIZE;
339
340 ::grstarts = new int32_t[(grstarts_size + 3) / 4];
341
342 fname = ::data_dir + ::gheadname + ::extension;
343
344 handle.open(fname);
345
346 if (!handle.is_open()) {
347 ::CA_CannotOpen(fname);
348 }
349
350 handle.read(::grstarts, grstarts_size);
351
352 //
353 // Open the graphics file, leaving it open until the game is finished
354 //
355 ::OpenGrFile();
356
357 //
358 // load the pic and sprite headers into the arrays in the data segment
359 //
360 ::pictable = new pictabletype[NUMPICS];
361 ::CAL_GetGrChunkLength(STRUCTPIC); // position file pointer
362 compseg = new uint8_t[::chunkcomplen];
363 ::grhandle.read(compseg, ::chunkcomplen);
364
365 ::CAL_HuffExpand(
366 compseg,
367 reinterpret_cast<uint8_t*>(pictable),
368 NUMPICS * sizeof(pictabletype),
369 ::grhuffman);
370
371 delete [] compseg;
372 }
373
CAL_SetupMapFile()374 void CAL_SetupMapFile()
375 {
376 int16_t i;
377 bstone::FileStream handle;
378 int32_t pos;
379 std::string fname;
380 mapfiletype header;
381 maptype* map_header;
382
383 //
384 // load maphead.ext (offsets and tileinfo for map file)
385 //
386
387 fname = ::data_dir + ::mheadname + ::extension;
388
389 handle.open(fname);
390
391 if (!handle.is_open()) {
392 CA_CannotOpen(fname);
393 }
394
395 handle.read(&header.RLEWtag, sizeof(header.RLEWtag));
396 handle.read(&header.headeroffsets, sizeof(header.headeroffsets));
397
398 rlew_tag = header.RLEWtag;
399
400 //
401 // open the data file
402 //
403 OpenMapFile();
404
405 //
406 // load all map header
407 //
408 for (i = 0; i < NUMMAPS; ++i) {
409 pos = header.headeroffsets[i];
410
411 if (pos < 0) {
412 continue;
413 }
414
415 mapheaderseg[i] = new maptype();
416 map_header = mapheaderseg[i];
417
418 maphandle.set_position(pos);
419
420 maphandle.read(
421 &map_header->planestart,
422 sizeof(map_header->planestart));
423
424 maphandle.read(
425 &map_header->planelength,
426 sizeof(map_header->planelength));
427
428 maphandle.read(
429 &map_header->width,
430 sizeof(map_header->width));
431
432 maphandle.read(
433 &map_header->height,
434 sizeof(map_header->height));
435
436 maphandle.read(
437 &map_header->name,
438 sizeof(map_header->name));
439 }
440
441 //
442 // allocate space for 3 64*64 planes
443 //
444 for (i = 0; i < MAPPLANES; ++i) {
445 mapsegs[i] = new uint16_t[64 * 64];
446 }
447
448 CloseMapFile();
449 }
450
451
452 // --------------------- Other general functions ------------------------
453
454 extern CP_itemtype NewEmenu[];
455 extern int16_t EpisodeSelect[];
456
457
458 namespace {
459
460
get_ref_vgahead_offset_count(GameType game_type)461 int get_ref_vgahead_offset_count(
462 GameType game_type)
463 {
464 switch (game_type) {
465 case GameType::aog_sw:
466 return 213;
467
468 case GameType::aog_full_v1_0:
469 return 213;
470
471 case GameType::aog_full_v2_x:
472 return 224;
473
474 case GameType::aog_full_v3_0:
475 return 226;
476
477 case GameType::ps:
478 return 249;
479
480 default:
481 throw std::invalid_argument("Invalid game type.");
482 }
483 }
484
get_file_names(GameType game_type)485 const bstone::StringList& get_file_names(
486 GameType game_type)
487 {
488 static const bstone::StringList aog_sw_file_names = {
489 "AUDIOHED.BS1",
490 "AUDIOT.BS1",
491 "IANIM.BS1",
492 "MAPHEAD.BS1",
493 "MAPTEMP.BS1",
494 "SANIM.BS1",
495 "VGADICT.BS1",
496 "VGAGRAPH.BS1",
497 "VGAHEAD.BS1",
498 "VSWAP.BS1",
499 }; // aog_sw_file_names
500
501 static const bstone::StringList aog_full_file_names = {
502 "AUDIOHED.BS6",
503 "AUDIOT.BS6",
504 "EANIM.BS6",
505 "GANIM.BS6",
506 "IANIM.BS6",
507 "MAPHEAD.BS6",
508 "MAPTEMP.BS6",
509 "SANIM.BS6",
510 "VGADICT.BS6",
511 "VGAGRAPH.BS6",
512 "VGAHEAD.BS6",
513 "VSWAP.BS6",
514 }; // aog_file_names
515
516 static const bstone::StringList ps_file_names = {
517 "AUDIOHED.VSI",
518 "AUDIOT.VSI",
519 "EANIM.VSI",
520 "IANIM.VSI",
521 "MAPHEAD.VSI",
522 "MAPTEMP.VSI",
523 "VGADICT.VSI",
524 "VGAGRAPH.VSI",
525 "VGAHEAD.VSI",
526 "VSWAP.VSI",
527 }; // ps_file_names
528
529
530 switch (game_type) {
531 case GameType::aog_sw:
532 return aog_sw_file_names;
533
534 case GameType::aog_full_v1_0:
535 case GameType::aog_full_v2_x:
536 case GameType::aog_full_v3_0:
537 return aog_full_file_names;
538
539 case GameType::ps:
540 return ps_file_names;
541
542 default:
543 throw std::invalid_argument("Invalid game type.");
544 }
545 }
546
get_file_extension(GameType game_type)547 const std::string& get_file_extension(
548 GameType game_type)
549 {
550 static const std::string aog_sw_extension = "BS1";
551 static const std::string aog_full_extension = "BS6";
552 static const std::string ps_extension = "VSI";
553
554 switch (game_type) {
555 case GameType::aog_sw:
556 return aog_sw_extension;
557
558 case GameType::aog_full_v1_0:
559 case GameType::aog_full_v2_x:
560 case GameType::aog_full_v3_0:
561 return aog_full_extension;
562
563 case GameType::ps:
564 return ps_extension;
565
566 default:
567 throw std::invalid_argument("Invalid game type.");
568 }
569 }
570
are_files_exist(GameType game_type)571 bool are_files_exist(
572 GameType game_type)
573 {
574 auto&& file_names = get_file_names(game_type);
575
576 for (const auto& file_name : file_names) {
577 auto file_path = ::data_dir + file_name;
578
579 if (!bstone::FileStream::is_exists(file_path)) {
580 return false;
581 }
582 }
583
584 return true;
585 }
586
get_vgahead_offset_count(GameType game_type)587 int get_vgahead_offset_count(
588 GameType game_type)
589 {
590 auto file_name = "VGAHEAD." + get_file_extension(game_type);
591
592 bstone::FileStream stream(::data_dir + file_name);
593
594 if (!stream.is_open()) {
595 return 0;
596 }
597
598 auto file_size = stream.get_size();
599
600 if ((file_size % FILEPOSSIZE) != 0) {
601 return 0;
602 }
603
604 return static_cast<int>(file_size / FILEPOSSIZE);
605 }
606
check_vgahead_offset_count(GameType game_type)607 bool check_vgahead_offset_count(
608 GameType game_type)
609 {
610 auto offset_count = get_vgahead_offset_count(game_type);
611 return offset_count == get_ref_vgahead_offset_count(game_type);
612 }
613
set_game_type(GameType game_type)614 static bool set_game_type(
615 GameType game_type)
616 {
617 if (!are_files_exist(game_type)) {
618 return false;
619 }
620
621 if (!check_vgahead_offset_count(game_type)) {
622 return false;
623 }
624
625 ::g_game_type = game_type;
626
627 return true;
628 }
629
630
631 } // namespace
632
633
CheckForEpisodes()634 void CheckForEpisodes()
635 {
636 bool is_succeed = true;
637
638 ::g_game_type = GameType::none;
639
640 if (::g_args.has_option("aog_sw")) {
641 bstone::Log::write("Forcing Aliens Of Gold (shareware, v3.0).\n");
642
643 if (!::set_game_type(GameType::aog_sw)) {
644 is_succeed = false;
645 }
646 } else if (::g_args.has_option("aog_10")) {
647 bstone::Log::write("Forcing Aliens Of Gold (full, v1.0).\n");
648
649 if (!::set_game_type(GameType::aog_full_v1_0)) {
650 is_succeed = false;
651 }
652 } else if (::g_args.has_option("aog_2x")) {
653 bstone::Log::write("Forcing Aliens Of Gold (full, v2.x).\n");
654
655 if (!::set_game_type(GameType::aog_full_v2_x)) {
656 is_succeed = false;
657 }
658 } else if (::g_args.has_option("aog_30")) {
659 bstone::Log::write("Forcing Aliens Of Gold (full, v3.0).\n");
660
661 if (!::set_game_type(GameType::aog_full_v3_0)) {
662 is_succeed = false;
663 }
664 } else if (::g_args.has_option("ps")) {
665 bstone::Log::write("Forcing Planet Strike (full, v1.0/v1.1).\n");
666
667 if (!::set_game_type(GameType::ps)) {
668 is_succeed = false;
669 }
670 } else {
671 bool is_found = false;
672
673 bstone::Log::write("Searching for data files...");
674
675 if (!is_found) {
676 is_found = ::set_game_type(GameType::aog_full_v3_0);
677 }
678
679 if (!is_found) {
680 is_found = ::set_game_type(GameType::aog_full_v2_x);
681 }
682
683 if (!is_found) {
684 is_found = ::set_game_type(GameType::aog_full_v1_0);
685 }
686
687 if (!is_found) {
688 is_found = ::set_game_type(GameType::ps);
689 }
690
691 if (!is_found) {
692 is_found = ::set_game_type(GameType::aog_sw);
693 }
694
695 if (is_found) {
696 switch (::g_game_type) {
697 case GameType::aog_sw:
698 bstone::Log::write("Found Aliens Of Gold (shareware, v3.0).\n");
699 break;
700
701 case GameType::aog_full_v1_0:
702 bstone::Log::write("Found Aliens Of Gold (full, v1.0).\n");
703 break;
704
705 case GameType::aog_full_v2_x:
706 bstone::Log::write("Found Aliens Of Gold (full, v2.x).\n");
707 break;
708
709 case GameType::aog_full_v3_0:
710 bstone::Log::write("Found Aliens Of Gold (full, v3.0).\n");
711 break;
712
713 case GameType::ps:
714 bstone::Log::write("Found Planet Strike (v1.x).\n");
715 break;
716
717 default:
718 is_succeed = false;
719 break;
720 }
721 } else {
722 is_succeed = false;
723 }
724 }
725
726 if (!is_succeed) {
727 ::Quit("Data files not found.");
728 }
729
730
731 ::extension = ::get_file_extension(::g_game_type);
732
733 for (int i = 0; i < mv_NUM_MOVIES; ++i) {
734 ::movies[i].file_name += ::extension;
735 }
736
737 if (::is_aog_full()) {
738 for (int i = 1; i < 6; ++i) {
739 ::NewEmenu[i].active = AT_ENABLED;
740 ::EpisodeSelect[i] = 1;
741 }
742 }
743
744 ::PageFileName += ::extension;
745 ::audioname += ::extension;
746 }
747
748
749 extern const char* MainStrs[];
750 extern char bc_buffer[];
751
752
PreDemo()753 void PreDemo()
754 {
755 if (::no_screens) {
756 return;
757 }
758
759 VL_SetPaletteIntensity(0, 255, vgapal, 0);
760
761 if (!(gamestate.flags & GS_NOWAIT)) {
762 if (::is_aog_full()) {
763 // ---------------------
764 // Anti-piracy screen
765 // ---------------------
766
767 // Cache pic
768 //
769 CA_CacheScreen(PIRACYPIC);
770
771 // Cache and set palette. AND Fade it in!
772 //
773 CA_CacheGrChunk(PIRACYPALETTE);
774 VL_SetPalette(0, 256, static_cast<const uint8_t*>(grsegs[PIRACYPALETTE]));
775 VL_SetPaletteIntensity(0, 255, static_cast<const uint8_t*>(grsegs[PIRACYPALETTE]), 0);
776 VW_UpdateScreen();
777
778 VL_FadeOut(0, 255, 0, 0, 25, 20);
779 VL_FadeIn(0, 255, static_cast<const uint8_t*>(grsegs[PIRACYPALETTE]), 30);
780
781 // Wait a little
782 //
783 IN_UserInput(TickBase * 20);
784
785 // Free palette
786 //
787 UNCACHEGRCHUNK(PIRACYPALETTE);
788
789 VL_FadeOut(0, 255, 0, 0, 25, 20);
790 VW_FadeOut();
791
792 // Cleanup screen for upcoming SetPalette call
793 //
794 ::VL_Bar(0, 0, 320, 200, 0);
795 }
796
797 // ---------------------
798 // Apogee presents
799 // ---------------------
800
801 // Cache pic
802 //
803 CA_CacheScreen(APOGEEPIC);
804
805 // Load and start music
806 //
807 CA_CacheAudioChunk(STARTMUSIC + APOGFNFM_MUS);
808
809 ::SD_StartMusic(APOGFNFM_MUS);
810
811 // Cache and set palette. AND Fade it in!
812 //
813 CA_CacheGrChunk(APOGEEPALETTE);
814 VL_SetPalette(0, 256, static_cast<const uint8_t*>(grsegs[APOGEEPALETTE]));
815 VL_SetPaletteIntensity(0, 255, static_cast<const uint8_t*>(grsegs[APOGEEPALETTE]), 0);
816 VW_UpdateScreen();
817 if (::is_aog()) {
818 VL_FadeOut(0, 255, 0, 0, 0, 20);
819 } else {
820 VL_FadeOut(0, 255, 25, 29, 53, 20);
821 }
822 VL_FadeIn(0, 255, static_cast<const uint8_t*>(grsegs[APOGEEPALETTE]), 30);
823
824 // Wait for end of fanfare
825 //
826 if (::sd_is_music_enabled) {
827 IN_StartAck();
828 while ((!sqPlayedOnce) && (!IN_CheckAck())) {
829 }
830 } else {
831 IN_UserInput(TickBase * 6);
832 }
833
834 SD_MusicOff();
835
836 // Free palette and music. AND Restore palette
837 //
838 UNCACHEGRCHUNK(APOGEEPALETTE);
839
840 delete [] audiosegs[STARTMUSIC + APOGFNFM_MUS];
841 audiosegs[STARTMUSIC + APOGFNFM_MUS] = nullptr;
842
843 if (::is_ps()) {
844 // Do A Blue Flash!
845 ::VL_FadeOut(0, 255, 25, 29, 53, 20);
846 } else {
847 ::VL_FadeOut(0, 255, 0, 0, 0, 30);
848 }
849
850 // ---------------------
851 // JAM logo intro
852 // ---------------------
853
854 // Load and start music
855 //
856 CA_CacheAudioChunk(STARTMUSIC + TITLE_LOOP_MUSIC);
857 ::SD_StartMusic(TITLE_LOOP_MUSIC);
858
859 // Show JAM logo
860 //
861 if (!DoMovie(mv_intro, 0)) {
862 ::Quit("JAM animation (IANIM.xxx) does not exist.");
863 }
864
865 // ---------------------
866 // PC-13
867 // ---------------------
868 VL_Bar(0, 0, 320, 200, 0x14);
869 CacheDrawPic(0, 64, PC13PIC);
870 VW_UpdateScreen();
871 VW_FadeIn();
872 IN_UserInput(TickBase * 2);
873
874 // Do A Red Flash!
875
876 if (::is_aog()) {
877 ::VL_FadeOut(0, 255, 39, 0, 0, 20);
878 } else {
879 ::VL_FadeOut(0, 255, 0, 0, 0, 20);
880 }
881
882 VW_FadeOut();
883 }
884 }
885
InitGame()886 void InitGame()
887 {
888 int16_t i, x, y;
889 uint16_t* blockstart;
890
891 CA_Startup();
892 VW_Startup();
893 IN_Startup();
894 PM_Startup();
895 SD_Startup();
896 US_Startup();
897
898 VL_SetPalette(0, 256, vgapal);
899
900 //
901 // build some tables
902 //
903
904 InitDigiMap();
905
906 for (i = 0; i < MAPSIZE; i++) {
907 nearmapylookup[i] = &tilemap[0][0] + MAPSIZE * i;
908 farmapylookup[i] = i * 64;
909 }
910
911 for (i = 0; i < PORTTILESHIGH; i++) {
912 uwidthtable[i] = UPDATEWIDE * i;
913 }
914
915 blockstart = &blockstarts[0];
916 for (y = 0; y < UPDATEHIGH; y++) {
917 for (x = 0; x < UPDATEWIDE; x++) {
918 *blockstart++ = SCREENWIDTH * 16 * y + x * TILEWIDTH;
919 }
920 }
921
922 updateptr = &update[0];
923
924 bufferofs = 0;
925
926 ::ReadConfig();
927 ::read_high_scores();
928
929
930 //
931 // load in and lock down some basic chunks
932 //
933
934 LoadFonts();
935
936 LoadLatchMem();
937 BuildTables(); // trig tables
938 SetupWalls();
939 NewViewSize();
940
941 //
942 // initialize variables
943 //
944
945 InitRedShifts();
946 }
947
scan_atoi(const char * s)948 uint16_t scan_atoi(
949 const char* s)
950 {
951 while (*s && (!isdigit(*s))) { // First scans for a digit...
952 s++;
953 }
954
955 return static_cast<uint16_t>(atoi(s)); // Then converts to integer...
956 }
957
958
959 extern const char* MainStrs[];
960 extern int16_t starting_episode, starting_level, starting_difficulty;
961
962
freed_main()963 void freed_main()
964 {
965 if (::g_args.has_option("version")) {
966 bstone::Log::write_version();
967 ::Quit();
968 }
969
970 // Setup for APOGEECD thingie.
971 //
972 ::InitDestPath();
973
974 // Make sure there's room to play the game
975 //
976 ::CheckDiskSpace(DISK_SPACE_NEEDED, CANT_PLAY_TXT, cds_dos_print);
977
978 // Which version is this? (SHAREWARE? 1-3? 1-6?)
979 //
980 ::CheckForEpisodes();
981
982 // BBi
983 ::initialize_sprites();
984 ::initialize_gfxv_contants();
985 ::initialize_states();
986 ::initialize_tp_shape_table();
987 ::initialize_tp_animation_table();
988 ::initialize_audio_constants();
989 ::initialize_songs();
990 ::initialize_static_info_constants();
991 ::initialize_weapon_constants();
992 ::initialize_grenade_shape_constants();
993 ::initialize_static_health_table();
994 ::initialize_boss_constants();
995 ::initialize_messages();
996 ::initialize_ca_constants();
997 ::gamestuff.initialize();
998
999 if (::g_args.has_option("no_screens")) {
1000 ::no_screens = true;
1001 }
1002
1003 if (::g_args.has_option("cheats")) {
1004 ::DebugOk = true;
1005 }
1006
1007 ::InitGame();
1008
1009 ::PreDemo();
1010 }
1011