ref: 69f062a7028f072a24712cf3034f208677cd7079
dir: /src/rt_main.c/
/* Copyright (C) 1994-1995 Apogee Software, Ltd. Copyright (C) 2002-2015 icculus.org, GNU/Linux port Copyright (C) 2017-2018 Steven LeVesque This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include "rt_def.h" #include "lumpy.h" #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <fcntl.h> #include <string.h> #include <signal.h> #if USE_SDL /* Need to redefine main to SDL_main on some platforms... */ #include "SDL2/SDL.h" #endif #include "rt_actor.h" #include "rt_stat.h" #include "rt_vid.h" #include "rt_menu.h" #include "rt_sound.h" #include "watcom.h" #include "scriplib.h" #include "rt_main.h" #include "_rt_main.h" #include "rt_com.h" #include "rt_util.h" #include "z_zone.h" #include "w_wad.h" #include "rt_game.h" #include "rt_floor.h" #include "rt_playr.h" #include "rt_draw.h" #include "rt_str.h" #include "rt_view.h" #include "rt_door.h" #include "rt_ted.h" #include "rt_in.h" #include "rt_map.h" #include "rt_rand.h" #include "rt_debug.h" #include "isr.h" #include "rt_cfg.h" #include "develop.h" #include "version.h" #include "rt_menu.h" #include "rt_dr_a.h" #include "rt_msg.h" #include "rt_build.h" #include "rt_error.h" #include "modexlib.h" #include "rt_net.h" #include "cin_main.h" #include "rottnet.h" #include "rt_scale.h" #include "music.h" #include "fx_man.h" volatile int oldtime; volatile int gametime; boolean tedlevel; int tedlevelnum; int tedx=0; int tedy=0; boolean warp; int warpx=0; int warpy=0; int warpa=0; int NoSound; int polltime; int oldpolltime; boolean fizzlein = false; int pheight; boolean SCREENSHOTS = false; boolean MONOPRESENT = false; boolean MAPSTATS = false; boolean TILESTATS = false; boolean HUD = false; boolean IS8250 = false; boolean dopefish; boolean newlevel = false; boolean infopause; boolean quiet = false; boolean DebugOk = false; #if SAVE_SCREEN static char savename[13] = "ROTT0000.LBM"; static int totalbytes; static byte *bptr; #endif static boolean turbo; static int NoWait; static int startlevel=0; static int demonumber=-1; char CWD[40]; // curent working directory static boolean quitactive = false; int timelimit; int maxtimelimit; boolean timelimitenabled; boolean demoexit; boolean noecho; void CheckCommandLineParameters( void ); void PlayTurboGame( void ); void Init_Tables (void); void CheckRemoteRidicule ( int scancode ); void SetRottScreenRes (int Width, int Height); extern void crash_print (int); extern int setup_homedir (void); //extern int G_argc; //extern char G_argv[30][80]; int G_weaponscale; extern int iDropDemo; extern boolean iG_aimCross; extern boolean sdl_fullscreen; extern boolean borderWindow; extern boolean borderlessWindow; extern void ComSetTime ( void ); extern void VH_UpdateScreen (void); extern void RottConsole ( void ); extern void ReadDelay(long delay); extern void RecordDemoQuery ( void ); extern int CountDigits(const int number); /* FIXME plan9 hacks */ u32int sounddebugDeallocateSoundCalls; u32int sounddebugActiveSounds; int g_CV_CubicInterpolation; u32int sounddebugAllocateSoundCalls; int main (int argc, char *argv[]) { extern char *BATTMAPS; _argc = argc; _argv = argv; Mix_Init(1); #if defined(PLATFORM_MACOSX) { /* OS X will give us a path in the form '/Applications/Rise of the Triad.app/Contents/MacOS/Rise of the Triad'. Our data is in Contents/Resources. */ char *path; const char suffix[] = "/Resources/"; int end; path = (char *)malloc(strlen(argv[0]) + strlen(suffix) + 1); if (path == NULL) return 1; strcpy(path, argv[0]); /* Back up two '/'s. */ for (end = strlen(path)-1; end >= 0 && path[end] != '/'; end--); if (end >= 0) for (--end; end >= 0 && path[end] != '/'; end--); strcpy(&path[end], suffix); printf("Changing to working directory: %s\n", path); chdir(path); free(path); } #endif // signal (11, crash_print); if (setup_homedir() == -1) return 1; // Set which release version we're on gamestate.Version = ROTTVERSION; #if ( SHAREWARE == 1 ) BATTMAPS = strdup(STANDARDBATTLELEVELS); FixFilePath(BATTMAPS); gamestate.Product = ROTT_SHAREWARE; #else BATTMAPS = strdup(SITELICENSEBATTLELEVELS); FixFilePath(BATTMAPS); if (!access(BATTMAPS, R_OK)) { gamestate.Product = ROTT_SITELICENSE; } else { free(BATTMAPS); BATTMAPS = strdup(SUPERROTTBATTLELEVELS); FixFilePath(BATTMAPS); if (!access(BATTMAPS, R_OK)) { gamestate.Product = ROTT_SUPERCD; } else { free(BATTMAPS); BATTMAPS = strdup(STANDARDBATTLELEVELS); FixFilePath(BATTMAPS); gamestate.Product = ROTT_REGISTERED; } } #endif DrawRottTitle (); gamestate.randomseed=-1; gamestate.autorun = 0; StartupSoftError(); // UL_ErrorStartup (); CheckCommandLineParameters(); // Start up Memory manager with a certain amount of reserved memory Z_Init(50000,1000000); IN_Startup (); InitializeGameCommands(); if (standalone==false) { ReadConfig (); ReadSETUPFiles (); doublestep=0; SetupWads(); BuildTables (); GetMenuInfo (); } SetRottScreenRes (iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT); // if (modemgame==true) // { // SCREENSHOTS=true; // if (standalone==false) // { // MenuFixup (); // } // MAPSTATS=true; // } if (standalone==false) { int status2 = 0; if ( !NoSound && !IS8250 ) { if (!quiet) printf( "MU_Startup: " ); MU_Startup(false); if (!quiet) printf( "%s\n", MUSIC_ErrorString( MUSIC_Error ) ); } else if ( IS8250 ) { printf( "==============================================================================\n"); printf( "WARNING: 8250 detected.\n" ); printf( "Music has been disabled. This is necessary to maintain high interrupt\n" ); printf( "rates with the 8250 UART which will improve overall game performance.\n"); printf( " < Press any key to continue >\n"); printf( "==============================================================================\n"); getch(); } if (!NoSound) { int nv, nb, nc; if (!quiet) printf( "SD_SetupFXCard: " ); status2 = SD_SetupFXCard (&nv, &nb, &nc); if (!quiet) printf( "%s\n", FX_ErrorString( FX_Error ) ); if ( !status2 ) { if (!quiet) printf( "SD_Startup: " ); SD_Startup(false); if (!quiet) printf( "%s\n", FX_ErrorString( FX_Error ) ); } } else { if (!quiet) printf( "Sound FX disabled.\n" ); } Init_Tables (); InitializeRNG (); InitializeMessages(); LoadColorMap(); } if (infopause==true) { printf("\n< Press any key to continue >\n"); getch(); } I_StartupTimer(); I_StartupKeyboard(); locplayerstate = &PLAYERSTATE[consoleplayer]; if (standalone==true) ServerLoop(); VL_SetVGAPlaneMode(); VL_SetPalette(origpal); if (mouseenabled) { SDL_SetRelativeMouseMode(SDL_TRUE); } // SetTextMode(); // GraphicsMode(); // SetTextMode(); // VL_SetVGAPlaneMode(); // VL_SetPalette(origpal); // SetBorderColor(155); SetViewSize(8); playstate = ex_titles; // I_SetKeyboardLEDs( caps_lock, 0 ); gamestate.battlemode = battle_StandAloneGame; BATTLE_SetOptions( &BATTLE_Options[ battle_StandAloneGame ] ); if (turbo || tedlevel) { if (modemgame == true) { turbo = false; NoWait = true; } else { PlayTurboGame(); } } else { #if (SHAREWARE == 0) if ( dopefish == true ) { DopefishTitle(); } else if ( NoWait == false ) { ApogeeTitle(); } #else if ( NoWait == false ) { if (W_CheckNumForName("svendor") != -1) { lbm_t * LBM; LBM = (lbm_t *) W_CacheLumpName( "svendor", PU_CACHE, Cvt_lbm_t, 1); VL_DecompressLBM (LBM,true); I_Delay(40); MenuFadeOut(); } // ParticleIntro (); ApogeeTitle(); } #endif } //SDL_WM_GrabInput( SDL_GRAB_ON ); GameLoop(); QuitGame(); return 0; } void DrawRottTitle ( void ) { char title[80]; char buf[5]; SetTextMode(); if (CheckParm("QUIET") == 0) { SetTextMode(); char rottStartupStr[] = "Rise of the Triad Startup Version "; strncpy (title,rottStartupStr, sizeof(rottStartupStr)); strncat (title,itoa(ROTTMAJORVERSION,&buf[0],10), CountDigits(ROTTMAJORVERSION)); strncat (title,".", 1); #if (SHAREWARE==1)||(DOPEFISH==0) strncat (title,itoa(ROTTMINORVERSION,&buf[0],10), CountDigits(ROTTMINORVERSION)); #else strcat (title,"DFISH"); #endif strncat (title,"\n", 1); px=(80-strlen(title))>>1; py=0; printf("%s ", title); memset (title,0,sizeof(title)); if (gamestate.Product == ROTT_SHAREWARE) { #if (DELUXE==1) char header[] = "Lasersoft Deluxe Version"; #elif (LOWCOST==1) char header[] = "Episode One"; #else char header[] = "Shareware Version"; #endif strncpy(title,header, strlen(header)); } else if (gamestate.Product == ROTT_SUPERCD) { char header[] = "CD Version"; strncpy(title,header, strlen(header)); } else if (gamestate.Product == ROTT_SITELICENSE) { char header[] = "Site License CD Version"; strncpy(title,header, strlen(header)); } else { char header[] = "Commercial Version"; strncpy(title,header, strlen(header)); } //strncpy(title, header, ) px=(80-strlen(title))>>1; py=1; printf("%s ", title); printf ("\n"); } } void CheckCommandLineParameters( void ) { char *PStrings[] = {"TEDLEVEL","NOWAIT","NOSOUND","NOW", "TRANSPORT","DOPEFISH","SCREENSHOTS", "MONO","MAPSTATS","TILESTATS","VER","net", "PAUSE","SOUNDSETUP","WARP","IS8250","ENABLEVR", "TIMELIMIT","MAXTIMELIMIT","NOECHO","DEMOEXIT","QUIET",NULL }; int i,n; infopause=false; tedlevel=false; NoWait=false; NoSound=false; turbo=false; warp=false; dopefish=false; modemgame=false; SCREENSHOTS=false; MONOPRESENT=false; MAPSTATS=false; TILESTATS=false; IS8250 = false; demoexit = false; modemgame=false; networkgame=false; consoleplayer=0; numplayers = 1; timelimit=-1; timelimitenabled=false; noecho = false; quiet = false; if ( (CheckParm("?\0")) || (CheckParm("HELP")) || ( (_argc>1) && (_argv[1][0]=='?') ) ) { SetTextMode (); printf ("Rise of the Triad (c) 1995 Apogee Software\n\n"); printf ("COMMAND LINE PARAMETERS\n"); printf (" AIM - Give Aim Crosshair.\n"); printf (" FULLSCREEN - Start in fullscreen mode\n"); printf (" WINDOW - Start in windowed mode\n"); printf (" RESOLUTION - Specify the screen resolution to use\n"); printf (" - next param is <widthxheight>, valid resolutions are:\n"); printf (" - 320x200, 640x480 and 800x600\n"); #if (SHAREWARE==0) printf (" FILERTL - used to load Userlevels (RTL files)\n"); printf (" - next parameter is RTL filename\n"); printf (" FILERTC - used to load Battlelevels (RTC files)\n"); printf (" - next parameter is RTC filename\n"); printf (" FILE - used to load Extern WAD files\n"); printf (" - next parameter is WAD filename\n"); #endif printf (" NOJOYS - Disable check for joystick.\n"); printf (" NOMOUSE - Disable check for mouse.\n"); printf (" VER - Version number.\n"); printf (" MAPSTATS - Dump Map statistics to ERROR.\n"); printf (" TILESTATS - Dump Tile statistics to ERROR.\n"); printf (" MONO - Enable mono-monitor support.\n"); printf (" SCREENSHOTS- Clean screen capture for shots.\n"); printf (" PAUSE - Pauses startup screen information.\n"); printf (" ENABLEVR - Enable VR helmet input devices\n"); printf (" NOECHO - Turn off sound reverb\n"); printf (" DEMOEXIT - Exit program when demo is terminated\n"); printf (" WARP - Warp to specific ROTT level\n"); printf (" next parameter is level to start on\n"); printf (" TIMELIMIT - Play ROTT in time limit mode\n"); printf (" next parameter is time in seconds\n"); printf (" MAXTIMELIMIT - Maximimum time to count down from\n"); printf (" next parameter is time in seconds\n"); printf (" DOPEFISH - ?\n"); printf (" \n"); printf ("CONTROLS\n"); printf (" Arrows - Move\n"); printf (" Ctrl - Fire\n"); printf (" Comma/Alt+left - Sidestep Left\n"); printf (" Period/Alt+right - Sidestep Right\n"); printf (" Shift - Run/Turn faster\n"); printf (" Space - Use/Open\n"); printf (" 1-4 - Choose Weapon\n"); printf (" 5-6 - Scale Weapon Up/Down\n"); printf (" Enter - Swap Weapon\n"); printf (" Backspace - Turn 180\n"); printf (" Delete - Drop Weapon\n"); printf (" +/- - Change Viewsize\n"); printf (" PgUp/PgDn - Look Up/Down\n"); printf (" Home/End - Aim Up/Down\n"); printf (" [ ] - Sound Volumen\n"); printf (" ( ) - Music Volumen\n"); printf (" Tab - Enter Automapper\n"); printf (" \n"); printf ("AUTO-MAPPER\n"); printf (" Arrows - Scroll around\n"); printf (" PgUp - Zoom Out\n"); printf (" PgDn - Zoom In\n"); printf (" Tab - Exit Auto-Mapper\n"); printf (" \n"); printf ("HOTKEYS\n"); printf (" F1 - Help\n"); printf (" F2 - Save Game\n"); printf (" F3 - Restore Game\n"); printf (" F4 - Controls/Sound/Music\n"); printf (" F5 - Change Detail Level\n"); printf (" F6 - Quick Save\n"); printf (" F7 - Messages On/Off\n"); printf (" F8 - End Game\n"); printf (" F9 - Quick Load\n"); printf (" F10 - Quit\n"); printf (" F11 - Gamma Correction\n"); printf (" \n"); printf ("COMM-BAT\n"); printf (" F1 - F10 - RemoteRidicule(tm) sounds\n"); printf (" F12 - Live RemoteRidicule\n"); printf (" T - Type message to all\n"); printf (" Z - Type directed message\n"); printf (" Tab - Toggle KillCount display\n"); printf (" \n"); printf ("SCREENSHOOT\n"); printf (" Alt+C - Screenshoot in PCX format\n"); exit (0); } // Check For command line parameters for (i = 1; i < _argc; i++) { n = US_CheckParm(_argv[i],PStrings); switch(n) { #if (TEDLAUNCH==1) case 0: tedlevelnum = ParseNum(_argv[i + 1]); tedlevel=true; if (i+3>=_argc) { tedx=0; tedy=0; } else { tedx=ParseNum(_argv[i + 2]); tedy=ParseNum(_argv[i + 3]); } MenuFixup (); break; #endif case 1: NoWait = true; break; case 2: NoSound = true; break; case 3: turbo = true; break; case 4: warp = true; warpx=ParseNum(_argv[i + 1]); warpy=ParseNum(_argv[i + 2]); warpa=ParseNum(_argv[i + 3]); break; case 5: dopefish=true; break; case 6: SCREENSHOTS = true; break; case 7: MONOPRESENT = true; break; case 8: MAPSTATS = true; break; case 9: TILESTATS = true; break; case 10: SetTextMode (); printf ("Rise of the Triad (c) 1995 Apogee Software\n"); if (gamestate.Product == ROTT_SHAREWARE) { #if (DELUXE==1) printf("Lasersoft Deluxe "); #elif (LOWCOST==1) printf("Episode One "); #else printf("Shareware "); #endif } else if (gamestate.Product == ROTT_SUPERCD) printf("CD "); else if (gamestate.Product == ROTT_SITELICENSE) printf("Site License "); else printf("Commercial "); printf ("Version %d.%d\n", ROTTMAJORVERSION,ROTTMINORVERSION); exit (0); break; case 11: InitROTTNET(); numplayers = rottcom->numplayers; if (numplayers>MAXPLAYERS) Error("Too many players.\n"); if (!quiet) printf("Playing %ld player ROTT\n",(long int)numplayers); modemgame=true; if (rottcom->gametype==NETWORK_GAME) { if (!quiet) printf("NETWORK GAME\n"); networkgame=true; } else { if (!quiet) printf("MODEM GAME\n"); } break; case 12: infopause=true; break; case 13: break; case 14: startlevel = (ParseNum(_argv[i + 1])-1); break; case 15: IS8250 = true; break; case 16: break; case 17: timelimitenabled = true; timelimit = ParseNum(_argv[i + 1]); if (!quiet) printf("Time Limit = %ld Seconds\n",(long int)timelimit); timelimit *= VBLCOUNTER; break; case 18: maxtimelimit = ParseNum(_argv[i + 1]); maxtimelimit *= VBLCOUNTER; break; case 19: noecho = true; break; case 20: demoexit = true; break; case 21: quiet = true; break; } } } void SetupWads( void ) { char *newargs[99]; int i, arg, argnum = 0; char *tempstr = NULL; char *PStrings[] = {"AIM", "FULLSCREEN", "WINDOW", "BORDERLESS", "RESOLUTION", NULL }; // These must be checked here so that they can override the cfg file for (i = 1; i < _argc; i++) { arg = US_CheckParm(_argv[i],PStrings); switch(arg) { case 0: iG_aimCross = 1; break; case 1: sdl_fullscreen = 1; borderWindow = 0; borderlessWindow = 0; break; case 2: sdl_fullscreen = 0; borderWindow = 1; borderlessWindow = 0; break; case 3: sdl_fullscreen = 0; borderWindow = 0; borderlessWindow = 1; break; case 4: i++; if (i < _argc) { int width, height; unsigned int numResParams = sscanf(_argv[i], "%dx%d", &width, &height); if ( numResParams == 2) { iGLOBAL_SCREENWIDTH = width; iGLOBAL_SCREENHEIGHT = height; } /* else printf("Invalid resolution parameter: %s\n", _argv[i]); */ } else printf("Missing resolution parameter\n"); break; } } #if (SHAREWARE==0) // Check for rtl files arg = CheckParm ("filertl"); if (arg!=0) { FILE *f; char *buf = malloc(32); if (_argv[arg+1] != 0) { //are there a filename included int templen = 129 + strlen(_argv[arg+1]); tempstr = realloc(tempstr, templen); snprintf(tempstr, templen,"%s", _argv[arg+1]); //strncpy (tempstr,_argv[arg+1], strlen(_argv[arg+1]));//copy it to tempstr if (strlen (tempstr) < MAX_PATH) { if (access (tempstr, 0) != 0) { //try open strncat (tempstr,".rtl", 4);//non exists, try add .rtc if (access (tempstr, 0) != 0) { //try open again //stil no useful filename char notfoundStr[] = " not found, skipping RTL file \n"; strncat (tempstr,notfoundStr, strlen(notfoundStr)); printf("%s", tempstr); goto NoRTL; } } if((f = fopen( tempstr, "r" )) == NULL ) { //try opnong file char cannotOpenStr[] = " not could be opened, skipping RTL file \n"; strncat (tempstr, cannotOpenStr, strlen(cannotOpenStr)); printf("%s", tempstr); goto NoRTL; } else { fread(buf,3,3,f);//is the 3 first letters RTL (RTC) if (((strstr(buf,"RTL") != 0)||strstr(buf,"RTC") != 0)) { GameLevels.file = strdup(tempstr); GameLevels.avail++; buf = realloc(buf, 32 + strlen(tempstr)); strncpy (buf,"Adding ", 7); strncat (buf,tempstr, strlen(tempstr) + 32); printf("%s \n", buf); } fclose(f); } } } else { printf("Missing RTL filename"); } free(buf); } NoRTL: // Check for rtc files arg = CheckParm ("filertc"); if (arg!=0) { FILE *f; char *buf = malloc(32); if (_argv[arg+1] != 0) { //are there a filename included int templen = 129 + strlen(_argv[arg+1]); tempstr = realloc(tempstr, templen); snprintf(tempstr, templen, "%s", _argv[arg+1]); //strncpy (tempstr,_argv[arg+1], sizeof(&_argv[arg+1]));//copy it to tempstr if (strlen (tempstr) < MAX_PATH) { if (access (tempstr, 0) != 0) { //try open strncat (tempstr,".rtc", 4);//non exists, try add .rtc if (access (tempstr, 0) != 0) { //try open again //stil no useful filename char notfoundRTC[] = " not found, skipping RTC file "; strncat (tempstr,notfoundRTC, strlen(notfoundRTC)); goto NoRTC; } } if((f = fopen( tempstr, "r" )) == NULL ) { //try opening file char cannotOpenRTC[] = " could not be opened, skipping RTC file "; strncat (tempstr,cannotOpenRTC, strlen(cannotOpenRTC)); goto NoRTL; } else { fread(buf,3,3,f);//is the 3 first letters RTL (RTC) if (((strstr(buf,"RTL") != 0)||strstr(buf,"RTC") != 0)) { BattleLevels.file = strdup(tempstr); BattleLevels.avail++; buf = realloc(buf, 32 + strlen(tempstr)); strncpy (buf,"Adding ", 7); strncat (buf,tempstr, strlen(tempstr) + 32); printf("%s \n", buf); } fclose(f); } } } else { printf("Missing RTC filename"); } free(buf); } NoRTC: ; // Check for User wads arg = CheckParm ("file"); if (arg!=0) { newargs [argnum++] = _argv[arg+1]; } arg = CheckParm ("file1"); if (arg!=0) { newargs [argnum++] = _argv[arg+1]; } arg = CheckParm ("file2"); if (arg!=0) { newargs [argnum++] = _argv[arg+1]; } #else if ( (CheckParm ("file") > 0) || (CheckParm ("file1") > 0) || (CheckParm ("file2") > 0) ) printf("External wads ignored.\n"); #endif // Normal ROTT wads #if (SHAREWARE) newargs [argnum++] = DATADIR "HUNTBGIN.WAD"; #else newargs [argnum++] = DATADIR "darkwar.wad"; #endif // newargs [argnum++] = "credits.wad"; // Check for Remote Ridicule WAD if (RemoteSounds.avail == true) { char *src; tempstr = realloc(tempstr, strlen(RemoteSounds.path) + strlen(RemoteSounds.file) + 2); strncpy (tempstr,RemoteSounds.path, strlen(RemoteSounds.path)); src = RemoteSounds.path + strlen(RemoteSounds.path) - 1; if (*src != '\\') strncat (tempstr,"\\\0", 1); strncat (tempstr,RemoteSounds.file, strlen(RemoteSounds.file)); newargs [argnum++] = strdup(tempstr); } else { newargs [argnum++] = DATADIR "remote1.rts"; } if (tempstr) free(tempstr); newargs [argnum++] = NULL; W_InitMultipleFiles(newargs); } void PlayTurboGame ( void ) { NewGame = true; locplayerstate->player = DefaultPlayerCharacter; playstate = ex_resetgame; GameLoop(); } //*************************************************************************** // // Init_Tables () - Init tables needed for double buffering // //*************************************************************************** void Init_Tables (void) { int i; int x, y; unsigned *blockstart; byte * shape; memset (&CWD[0], 0, 40); getcwd (CWD, 40); // get the current directory origpal=SafeMalloc(768); memcpy (origpal, W_CacheLumpName("pal",PU_CACHE, CvtNull, 1), 768); FindEGAColors(); for (i=0; i<PORTTILESHIGH; i++) uwidthtable[i] = UPDATEWIDE*i; updateptr = &update[0]; blockstart = &blockstarts[0]; for (y=0; y<UPDATEHIGH; y++) for (x=0; x<UPDATEWIDE; x++) *blockstart++ = iG_SCREENWIDTH*16*y+x*TILEWIDTH; for (i = 0; i < 0x300; i++) *(origpal+(unsigned int)i) = (*(origpal+(unsigned int)i))>>2; // Cache in fonts shape = W_CacheLumpNum (W_GetNumForName ("smallfont"), PU_STATIC, Cvt_font_t, 1); smallfont = (font_t *)shape; CurrentFont = smallfont; // Cache in tiny font shape = W_CacheLumpNum (W_GetNumForName ("tinyfont"), PU_STATIC, Cvt_font_t, 1); tinyfont = (font_t *)shape; intensitytable=W_CacheLumpNum(W_GetNumForName("menucmap"),PU_STATIC, CvtNull, 1); fontcolor = egacolor[4]; if (!quiet) printf("RT_MAIN: Fonts Initialized\n"); } int NumberOfTeams ( void ) { int index; int team[ MAXPLAYERCOLORS ]; int count; int color; memset( team, 0, sizeof( team ) ); count = 0; for( index = 0; index < numplayers; index++ ) { color = PLAYERSTATE[ index ].uniformcolor; if ( !team[ color ] ) { team[ color ] = true; count++; } } return( count ); } extern boolean allowBlitzMoreMissileWeps; extern boolean enableZomROTT; extern boolean doRescaling; void GameLoop (void) { int NextLevel; while (1) { //no longer needed in SDL2 //SDL_WarpMouse(iGLOBAL_SCREENWIDTH<<1, iGLOBAL_SCREENHEIGHT<<1); if ( playstate == ex_battledone ) { while( damagecount > 0 ) { DoBorderShifts(); } damagecount = 0; SetBorderColor (0); StopWind(); ShutdownClientControls(); SD_Play (SD_LEVELDONESND); if ( ( player->flags & FL_DOGMODE ) || ( gamestate.battlemode == battle_Eluder ) ) MU_StartSong(song_dogend); else MU_StartSong(song_endlevel); VL_FillPalette(255,255,255); VL_FadeIn(0,255,origpal,10); BattleLevelCompleted( consoleplayer ); BATTLE_Shutdown(); Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level ingame = false; if ( networkgame == true ) { AddGameEndCommand (); } AdjustMenuStruct (); CalcTics(); CalcTics(); playstate = ex_titles; } switch (playstate) { case ex_titles: BATTLE_Shutdown(); MU_StartSong(song_title); EnableScreenStretch(); if ((NoWait==false)&&(!modemgame)) { byte dimpal[768]; int i; for (i = 0; i < 0x300; i++) dimpal[i] = origpal[i]>>2; CalcTics(); CalcTics(); IN_ClearKeysDown (); while (IN_GetMouseButtons()) {} while ((!LastScan) && (!IN_GetMouseButtons())) { int i; byte *tempbuf; MenuFadeOut(); ClearGraphicsScreen(); SetPalette((char*)&dimpal[0]); PlayMovie ("shartitl", true); if ( ( LastScan ) || ( IN_GetMouseButtons() ) ) { break; } PlayMovie ("shartit2", true); if ( ( LastScan ) || ( IN_GetMouseButtons() ) ) { break; } SD_Play (SD_LIGHTNINGSND); MenuFadeIn(); I_Delay(30); SD_Play (SD_ACTORSQUISHSND); tempbuf=bufferofs; bufferofs=page1start; // fixed, was displayofs DrawNormalSprite(320-94,200-41,W_GetNumForName("rsac")); VW_UpdateScreen(); // fixed, was missing bufferofs=tempbuf; I_Delay(30); if ( ( LastScan ) || ( IN_GetMouseButtons() ) ) { break; } DoCreditScreen (); if ((!LastScan) && (!IN_GetMouseButtons())) CheckHighScore (0, 0, false); #if (SHAREWARE==0) if ((!LastScan) && (!IN_GetMouseButtons())) { DoMicroStoryScreen (); } #endif if ( (!LastScan) && (!IN_GetMouseButtons()) && (lowmemory==0) && (GameLevels.avail==false) ) { if (demonumber==-1) demonumber=RandomNumber("GameLoop",0); for (i=0; i<4; i++) { demonumber=(demonumber+1)%4; if (DemoExists (demonumber+1) == true) break; } if (DemoExists (demonumber+1) == true) { ingame=true; LoadDemo (demonumber+1); break; } } } } if (playstate != ex_demoplayback) { if (demoexit == true) { QuitGame(); } NoWait = false; SwitchPalette(origpal,35); CP_MainMenu(); } break; case ex_resetgame: // SetTextMode ( ); //12345678 EnableScreenStretch();//bna++ shut on streech mode InitCharacter(); InitializeMessages(); fizzlein = true; BATTLE_GetSpecials(); BATTLE_SetOptions( &BATTLE_Options[ gamestate.battlemode ] ); if ( modemgame == true ) { fizzlein = false; if ( consoleplayer == 0 ) { // Setup Master SetupGameMaster(); } else { // Setup slave SetupGamePlayer(); } if ( gamestate.Version < ROTTVERSION ) { Error( "This version of Rise of the Triad (%d.%d) is incompatible with\n" "version %d.%d.", ROTTMAJORVERSION, ROTTMINORVERSION, gamestate.Version / 10, gamestate.Version % 10 ); } if ( gamestate.teamplay ) { int teams; teams = NumberOfTeams(); if ( gamestate.battlemode == battle_CaptureTheTriad ) { if ( teams != 2 ) { CP_CaptureTheTriadError(); playstate = ex_titles; continue; } } else if ( teams < 2 ) { CP_TeamPlayErrorMessage(); playstate = ex_titles; continue; } } } InitCharacter(); BATTLE_Init( gamestate.battlemode, numplayers ); NewGame = true; if ( ( BATTLEMODE ) && ( BATTLE_ShowKillCount ) ) { StatusBar |= STATUS_KILLS; } else { StatusBar &= ~STATUS_KILLS; } if (loadedgame == false) { if ( !BATTLEMODE ) { PlayCinematic(); } SetupGameLevel(); } IN_ClearKeyboardQueue(); SetupScreen (true); MenuFixup (); playstate=ex_stillplaying; DisableScreenStretch();//bna++ shut off streech mode break; case ex_stillplaying: InitializeMessages(); EnableHudStretch(); SHAKETICS = 0xFFFF; if (modemgame==true) { ComSetTime(); turbo = false; } else if (turbo==true) turbo=false; else newlevel=true; PlayLoop (); break; case ex_died: // SetTextMode ( ); //12345678 Died (); StopWind(); DisableHudStretch(); DisableScreenStretch();//bna++ shut off streech mode while (damagecount>0) DoBorderShifts(); damagecount = 0; SetBorderColor (0); if (demorecord) { FreeDemo (); } if (demoplayback) { FreeDemo (); playstate=ex_demodone; } else { ShutdownClientControls(); Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level if (CheckForQuickLoad()==false) { if (locplayerstate->lives < 0) { if (timelimitenabled == false) { CheckHighScore (gamestate.score, gamestate.mapon+1, false); playstate = ex_titles; AdjustMenuStruct (); ingame = false; locplayerstate->health = MaxHitpointsForCharacter(locplayerstate); gamestate.score = 0; locplayerstate->lives = 3; locplayerstate->weapon = wp_pistol; locplayerstate->triads = 0; UpdateLives (locplayerstate->lives); UpdateScore (gamestate.score); } else { QuitGame(); } } else { fizzlein = true; SetupGameLevel (); UpdateTriads(player,0); playstate = ex_stillplaying; DisableScreenStretch(); } } } break; case ex_warped: StopWind(); TurnShakeOff(); SHAKETICS = 0xffff; gamestate.TimeCount = 0; gamestate.frame=0; Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level fizzlein = true; SetupGameLevel (); playstate = ex_stillplaying; DisableScreenStretch();//bna++ shut off streech mode break; case ex_skiplevel: case ex_secretdone: case ex_secretlevel: case ex_completed: case ex_bossdied: ShutdownClientControls(); TurnShakeOff(); SHAKETICS = 0xffff; if (timelimitenabled == false) { gamestate.TimeCount = 0; gamestate.frame=0; } StopWind(); #if (SHAREWARE==0) if ((playstate==ex_bossdied) && (gamestate.mapon!=30)) { int shape; lbm_t * LBM; byte *s; patch_t *p; char * str = NULL; int width, height; LBM = (lbm_t *) W_CacheLumpName( "deadboss", PU_CACHE, Cvt_lbm_t, 1); VL_DecompressLBM (LBM,false); MenuFadeOut(); switch (gamestate.mapon) { case 6: shape = W_GetNumForName("deadstev"); break; case 14: shape = W_GetNumForName("deadjoe"); break; case 22: shape = W_GetNumForName("deadrobo"); break; case 33: shape = W_GetNumForName("deadtom"); break; // default: // Error("Boss died on an illegal level\n"); // break; } s = W_CacheLumpNum (shape, PU_CACHE, Cvt_patch_t, 1); p = (patch_t *)s; DrawNormalSprite ((320-p->origsize)>>1, (230-(p->height-p->topoffset))>>1, shape); switch (gamestate.mapon) { case 6: str = "\"General\" John Darian"; //strncpy(&str[0],"\"General\" John Darian"); break; case 14: str = "Sebastian \"Doyle\" Krist"; //strcpy(&str[0],"Sebastian \"Doyle\" Krist"); break; case 22: str = "the NME"; //strcpy(&str[0],"the NME"); break; case 33: str = "El Oscuro"; //strcpy(&str[0],"El Oscuro"); break; // default: // Error("Boss died on an illegal level\n"); // break; } CurrentFont=smallfont; US_MeasureStr (&width, &height, "%s", str); US_ClippedPrint ((320-width)>>1, 180, str); VW_UpdateScreen(); MenuFadeIn(); WaitKeyUp(); LastScan = 0; while (!LastScan) IN_UpdateKeyboard(); // Thanks again DrLex LastScan=0; } #endif LevelCompleted ( playstate ); NextLevel = GetNextMap(player->tilex,player->tiley); demoplayback = false; Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level if (NextLevel != -1 ) { gamestate.mapon = NextLevel; PlayCinematic(); fizzlein = true; SetupGameLevel (); playstate = ex_stillplaying; DisableScreenStretch();//bna++ shut off streech mode } else { playstate = ex_gameover; } break; case ex_demodone: ingame=false; ShutdownClientControls(); TurnShakeOff(); SHAKETICS = 0xffff; gamestate.TimeCount = 0; gamestate.frame=0; demoplayback = false; Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level if (predemo_violence != -1) { gamestate.violence = predemo_violence; predemo_violence = -1; } playstate=ex_titles; break; case ex_gameover: StopWind(); DoEndCinematic(); if (playstate==ex_gameover) { CheckHighScore (gamestate.score, gamestate.mapon+1, false); ingame = false; AdjustMenuStruct (); playstate = ex_titles; } break; case ex_demorecord: ShutdownClientControls(); Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level RecordDemo(); SetupGameLevel (); fizzlein = true; playstate = ex_stillplaying; break; case ex_demoplayback: ShutdownClientControls(); Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level SetupDemo(); SetupGameLevel (); fizzlein = true; playstate = ex_stillplaying; break; default: ; } } } boolean CheckForQuickLoad (void ) { EnableScreenStretch();//bna++ if ( pickquick ) { SetupMenuBuf(); pickquick = CP_DisplayMsg( "\nQuick load saved game?\n", 12 ); if ( pickquick ) { AllocateSavedScreenPtr(); CP_LoadGame( 1, 1 ); FreeSavedScreenPtr(); } else { // Erase the quick load message VL_FadeOut( 0, 255, 0, 0, 0, 20 ); } ShutdownMenuBuf(); } return( pickquick ); } //=========================================================================== void ShutDown ( void ) { if (standalone == false) { WriteConfig (); } // if ( // (networkgame==false) && // (modemgame==true) // ) // { // ShutdownModemGame (); // } ShutdownClientControls(); I_ShutdownKeyboard(); ShutdownGameCommands(); MU_Shutdown(); I_ShutdownTimer(); SD_Shutdown(); IN_Shutdown (); ShutdownSoftError (); Z_ShutDown(); // _settextcursor (0x0607); } //=========================================================================== void QuitGame ( void ) { MU_FadeOut(200); while (MU_FadeActive()) { int time=GetTicCount(); while (GetTicCount()==time) {} } Mix_HaltMusic(); PrintMapStats(); PrintTileStats(); SetTextMode(); ClearScanCodes(); exit(0); } void InitCharacter ( void ) { locplayerstate->health = MaxHitpointsForCharacter( locplayerstate ); if (timelimitenabled == true) { locplayerstate->lives = 1; } else { locplayerstate->lives = 3; } ClearTriads (locplayerstate); locplayerstate->playerheight = characters[ locplayerstate->player ].height; // locplayerstate->stepwhich = 0; // locplayerstate->steptime = 0; gamestate.score = 0; if ( gamestate.battlemode == battle_StandAloneGame ) { gamestate.mapon = startlevel; gamestate.difficulty = DefaultDifficulty; } else { gamestate.difficulty = gd_hard; } gamestate.dipballs = 0; gamestate.TimeCount = 0; godmode = 0; damagecount = 0; UpdateScore( gamestate.score ); } extern boolean enableZomROTT; void UpdateGameObjects ( void ) { int j; volatile int atime; objtype * ob,*temp; battle_status BattleStatus; if (controlupdatestarted==0) { return; } atime=GetFastTics(); UpdateClientControls (); if (demoplayback == false) PollControls (); CalcTics (); UpdateClientControls (); while (oldpolltime<oldtime) { UpdateClientControls (); MoveDoors(); ProcessElevators(); MovePWalls(); UpdateLightning (); TriggerStuff(); CheckCriticalStatics(); if (enableZomROTT && gamestate.killcount > 0) { ResurrectEnemies(); } for(j=0; j<numclocks; j++) if (Clocks[j].time1 && ((gamestate.TimeCount == Clocks[j].time1) || (gamestate.TimeCount == Clocks[j].time2))) TRIGGER[Clocks[j].linkindex]=1; for (ob = firstactive; ob;) { temp = ob->nextactive; DoActor (ob); ob = temp; } BattleStatus = BATTLE_CheckGameStatus( battle_refresh, 0 ); if ( BattleStatus != battle_no_event ) { switch( BattleStatus ) { case battle_end_game : case battle_out_of_time : playstate = ex_battledone; break; case battle_end_round : SetWhoHaveWeapons(); break; default: ; } if ( playstate == ex_battledone ) { break; } } #if (SYNCCHECK == 1) CheckForSyncCheck(); #endif if (timelimitenabled == true) { if (timelimit-gamestate.TimeCount>maxtimelimit) timelimit = maxtimelimit+gamestate.TimeCount; if (gamestate.TimeCount == timelimit) { locplayerstate->lives=-1; playstate=ex_died; } } gamestate.TimeCount ++; ResetCurrentCommand(); oldpolltime++; if (GamePaused==true) break; } actortime=GetFastTics()-atime; UpdateClientControls (); if (noecho == false) { if ( player->flags & FL_SHROOMS ) { FX_SetReverb( 230 ); } else if (sky == 0) { FX_SetReverb( min( numareatiles[ player->areanumber ] >> 1, 90 ) ); } } } extern boolean doRescaling; void PauseLoop ( void ) { StopWind(); UpdateClientControls (); while (oldpolltime<oldtime) { CheckUnPause(); #if (SYNCCHECK == 1) CheckForSyncCheck(); #endif oldpolltime++; if (GamePaused==false) { //bna++ section if (( playstate == ex_stillplaying )&&(iGLOBAL_SCREENWIDTH > 320)) { pic_t *shape; shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 ); DrawTiledRegion( 0, 16, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT - 32, 0, 16, shape ); DisableScreenStretch();//dont strech when we go BACK TO GAME DrawPlayScreen(true);//repaint ammo and life stat EnableHudStretch(); VW_UpdateScreen ();//update screen } StartupClientControls(); //bna section end break; } } CalcTics (); if (demoplayback==false) PollControls (); if ((RefreshPause == true) && (GamePaused == true) && ((GetTicCount() - pausedstartedticcount) >= blanktime)) { RefreshPause = false; StartupScreenSaver(); } } void PlayLoop ( void ) { volatile int atime; boolean canquit = true; int quittime = 0; if ( (loadedgame == false) && (timelimitenabled == false) ) { gamestate.TimeCount = 0; gamestate.frame = 0; } fromloadedgame: GamePaused = false; if ( loadedgame == false ) { DrawPlayScreen( true ); missobj = NULL; } else { loadedgame = false; DoLoadGameSequence(); } drawtime = 0; actortime = 0; tics = 0; SetFastTics(0); if ( fizzlein == false ) { StartupClientControls(); } else { ShutdownClientControls(); } // set detail level doublestep = 2 - DetailLevel; ResetMessageTime(); DeletePriorityMessage( MSG_SYSTEM ); if ( ( gamestate.battlemode == battle_Normal ) && ( numplayers == 1 ) ) { AddMessage( "Comm-bat is for Modem and Network games.", MSG_GAME ); AddMessage( "You will not be facing any", MSG_GAME ); AddMessage( "opponents. Have fun and explore.", MSG_GAME ); } while( playstate == ex_stillplaying ) { UpdateClientControls(); if ( GamePaused ) { PauseLoop(); atime = GetFastTics(); if ( RefreshPause ) { ThreeDRefresh(); } else { UpdateScreenSaver(); } } else { if (controlupdatestarted == 1) UpdateGameObjects(); atime = GetFastTics(); ThreeDRefresh(); } SyncToServer(); drawtime = GetFastTics() - atime; // Don't allow player to quit if entering message canquit = !MSG.messageon; PollKeyboard(); MISCVARS->madenoise = false; AnimateWalls(); UpdateClientControls(); if ( AutoDetailOn == true ) { AdaptDetail(); } UpdateClientControls(); DoSprites(); DoAnimatedMaskedWalls(); UpdatePlayers(); DrawTime( false ); UpdateClientControls(); if ( ( !BATTLEMODE ) && ( CP_CheckQuick( LastScan ) ) ) { boolean escaped=false; if (LastScan == sc_Escape) { MU_StoreSongPosition(); MU_StartSong(song_menu); escaped = true; } TurnShakeOff(); StopWind(); SetBorderColor( 0 ); ShutdownClientControls(); if (demoplayback==true) { FreeDemo(); playstate = ex_demodone; if (demoexit==true) { QuitGame(); } return; } ControlPanel( LastScan ); // set detail level doublestep = 2 - DetailLevel; inmenu = false; if ( playstate == ex_titles ) { return; } if ( playstate == ex_stillplaying ) { SetupScreen( false ); } if ( loadedgame == true ) { goto fromloadedgame; } if ( ( playstate == ex_stillplaying ) && ( ( fizzlein == false ) || ( GamePaused ) ) ) { StartupClientControls(); } if ( (playstate == ex_stillplaying) && (GamePaused == false) && (escaped == true) ) { MU_StartSong(song_level); MU_RestoreSongPosition(); } } if ( BATTLEMODE ) { if ( MSG.messageon == false ) { CheckRemoteRidicule( LastScan ); } if ( quitactive == false ) { if ( ( LastScan == sc_Escape ) && ( canquit ) ) { quitactive = true; quittime = GetTicCount() + QUITTIMEINTERVAL; if ( (consoleplayer == 0) || (networkgame == false) ) { AddMessage( "Do you want to end this game? " "(\\FY\\O/\\FN\\O)", MSG_QUIT ); } else { AddMessage( "Do you want to exit to DOS? " "(\\FY\\O/\\EN\\O)", MSG_QUIT ); } } } else { if ( GetTicCount() > quittime ) { quitactive = false; } else if ( LastScan == sc_N ) { DeletePriorityMessage( MSG_QUIT ); quitactive = false; } else if ( LastScan == sc_Y ) { DeletePriorityMessage( MSG_QUIT ); if ( (consoleplayer == 0) || (networkgame==false) ) { AddEndGameCommand(); } else { AddQuitCommand(); } } } } } } //****************************************************************************** // // CheckRemoteRidicule () // //****************************************************************************** void CheckRemoteRidicule ( int scancode ) { int num=-1; switch (scancode) { case sc_F1: num=0; break; case sc_F2: num=1; break; case sc_F3: num=2; break; case sc_F4: num=3; break; case sc_F5: if ( !Keyboard[ sc_RShift ] ) { num=4; } break; case sc_F6: num=5; break; case sc_F7: if ( !Keyboard[ sc_RShift ] ) { num=6; } break; case sc_F8: num=7; break; case sc_F9: num=8; break; case sc_F10: num=9; break; } if (num>=0) { AddRemoteRidiculeCommand ( consoleplayer, MSG_DIRECTED_TO_ALL, num ); LastScan=0; } } //****************************************************************************** // // DoBossKey () // //****************************************************************************** void DoBossKey ( void ) { STUB_FUNCTION; } //****************************************************************************** // // PollKeyboard () // //****************************************************************************** void PollKeyboard ( void ) { static char autopressed = false; if (demoplayback==true) { IN_UpdateKeyboard(); } if ( !BATTLEMODE ) { CheckDebug (); if ( ( Keyboard[ sc_CapsLock ] ) && ( DebugOk ) ) { DebugKeys (); } } if ( locplayerstate->buttonstate[ bt_autorun ] ) { if ( !autopressed ) { autopressed = true; gamestate.autorun ^= 1; if ( gamestate.autorun == 0 ) { AddMessage( "AutoRun is \\cOFF", MSG_SYSTEM ); } else { AddMessage( "AutoRun is \\cON", MSG_SYSTEM ); } } } else { autopressed = false; } if ( ( MSG.messageon == false ) && ( !quitactive ) ) { if ( ( Keyboard[ buttonscan[ bt_message ] ] ) && ( BATTLEMODE ) ) { // Send message to all MSG.messageon = true; MSG.directed = false; MSG.inmenu = false; MSG.remoteridicule = -1; MSG.towho = MSG_DIRECTED_TO_ALL; MSG.textnum = AddMessage( "_", MSG_MODEM ); MSG.length = 1; DeletePriorityMessage( MSG_MACRO ); } else if ( ( Keyboard[ buttonscan[ bt_directmsg ] ] ) && ( BATTLEMODE ) ) { // Send directed message MSG.messageon = true; MSG.directed = true; MSG.inmenu = false; MSG.remoteridicule = -1; MSG.towho = 0; MSG.textnum = AddMessage( "_", MSG_MODEM ); MSG.length = 1; DeletePriorityMessage( MSG_MACRO ); } if ( buttonpoll[ bt_map ] ) { if ( !BATTLEMODE ) { // Automap StopWind(); DoMap( player->tilex, player->tiley ); } else { // Show kill counts if ( SHOW_KILLS() ) { BATTLE_ShowKillCount = false; StatusBar &= ~STATUS_KILLS; } else { StatusBar |= STATUS_KILLS; BATTLE_ShowKillCount = true; } SetupScreen( true ); } } // Shrink screen if ( Keyboard[ sc_Minus ] ) { Keyboard[ sc_Minus ] = false; // HDG debounce if ( viewsize > 0 ) { viewsize--; SetupScreen( true ); } } // Expand screen if ( Keyboard[ sc_Plus ] ) { Keyboard[ sc_Plus ] = false; // HDG debounce if ( viewsize < MAXVIEWSIZES - 1 ) { viewsize++; SetupScreen( true ); } } // Set detail if ( ( Keyboard[ sc_F5 ] ) && ( ( !BATTLEMODE ) || ( Keyboard[ sc_RShift ] ) ) ) { Keyboard[ sc_F5 ] = false; LastScan = 0; DetailLevel++; if ( DetailLevel > 2 ) { DetailLevel = 0; } switch( DetailLevel ) { case 0 : AddMessage( "Low detail", MSG_SYSTEM ); break; case 1 : AddMessage( "Medium detail", MSG_SYSTEM ); break; case 2 : AddMessage( "High detail", MSG_SYSTEM ); break; } doublestep = 2 - DetailLevel; } // Turn messages on/off if ( ( Keyboard[ sc_F7 ] ) && ( ( !BATTLEMODE ) || ( Keyboard[ sc_RShift ] ) ) ) { Keyboard[ sc_F7 ] = false; LastScan = 0; MessagesEnabled = !MessagesEnabled; if ( !MessagesEnabled ) { AddMessage( "Messages disabled.", MSG_MSGSYSTEM ); } else { AddMessage( "Messages enabled.", MSG_MSGSYSTEM ); } } if ( ( Keyboard[ sc_F6 ] ) && ( !BATTLEMODE ) ) { Keyboard[ sc_F6 ] = false; if (Keyboard[sc_RShift]) { ShutdownClientControls(); UndoQuickSaveGame(); StartupClientControls(); } else if (quicksaveslot==-1) { ShutdownClientControls(); LastScan=sc_F2; inmenu = true; ControlPanel( LastScan ); StartupClientControls(); } else { LastScan = 0; ShutdownClientControls(); ThreeDRefresh(); QuickSaveGame(); StartupClientControls(); } } if ( ( Keyboard[ sc_F12 ] ) && ( !BATTLEMODE ) ) { Keyboard[ sc_F12 ] = false; LastScan = 0; DoBossKey(); } // Gamma correction if ( Keyboard[ sc_F11 ] ) { char str[ 50 ] = "Gamma Correction Level "; char str2[ 10 ]; gammaindex++; if ( gammaindex == NUMGAMMALEVELS ) { gammaindex = 0; } VL_SetPalette( origpal ); itoa( gammaindex, str2, 10 ); strncat( str, str2, strlen(str2) ); AddMessage( str, MSG_SYSTEM ); while( Keyboard[ sc_F11 ] ) { IN_UpdateKeyboard(); } } // Increase volume if ( Keyboard[ sc_CloseBracket ] ) { if ( Keyboard[ sc_RShift ] ) { char str[ 50 ] = "Music Volume Level "; char str2[ 10 ]; if ( MUvolume < 255 ) { MUvolume++; } MU_SetVolume( MUvolume ); itoa( MUvolume, str2, 10 ); strncat( str, str2, strlen(str2) ); AddMessage( str, MSG_SYSTEM ); } else { char str[ 50 ] = "Sound FX Volume Level "; char str2[ 10 ]; if ( FXvolume < 255 ) { FXvolume++; } FX_SetVolume( FXvolume ); itoa( FXvolume, str2, 10 ); strncat( str, str2, strlen(str2) ); AddMessage( str, MSG_SYSTEM ); } } // Decrease volume if ( Keyboard[ sc_OpenBracket ] ) { if ( Keyboard[ sc_RShift ] ) { char str[ 50 ] = "Music Volume Level "; char str2[ 10 ]; if ( MUvolume > 0 ) { MUvolume--; } MU_SetVolume( MUvolume ); itoa( MUvolume, str2, 10 ); strncat( str, str2, strlen(str2) ); AddMessage( str, MSG_SYSTEM ); } else { char str[ 50 ] = "Sound FX Volume Level "; char str2[ 10 ]; if ( FXvolume > 0 ) { FXvolume--; } FX_SetVolume( FXvolume ); itoa( FXvolume, str2, 10 ); strncat( str, str2, strlen(str2) ); AddMessage( str, MSG_SYSTEM ); } } #if SAVE_SCREEN else if ( Keyboard[ sc_Alt] && Keyboard[ sc_C ] ) { SaveScreen( false ); } #endif } #ifdef USE_SDL /* SDL doesn't send proper release events for these */ if (Keystate[sc_CapsLock]) { Keystate[sc_CapsLock]++; if (Keystate[sc_CapsLock] == 3) Keystate[sc_CapsLock] = 0; } if (Keystate[0x45]) /* numlock */ { Keystate[0x45]++; if (Keystate[0x45] == 3) Keystate[0x45] = 0; } #endif } #if SAVE_SCREEN short BigShort (short l) { byte b1,b2; b1 = l&255; b2 = (l>>8)&255; return (b1<<8) + b2; } long BigLong (long l) { byte b1,b2,b3,b4; b1 = l&255; b2 = (l>>8)&255; b3 = (l>>16)&255; b4 = (l>>24)&255; return ((long)b1<<24) + ((long)b2<<16) + ((long)b3<<8) + b4; } /* ============== = = WriteLBMfile = ============== */ void WriteLBMfile (char *filename, byte *data, int width, int height) { byte *lbm, *lbmptr; long *formlength, *bmhdlength, *cmaplength, *bodylength; long length; bmhd_t basebmhd; int handle; int i; lbm = lbmptr = (byte *) SafeMalloc ((iGLOBAL_SCREENWIDTH*iGLOBAL_SCREENHEIGHT)+4000); // // start FORM // *lbmptr++ = 'F'; *lbmptr++ = 'O'; *lbmptr++ = 'R'; *lbmptr++ = 'M'; formlength = (long*)lbmptr; lbmptr+=4; // leave space for length *lbmptr++ = 'P'; *lbmptr++ = 'B'; *lbmptr++ = 'M'; *lbmptr++ = ' '; // // write BMHD // *lbmptr++ = 'B'; *lbmptr++ = 'M'; *lbmptr++ = 'H'; *lbmptr++ = 'D'; bmhdlength = (long *)lbmptr; lbmptr+=4; // leave space for length memset (&basebmhd,0,sizeof(basebmhd)); basebmhd.w = BigShort(width); basebmhd.h = BigShort(height); basebmhd.nPlanes = BigShort(8); basebmhd.xAspect = BigShort(5); basebmhd.yAspect = BigShort(6); basebmhd.pageWidth = BigShort(width); basebmhd.pageHeight = BigShort(height); memcpy (lbmptr,&basebmhd,sizeof(basebmhd)); lbmptr += sizeof(basebmhd); length = lbmptr-(byte *)bmhdlength-4; *bmhdlength = BigLong(length); if (length&1) *lbmptr++ = 0; // pad chunk to even offset // // write CMAP // *lbmptr++ = 'C'; *lbmptr++ = 'M'; *lbmptr++ = 'A'; *lbmptr++ = 'P'; cmaplength = (long *)lbmptr; lbmptr+=4; // leave space for length for (i = 0; i < 0x300; i++) *lbmptr++ = (*(origpal+i))<<2; // memcpy (lbmptr,&origpal[0],768); // lbmptr += 768; length = lbmptr-(byte *)cmaplength-4; *cmaplength = BigLong(length); if (length&1) *lbmptr++ = 0; // pad chunk to even offset // // write BODY // *lbmptr++ = 'B'; *lbmptr++ = 'O'; *lbmptr++ = 'D'; *lbmptr++ = 'Y'; bodylength = (long *)lbmptr; lbmptr+=4; // leave space for length memcpy (lbmptr,data,width*height); lbmptr += width*height; length = lbmptr-(byte *)bodylength-4; *bodylength = BigLong(length); if (length&1) *lbmptr++ = 0; // pad chunk to even offset // // done // length = lbmptr-(byte *)formlength-4; *formlength = BigLong(length); if (length&1) *lbmptr++ = 0; // pad chunk to even offset // // write output file // handle = SafeOpenWrite (filename); SafeWrite (handle, lbm, lbmptr-lbm); close (handle); SafeFree(lbm); } //**************************************************************************** // // GetFileName () // //**************************************************************************** void GetFileName (boolean saveLBM) { int i; for (i = 0; i < 9999; i++) { char filename[128]; if (saveLBM) { sprintf(savename, "rott%04d.lbm", i); } else { sprintf(savename, "rott%04d.pcx", i); } GetPathFromEnvironment( filename, ApogeePath, savename ); if (access(filename, F_OK) != 0) { return; } } } //**************************************************************************** // // SaveScreen () // //**************************************************************************** boolean inhmenu; void SaveScreen (boolean saveLBM) { byte *buffer; byte * screen; boolean oldHUD; char filename[ 128 ]; oldHUD=HUD; HUD=false; doublestep=0; if (inhmenu==false) screen = (byte *) bufferofs; else screen = (byte *) displayofs; if (inhmenu==false) ThreeDRefresh (); doublestep = 2 - DetailLevel; //buffer = (byte *) SafeMalloc (65000); buffer = (byte *) SafeMalloc ((iGLOBAL_SCREENHEIGHT*iGLOBAL_SCREENWIDTH)+4000); GetFileName (saveLBM); GetPathFromEnvironment( filename, ApogeePath, savename ); // memcpy(buffer,screen, iGLOBAL_SCREENWIDTH*iGLOBAL_SCREENHEIGHT); //bna //bna--VL_CopyPlanarPageToMemory(screen,buffer); if (saveLBM) { WriteLBMfile (filename, buffer, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT); while (Keyboard[sc_Alt] && Keyboard[sc_V]) IN_UpdateKeyboard (); } else { WritePCX (filename, buffer); while (Keyboard[sc_Alt] && Keyboard[sc_C]) IN_UpdateKeyboard (); } SafeFree(buffer); HUD=oldHUD; } //**************************************************************************** // // WritePCX () // //**************************************************************************** void WritePCX (char * file, byte * source) { PCX_HEADER pcxHDR; byte *tempbuffer; byte pal[0x300]; int pcxhandle; int i, j, y; unsigned char c; unsigned char buffer1[GAP_SIZE]; pcxhandle = SafeOpenWrite (file); /* --- init the header that we'll write. * Note: since DPaint never reads & writes at the same time, * it is okay to share the same read & write structure, * unlike in CONVERT.EXE. */ memset (&pcxHDR, 0, sizeof(PCX_HEADER)); pcxHDR.manufacturer = 10; pcxHDR.version = 5; pcxHDR.encoding = 1; pcxHDR.bitsperpixel = 8; //bpp; pcxHDR.xmin = pcxHDR.ymin = 0; pcxHDR.xmax = iGLOBAL_SCREENWIDTH - 1; pcxHDR.ymax = iGLOBAL_SCREENHEIGHT - 1; pcxHDR.hres = iGLOBAL_SCREENWIDTH; //N_COLUMNS; pcxHDR.vres = iGLOBAL_SCREENHEIGHT; //N_LINES; // bytesperline doesn't take into account multiple planes. // Output in same format as bitmap (planar vs packed). // pcxHDR.bytesperline = iGLOBAL_SCREENWIDTH; //bitmap->width; pcxHDR.nplanes = 1; //bitmap->planes; pcxHDR.reserved = 0; // First 16 colors of our palette info. for (i = 0, j = 0; i < 16; ++i, j += 3) { pcxHDR.colormap[i][0] = (unsigned char)(origpal[j]); pcxHDR.colormap[i][1] = (unsigned char)(origpal[j]+2); pcxHDR.colormap[i][2] = (unsigned char)(origpal[j]+3); } // // Write the 128-byte header // SafeWrite(pcxhandle,&pcxHDR, sizeof (PCX_HEADER)); memset (buffer1, 0, GAP_SIZE); SafeWrite (pcxhandle, &buffer1, GAP_SIZE); tempbuffer = (byte *) SafeMalloc ((iGLOBAL_SCREENHEIGHT*iGLOBAL_SCREENWIDTH)+4000); bptr = tempbuffer; totalbytes = 0; // // Write to a bit-packed file. // for (y = 0; y < iGLOBAL_SCREENHEIGHT; ++y) // for each line in band if (PutBytes (((unsigned char *) (source+(y*iGLOBAL_SCREENWIDTH))), pcxHDR.bytesperline)) Error ("Error writing PCX bit-packed line!\n"); SafeWrite (pcxhandle, tempbuffer, totalbytes); // // Write out PCX palette // c = 0x0C; for (i = 0; i < 0x300; i++) pal[i] = (*(origpal+i))<<2; SafeWrite (pcxhandle, &c, 1); SafeWrite (pcxhandle, &pal[0], 768); close (pcxhandle); SafeFree (tempbuffer); } //**************************************************************************** // // PutBytes () // // Write bytes to a file, handling packing as it goes. // Returns : 0 == SUCCESS // 1 == FAIL. // //**************************************************************************** int PutBytes (unsigned char *ptr, unsigned int bytes) { unsigned int startbyte, count; char b; while (bytes > 0) { // check for a repeating byte value startbyte = *ptr; *ptr++ = 0; --bytes; count = 1; while (*ptr == startbyte && bytes > 0 && count < 63) { *ptr = 0; ++ptr; --bytes; ++count; } // If we can pack the sequence, or if we have to add a // byte before it because the top 2 bits of the value // are 1's, write a packed sequence of 2 bytes. // Otherwise, just write the byte value. // if (count > 1 || (startbyte & 0xc0) == 0xc0) { b = 0xc0 | count; *bptr++ = b; totalbytes++; } b = startbyte; *bptr++ = b; totalbytes++; } return (0); } #endif //**************************************************************************** // // PlayCinematic () - Play intro cinematics // //**************************************************************************** void PlayCinematic (void) { if ((tedlevel == true) || (turbo == true)) return; switch (gamestate.mapon) { #if (SHAREWARE == 0) byte pal[768]; case 0: // Start of EPISODE 1 MU_StartSong ( song_cinematic1 ); VL_FadeOut (0, 255, 0, 0, 0, 20); VL_ClearBuffer (bufferofs, 0); DrawNormalSprite(0,30,W_GetNumForName("nicolas")); DrawNormalSprite(0,168,W_GetNumForName("oneyear")); FlipPage(); memcpy(&pal[0],W_CacheLumpName("nicpal",PU_CACHE, CvtNull, 1),768); VL_NormalizePalette(&pal[0]); VL_FadeIn(0,255,pal,20); I_Delay (60); VL_FadeOut (0, 255, 0, 0, 0, 20); IN_UpdateKeyboard(); if (LastScan!=0) { LastScan=0; return; } SD_PlayPitchedSound(SD_LIGHTNINGSND,255,-1500); DoInBetweenCinematic (20, W_GetNumForName("binoculr"), 80, "The HUNT cases an\n" "ancient monastery." ); IN_UpdateKeyboard(); if (LastScan!=0) { LastScan=0; return; } SD_Play(SD_NMESEESND); DoInBetweenCinematic (20, W_GetNumForName("binosee"), 80, "\"There they are,\" says\n" "Cassatt. \"Let's get back\n" "to the boat and inform HQ.\"" ); IN_UpdateKeyboard(); if (LastScan!=0) { LastScan=0; return; } SD_Play(SD_HIGHGUARD1SEESND); DoInBetweenCinematic (20, W_GetNumForName("boatgard"), 80, "\"The intruders, on that hill!\"" ); IN_UpdateKeyboard(); if (LastScan!=0) { LastScan=0; return; } SD_Play(SD_EXPLODESND); DoInBetweenCinematic (20, W_GetNumForName("boatblow"), 80, "\"There goes our ride home,\"\n" "says Barrett. \"Looks like\n" "the only way out is in....\"" ); IN_UpdateKeyboard(); LastScan=0; break; case 8: // Start of EPISODE 2 MU_StartSong ( song_cinematic2 ); DoInBetweenCinematic (0, W_GetNumForName("epi12"), 1200, "The HUNT makes their way\n" "into the main keep." ); IN_UpdateKeyboard(); LastScan=0; break; case 16: // Start of EPISODE 3 MU_StartSong ( song_cinematic1 ); DoInBetweenCinematic (20, W_GetNumForName("epi23"), 1200, "The HUNT stands before a pair\n" "of ominous wooden doors.\n" "The sounds of machinery and\n" "servomotors fill the air.\n" ); IN_UpdateKeyboard(); LastScan=0; break; case 24: // Start of EPISODE 4 MU_StartSong ( song_cinematic2 ); DoInBetweenCinematic (0, W_GetNumForName("epi34"), 1200, "Stairs lead down beneath the\n" "keep. From behind the doors\n" "come the moans of the undead." ); IN_UpdateKeyboard(); LastScan=0; break; #endif } }