1 /*
2 Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20 #include "rt_def.h"
21 #include "lumpy.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 #include <fcntl.h>
26 #include <string.h>
27
28 #ifdef DOS
29 #include <malloc.h>
30 #include <dos.h>
31 #include <io.h>
32 #include <conio.h>
33 #include <graph.h>
34 #include <process.h>
35 #include <direct.h>
36 #include <bios.h>
37 #else
38 #include <signal.h>
39 #endif
40
41 #if USE_SDL
42 /* Need to redefine main to SDL_main on some platforms... */
43 #include "SDL.h"
44 #endif
45
46 #include "rt_actor.h"
47 #include "rt_stat.h"
48 #include "rt_vid.h"
49 #include "rt_menu.h"
50 #include "rt_sound.h"
51 #include "watcom.h"
52 #include "scriplib.h"
53 #include "rt_main.h"
54 #include "_rt_main.h"
55 #include "rt_com.h"
56 #include "rt_util.h"
57 #include "z_zone.h"
58 #include "w_wad.h"
59 #include "rt_game.h"
60 #include "rt_floor.h"
61 #include "rt_playr.h"
62 #include "rt_draw.h"
63 #include "rt_str.h"
64 #include "rt_view.h"
65 #include "rt_door.h"
66 #include "rt_ted.h"
67 #include "rt_in.h"
68 #include "rt_map.h"
69 #include "rt_rand.h"
70 #include "rt_debug.h"
71 #include "isr.h"
72 #include "rt_cfg.h"
73 #include "develop.h"
74 #include "version.h"
75 #include "rt_menu.h"
76 #include "rt_dr_a.h"
77 #include "rt_msg.h"
78 #include "rt_build.h"
79 #include "rt_error.h"
80 #include "modexlib.h"
81 #include "rt_net.h"
82 #include "cin_main.h"
83 #include "rottnet.h"
84 #include "rt_scale.h"
85
86 #include "music.h"
87 #include "fx_man.h"
88 //MED
89 #include "memcheck.h"
90
91 volatile int oldtime;
92 volatile int gametime;
93
94 boolean tedlevel;
95 int tedlevelnum;
96 int tedx=0;
97 int tedy=0;
98 boolean warp;
99 int warpx=0;
100 int warpy=0;
101 int warpa=0;
102 int NoSound;
103 int polltime;
104 int oldpolltime;
105 boolean fizzlein = false;
106 int pheight;
107
108 boolean SCREENSHOTS = false;
109 boolean MONOPRESENT = false;
110 boolean MAPSTATS = false;
111 boolean TILESTATS = false;
112 boolean HUD = false;
113 boolean IS8250 = false;
114
115 boolean dopefish;
116
117 boolean newlevel = false;
118 boolean infopause;
119 boolean SOUNDSETUP=false;
120 boolean quiet = false;
121
122 #if (DEVELOPMENT == 1)
123 boolean DebugOk = true;
124 #else
125 boolean DebugOk = false;
126 #endif
127
128 #if (WHEREAMI==1)
129 int programlocation=-1;
130 #endif
131
132 #if SAVE_SCREEN
133 static char savename[13] = "ROTT0000.LBM";
134 static int totalbytes;
135 static byte *bptr;
136 #endif
137 static boolean turbo;
138
139 static int NoWait;
140 static int startlevel=0;
141 static int demonumber=-1;
142
143 char CWD[40]; // curent working directory
144 static boolean quitactive = false;
145
146 int timelimit;
147 int maxtimelimit;
148 boolean timelimitenabled;
149 boolean demoexit;
150 boolean noecho;
151
152 void CheckCommandLineParameters( void );
153 void PlayTurboGame( void );
154 void Init_Tables (void);
155 void CheckRemoteRidicule ( int scancode );
156
157 #ifndef DOS
158 extern void crash_print (int);
159 extern int setup_homedir (void);
160 #endif
161
main(int argc,char * argv[])162 int main (int argc, char *argv[])
163 {
164 char *macwd;
165 #ifndef DOS
166 _argc = argc;
167 _argv = argv;
168 #endif
169
170 #if defined(PLATFORM_MACOSX)
171 {
172 /* OS X will give us a path in the form '/Applications/Rise of the Triad.app/Contents/MacOS/Rise of the Triad'.
173 Our data is in Contents/Resources. */
174 char *path;
175 const char suffix[] = "/Resources/";
176 int end;
177 path = (char *)malloc(strlen(argv[0]) + strlen(suffix) + 1);
178 if (path == NULL) return 1;
179 strcpy(path, argv[0]);
180 /* Back up two '/'s. */
181 for (end = strlen(path)-1; end >= 0 && path[end] != '/'; end--);
182 if (end >= 0) for (--end; end >= 0 && path[end] != '/'; end--);
183 strcpy(&path[end], suffix);
184 printf("Changing to working directory: %s\n", path);
185 chdir(path);
186 free(path);
187 }
188 #endif
189
190 #ifdef DC
191 platform_init();
192 #elif !defined(DOS)
193 signal (11, crash_print);
194
195 if (setup_homedir() == -1) return 1;
196 #endif
197
198 // Set which release version we're on
199 gamestate.Version = ROTTVERSION;
200
201 #if ( SHAREWARE == 1 )
202 gamestate.Product = ROTT_SHAREWARE;
203 #else
204 {
205 struct {
206 const char *file;
207 version_type ver;
208 } const list[] = {
209 {"ROTTSITE.RTC",ROTT_SITELICENSE},
210 {"ROTTCD.RTC",ROTT_SUPERCD},
211 {"DARKWAR.RTC",ROTT_REGISTERED},
212 {"HUNTBGIN.RTC",ROTT_SHAREWARE},
213 };
214 extern char * ROTTMAPS;
215 extern char * BATTMAPS;
216
217 int i;
218 for(i=0;i<sizeof(list)/sizeof(list[0])-1;i++) {
219 if (access(list[i].file,F_OK)==0) break;
220 }
221 gamestate.Product = list[i].ver;
222 BATTMAPS = list[i].file;
223 ROTTMAPS = list[i].ver==ROTT_SHAREWARE?"HUNTBGIN.RTL":"DARKWAR.RTL";
224 }
225 #endif
226
227 DrawRottTitle ();
228 gamestate.randomseed=-1;
229
230 gamestate.autorun = 0;
231 StartupSoftError();
232 // UL_ErrorStartup ();
233
234 CheckCommandLineParameters();
235
236 // Start up Memory manager with a certain amount of reserved memory
237
238 Z_Init(50000,1000000);
239
240 IN_Startup ();
241
242 InitializeGameCommands();
243 if (standalone==false)
244 {
245 ReadConfig ();
246 ReadSETUPFiles ();
247 doublestep=0;
248 SetupWads();
249 BuildTables ();
250 GetMenuInfo ();
251 }
252
253 // if (modemgame==true)
254 // {
255 // SCREENSHOTS=true;
256 // if (standalone==false)
257 // {
258 // MenuFixup ();
259 // }
260 // MAPSTATS=true;
261 // }
262 if (standalone==false)
263 {
264 int status1 = 0;
265 int status2 = 0;
266 int status3 = 0;
267
268 if ( !NoSound && !IS8250 )
269 {
270 if (!quiet)
271 printf( "MU_Startup: " );
272 status1 = MU_Startup(false);
273 if (!quiet)
274 printf( "%s\n", MUSIC_ErrorString( MUSIC_Error ) );
275 }
276 else if ( IS8250 )
277 {
278 printf( "==============================================================================\n");
279 printf( "WARNING: 8250 detected.\n" );
280 printf( "Music has been disabled. This is necessary to maintain high interrupt\n" );
281 printf( "rates with the 8250 UART which will improve overall game performance.\n");
282 printf( " < Press any key to continue >\n");
283 printf( "==============================================================================\n");
284 getch();
285 }
286
287 if (!NoSound)
288 {
289 int nv, nb, nc;
290
291 if (!quiet)
292 printf( "SD_SetupFXCard: " );
293 status2 = SD_SetupFXCard (&nv, &nb, &nc);
294 if (!quiet)
295 printf( "%s\n", FX_ErrorString( FX_Error ) );
296
297 if ( !status2 )
298 {
299 if (!quiet)
300 printf( "SD_Startup: " );
301 status3 = SD_Startup(false);
302 if (!quiet)
303 printf( "%s\n", FX_ErrorString( FX_Error ) );
304 }
305 }
306 else
307 {
308 if (!quiet)
309 printf( "Sound FX disabled.\n" );
310 }
311
312 if ( status1 || status2 || status3 )
313 {
314 printf( "\n\nROTT was unable to initialize your " );
315 if ( status1 )
316 {
317 printf( "music " );
318 MusicMode = 0;
319 }
320 if ( status2 || status3 )
321 {
322 if ( status1 )
323 {
324 printf( "or " );
325 }
326 printf( "sound fx " );
327
328 FXMode = 0;
329 }
330
331 printf( "hardware.\n"
332 "Now entering sound setup.\n" );
333 SOUNDSETUP = true;
334 }
335
336 Init_Tables ();
337 InitializeRNG ();
338 InitializeMessages();
339 LoadColorMap();
340 }
341 if (infopause==true)
342 {
343 printf("\n< Press any key to continue >\n");
344 getch();
345 }
346 I_StartupTimer();
347 I_StartupKeyboard();
348 #if 0
349 #if (SHAREWARE == 1)
350 if ((!SOUNDSETUP) && (standalone==false))
351 {
352 byte * txtscn;
353 int i;
354
355 for (i=0;i<20;i++)
356 printf("\n");
357 txtscn = (byte *) W_CacheLumpNum (W_GetNumForName ("rotts10"), PU_CACHE);
358 memcpy ((byte *)0xB8000, txtscn, 4000);
359 I_Delay (600);
360 }
361 #endif
362 #endif
363 locplayerstate = &PLAYERSTATE[consoleplayer];
364
365 if (standalone==true)
366 ServerLoop();
367
368 VL_SetVGAPlaneMode();
369 VL_SetPalette(origpal);
370
371 // SetTextMode();
372 // GraphicsMode();
373 // SetTextMode();
374 // VL_SetVGAPlaneMode();
375 // VL_SetPalette(origpal);
376 // SetBorderColor(155);
377 SetViewSize(8);
378
379 if ( SOUNDSETUP )
380 {
381 SwitchPalette( origpal, 35 );
382 CP_SoundSetup();
383 }
384
385 playstate = ex_titles;
386
387 // I_SetKeyboardLEDs( caps_lock, 0 );
388
389 gamestate.battlemode = battle_StandAloneGame;
390
391 BATTLE_SetOptions( &BATTLE_Options[ battle_StandAloneGame ] );
392
393 if (turbo || tedlevel)
394 {
395 if (modemgame == true)
396 {
397 turbo = false;
398 NoWait = true;
399 }
400 else
401 {
402 PlayTurboGame();
403 }
404 }
405 else
406 {
407 #if (SHAREWARE == 0)
408 if ( dopefish == true )
409 {
410 DopefishTitle();
411 }
412 else if ( NoWait == false )
413 {
414 ApogeeTitle();
415 }
416 #else
417 if ( NoWait == false )
418 {
419 if (W_CheckNumForName("svendor") != -1)
420 {
421 lbm_t * LBM;
422
423 LBM = (lbm_t *) W_CacheLumpName( "svendor", PU_CACHE, Cvt_lbm_t, 1);
424 VL_DecompressLBM (LBM,true);
425 I_Delay(40);
426 MenuFadeOut();
427 }
428 // ParticleIntro ();
429 ApogeeTitle();
430 }
431 #endif
432 }
433
434 GameLoop();
435
436
437 QuitGame();
438
439 return 0;
440 }
441
DrawRottTitle(void)442 void DrawRottTitle ( void )
443 {
444 char title[80];
445 char buf[5];
446
447 SetTextMode();
448 TurnOffTextCursor ();
449
450 if (CheckParm("QUIET") == 0)
451 {
452 SetTextMode();
453 TurnOffTextCursor ();
454 if (CheckParm ("SOUNDSETUP") == 0)
455 {
456 #ifdef ANSIESC
457 printf("\n\n\n");
458 #endif
459 strcpy (title,"Rise of the Triad Startup Version ");
460 strcat (title,itoa(ROTTMAJORVERSION,&buf[0],10));
461 strcat (title,".");
462 //MED
463 #if (SHAREWARE==1)||(DOPEFISH==0)
464 strcat (title,itoa(ROTTMINORVERSION,&buf[0],10));
465 #else
466 strcat (title,"DFISH");
467 #endif
468 #ifndef ANSIESC
469 strcat (title,"\n");
470 #endif
471
472 px=(80-strlen(title))>>1;
473 py=0;
474
475 UL_printf(title);
476
477 memset (title,0,sizeof(title));
478
479 if (gamestate.Product == ROTT_SHAREWARE)
480 {
481 #if (DELUXE==1)
482 strcpy(title,"Lasersoft Deluxe Version");
483 #elif (LOWCOST==1)
484 strcpy(title,"Episode One");
485 #else
486 strcpy(title,"Shareware Version");
487 #endif
488 }
489 else if (gamestate.Product == ROTT_SUPERCD)
490 strcpy(title,"CD Version");
491 else if (gamestate.Product == ROTT_SITELICENSE)
492 strcpy(title,"Site License CD Version");
493 else
494 strcpy(title,"Commercial Version");
495
496 px=(80-strlen(title))>>1;
497 py=1;
498
499 UL_printf(title);
500 #ifndef ANSIESC
501 printf ("\n");
502 #endif
503
504 UL_ColorBox (0, 0, 80, 2, 0x1e);
505 }
506 else
507 {
508 printf("\n\n");
509 strcpy (title,"Rise of the Triad Sound Setup Version ");
510 strcat (title,itoa(ROTTMAJORVERSION,&buf[0],10));
511 strcat (title,".");
512 strcat (title,itoa(ROTTMINORVERSION,&buf[0],10));
513
514 px=(80-strlen(title))>>1;
515 py=0;
516
517 UL_printf(title);
518
519 UL_ColorBox (0, 0, 80, 1, 0x1e);
520 }
521 }
522 else
523 {
524 TurnOffTextCursor ();
525 }
526
527 }
528
CheckCommandLineParameters(void)529 void CheckCommandLineParameters( void )
530 {
531 char *PStrings[] = {"TEDLEVEL","NOWAIT","NOSOUND","NOW",
532 "TRANSPORT","DOPEFISH","SCREENSHOTS",
533 "MONO","MAPSTATS","TILESTATS","VER","net",
534 "PAUSE","SOUNDSETUP","WARP","IS8250","ENABLEVR",
535 "TIMELIMIT","MAXTIMELIMIT","NOECHO","DEMOEXIT","QUIET",NULL};
536 int i,n;
537
538 infopause=false;
539 SOUNDSETUP = false;
540 tedlevel=false;
541 NoWait=false;
542 NoSound=false;
543 turbo=false;
544 warp=false;
545 dopefish=false;
546 modemgame=false;
547 SCREENSHOTS=false;
548 MONOPRESENT=false;
549 MAPSTATS=false;
550 TILESTATS=false;
551 IS8250 = false;
552 vrenabled = false;
553 demoexit = false;
554
555 modemgame=false;
556 networkgame=false;
557 consoleplayer=0;
558 numplayers = 1;
559 timelimit=-1;
560 timelimitenabled=false;
561 noecho = false;
562 quiet = false;
563
564 if (
565 (CheckParm("?\0")) ||
566 (CheckParm("HELP")) ||
567 (
568 (_argc>1) &&
569 (_argv[1][0]=='?')
570 )
571 )
572 {
573 SetTextMode ();
574 printf ("Rise of the Triad (c) 1995 Apogee Software\n\n");
575 printf ("COMMAND LINE PARAMETERS\n");
576 printf (" SPACEBALL - Enable check for Spaceball.\n");
577 printf (" NOJOYS - Disable check for joystick.\n");
578 printf (" NOMOUSE - Disable check for mouse.\n");
579 printf (" CYBERMAN - Enable check for Cyberman.\n");
580 printf (" ASSASSIN - Enable check for Wingman Assassin.\n");
581 printf (" VER - Version number.\n");
582 printf (" MAPSTATS - Dump Map statistics to ERROR.\n");
583 printf (" TILESTATS - Dump Tile statistics to ERROR.\n");
584 printf (" MONO - Enable mono-monitor support.\n");
585 printf (" SCREENSHOTS- Clean screen capture for shots.\n");
586 printf (" PAUSE - Pauses startup screen information.\n");
587 printf (" SOUNDSETUP - Setup sound for ROTT\n");
588 printf (" ENABLEVR - Enable VR helmet input devices\n");
589 printf (" NOECHO - Turn off sound reverb\n");
590 printf (" DEMOEXIT - Exit program when demo is terminated\n");
591 printf (" WARP - Warp to specific ROTT level\n");
592 printf (" next paramater is level to start on\n");
593 printf (" TIMELIMIT - Play ROTT in time limit mode\n");
594 printf (" next paramater is time in seconds\n");
595 printf (" MAXTIMELIMIT - Maximimum time to count down from\n");
596 printf (" next paramater is time in seconds\n");
597 printf (" DOPEFISH - ?\n");
598 exit (0);
599 }
600
601 // Check For command line parameters
602
603 for (i = 1;i < _argc;i++)
604 {
605 n = US_CheckParm(_argv[i],PStrings);
606 switch(n)
607 {
608 #if (TEDLAUNCH==1)
609 case 0:
610 tedlevelnum = ParseNum(_argv[i + 1]);
611 tedlevel=true;
612 if (i+3>=_argc)
613 {
614 tedx=0;
615 tedy=0;
616 }
617 else
618 {
619 tedx=ParseNum(_argv[i + 2]);
620 tedy=ParseNum(_argv[i + 3]);
621 }
622 MenuFixup ();
623 break;
624 #endif
625 case 1:
626 NoWait = true;
627 break;
628 case 2:
629 NoSound = true;
630 break;
631 case 3:
632 turbo = true;
633 break;
634 case 4:
635 warp = true;
636 warpx=ParseNum(_argv[i + 1]);
637 warpy=ParseNum(_argv[i + 2]);
638 warpa=ParseNum(_argv[i + 3]);
639 break;
640 case 5:
641 dopefish=true;
642 break;
643 case 6:
644 SCREENSHOTS = true;
645 break;
646 case 7:
647 MONOPRESENT = true;
648 break;
649 case 8:
650 MAPSTATS = true;
651 break;
652 case 9:
653 TILESTATS = true;
654 break;
655 case 10:
656 SetTextMode ();
657 printf ("Rise of the Triad (c) 1995 Apogee Software\n");
658 //MED
659 if (gamestate.Product == ROTT_SHAREWARE)
660 {
661 #if (DELUXE==1)
662 printf("Lasersoft Deluxe ");
663 #elif (LOWCOST==1)
664 printf("Episode One ");
665 #else
666 printf("Shareware ");
667 #endif
668 }
669 else if (gamestate.Product == ROTT_SUPERCD)
670 printf("CD ");
671 else if (gamestate.Product == ROTT_SITELICENSE)
672 printf("Site License ");
673 else
674 printf("Commercial ");
675 printf ("Version %d.%d\n", ROTTMAJORVERSION,ROTTMINORVERSION);
676 exit (0);
677 break;
678 case 11:
679 InitROTTNET();
680 numplayers = rottcom->numplayers;
681 if (numplayers>MAXPLAYERS)
682 Error("Too many players.\n");
683 if (!quiet)
684 printf("Playing %ld player ROTT\n",(long int)numplayers);
685 modemgame=true;
686 if (rottcom->gametype==NETWORK_GAME)
687 {
688 if (!quiet)
689 printf("NETWORK GAME\n");
690 networkgame=true;
691 }
692 else
693 {
694 if (!quiet)
695 printf("MODEM GAME\n");
696 }
697 break;
698 case 12:
699 infopause=true;
700 break;
701 case 13:
702 SOUNDSETUP = true;
703 break;
704 case 14:
705 startlevel = (ParseNum(_argv[i + 1])-1);
706 break;
707 case 15:
708 IS8250 = true;
709 break;
710 case 16:
711 vrenabled = true;
712 if (!quiet)
713 printf("Virtual Reality Mode enabled\n");
714 break;
715 case 17:
716 timelimitenabled = true;
717 timelimit = ParseNum(_argv[i + 1]);
718 if (!quiet)
719 printf("Time Limit = %ld Seconds\n",(long int)timelimit);
720 timelimit *= VBLCOUNTER;
721 break;
722
723 case 18:
724 maxtimelimit = ParseNum(_argv[i + 1]);
725 maxtimelimit *= VBLCOUNTER;
726 break;
727 case 19:
728 noecho = true;
729 break;
730 case 20:
731 demoexit = true;
732 break;
733 case 21:
734 quiet = true;
735 break;
736 }
737 }
738 }
739
SetupWads(void)740 void SetupWads( void )
741 {
742 char *newargs[99];
743 int argnum = 0;
744 #if (SHAREWARE==0)
745 int arg;
746 #endif
747 char tempstr[129];
748
749 #if (SHAREWARE==0)
750
751 // Check for User wads
752
753 arg = CheckParm ("file");
754 if (arg!=0)
755 {
756 newargs [argnum++] = _argv[arg+1];
757 }
758
759 arg = CheckParm ("file1");
760 if (arg!=0)
761 {
762 newargs [argnum++] = _argv[arg+1];
763 }
764
765 arg = CheckParm ("file2");
766 if (arg!=0)
767 {
768 newargs [argnum++] = _argv[arg+1];
769 }
770
771 #else
772 if (
773 (CheckParm ("file") > 0) ||
774 (CheckParm ("file1") > 0) ||
775 (CheckParm ("file2") > 0)
776 )
777 printf("External wads ignored.\n");
778
779 #endif
780
781 // Normal ROTT wads
782
783 if (isSHAREWARE)
784 newargs [argnum++] = "huntbgin.wad";
785 else
786 newargs [argnum++] = "darkwar.wad";
787
788 // newargs [argnum++] = "credits.wad";
789
790 // Check for Remote Ridicule WAD
791
792 if (RemoteSounds.avail == true)
793 {
794 char *src;
795
796 strcpy (tempstr,RemoteSounds.path);
797 src = RemoteSounds.path + strlen(RemoteSounds.path) - 1;
798 if (*src != '\\')
799 strcat (tempstr,"\\\0");
800 strcat (tempstr,RemoteSounds.file);
801 newargs [argnum++] = tempstr;
802 }
803 else
804 {
805 newargs [argnum++] = "remote1.rts";
806 }
807
808 newargs [argnum++] = NULL;
809
810 W_InitMultipleFiles(newargs);
811 }
812
PlayTurboGame(void)813 void PlayTurboGame
814 (
815 void
816 )
817
818 {
819 NewGame = true;
820 locplayerstate->player = DefaultPlayerCharacter;
821 playstate = ex_resetgame;
822 GameLoop();
823 }
824
825
826 //***************************************************************************
827 //
828 // Init_Tables () - Init tables needed for double buffering
829 //
830 //***************************************************************************
831
Init_Tables(void)832 void Init_Tables (void)
833 {
834 int i;
835 int x,
836 y;
837 unsigned *blockstart;
838 byte * shape;
839
840 memset (&CWD[0], 0, 40);
841 getcwd (CWD, 40); // get the current directory
842
843 origpal=SafeMalloc(768);
844 memcpy (origpal, W_CacheLumpName("pal",PU_CACHE, CvtNull, 1), 768);
845
846 FindEGAColors();
847
848 for (i=0;i<PORTTILESHIGH;i++)
849 uwidthtable[i] = UPDATEWIDE*i;
850
851 updateptr = &update[0];
852
853 blockstart = &blockstarts[0];
854 for (y=0;y<UPDATEHIGH;y++)
855 for (x=0;x<UPDATEWIDE;x++)
856 *blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH;
857
858 for (i = 0; i < 0x300; i++)
859 *(origpal+(unsigned int)i) = (*(origpal+(unsigned int)i))>>2;
860
861 // Cache in fonts
862 shape = W_CacheLumpNum (W_GetNumForName ("smallfont"), PU_STATIC, Cvt_font_t, 1);
863 smallfont = (font_t *)shape;
864 CurrentFont = smallfont;
865
866 // Cache in tiny font
867 shape = W_CacheLumpNum (W_GetNumForName ("tinyfont"), PU_STATIC, Cvt_font_t, 1);
868 tinyfont = (font_t *)shape;
869
870 intensitytable=W_CacheLumpNum(W_GetNumForName("menucmap"),PU_STATIC, CvtNull, 1);
871 fontcolor = egacolor[4];
872
873 if (!quiet)
874 printf("RT_MAIN: Fonts Initialized\n");
875 }
876
877
878
879
NumberOfTeams(void)880 int NumberOfTeams
881 (
882 void
883 )
884
885 {
886 int index;
887 int team[ MAXPLAYERCOLORS ];
888 int count;
889 int color;
890
891 memset( team, 0, sizeof( team ) );
892
893 count = 0;
894 for( index = 0; index < numplayers; index++ )
895 {
896 color = PLAYERSTATE[ index ].uniformcolor;
897 if ( !team[ color ] )
898 {
899 team[ color ] = true;
900 count++;
901 }
902 }
903
904 return( count );
905 }
906
GameLoop(void)907 void GameLoop (void)
908 {
909 boolean done = false;
910 boolean loadit = false;
911 int NextLevel;
912
913 wami(1);
914
915 while (1)
916 {
917 if ( playstate == ex_battledone )
918 {
919 while( damagecount > 0 )
920 {
921 DoBorderShifts();
922 }
923 damagecount = 0;
924 SetBorderColor (0);
925
926 StopWind();
927
928 ShutdownClientControls();
929
930 SD_Play (SD_LEVELDONESND);
931
932 if ( ( player->flags & FL_DOGMODE ) ||
933 ( gamestate.battlemode == battle_Eluder ) )
934 MU_StartSong(song_dogend);
935 else
936 MU_StartSong(song_endlevel);
937
938
939 VL_FillPalette(255,255,255);
940 VL_FadeIn(0,255,origpal,10);
941
942 BattleLevelCompleted( consoleplayer );
943
944 BATTLE_Shutdown();
945
946 Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
947
948 ingame = false;
949
950 if ( networkgame == true )
951 {
952 AddGameEndCommand ();
953 }
954
955 AdjustMenuStruct ();
956
957 CalcTics();
958 CalcTics();
959
960 playstate = ex_titles;
961 }
962
963 switch (playstate)
964 {
965 case ex_titles:
966 BATTLE_Shutdown();
967 MU_StartSong(song_title);
968 if ((NoWait==false)&&(!modemgame))
969 {
970 byte dimpal[768];
971 int i;
972
973 for (i = 0; i < 0x300; i++)
974 dimpal[i] = origpal[i]>>2;
975 CalcTics();
976 CalcTics();
977 IN_ClearKeysDown ();
978 while (IN_GetMouseButtons()) {}
979 while ((!LastScan) && (!IN_GetMouseButtons()))
980 {
981 int i;
982 unsigned tempbuf;
983 MenuFadeOut();
984 ClearGraphicsScreen();
985 SetPalette(&dimpal[0]);
986 PlayMovie ("shartitl", true);
987 if ( ( LastScan ) || ( IN_GetMouseButtons() ) )
988 {
989 break;
990 }
991
992 PlayMovie ("shartit2", true);
993
994 if ( ( LastScan ) || ( IN_GetMouseButtons() ) )
995 {
996 break;
997 }
998 SD_Play (SD_LIGHTNINGSND);
999 MenuFadeIn();
1000 I_Delay(30);
1001 SD_Play (SD_ACTORSQUISHSND);
1002 tempbuf=bufferofs;
1003 bufferofs=displayofs;
1004 DrawNormalSprite(320-94,200-41,W_GetNumForName("rsac"));
1005 bufferofs=tempbuf;
1006 I_Delay(30);
1007
1008 if ( ( LastScan ) || ( IN_GetMouseButtons() ) )
1009 {
1010 break;
1011 }
1012
1013 DoCreditScreen ();
1014 if ((!LastScan) && (!IN_GetMouseButtons()))
1015 CheckHighScore (0, 0, false);
1016 #if (SHAREWARE==0)
1017 if ((!LastScan) && (!IN_GetMouseButtons()))
1018 {
1019 DoMicroStoryScreen ();
1020 }
1021 #endif
1022 if (
1023 (!LastScan) &&
1024 (!IN_GetMouseButtons()) &&
1025 (lowmemory==0) &&
1026 (GameLevels.avail==false)
1027 )
1028 {
1029 if (demonumber==-1)
1030 demonumber=RandomNumber("GameLoop",0);
1031 for (i=0;i<4;i++)
1032 {
1033 demonumber=(demonumber+1)%4;
1034 if (DemoExists (demonumber+1) == true)
1035 break;
1036 }
1037 if (DemoExists (demonumber+1) == true)
1038 {
1039 ingame=true;
1040 LoadDemo (demonumber+1);
1041 break;
1042 }
1043 }
1044 }
1045 }
1046
1047 if (playstate != ex_demoplayback)
1048 {
1049 if (demoexit == true)
1050 {
1051 QuitGame();
1052 }
1053 NoWait = false;
1054 SwitchPalette(origpal,35);
1055 CP_MainMenu();
1056 }
1057 break;
1058
1059 case ex_resetgame:
1060 InitCharacter();
1061
1062 InitializeMessages();
1063
1064 fizzlein = true;
1065 BATTLE_GetSpecials();
1066 BATTLE_SetOptions( &BATTLE_Options[ gamestate.battlemode ] );
1067
1068 if ( modemgame == true )
1069 {
1070 fizzlein = false;
1071
1072 if ( consoleplayer == 0 )
1073 {
1074 // Setup Master
1075 SetupGameMaster();
1076 }
1077 else
1078 {
1079 // Setup slave
1080 SetupGamePlayer();
1081 }
1082
1083 if ( gamestate.Version < ROTTVERSION )
1084 {
1085 Error( "This version of Rise of the Triad (%d.%d) is incompatible with\n"
1086 "version %d.%d.", ROTTMAJORVERSION, ROTTMINORVERSION,
1087 gamestate.Version / 10, gamestate.Version % 10 );
1088 }
1089 if ( gamestate.teamplay )
1090 {
1091 int teams;
1092
1093 teams = NumberOfTeams();
1094 if ( gamestate.battlemode == battle_CaptureTheTriad )
1095 {
1096 if ( teams != 2 )
1097 {
1098 CP_CaptureTheTriadError();
1099 playstate = ex_titles;
1100 continue;
1101 }
1102 }
1103 else if ( teams < 2 )
1104 {
1105 CP_TeamPlayErrorMessage();
1106 playstate = ex_titles;
1107 continue;
1108 }
1109 }
1110 }
1111
1112 InitCharacter();
1113
1114 BATTLE_Init( gamestate.battlemode, numplayers );
1115
1116 NewGame = true;
1117
1118 if ( ( BATTLEMODE ) && ( BATTLE_ShowKillCount ) )
1119 {
1120 StatusBar |= STATUS_KILLS;
1121 }
1122 else
1123 {
1124 StatusBar &= ~STATUS_KILLS;
1125 }
1126
1127 if (loadedgame == false)
1128 {
1129 if ( !BATTLEMODE )
1130 {
1131 PlayCinematic();
1132 }
1133
1134 SetupGameLevel();
1135 }
1136
1137 IN_ClearKeyboardQueue();
1138
1139 SetupScreen (true);
1140
1141 MenuFixup ();
1142 playstate=ex_stillplaying;
1143 break;
1144
1145 case ex_stillplaying:
1146 InitializeMessages();
1147
1148 SHAKETICS = 0xFFFF;
1149 if (modemgame==true)
1150 {
1151 ComSetTime();
1152 turbo = false;
1153 }
1154 else if (turbo==true)
1155 turbo=false;
1156 else
1157 newlevel=true;
1158 PlayLoop ();
1159 break;
1160
1161 case ex_died:
1162 loadit = done = false;
1163
1164 Died ();
1165 StopWind();
1166
1167 while (damagecount>0)
1168 DoBorderShifts();
1169
1170 damagecount = 0;
1171 SetBorderColor (0);
1172 if (demorecord)
1173 {
1174 FreeDemo ();
1175 }
1176 if (demoplayback)
1177 {
1178 FreeDemo ();
1179 playstate=ex_demodone;
1180 }
1181 else
1182 {
1183 ShutdownClientControls();
1184
1185 Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
1186
1187 if (CheckForQuickLoad()==false)
1188 {
1189 if (locplayerstate->lives < 0)
1190 {
1191 if (timelimitenabled == false)
1192 {
1193 CheckHighScore (gamestate.score, gamestate.mapon+1, false);
1194 playstate = ex_titles;
1195 AdjustMenuStruct ();
1196 ingame = false;
1197 locplayerstate->health = MaxHitpointsForCharacter(locplayerstate);
1198 gamestate.score = 0;
1199 locplayerstate->lives = 3;
1200 locplayerstate->weapon = wp_pistol;
1201 locplayerstate->triads = 0;
1202 UpdateLives (locplayerstate->lives);
1203 UpdateScore (gamestate.score);
1204 }
1205 else
1206 {
1207 QuitGame();
1208 }
1209 }
1210 else
1211 {
1212 fizzlein = true;
1213 SetupGameLevel ();
1214 UpdateTriads(player,0);
1215 playstate = ex_stillplaying;
1216 }
1217 }
1218 }
1219 break;
1220
1221 case ex_warped:
1222 StopWind();
1223 TurnShakeOff();
1224 SHAKETICS = 0xffff;
1225 gamestate.TimeCount = 0;
1226 gamestate.frame=0;
1227
1228 Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
1229
1230 fizzlein = true;
1231 SetupGameLevel ();
1232
1233 playstate = ex_stillplaying;
1234 break;
1235
1236 case ex_skiplevel:
1237 case ex_secretdone:
1238 case ex_secretlevel:
1239 case ex_completed:
1240 case ex_bossdied:
1241
1242 ShutdownClientControls();
1243 TurnShakeOff();
1244 SHAKETICS = 0xffff;
1245 if (timelimitenabled == false)
1246 {
1247 gamestate.TimeCount = 0;
1248 gamestate.frame=0;
1249 }
1250 StopWind();
1251 #if (SHAREWARE==0)
1252 if ((playstate==ex_bossdied) && (gamestate.mapon!=30))
1253 {
1254 int shape;
1255 lbm_t * LBM;
1256 byte *s;
1257 patch_t *p;
1258 char str[50];
1259 int width, height;
1260
1261 LBM = (lbm_t *) W_CacheLumpName( "deadboss", PU_CACHE, Cvt_lbm_t, 1);
1262 VL_DecompressLBM (LBM,false);
1263 MenuFadeOut();
1264 switch (gamestate.mapon)
1265 {
1266 case 6:
1267 shape = W_GetNumForName("deadstev");
1268 break;
1269 case 14:
1270 shape = W_GetNumForName("deadjoe");
1271 break;
1272 case 22:
1273 shape = W_GetNumForName("deadrobo");
1274 break;
1275 case 33:
1276 shape = W_GetNumForName("deadtom");
1277 break;
1278 // default:
1279 // Error("Boss died on an illegal level\n");
1280 // break;
1281 }
1282 s = W_CacheLumpNum (shape, PU_CACHE, Cvt_patch_t, 1);
1283 p = (patch_t *)s;
1284 DrawNormalSprite ((320-p->origsize)>>1, (230-(p->height-p->topoffset))>>1, shape);
1285 switch (gamestate.mapon)
1286 {
1287 case 6:
1288 strcpy(&str[0],"\"General\" John Darian");
1289 break;
1290 case 14:
1291 strcpy(&str[0],"Sebastian \"Doyle\" Krist");
1292 break;
1293 case 22:
1294 strcpy(&str[0],"the NME");
1295 break;
1296 case 33:
1297 strcpy(&str[0],"El Oscuro");
1298 break;
1299 // default:
1300 // Error("Boss died on an illegal level\n");
1301 // break;
1302 }
1303 CurrentFont=smallfont;
1304 US_MeasureStr (&width, &height, str);
1305 US_ClippedPrint ((320-width)>>1, 180, str);
1306 VW_UpdateScreen();
1307 MenuFadeIn();
1308
1309 WaitKeyUp();
1310 LastScan = 0;
1311 while (!LastScan)
1312 ;
1313 LastScan=0;
1314 }
1315 #endif
1316 LevelCompleted ( playstate );
1317
1318 NextLevel = GetNextMap(player->tilex,player->tiley);
1319
1320 demoplayback = false;
1321
1322 Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
1323 if (NextLevel != -1 )
1324 {
1325 gamestate.mapon = NextLevel;
1326 PlayCinematic();
1327 fizzlein = true;
1328 SetupGameLevel ();
1329 playstate = ex_stillplaying;
1330 }
1331 else
1332 {
1333 playstate = ex_gameover;
1334 }
1335 break;
1336
1337 case ex_demodone:
1338 ingame=false;
1339 ShutdownClientControls();
1340 TurnShakeOff();
1341 SHAKETICS = 0xffff;
1342 gamestate.TimeCount = 0;
1343 gamestate.frame=0;
1344
1345 demoplayback = false;
1346
1347 Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
1348 playstate=ex_titles;
1349 break;
1350
1351 case ex_gameover:
1352 StopWind();
1353 DoEndCinematic();
1354 if (playstate==ex_gameover)
1355 {
1356 CheckHighScore (gamestate.score, gamestate.mapon+1, false);
1357
1358 ingame = false;
1359 AdjustMenuStruct ();
1360 playstate = ex_titles;
1361 }
1362 break;
1363
1364 case ex_demorecord:
1365 ShutdownClientControls();
1366 Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
1367
1368 RecordDemo();
1369 SetupGameLevel ();
1370
1371 fizzlein = true;
1372 playstate = ex_stillplaying;
1373 break;
1374
1375 case ex_demoplayback:
1376 ShutdownClientControls();
1377 Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
1378
1379 SetupDemo();
1380 SetupGameLevel ();
1381
1382 fizzlein = true;
1383 playstate = ex_stillplaying;
1384 break;
1385 default:
1386 ;
1387 }
1388 }
1389 waminot();
1390 }
1391
CheckForQuickLoad(void)1392 boolean CheckForQuickLoad
1393 (
1394 void
1395 )
1396
1397 {
1398 if ( pickquick )
1399 {
1400 SetupMenuBuf();
1401
1402 pickquick = CP_DisplayMsg( "\nQuick load saved game?\n", 12 );
1403 if ( pickquick )
1404 {
1405 AllocateSavedScreenPtr();
1406 CP_LoadGame( 1, 1 );
1407 FreeSavedScreenPtr();
1408 }
1409 else
1410 {
1411 // Erase the quick load message
1412 VL_FadeOut( 0, 255, 0, 0, 0, 20 );
1413 }
1414
1415 ShutdownMenuBuf();
1416 }
1417
1418 return( pickquick );
1419 }
1420
1421 //===========================================================================
1422
ShutDown(void)1423 void ShutDown ( void )
1424 {
1425 if ( ( standalone == false ) || ( SOUNDSETUP ) )
1426 {
1427 WriteConfig ();
1428 }
1429
1430 // if (
1431 // (networkgame==false) &&
1432 // (modemgame==true)
1433 // )
1434 // {
1435 // ShutdownModemGame ();
1436 // }
1437
1438 ShutdownClientControls();
1439 I_ShutdownKeyboard();
1440 #ifdef DOS /* the UL_ErrorStartup() call is commented out... */
1441 UL_ErrorShutdown ();
1442 #endif
1443 ShutdownGameCommands();
1444 MU_Shutdown();
1445 I_ShutdownTimer();
1446 SD_Shutdown();
1447 IN_Shutdown ();
1448 ShutdownSoftError ();
1449 Z_ShutDown();
1450 // _settextcursor (0x0607);
1451 }
1452
1453 //===========================================================================
1454
1455 #if (DEVELOPMENT == 1)
1456 extern int totallevelsize;
1457 #endif
1458
QuitGame(void)1459 void QuitGame ( void )
1460 {
1461 #if (DEBUG == 1)
1462 char buf[5];
1463 #endif
1464
1465 #if (DEVELOPMENT == 1)
1466 int temp;
1467 #else
1468 byte *txtscn;
1469 #endif
1470 int k;
1471
1472 MU_FadeOut(200);
1473 while (MU_FadeActive())
1474 {
1475 int time=GetTicCount();
1476 while (GetTicCount()==time) {}
1477 }
1478
1479 PrintMapStats();
1480 PrintTileStats();
1481 SetTextMode();
1482
1483 #if (DEVELOPMENT == 1)
1484 printf("Clean Exit\n");
1485 if (gamestate.TimeCount)
1486 {
1487 temp=(gamestate.frame*VBLCOUNTER*100)/gamestate.TimeCount;
1488 printf("fps = %2ld.%2ld\n",temp/100,temp%100);
1489 }
1490 printf("argc=%ld\n",_argc);
1491 for (k=0;k<_argc;k++) printf("%s\n",_argv[k]);
1492 switch( _heapchk() )
1493 {
1494 case _HEAPOK:
1495 printf( "OK - heap is good\n" );
1496 break;
1497 case _HEAPEMPTY:
1498 printf( "OK - heap is empty\n" );
1499 break;
1500 case _HEAPBADBEGIN:
1501 printf( "ERROR - heap is damaged\n" );
1502 break;
1503 case _HEAPBADNODE:
1504 printf( "ERROR - bad node in heap\n" );
1505 break;
1506 }
1507 printf("\nLight Characteristics\n");
1508 printf("---------------------\n");
1509 if (fog)
1510 printf("FOG is ON\n");
1511 else
1512 printf("FOG is OFF\n");
1513 printf("LIGHTLEVEL=%ld\n",GetLightLevelTile());
1514 printf("LIGHTRATE =%ld\n",GetLightRateTile());
1515 printf("\nCENTERY=%ld\n",centery);
1516 #else
1517 if ( !SOUNDSETUP )
1518 {
1519 #if (SHAREWARE==0)
1520 txtscn = (byte *) W_CacheLumpNum (W_GetNumForName ("regend"), PU_CACHE, CvtNull, 1);
1521 #else
1522 txtscn = (byte *) W_CacheLumpNum (W_GetNumForName ("shareend"), PU_CACHE, CvtNull, 1);
1523 #endif
1524 #if DOS
1525 for (k = 0; k < 23; k++)
1526 printf ("\n");
1527 memcpy ((byte *)0xB8000, txtscn, 4000);
1528 #elif defined (ANSIESC)
1529 DisplayTextSplash (txtscn, 25);
1530 #endif
1531
1532 #if (DEBUG == 1)
1533 px = ERRORVERSIONCOL;
1534 py = ERRORVERSIONROW;
1535 #if (BETA == 1)
1536 UL_printf ("�");
1537 #else
1538 UL_printf (itoa(ROTTMAJORVERSION,&buf[0],10));
1539 #endif
1540 // Skip the dot
1541 px++;
1542
1543 UL_printf (itoa(ROTTMINORVERSION,&buf[0],10));
1544 #endif
1545 }
1546 #endif
1547
1548 if ( SOUNDSETUP )
1549 {
1550 printf( "\nSound setup complete.\n"
1551 "Type ROTT to run the game.\n" );
1552 }
1553 ShutDown();
1554 #ifdef DC
1555 platform_exit(); // save ramdisk to vmu
1556 #endif
1557
1558 exit(0);
1559 }
1560
InitCharacter(void)1561 void InitCharacter
1562 (
1563 void
1564 )
1565
1566 {
1567 locplayerstate->health = MaxHitpointsForCharacter( locplayerstate );
1568 if (timelimitenabled == true)
1569 {
1570 locplayerstate->lives = 1;
1571 }
1572 else
1573 {
1574 locplayerstate->lives = 3;
1575 }
1576
1577 ClearTriads (locplayerstate);
1578 locplayerstate->playerheight = characters[ locplayerstate->player ].height;
1579 // locplayerstate->stepwhich = 0;
1580 // locplayerstate->steptime = 0;
1581
1582 gamestate.score = 0;
1583
1584 if ( gamestate.battlemode == battle_StandAloneGame )
1585 {
1586 gamestate.mapon = startlevel;
1587 gamestate.difficulty = DefaultDifficulty;
1588 }
1589 else
1590 {
1591 gamestate.difficulty = gd_hard;
1592 }
1593
1594 gamestate.dipballs = 0;
1595 gamestate.TimeCount = 0;
1596
1597 godmode = 0;
1598 damagecount = 0;
1599
1600 UpdateScore( gamestate.score );
1601 }
1602
1603
1604
1605
UpdateGameObjects(void)1606 void UpdateGameObjects ( void )
1607 {
1608 int j;
1609 volatile int atime;
1610 objtype * ob,*temp;
1611 battle_status BattleStatus;
1612
1613 wami(2);
1614
1615 if (controlupdatestarted==0)
1616 {
1617 return;
1618 waminot();
1619 }
1620
1621 atime=GetFastTics();
1622
1623 UpdateClientControls ();
1624
1625 if (demoplayback == false)
1626 PollControls ();
1627
1628 CalcTics ();
1629
1630 UpdateClientControls ();
1631
1632
1633 while (oldpolltime<oldtime)
1634 {
1635 UpdateClientControls ();
1636 MoveDoors();
1637 ProcessElevators();
1638 MovePWalls();
1639 UpdateLightning ();
1640 TriggerStuff();
1641 CheckCriticalStatics();
1642 for(j=0;j<numclocks;j++)
1643 if (Clocks[j].time1 &&
1644 ((gamestate.TimeCount == Clocks[j].time1) ||
1645 (gamestate.TimeCount == Clocks[j].time2)))
1646 TRIGGER[Clocks[j].linkindex]=1;
1647 for (ob = firstactive; ob;)
1648 {
1649 temp = ob->nextactive;
1650 DoActor (ob);
1651 #if (DEVELOPMENT == 1)
1652 if ((ob->x<=0) || (ob->y<=0))
1653 Error("object xy below zero obj->x=%ld obj->y=%ld obj->obclass=%ld\n",ob->x,ob->y,ob->obclass);
1654 if ((ob->angle<0) || (ob->angle>=FINEANGLES))
1655 Error("object angle below zero obj->angle=%ld obj->obclass=%ld\n",ob->angle,ob->obclass);
1656 #endif
1657 ob = temp;
1658 }
1659
1660 BattleStatus = BATTLE_CheckGameStatus( battle_refresh, 0 );
1661 if ( BattleStatus != battle_no_event )
1662 {
1663 switch( BattleStatus )
1664 {
1665 case battle_end_game :
1666 case battle_out_of_time :
1667 playstate = ex_battledone;
1668 break;
1669
1670 case battle_end_round :
1671 SetWhoHaveWeapons();
1672 break;
1673 default:
1674 ;
1675 }
1676 if ( playstate == ex_battledone )
1677 {
1678 break;
1679 }
1680 }
1681 #if (SYNCCHECK == 1)
1682 CheckForSyncCheck();
1683 #endif
1684 if (timelimitenabled == true)
1685 {
1686 if (timelimit-gamestate.TimeCount>maxtimelimit)
1687 timelimit = maxtimelimit+gamestate.TimeCount;
1688 if (gamestate.TimeCount == timelimit)
1689 {
1690 locplayerstate->lives=-1;
1691 playstate=ex_died;
1692 }
1693 }
1694
1695 gamestate.TimeCount ++;
1696
1697 ResetCurrentCommand();
1698
1699 oldpolltime++;
1700 if (GamePaused==true)
1701 break;
1702 }
1703 actortime=GetFastTics()-atime;
1704
1705 UpdateClientControls ();
1706
1707 if (noecho == false)
1708 {
1709 if ( player->flags & FL_SHROOMS )
1710 {
1711 FX_SetReverb( 230 );
1712 }
1713 else if (sky == 0)
1714 {
1715 FX_SetReverb( min( numareatiles[ player->areanumber ] >> 1, 90 ) );
1716 }
1717 }
1718
1719 waminot();
1720
1721 }
1722
1723
PauseLoop(void)1724 void PauseLoop ( void )
1725 {
1726 StopWind();
1727
1728 UpdateClientControls ();
1729
1730 while (oldpolltime<oldtime)
1731 {
1732 CheckUnPause();
1733 #if (SYNCCHECK == 1)
1734 CheckForSyncCheck();
1735 #endif
1736 oldpolltime++;
1737 if (GamePaused==false)
1738 {
1739 break;
1740 }
1741 }
1742
1743 CalcTics ();
1744 if (demoplayback==false)
1745 PollControls ();
1746
1747 if ((RefreshPause == true) &&
1748 (GamePaused == true) &&
1749 ((GetTicCount() - pausedstartedticcount) >= blanktime))
1750 {
1751 RefreshPause = false;
1752 StartupScreenSaver();
1753 }
1754 }
1755
1756
1757
PlayLoop(void)1758 void PlayLoop
1759 (
1760 void
1761 )
1762
1763 {
1764 volatile int atime;
1765
1766 boolean canquit = true;
1767 int quittime = 0;
1768
1769 wami(3);
1770
1771
1772 if ( (loadedgame == false) && (timelimitenabled == false) )
1773 {
1774 gamestate.TimeCount = 0;
1775 gamestate.frame = 0;
1776 }
1777
1778 fromloadedgame:
1779
1780 GamePaused = false;
1781
1782 if ( loadedgame == false )
1783 {
1784 DrawPlayScreen( true );
1785 missobj = NULL;
1786 }
1787 else
1788 {
1789 loadedgame = false;
1790 DoLoadGameSequence();
1791 }
1792
1793 drawtime = 0;
1794 actortime = 0;
1795 tics = 0;
1796 SetFastTics(0);
1797
1798 if ( fizzlein == false )
1799 {
1800 StartupClientControls();
1801 }
1802 else
1803 {
1804 ShutdownClientControls();
1805 }
1806
1807 // set detail level
1808 doublestep = 2 - DetailLevel;
1809
1810 ResetMessageTime();
1811 DeletePriorityMessage( MSG_SYSTEM );
1812
1813 if ( ( gamestate.battlemode == battle_Normal ) &&
1814 ( numplayers == 1 ) )
1815 {
1816 AddMessage( "Comm-bat is for Modem and Network games.", MSG_GAME );
1817 AddMessage( "You will not be facing any", MSG_GAME );
1818 AddMessage( "opponents. Have fun and explore.", MSG_GAME );
1819 }
1820
1821
1822 while( playstate == ex_stillplaying )
1823 {
1824 UpdateClientControls();
1825
1826 if ( GamePaused )
1827 {
1828 PauseLoop();
1829
1830 atime = GetFastTics();
1831
1832 if ( RefreshPause )
1833 {
1834 ThreeDRefresh();
1835 }
1836 else
1837 {
1838 UpdateScreenSaver();
1839 }
1840 }
1841 else
1842 {
1843 if (controlupdatestarted == 1)
1844 UpdateGameObjects();
1845
1846 atime = GetFastTics();
1847
1848 ThreeDRefresh();
1849 }
1850
1851 SyncToServer();
1852
1853 drawtime = GetFastTics() - atime;
1854
1855 // Don't allow player to quit if entering message
1856 canquit = !MSG.messageon;
1857
1858 PollKeyboard();
1859
1860 MISCVARS->madenoise = false;
1861
1862 AnimateWalls();
1863
1864 UpdateClientControls();
1865
1866 #if (DEVELOPMENT == 1)
1867 Z_CheckHeap();
1868 #endif
1869
1870 if ( AutoDetailOn == true )
1871 {
1872 AdaptDetail();
1873 }
1874
1875 UpdateClientControls();
1876
1877 DoSprites();
1878 DoAnimatedMaskedWalls();
1879
1880 UpdatePlayers();
1881
1882 DrawTime( false );
1883
1884 UpdateClientControls();
1885
1886 if ( ( !BATTLEMODE ) && ( CP_CheckQuick( LastScan ) ) )
1887 {
1888 boolean escaped=false;
1889
1890 if (LastScan == sc_Escape)
1891 {
1892 MU_StoreSongPosition();
1893 MU_StartSong(song_menu);
1894 escaped = true;
1895 }
1896 TurnShakeOff();
1897 StopWind();
1898 SetBorderColor( 0 );
1899 ShutdownClientControls();
1900 if (demoplayback==true)
1901 {
1902 FreeDemo();
1903 playstate = ex_demodone;
1904 if (demoexit==true)
1905 {
1906 QuitGame();
1907 }
1908 return;
1909 }
1910
1911 ControlPanel( LastScan );
1912
1913 // set detail level
1914 doublestep = 2 - DetailLevel;
1915
1916 inmenu = false;
1917
1918 if ( playstate == ex_titles )
1919 {
1920 return;
1921 }
1922
1923 if ( playstate == ex_stillplaying )
1924 {
1925 SetupScreen( false );
1926 }
1927
1928 if ( loadedgame == true )
1929 {
1930 goto fromloadedgame;
1931 }
1932
1933 if (
1934 ( playstate == ex_stillplaying ) &&
1935 ( ( fizzlein == false ) ||
1936 ( GamePaused )
1937 )
1938 )
1939 {
1940 StartupClientControls();
1941 }
1942
1943 if (
1944 (playstate == ex_stillplaying) &&
1945 (GamePaused == false) &&
1946 (escaped == true)
1947 )
1948 {
1949 MU_StartSong(song_level);
1950 MU_RestoreSongPosition();
1951 }
1952 }
1953
1954 if ( BATTLEMODE )
1955 {
1956 if ( MSG.messageon == false )
1957 {
1958 CheckRemoteRidicule( LastScan );
1959 }
1960 if ( quitactive == false )
1961 {
1962 if ( ( LastScan == sc_Escape ) && ( canquit ) )
1963 {
1964 quitactive = true;
1965 quittime = GetTicCount() + QUITTIMEINTERVAL;
1966
1967 if ( (consoleplayer == 0) || (networkgame == false) )
1968 {
1969 AddMessage( "Do you want to end this game? "
1970 "(\\FY\\O/\\FN\\O)", MSG_QUIT );
1971 }
1972 else
1973 {
1974 AddMessage( "Do you want to exit to DOS? "
1975 "(\\FY\\O/\\EN\\O)", MSG_QUIT );
1976 }
1977 }
1978 }
1979 else
1980 {
1981 if ( GetTicCount() > quittime )
1982 {
1983 quitactive = false;
1984 }
1985 else if ( LastScan == sc_N )
1986 {
1987 DeletePriorityMessage( MSG_QUIT );
1988 quitactive = false;
1989 }
1990 else if ( LastScan == sc_Y )
1991 {
1992 DeletePriorityMessage( MSG_QUIT );
1993 if ( (consoleplayer == 0) || (networkgame==false) )
1994 {
1995 AddEndGameCommand();
1996 }
1997 else
1998 {
1999 AddQuitCommand();
2000 }
2001 }
2002 }
2003 }
2004 }
2005 waminot();
2006 }
2007
2008 //******************************************************************************
2009 //
2010 // CheckRemoteRidicule ()
2011 //
2012 //******************************************************************************
2013
CheckRemoteRidicule(int scancode)2014 void CheckRemoteRidicule ( int scancode )
2015 {
2016 int num=-1;
2017
2018 wami(4);
2019 switch (scancode)
2020 {
2021 case sc_F1:
2022 num=0;
2023 break;
2024 case sc_F2:
2025 num=1;
2026 break;
2027 case sc_F3:
2028 num=2;
2029 break;
2030 case sc_F4:
2031 num=3;
2032 break;
2033 case sc_F5:
2034 if ( !Keyboard[ sc_RShift ] )
2035 {
2036 num=4;
2037 }
2038 break;
2039 case sc_F6:
2040 num=5;
2041 break;
2042 case sc_F7:
2043 if ( !Keyboard[ sc_RShift ] )
2044 {
2045 num=6;
2046 }
2047 break;
2048 case sc_F8:
2049 num=7;
2050 break;
2051 case sc_F9:
2052 num=8;
2053 break;
2054 case sc_F10:
2055 num=9;
2056 break;
2057 }
2058 if (num>=0)
2059 {
2060 AddRemoteRidiculeCommand ( consoleplayer, MSG_DIRECTED_TO_ALL, num );
2061 LastScan=0;
2062 }
2063 waminot();
2064 }
2065
2066 //******************************************************************************
2067 //
2068 // DoBossKey ()
2069 //
2070 //******************************************************************************
2071
DoBossKey(void)2072 void DoBossKey ( void )
2073 {
2074 #ifdef DOS
2075 union REGS regs;
2076 ShutdownClientControls();
2077
2078 SetTextMode();
2079
2080 // move cursor to the row 0 column 4
2081 regs.w.ax = 0x0200;
2082 regs.w.bx = 0;
2083 regs.w.dx = 0x0004;
2084 int386(0x10,®s,®s);
2085 px=0;
2086 py=0;
2087 UL_printf("C:\\>\n");
2088
2089 LastScan = 0;
2090 IN_WaitForKey ();
2091 VL_SetVGAPlaneMode();
2092 VL_SetPalette(origpal);
2093 SetBorderColor(0);
2094 TurnShakeOff();
2095 SetupScreen(true);
2096 ThreeDRefresh();
2097
2098 StartupClientControls();
2099 #else
2100 STUB_FUNCTION;
2101 #endif
2102 }
2103
2104
2105 //******************************************************************************
2106 //
2107 // PollKeyboard ()
2108 //
2109 //******************************************************************************
2110
PollKeyboard(void)2111 void PollKeyboard
2112 (
2113 void
2114 )
2115
2116 {
2117 static char autopressed = false;
2118
2119 wami(5);
2120
2121 if (demoplayback==true)
2122 {
2123 IN_UpdateKeyboard();
2124 }
2125
2126 if ( !BATTLEMODE )
2127 {
2128 CheckDebug ();
2129 if (
2130 ( Keyboard[ sc_CapsLock ] ) &&
2131 ( DebugOk )
2132 )
2133 {
2134 DebugKeys ();
2135 }
2136 }
2137
2138 if ( locplayerstate->buttonstate[ bt_autorun ] )
2139 {
2140 if ( !autopressed )
2141 {
2142 autopressed = true;
2143 gamestate.autorun ^= 1;
2144 if ( gamestate.autorun == 0 )
2145 {
2146 AddMessage( "AutoRun is \\cOFF", MSG_SYSTEM );
2147 }
2148 else
2149 {
2150 AddMessage( "AutoRun is \\cON", MSG_SYSTEM );
2151 }
2152 }
2153 }
2154 else
2155 {
2156 autopressed = false;
2157 }
2158
2159 #if 0
2160 if ( modemgame == false )
2161 {
2162 CheckDevelopmentKeys();
2163 }
2164 #endif
2165
2166 if ( ( MSG.messageon == false ) && ( !quitactive ) )
2167 {
2168 if ( ( Keyboard[ buttonscan[ bt_message ] ] ) && ( BATTLEMODE ) )
2169 {
2170 // Send message to all
2171 MSG.messageon = true;
2172 MSG.directed = false;
2173 MSG.inmenu = false;
2174 MSG.remoteridicule = -1;
2175 MSG.towho = MSG_DIRECTED_TO_ALL;
2176 MSG.textnum = AddMessage( "_", MSG_MODEM );
2177 MSG.length = 1;
2178 DeletePriorityMessage( MSG_MACRO );
2179 }
2180 else if ( ( Keyboard[ buttonscan[ bt_directmsg ] ] ) && ( BATTLEMODE ) )
2181 {
2182 // Send directed message
2183 MSG.messageon = true;
2184 MSG.directed = true;
2185 MSG.inmenu = false;
2186 MSG.remoteridicule = -1;
2187 MSG.towho = 0;
2188 MSG.textnum = AddMessage( "_", MSG_MODEM );
2189 MSG.length = 1;
2190 DeletePriorityMessage( MSG_MACRO );
2191 }
2192 if ( buttonpoll[ bt_map ] )
2193 {
2194 if ( !BATTLEMODE )
2195 {
2196 // Automap
2197 StopWind();
2198 DoMap( player->tilex, player->tiley );
2199 }
2200 else
2201 {
2202 // Show kill counts
2203 if ( SHOW_KILLS() )
2204 {
2205 BATTLE_ShowKillCount = false;
2206 StatusBar &= ~STATUS_KILLS;
2207 }
2208 else
2209 {
2210 StatusBar |= STATUS_KILLS;
2211 BATTLE_ShowKillCount = true;
2212 }
2213
2214 SetupScreen( true );
2215 }
2216 }
2217
2218 // Shrink screen
2219 if ( Keyboard[ sc_Minus ] )
2220 {
2221 if ( viewsize > 0 )
2222 {
2223 viewsize--;
2224 SetupScreen( true );
2225 }
2226 }
2227
2228 // Expand screen
2229 if ( Keyboard[ sc_Plus ] )
2230 {
2231 if ( viewsize < MAXVIEWSIZES - 1 )
2232 {
2233 viewsize++;
2234 SetupScreen( true );
2235 }
2236 }
2237
2238 // Set detail
2239 if ( ( Keyboard[ sc_F5 ] ) && ( ( !BATTLEMODE ) ||
2240 ( Keyboard[ sc_RShift ] ) ) )
2241 {
2242 Keyboard[ sc_F5 ] = false;
2243 LastScan = 0;
2244 DetailLevel++;
2245 if ( DetailLevel > 2 )
2246 {
2247 DetailLevel = 0;
2248 }
2249
2250 switch( DetailLevel )
2251 {
2252 case 0 :
2253 AddMessage( "Low detail", MSG_SYSTEM );
2254 break;
2255
2256 case 1 :
2257 AddMessage( "Medium detail", MSG_SYSTEM );
2258 break;
2259
2260 case 2 :
2261 AddMessage( "High detail", MSG_SYSTEM );
2262 break;
2263 }
2264 doublestep = 2 - DetailLevel;
2265 }
2266
2267 // Turn messages on/off
2268
2269 if ( ( Keyboard[ sc_F7 ] ) && ( ( !BATTLEMODE ) ||
2270 ( Keyboard[ sc_RShift ] ) ) )
2271 {
2272 Keyboard[ sc_F7 ] = false;
2273 LastScan = 0;
2274 MessagesEnabled = !MessagesEnabled;
2275 if ( !MessagesEnabled )
2276 {
2277 AddMessage( "Messages disabled.", MSG_MSGSYSTEM );
2278 }
2279 else
2280 {
2281 AddMessage( "Messages enabled.", MSG_MSGSYSTEM );
2282 }
2283 }
2284
2285 if ( ( Keyboard[ sc_F6 ] ) && ( !BATTLEMODE ) )
2286 {
2287 Keyboard[ sc_F6 ] = false;
2288 if (Keyboard[sc_RShift])
2289 {
2290 ShutdownClientControls();
2291 UndoQuickSaveGame();
2292 StartupClientControls();
2293 }
2294 else if (quicksaveslot==-1)
2295 {
2296 ShutdownClientControls();
2297 LastScan=sc_F2;
2298 inmenu = true;
2299 ControlPanel( LastScan );
2300 StartupClientControls();
2301 }
2302 else
2303 {
2304 LastScan = 0;
2305 ShutdownClientControls();
2306 ThreeDRefresh();
2307 QuickSaveGame();
2308 StartupClientControls();
2309 }
2310 }
2311
2312 //#if 0
2313 if ( ( Keyboard[ sc_F12 ] ) && ( !BATTLEMODE ) )
2314 {
2315 Keyboard[ sc_F12 ] = false;
2316 LastScan = 0;
2317 DoBossKey();
2318 }
2319 //#endif
2320
2321 // Gamma correction
2322 if ( Keyboard[ sc_F11 ] )
2323 {
2324 char str[ 50 ] = "Gamma Correction Level ";
2325 char str2[ 10 ];
2326
2327 gammaindex++;
2328 if ( gammaindex == NUMGAMMALEVELS )
2329 {
2330 gammaindex = 0;
2331 }
2332 VL_SetPalette( origpal );
2333 itoa( gammaindex, str2, 10 );
2334 strcat( str, str2 );
2335 AddMessage( str, MSG_SYSTEM );
2336
2337 while( Keyboard[ sc_F11 ] )
2338 {
2339 IN_UpdateKeyboard();
2340 }
2341 }
2342 #if 0
2343 if ( Keyboard[ sc_M ] )
2344 {
2345 char str[ 50 ] = "Mouse Y-Rotation Input Scale ";
2346 char str2[ 10 ];
2347
2348 if ( Keyboard[ sc_RShift ] )
2349 mouse_ry_input_scale += 50;
2350 else
2351 mouse_ry_input_scale -= 50;
2352
2353 itoa(mouse_ry_input_scale,str2,10);
2354 strcat( str, str2 );
2355 AddMessage( str, MSG_SYSTEM );
2356
2357 }
2358 #endif
2359 // Increase volume
2360 if ( Keyboard[ sc_CloseBracket ] )
2361 {
2362 if ( Keyboard[ sc_RShift ] )
2363 {
2364 char str[ 50 ] = "Music Volume Level ";
2365 char str2[ 10 ];
2366
2367 if ( MUvolume < 255 )
2368 {
2369 MUvolume++;
2370 }
2371 MU_SetVolume( MUvolume );
2372
2373 itoa( MUvolume, str2, 10 );
2374 strcat( str, str2 );
2375 AddMessage( str, MSG_SYSTEM );
2376 }
2377 else
2378 {
2379 char str[ 50 ] = "Sound FX Volume Level ";
2380 char str2[ 10 ];
2381
2382 if ( FXvolume < 255 )
2383 {
2384 FXvolume++;
2385 }
2386 FX_SetVolume( FXvolume );
2387
2388 itoa( FXvolume, str2, 10 );
2389 strcat( str, str2 );
2390 AddMessage( str, MSG_SYSTEM );
2391 }
2392 }
2393
2394 // Decrease volume
2395 if ( Keyboard[ sc_OpenBracket ] )
2396 {
2397 if ( Keyboard[ sc_RShift ] )
2398 {
2399 char str[ 50 ] = "Music Volume Level ";
2400 char str2[ 10 ];
2401
2402 if ( MUvolume > 0 )
2403 {
2404 MUvolume--;
2405 }
2406 MU_SetVolume( MUvolume );
2407
2408 itoa( MUvolume, str2, 10 );
2409 strcat( str, str2 );
2410 AddMessage( str, MSG_SYSTEM );
2411 }
2412 else
2413 {
2414 char str[ 50 ] = "Sound FX Volume Level ";
2415 char str2[ 10 ];
2416
2417 if ( FXvolume > 0 )
2418 {
2419 FXvolume--;
2420 }
2421 FX_SetVolume( FXvolume );
2422
2423 itoa( FXvolume, str2, 10 );
2424 strcat( str, str2 );
2425 AddMessage( str, MSG_SYSTEM );
2426 }
2427 }
2428
2429 #if SAVE_SCREEN
2430 #if (DEVELOPMENT == 1)
2431 if ( Keyboard[ sc_CapsLock ] && Keyboard[ sc_C ] )
2432 {
2433 SaveScreen( true );
2434 }
2435 else if ( Keyboard[ sc_CapsLock ] && Keyboard[ sc_X ] )
2436 {
2437 SaveScreen( false );
2438 }
2439 #endif
2440 else if ( Keyboard[ sc_Alt] && Keyboard[ sc_C ] )
2441 {
2442 SaveScreen( false );
2443 }
2444 else if ( Keyboard[ sc_Alt] && Keyboard[ sc_V ] )
2445 {
2446 SaveScreen( true );
2447 }
2448 #endif
2449 }
2450 waminot();
2451 }
2452
2453
2454 //******************************************************************************
2455 //
2456 // CheckDevelopmentKeys ()
2457 //
2458 //******************************************************************************
2459 #if 0
2460 void CheckDevelopmentKeys
2461 (
2462 void
2463 )
2464
2465 {
2466 #if (DEBUG == 1)
2467 if ( Keyboard[ sc_CapsLock ] && Keyboard[ sc_T ] )
2468 {
2469 if ( warp == true )
2470 {
2471 player->x = warpx;
2472 player->y = warpy;
2473 player->angle = warpa;
2474 locplayerstate->anglefrac = warpa << ANGLEBITS;
2475 player->momentumx = 0;
2476 player->momentumy = 0;
2477 player->momentumz = 0;
2478 }
2479 return;
2480 }
2481 #endif
2482
2483 // Lower wall height
2484 if ( Keyboard[ sc_5 ] )
2485 {
2486 if ( levelheight > 1 )
2487 {
2488 levelheight--;
2489 }
2490
2491 while( Keyboard[ sc_5 ] )
2492 {
2493 IN_UpdateKeyboard ();
2494 }
2495
2496 maxheight = ( levelheight << 6 ) - 32;
2497 nominalheight = maxheight - 32;
2498 }
2499
2500 // Raise wall height
2501 if ( Keyboard[ sc_6 ] )
2502 {
2503 levelheight++;
2504
2505 while( Keyboard[ sc_6 ] )
2506 {
2507 IN_UpdateKeyboard();
2508 }
2509
2510 maxheight = ( levelheight << 6 ) - 32;
2511 nominalheight = maxheight - 32;
2512 }
2513
2514 if ( Keyboard[ sc_8 ] )
2515 {
2516 char str[ 50 ] = "You are now player ";
2517 char str2[ 10 ];
2518
2519 locplayerstate->player++;
2520 if ( locplayerstate->player == 5 )
2521 {
2522 locplayerstate->player = 0;
2523 }
2524
2525 while( Keyboard[ sc_8 ] )
2526 {
2527 IN_UpdateKeyboard ();
2528 }
2529
2530 itoa( locplayerstate->player, str2, 10 );
2531 strcat( str, str2 );
2532 AddMessage( str, MSG_SYSTEM );
2533 }
2534
2535 #if 0
2536 // Cycle forward through wall textures
2537 if (Keyboard[sc_W] && (modemgame==false))
2538 {int i,j;
2539
2540 for(i=0;i<128;i++)
2541 for(j=0;j<128;j++)
2542 {if (IsWall(i,j))
2543 {if (tilemap[i][j] ==
2544 (W_GetNumForName("WALLSTOP")-W_GetNumForName("WALLSTRT")-1))
2545 tilemap[i][j] = 1;
2546 else
2547 tilemap[i][j] ++;
2548 }
2549 }
2550 while(Keyboard[sc_W])
2551 IN_UpdateKeyboard ();
2552
2553 }
2554
2555
2556
2557 if (Keyboard[sc_Q] && (modemgame==false))
2558 {int i,j;
2559
2560 for(i=0;i<128;i++)
2561 for(j=0;j<128;j++)
2562 {if (IsWall(i,j))
2563 {if (tilemap[i][j] == 1)
2564 tilemap[i][j] = 74;
2565 else
2566 tilemap[i][j] --;
2567 }
2568 }
2569 while(Keyboard[sc_Q])
2570 IN_UpdateKeyboard ();
2571
2572 }
2573
2574 #endif
2575 // Step through cieling/skies
2576 if ( Keyboard[ sc_K ] )
2577 {
2578 if ( sky > 0 )
2579 {
2580 MAPSPOT( 1, 0, 0 )++;
2581 if ( MAPSPOT( 1, 0, 0 ) > 239 )
2582 {
2583 MAPSPOT( 1, 0, 0 ) = 234;
2584 }
2585 }
2586 else
2587 {
2588 MAPSPOT( 1, 0, 0 )++;
2589 if ( MAPSPOT( 1, 0, 0 ) > 198 + 15 )
2590 {
2591 MAPSPOT( 1, 0, 0 ) = 198;
2592 }
2593 }
2594
2595 SetPlaneViewSize();
2596
2597 while( Keyboard[ sc_K ] )
2598 {
2599 IN_UpdateKeyboard();
2600 }
2601 }
2602
2603 // Step through floors
2604 if ( Keyboard[ sc_L ] )
2605 {
2606 MAPSPOT( 0, 0, 0 )++;
2607 if ( MAPSPOT( 0, 0, 0 ) > 180 + 15 )
2608 {
2609 MAPSPOT( 0, 0, 0 ) = 180;
2610 SetPlaneViewSize();
2611
2612 while( Keyboard[ sc_L ] )
2613 {
2614 IN_UpdateKeyboard();
2615 }
2616 }
2617 }
2618
2619 // Increase darkness level
2620 if ( Keyboard[ sc_M ] )
2621 {
2622 if ( darknesslevel < 7 )
2623 {
2624 darknesslevel++;
2625 }
2626
2627 SetLightLevels( darknesslevel );
2628
2629 while( Keyboard[ sc_M ] )
2630 {
2631 IN_UpdateKeyboard();
2632 }
2633 }
2634
2635 // Decrease darkness level
2636 if ( Keyboard[ sc_N ] )
2637 {
2638 if ( darknesslevel > 0 )
2639 {
2640 darknesslevel--;
2641 }
2642
2643 SetLightLevels( darknesslevel );
2644
2645 while( Keyboard[ sc_N ] )
2646 {
2647 IN_UpdateKeyboard();
2648 }
2649 }
2650
2651 // Increase light rate
2652 if ( Keyboard[ sc_B ] )
2653 {
2654 SetLightRate( GetLightRate() + 1 );
2655 myprintf( "normalshade = %ld\n", normalshade );
2656
2657 while( Keyboard[ sc_B ] )
2658 {
2659 IN_UpdateKeyboard();
2660 }
2661 }
2662
2663 // Decrease light rate
2664 if ( Keyboard[ sc_V ] )
2665 {
2666 SetLightRate( GetLightRate() - 1 );
2667 myprintf( "normalshade = %ld\n", normalshade );
2668
2669 while( Keyboard[ sc_V ] )
2670 {
2671 IN_UpdateKeyboard();
2672 }
2673 }
2674
2675 // Toggle light diminishing on/off
2676 if ( Keyboard[ sc_T ] )
2677 {
2678 fulllight ^= 1;
2679
2680 while( Keyboard[ sc_T ] )
2681 {
2682 IN_UpdateKeyboard();
2683 }
2684 }
2685 }
2686 #endif
2687
2688
2689 #if SAVE_SCREEN
2690
2691
BigShort(short l)2692 short BigShort (short l)
2693 {
2694 byte b1,b2;
2695
2696 b1 = l&255;
2697 b2 = (l>>8)&255;
2698
2699 return (b1<<8) + b2;
2700 }
2701
BigLong(long l)2702 long BigLong (long l)
2703 {
2704 byte b1,b2,b3,b4;
2705
2706 b1 = l&255;
2707 b2 = (l>>8)&255;
2708 b3 = (l>>16)&255;
2709 b4 = (l>>24)&255;
2710
2711 return ((long)b1<<24) + ((long)b2<<16) + ((long)b3<<8) + b4;
2712 }
2713
2714 /*
2715 ==============
2716 =
2717 = WriteLBMfile
2718 =
2719 ==============
2720 */
2721
WriteLBMfile(char * filename,byte * data,int width,int height)2722 void WriteLBMfile (char *filename, byte *data, int width, int height)
2723 {
2724 byte *lbm, *lbmptr;
2725 long *formlength, *bmhdlength, *cmaplength, *bodylength;
2726 long length;
2727 bmhd_t basebmhd;
2728 int handle;
2729 int i;
2730
2731 lbm = lbmptr = (byte *) SafeMalloc (65000);
2732
2733 //
2734 // start FORM
2735 //
2736 *lbmptr++ = 'F';
2737 *lbmptr++ = 'O';
2738 *lbmptr++ = 'R';
2739 *lbmptr++ = 'M';
2740
2741 formlength = (long*)lbmptr;
2742 lbmptr+=4; // leave space for length
2743
2744 *lbmptr++ = 'P';
2745 *lbmptr++ = 'B';
2746 *lbmptr++ = 'M';
2747 *lbmptr++ = ' ';
2748
2749 //
2750 // write BMHD
2751 //
2752 *lbmptr++ = 'B';
2753 *lbmptr++ = 'M';
2754 *lbmptr++ = 'H';
2755 *lbmptr++ = 'D';
2756
2757 bmhdlength = (long *)lbmptr;
2758 lbmptr+=4; // leave space for length
2759
2760 memset (&basebmhd,0,sizeof(basebmhd));
2761 basebmhd.w = BigShort(width);
2762 basebmhd.h = BigShort(height);
2763 basebmhd.nPlanes = BigShort(8);
2764 basebmhd.xAspect = BigShort(5);
2765 basebmhd.yAspect = BigShort(6);
2766 basebmhd.pageWidth = BigShort(width);
2767 basebmhd.pageHeight = BigShort(height);
2768
2769 memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
2770 lbmptr += sizeof(basebmhd);
2771
2772 length = lbmptr-(byte *)bmhdlength-4;
2773 *bmhdlength = BigLong(length);
2774 if (length&1)
2775 *lbmptr++ = 0; // pad chunk to even offset
2776
2777 //
2778 // write CMAP
2779 //
2780 *lbmptr++ = 'C';
2781 *lbmptr++ = 'M';
2782 *lbmptr++ = 'A';
2783 *lbmptr++ = 'P';
2784
2785 cmaplength = (long *)lbmptr;
2786 lbmptr+=4; // leave space for length
2787
2788 for (i = 0; i < 0x300; i++)
2789 *lbmptr++ = (*(origpal+i))<<2;
2790
2791 // memcpy (lbmptr,&origpal[0],768);
2792 // lbmptr += 768;
2793
2794 length = lbmptr-(byte *)cmaplength-4;
2795 *cmaplength = BigLong(length);
2796 if (length&1)
2797 *lbmptr++ = 0; // pad chunk to even offset
2798
2799 //
2800 // write BODY
2801 //
2802 *lbmptr++ = 'B';
2803 *lbmptr++ = 'O';
2804 *lbmptr++ = 'D';
2805 *lbmptr++ = 'Y';
2806
2807 bodylength = (long *)lbmptr;
2808 lbmptr+=4; // leave space for length
2809
2810 memcpy (lbmptr,data,width*height);
2811 lbmptr += width*height;
2812
2813 length = lbmptr-(byte *)bodylength-4;
2814 *bodylength = BigLong(length);
2815 if (length&1)
2816 *lbmptr++ = 0; // pad chunk to even offset
2817
2818 //
2819 // done
2820 //
2821 length = lbmptr-(byte *)formlength-4;
2822 *formlength = BigLong(length);
2823 if (length&1)
2824 *lbmptr++ = 0; // pad chunk to even offset
2825
2826 //
2827 // write output file
2828 //
2829 handle = SafeOpenWrite (filename);
2830
2831 SafeWrite (handle, lbm, lbmptr-lbm);
2832
2833 close (handle);
2834 SafeFree(lbm);
2835 }
2836
2837
2838 //****************************************************************************
2839 //
2840 // GetFileName ()
2841 //
2842 //****************************************************************************
2843
GetFileName(boolean saveLBM)2844 void GetFileName (boolean saveLBM)
2845 {
2846 #ifdef DOS
2847 char num[4];
2848 int cnt = 0;
2849 struct find_t fblock;
2850
2851 if (saveLBM)
2852 memcpy (savename, "ROTT0000.LBM\0", 13);
2853 else
2854 memcpy (savename, "ROTT0000.PCX\0", 13);
2855
2856 if (_dos_findfirst (savename, 0, &fblock) != 0)
2857 return;
2858
2859 do
2860 {
2861 cnt++;
2862 memset (&num[0], 0, 4);
2863 itoa (cnt, num, 10);
2864
2865 if (cnt > 99)
2866 {
2867 savename[5] = num[0];
2868 savename[6] = num[1];
2869 savename[7] = num[2];
2870 }
2871 else
2872 if (cnt > 9)
2873 {
2874 savename[6] = num[0];
2875 savename[7] = num[1];
2876 }
2877 else
2878 savename[7] = num[0];
2879 }
2880 while (_dos_findfirst (savename, 0, &fblock) == 0);
2881 #else
2882 int i;
2883
2884 for (i = 0; i < 9999; i++) {
2885 char filename[128];
2886
2887 if (saveLBM) {
2888 sprintf(savename, "rott%04d.lbm", i);
2889 } else {
2890 sprintf(savename, "rott%04d.pcx", i);
2891 }
2892
2893 GetPathFromEnvironment( filename, ApogeePath, savename );
2894
2895 if (access(filename, F_OK) != 0) {
2896 return;
2897 }
2898 }
2899 #endif
2900 }
2901
2902 //****************************************************************************
2903 //
2904 // SaveScreen ()
2905 //
2906 //****************************************************************************
2907
2908 boolean inhmenu;
2909
2910 #if (BETA == 1)
2911 #define SSX (160-(46*2))
2912 #define SSY (17)
2913 #endif
SaveScreen(boolean saveLBM)2914 void SaveScreen (boolean saveLBM)
2915 {
2916 byte *buffer;
2917 byte * screen;
2918 boolean oldHUD;
2919 char filename[ 128 ];
2920
2921 #if (BETA == 1)
2922 unsigned tmp;
2923 char buf[30];
2924 int i;
2925 #endif
2926
2927
2928 oldHUD=HUD;
2929 HUD=false;
2930 doublestep=0;
2931 if (inhmenu==false)
2932 screen = (byte *) bufferofs;
2933 else
2934 screen = (byte *) displayofs;
2935
2936 if (inhmenu==false)
2937 ThreeDRefresh ();
2938 doublestep = 2 - DetailLevel;
2939
2940 buffer = (byte *) SafeMalloc (65000);
2941
2942 #if (BETA == 1)
2943 if (SCREENSHOTS == false)
2944 {
2945 if (screen!=(byte *)bufferofs)
2946 {
2947 tmp=bufferofs;
2948 bufferofs=displayofs;
2949 }
2950 CurrentFont=tinyfont;
2951
2952 VGAMAPMASK(15);
2953 for (i=-1;i<6;i++)
2954 memset((byte *)bufferofs+(ylookup[i+SSY])+(SSX>>2),0,46);
2955 px=SSX;
2956 py=SSY;
2957 VW_DrawPropString(" Rise of the Triad (c) 1995 Apogee Version ");
2958 VW_DrawPropString(itoa(ROTTMAJORVERSION,&buf[0],10));
2959 VW_DrawPropString(".");
2960 VW_DrawPropString(itoa(ROTTMINORVERSION,&buf[0],10));
2961 px=SSX+13;
2962 py=SSY+8;
2963 VW_DrawPropString(" Episode ");
2964 VW_DrawPropString(itoa(gamestate.episode,&buf[0],10));
2965 VW_DrawPropString(" Area ");
2966 VW_DrawPropString(itoa(GetLevel(gamestate.episode, gamestate.mapon),&buf[0],10));
2967
2968 if (screen!=(byte *)bufferofs)
2969 bufferofs=tmp;
2970 }
2971 #endif
2972
2973 VL_CopyPlanarPageToMemory(screen,buffer);
2974
2975 GetFileName (saveLBM);
2976 GetPathFromEnvironment( filename, ApogeePath, savename );
2977
2978 if (saveLBM)
2979 {
2980 WriteLBMfile (filename, buffer, 320, 200);
2981 while (Keyboard[sc_CapsLock] && Keyboard[sc_C])
2982 IN_UpdateKeyboard ();
2983 }
2984 else
2985 {
2986 WritePCX (filename, buffer);
2987 while (Keyboard[sc_CapsLock] && Keyboard[sc_X])
2988 IN_UpdateKeyboard ();
2989 }
2990
2991 SafeFree(buffer);
2992 HUD=oldHUD;
2993 }
2994
2995 //****************************************************************************
2996 //
2997 // WritePCX ()
2998 //
2999 //****************************************************************************
3000
WritePCX(char * file,byte * source)3001 void WritePCX (char * file, byte * source)
3002 {
3003 PCX_HEADER pcxHDR;
3004 byte *tempbuffer;
3005 byte pal[0x300];
3006 int pcxhandle;
3007 int i, j, y;
3008 unsigned char c;
3009 unsigned char buffer1[GAP_SIZE];
3010
3011 pcxhandle = SafeOpenWrite (file);
3012
3013 /* --- init the header that we'll write.
3014 * Note: since DPaint never reads & writes at the same time,
3015 * it is okay to share the same read & write structure,
3016 * unlike in CONVERT.EXE.
3017 */
3018
3019 memset (&pcxHDR, sizeof(PCX_HEADER), 0);
3020
3021 pcxHDR.manufacturer = 10;
3022 pcxHDR.version = 5;
3023 pcxHDR.encoding = 1;
3024
3025 pcxHDR.bitsperpixel = 8; //bpp;
3026 pcxHDR.xmin = pcxHDR.ymin = 0;
3027 pcxHDR.xmax = 319; //bitmap->box.w - 1;
3028 pcxHDR.ymax = 199; //bitmap->box.h - 1;
3029 pcxHDR.hres = 320; //N_COLUMNS;
3030 pcxHDR.vres = 200; //N_LINES;
3031
3032 // bytesperline doesn't take into account multiple planes.
3033 // Output in same format as bitmap (planar vs packed).
3034 //
3035 pcxHDR.bytesperline = 320; //bitmap->width;
3036
3037 pcxHDR.nplanes = 1; //bitmap->planes;
3038 pcxHDR.reserved = 0;
3039
3040 // First 16 colors of our palette info.
3041 for (i = 0, j = 0; i < 16; ++i, j += 3) {
3042 pcxHDR.colormap[i][0] = (unsigned char)(origpal[j]);
3043 pcxHDR.colormap[i][1] = (unsigned char)(origpal[j]+2);
3044 pcxHDR.colormap[i][2] = (unsigned char)(origpal[j]+3);
3045 }
3046
3047 //
3048 // Write the 128-byte header
3049 //
3050 SafeWrite(pcxhandle,&pcxHDR, sizeof (PCX_HEADER));
3051
3052 memset (buffer1, GAP_SIZE, 0);
3053
3054 SafeWrite (pcxhandle, &buffer1, GAP_SIZE);
3055
3056 tempbuffer = (byte *) SafeMalloc (65000);
3057 bptr = tempbuffer;
3058 totalbytes = 0;
3059
3060 //
3061 // Write to a bit-packed file.
3062 //
3063 for (y = 0; y < 200; ++y) // for each line in band
3064 if (PutBytes (((unsigned char *) (source+(y*320))),
3065 pcxHDR.bytesperline))
3066 Error ("Error writing PCX bit-packed line!\n");
3067
3068 SafeWrite (pcxhandle, tempbuffer, totalbytes);
3069
3070 //
3071 // Write out PCX palette
3072 //
3073 c = 0x0C;
3074
3075 for (i = 0; i < 0x300; i++)
3076 pal[i] = (*(origpal+i))<<2;
3077
3078 SafeWrite (pcxhandle, &c, 1);
3079 SafeWrite (pcxhandle, &pal[0], 768);
3080
3081 close (pcxhandle);
3082 SafeFree (tempbuffer);
3083 }
3084
3085
3086 //****************************************************************************
3087 //
3088 // PutBytes ()
3089 //
3090 // Write bytes to a file, handling packing as it goes.
3091 // Returns : 0 == SUCCESS
3092 // 1 == FAIL.
3093 //
3094 //****************************************************************************
3095
PutBytes(unsigned char * ptr,unsigned int bytes)3096 int PutBytes (unsigned char *ptr, unsigned int bytes)
3097 {
3098 unsigned int startbyte, count;
3099 char b;
3100
3101 while (bytes > 0) {
3102 // check for a repeating byte value
3103 startbyte = *ptr;
3104 *ptr++ = 0;
3105 --bytes;
3106 count = 1;
3107 while (*ptr == startbyte && bytes > 0 && count < 63)
3108 {
3109 *ptr = 0;
3110 ++ptr;
3111 --bytes;
3112 ++count;
3113 }
3114 // If we can pack the sequence, or if we have to add a
3115 // byte before it because the top 2 bits of the value
3116 // are 1's, write a packed sequence of 2 bytes.
3117 // Otherwise, just write the byte value.
3118 //
3119 if (count > 1 || (startbyte & 0xc0) == 0xc0)
3120 {
3121 b = 0xc0 | count;
3122
3123 *bptr++ = b;
3124 totalbytes++;
3125 }
3126 b = startbyte;
3127
3128 *bptr++ = b;
3129 totalbytes++;
3130 }
3131 return (0);
3132 }
3133
3134
3135 #endif
3136
3137
3138 //****************************************************************************
3139 //
3140 // PlayCinematic () - Play intro cinematics
3141 //
3142 //****************************************************************************
3143
PlayCinematic(void)3144 void PlayCinematic (void)
3145 {
3146
3147 if ((tedlevel == true) || (turbo == true))
3148 return;
3149
3150 switch (gamestate.mapon)
3151 {
3152 #if (SHAREWARE == 0)
3153 byte pal[768];
3154 case 0: // Start of EPISODE 1
3155
3156 MU_StartSong ( song_cinematic1 );
3157 VL_FadeOut (0, 255, 0, 0, 0, 20);
3158 VL_ClearBuffer (bufferofs, 0);
3159 DrawNormalSprite(0,30,W_GetNumForName("nicolas"));
3160 DrawNormalSprite(0,168,W_GetNumForName("oneyear"));
3161 FlipPage();
3162 memcpy(&pal[0],W_CacheLumpName("nicpal",PU_CACHE, CvtNull, 1),768);
3163 VL_NormalizePalette(&pal[0]);
3164 VL_FadeIn(0,255,pal,20);
3165 I_Delay (60);
3166 VL_FadeOut (0, 255, 0, 0, 0, 20);
3167 IN_UpdateKeyboard();
3168 if (LastScan!=0)
3169 {
3170 LastScan=0;
3171 return;
3172 }
3173 SD_PlayPitchedSound(SD_LIGHTNINGSND,255,-1500);
3174 DoInBetweenCinematic (20, W_GetNumForName("binoculr"), 80,
3175 "The HUNT cases an\n"
3176 "ancient monastery."
3177 );
3178 IN_UpdateKeyboard();
3179 if (LastScan!=0)
3180 {
3181 LastScan=0;
3182 return;
3183 }
3184 SD_Play(SD_NMESEESND);
3185 DoInBetweenCinematic (20, W_GetNumForName("binosee"), 80,
3186 "\"There they are,\" says\n"
3187 "Cassatt. \"Let's get back\n"
3188 "to the boat and inform HQ.\""
3189 );
3190 IN_UpdateKeyboard();
3191 if (LastScan!=0)
3192 {
3193 LastScan=0;
3194 return;
3195 }
3196 SD_Play(SD_HIGHGUARD1SEESND);
3197 DoInBetweenCinematic (20, W_GetNumForName("boatgard"), 80,
3198 "\"The intruders, on that hill!\""
3199 );
3200 IN_UpdateKeyboard();
3201 if (LastScan!=0)
3202 {
3203 LastScan=0;
3204 return;
3205 }
3206 SD_Play(SD_EXPLODESND);
3207 DoInBetweenCinematic (20, W_GetNumForName("boatblow"), 80,
3208 "\"There goes our ride home,\"\n"
3209 "says Barrett. \"Looks like\n"
3210 "the only way out is in....\""
3211 );
3212 IN_UpdateKeyboard();
3213 LastScan=0;
3214 break;
3215
3216 case 8: // Start of EPISODE 2
3217 MU_StartSong ( song_cinematic2 );
3218 DoInBetweenCinematic (0, W_GetNumForName("epi12"), 1200,
3219 "The HUNT makes their way\n"
3220 "into the main keep."
3221 );
3222 IN_UpdateKeyboard();
3223 LastScan=0;
3224 break;
3225
3226 case 16: // Start of EPISODE 3
3227 MU_StartSong ( song_cinematic1 );
3228 DoInBetweenCinematic (20, W_GetNumForName("epi23"), 1200,
3229 "The HUNT stands before a pair\n"
3230 "of ominous wooden doors.\n"
3231 "The sounds of machinery and\n"
3232 "servomotors fill the air.\n"
3233 );
3234 IN_UpdateKeyboard();
3235 LastScan=0;
3236 break;
3237
3238 case 24: // Start of EPISODE 4
3239 MU_StartSong ( song_cinematic2 );
3240 DoInBetweenCinematic (0, W_GetNumForName("epi34"), 1200,
3241 "Stairs lead down beneath the\n"
3242 "keep. From behind the doors\n"
3243 "come the moans of the undead."
3244 );
3245 IN_UpdateKeyboard();
3246 LastScan=0;
3247 break;
3248 #endif
3249 }
3250 }
3251