ref: 4c510b80e7330e4cb77b1b564483f1b5c3a2dd0f
dir: /Game/src/global.c/
//------------------------------------------------------------------------- /* Copyright (C) 1996, 2003 - 3D Realms Entertainment This file is part of Duke Nukem 3D version 1.5 - Atomic Edition Duke Nukem 3D is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License aint32_t with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Original Source: 1996 - Todd Replogle Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms */ //------------------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <errno.h> #include "duke3d.h" uint8_t *mymembuf; uint8_t MusicPtr[72000]; crc32_t crc32lookup[] = { // good: { CRC_BASE_GRP_SHAREWARE_13, "SHAREWARE 1.3D", 11035779 }, { CRC_BASE_GRP_FULL_13, "FULL 1.3D ", 26524524 }, { CRC_BASE_GRP_PLUTONIUM_14, "PLUTONIUM 1.4 ", 44348015 }, { CRC_BASE_GRP_ATOMIC_15, "ATOMIC 1.5 ", 44356548 }, // unknown: { 0, "HACK/UNKNOWN ", 0} }; uint8_t conVersion = 13; uint8_t grpVersion = 0; // FIX_00015: Backward compliance with older demos (down to demos v27, 28, 116 and 117 only) // For BYTEVERSION diff, 27/116 vs 28/117 see extras\duke3d.h vs source\duke3d.h // from the official source code release. int BYTEVERSION_27 = 27; // 1.3 under 1.4 Plutonium. Not supported anymore int BYTEVERSION_116 = 116; // 1.4 Plutonium. Not supported anymore int BYTEVERSION_28 = 28; // 1.3 under 1.5 engine int BYTEVERSION_117 = 117; // 1.5 Atomic int BYTEVERSION_29 = 29; // 1.3 under xDuke v19.6. int BYTEVERSION_118 = 118; // 1.5 Atomic under xDuke v19.6. int BYTEVERSION_1_3 = 1; // for 1.3 demos (Not compatible) int BYTEVERSION = 119; // xDuke v19.7 short global_random; short neartagsector, neartagwall, neartagsprite; int32_t gc,neartaghitdist,lockclock,max_player_health,max_armour_amount,max_ammo_amount[MAX_WEAPONS]; // int32_t temp_data[MAXSPRITES][6]; struct weaponhit hittype[MAXSPRITES]; short spriteq[1024],spriteqloc,spriteqamount=64; // ported build engine has this, too. --ryan. #if PLATFORM_DOS short moustat = 0; #endif struct animwalltype animwall[MAXANIMWALLS]; short numanimwalls; int32_t *animateptr[MAXANIMATES], animategoal[MAXANIMATES], animatevel[MAXANIMATES], animatecnt; // int32_t oanimateval[MAXANIMATES]; short animatesect[MAXANIMATES]; int32_t msx[2048],msy[2048]; short cyclers[MAXCYCLERS][6],numcyclers; char fta_quotes[NUMOFFIRSTTIMEACTIVE][64]; char tempbuf[2048]; uint8_t packbuf[576]; char buf[80]; short camsprite; short mirrorwall[64], mirrorsector[64], mirrorcnt; int current_menu; uint8_t betaname[80]; char level_names[44][33]; char level_file_names[44][128]; int32_t partime[44],designertime[44]; char volume_names[4][33] = { "L.A. MELTDOWN", "LUNAR APOCALYPSE", "SHRAPNEL CITY", "" }; // Names are not in 1.3 con files. MUST be in code. char skill_names[5][33] = { "PIECE OF CAKE", "LET'S ROCK", "COME GET SOME", "DAMN I'M GOOD", "" }; volatile int32_t checksume; int32_t soundsiz[NUM_SOUNDS]; short soundps[NUM_SOUNDS],soundpe[NUM_SOUNDS],soundvo[NUM_SOUNDS]; uint8_t soundm[NUM_SOUNDS],soundpr[NUM_SOUNDS]; char sounds[NUM_SOUNDS][14]; short title_zoom; fx_device device; SAMPLE Sound[ NUM_SOUNDS ]; SOUNDOWNER SoundOwner[NUM_SOUNDS][4]; uint8_t numplayersprites,earthquaketime; int32_t fricxv,fricyv; struct player_orig po[MAXPLAYERS]; struct player_struct ps[MAXPLAYERS]; struct user_defs ud; uint8_t pus, pub; uint8_t syncstat, syncval[MAXPLAYERS][MOVEFIFOSIZ]; int32_t syncvalhead[MAXPLAYERS], syncvaltail, syncvaltottail; input sync[MAXPLAYERS], loc; input recsync[RECSYNCBUFSIZ]; int32_t avgfvel, avgsvel, avgavel, avghorz, avgbits; input inputfifo[MOVEFIFOSIZ][MAXPLAYERS]; input recsync[RECSYNCBUFSIZ]; int32_t movefifosendplc; //Multiplayer syncing variables short screenpeek; int32_t movefifoend[MAXPLAYERS]; //Game recording variables uint8_t playerreadyflag[MAXPLAYERS],ready2send; uint8_t playerquitflag[MAXPLAYERS]; int32_t vel, svel, angvel, horiz, ototalclock, respawnactortime=768, respawnitemtime=768, groupfile; int32_t script[MAXSCRIPTSIZE],*scriptptr,*insptr,*labelcode,labelcnt; int32_t *actorscrptr[MAXTILES],*parsing_actor; char *label,*textptr,error,warning ; uint8_t killit_flag; uint8_t *music_pointer; uint8_t actortype[MAXTILES]; uint8_t display_mirror,typebuflen; char typebuf[41]; char music_fn[4][11][13]; uint8_t music_select; char env_music_fn[4][13]; uint8_t rtsplaying; short weaponsandammosprites[15] = { RPGSPRITE, CHAINGUNSPRITE, DEVISTATORAMMO, RPGAMMO, RPGAMMO, JETPACK, SHIELD, FIRSTAID, STEROIDS, RPGAMMO, RPGAMMO, RPGSPRITE, RPGAMMO, FREEZESPRITE, FREEZEAMMO }; int32_t impact_damage; //GLOBAL.C - replace the end "my's" with this int32_t myx, omyx, myxvel, myy, omyy, myyvel, myz, omyz, myzvel; short myhoriz, omyhoriz, myhorizoff, omyhorizoff; short myang, omyang, mycursectnum, myjumpingcounter,frags[MAXPLAYERS][MAXPLAYERS]; uint8_t myjumpingtoggle, myonground, myhardlanding, myreturntocenter; int8_t multiwho, multipos, multiwhat, multiflag; int32_t fakemovefifoplc,movefifoplc; int32_t myxbak[MOVEFIFOSIZ], myybak[MOVEFIFOSIZ], myzbak[MOVEFIFOSIZ]; int32_t myhorizbak[MOVEFIFOSIZ],dukefriction = 0xcc00, show_shareware; short myangbak[MOVEFIFOSIZ]; char myname[2048] = {"XDUKE"}; uint8_t camerashitable,freezerhurtowner=0,lasermode; // CTW - MODIFICATION // uint8_t networkmode = 255, movesperpacket = 1,gamequit = 0,playonten = 0,everyothertime; uint8_t networkmode = 255, movesperpacket = 1,gamequit = 0,everyothertime; // CTW END - MODIFICATION int32_t numfreezebounces=3,rpgblastradius,pipebombblastradius,tripbombblastradius,shrinkerblastradius,morterblastradius,bouncemineblastradius,seenineblastradius; STATUSBARTYPE sbar; int32_t myminlag[MAXPLAYERS], mymaxlag, otherminlag, bufferjitter = 1; short numclouds,clouds[128],cloudx[128],cloudy[128]; int32_t cloudtotalclock = 0,totalmemory = 0; int32_t numinterpolations = 0, startofdynamicinterpolations = 0; int32_t oldipos[MAXINTERPOLATIONS]; int32_t bakipos[MAXINTERPOLATIONS]; int32_t *curipos[MAXINTERPOLATIONS]; // portability stuff. --ryan. // A good portion of this was ripped from GPL'd Rise of the Triad. --ryan. void FixFilePath(char *filename) { #if PLATFORM_UNIX uint8_t *ptr; uint8_t *lastsep = filename; if ((!filename) || (*filename == '\0')) return; if (access(filename, F_OK) == 0) /* File exists; we're good to go. */ return; for (ptr = filename; 1; ptr++) { if (*ptr == '\\') *ptr = PATH_SEP_CHAR; if ((*ptr == PATH_SEP_CHAR) || (*ptr == '\0')) { uint8_t pch = *ptr; struct dirent *dent = NULL; DIR *dir; if ((pch == PATH_SEP_CHAR) && (*(ptr + 1) == '\0')) return; /* eos is pathsep; we're done. */ if (lastsep == ptr) continue; /* absolute path; skip to next one. */ *ptr = '\0'; if (lastsep == filename) { dir = opendir((*lastsep == PATH_SEP_CHAR) ? ROOTDIR : CURDIR); if (*lastsep == PATH_SEP_CHAR) { lastsep++; } } else { *lastsep = '\0'; dir = opendir(filename); *lastsep = PATH_SEP_CHAR; lastsep++; } if (dir == NULL) { *ptr = PATH_SEP_CHAR; return; /* maybe dir doesn't exist? give up. */ } while ((dent = readdir(dir)) != NULL) { if (strcasecmp(dent->d_name, lastsep) == 0) { /* found match; replace it. */ strcpy(lastsep, dent->d_name); break; } } closedir(dir); *ptr = pch; lastsep = ptr; if (dent == NULL) return; /* no match. oh well. */ if (pch == '\0') /* eos? */ return; } } #endif } #if PLATFORM_DOS /* no-op. */ #elif PLATFORM_WIN32 int _dos_findfirst(uint8_t *filename, int x, struct find_t *f) { int32_t rc = _findfirst(filename, &f->data); f->handle = rc; if (rc != -1) { strncpy(f->name, f->data.name, sizeof (f->name) - 1); f->name[sizeof (f->name) - 1] = '\0'; return(0); } return(1); } int _dos_findnext(struct find_t *f) { int rc = 0; if (f->handle == -1) return(1); /* invalid handle. */ rc = _findnext(f->handle, &f->data); if (rc == -1) { _findclose(f->handle); f->handle = -1; return(1); } strncpy(f->name, f->data.name, sizeof (f->name) - 1); f->name[sizeof (f->name) - 1] = '\0'; return(0); } #elif defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX) int _dos_findfirst(char *filename, int x, struct find_t *f) { char *ptr; if (strlen(filename) >= sizeof (f->pattern)) return(1); strcpy(f->pattern, filename); FixFilePath(f->pattern); ptr = strrchr(f->pattern, PATH_SEP_CHAR); if (ptr == NULL) { ptr = filename; f->dir = opendir(CURDIR); } else { *ptr = '\0'; f->dir = opendir(f->pattern); memmove(f->pattern, ptr + 1, strlen(ptr + 1) + 1); } return(_dos_findnext(f)); } static int check_pattern_nocase(const char *x, const char *y) { if ((x == NULL) || (y == NULL)) return(0); /* not a match. */ while ((*x) && (*y)) { if (*x == '*') { x++; while (*y != '\0') { if (toupper((int) *x) == toupper((int) *y)) break; y++; } } else if (*x == '?') { if (*y == '\0') return(0); /* anything but EOS is okay. */ } else { if (toupper((int) *x) != toupper((int) *y)) return(0); /* not a match. */ } x++; y++; } return(*x == *y); /* it's a match (both should be EOS). */ } int _dos_findnext(struct find_t *f) { struct dirent *dent; if (f->dir == NULL) return(1); /* no such dir or we're just done searching. */ while ((dent = readdir(f->dir)) != NULL) { if (check_pattern_nocase(f->pattern, dent->d_name)) { if (strlen(dent->d_name) < sizeof (f->name)) { strcpy(f->name, dent->d_name); return(0); /* match. */ } } } closedir(f->dir); f->dir = NULL; return(1); /* no match in whole directory. */ } #else #error please define for your platform. #endif #if !PLATFORM_DOS void _dos_getdate(struct dosdate_t *date) { time_t curtime = time(NULL); struct tm *tm; if (date == NULL) { return; } memset(date, 0, sizeof(struct dosdate_t)); if ((tm = localtime(&curtime)) != NULL) { date->day = tm->tm_mday; date->month = tm->tm_mon + 1; date->year = tm->tm_year + 1900; date->dayofweek = tm->tm_wday + 1; } } #endif int FindDistance2D(int ix, int iy) { int t; ix= abs(ix); /* absolute values */ iy= abs(iy); if (ix<iy) { int tmp = ix; ix = iy; iy = tmp; } t = iy + (iy>>1); return (ix - (ix>>5) - (ix>>7) + (t>>2) + (t>>6)); } int FindDistance3D(int ix, int iy, int iz) { int t; ix= abs(ix); /* absolute values */ iy= abs(iy); iz= abs(iz); if (ix<iy) { int tmp = ix; ix = iy; iy = tmp; } if (ix<iz) { int tmp = ix; ix = iz; iz = tmp; } t = iy + iz; return (ix - (ix>>4) + (t>>2) + (t>>3)); } #include "SDL.h" void Error (int errorType, char *error, ...) { va_list argptr; SDL_Quit(); if(errorType==EXIT_FAILURE) printf("ERROR: Please copy that screen and visit http://duke3d.m-klein.com for report:\n"); else printf("http://duke3d.m-klein.com\n"); va_start (argptr, error); vprintf(error, argptr); va_end (argptr); printf("Press any key to continue...\n"); // FIX_00043: Nicer exit on error. Ask the user to hit a key on exits and error exits. getch(); exit (errorType); } void write2disk(int line, char * cfilename, char *filename2write, char *message) { // usage: write2disk(__LINE__, __FILE__, "c:\temp\my_dbug_file.txt", uint8_t * msg); int i, k=0; char filename[2048]; FILE *pFile; for(i=0; cfilename[i]; i++) { if(cfilename[i]=='\\') { i++; k = 0; } filename[k++]=(cfilename[i]=='.')?0:cfilename[i]; } pFile = fopen(filename2write,"a"); fprintf(pFile,"%-4d %-5s %s", line, filename, message); fclose(pFile); } int32 SafeOpenAppend (const char *_filename, int32 filetype) { int handle; char filename[MAX_PATH]; strncpy(filename, _filename, sizeof (filename)); filename[sizeof (filename) - 1] = '\0'; FixFilePath(filename); #if (defined PLATFORM_WIN32) handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_APPEND ); #else handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_APPEND , S_IREAD | S_IWRITE); #endif if (handle == -1) Error (EXIT_FAILURE, "Error opening for append %s: %s",filename,strerror(errno)); return handle; } boolean SafeFileExists ( const char * _filename ) { char filename[MAX_PATH]; strncpy(filename, _filename, sizeof (filename)); filename[sizeof (filename) - 1] = '\0'; FixFilePath(filename); #if( defined PLATFORM_WIN32) return(access(filename, 6) == 0); #else return(access(filename, F_OK) == 0); #endif } int32 SafeOpenWrite (const char *_filename, int32 filetype) { int handle; char filename[MAX_PATH]; strncpy(filename, _filename, sizeof (filename)); filename[sizeof (filename) - 1] = '\0'; FixFilePath(filename); #if (defined PLATFORM_WIN32) handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_TRUNC ); #else handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_TRUNC , S_IREAD | S_IWRITE); #endif if (handle == -1) Error (EXIT_FAILURE, "Error opening %s: %s",filename,strerror(errno)); return handle; } int32 SafeOpenRead (const char *_filename, int32 filetype) { int handle; char filename[MAX_PATH]; strncpy(filename, _filename, sizeof (filename)); filename[sizeof (filename) - 1] = '\0'; FixFilePath(filename); handle = open(filename,O_RDONLY | O_BINARY); if (handle == -1) Error (EXIT_FAILURE, "Error opening %s: %s",filename,strerror(errno)); return handle; } void SafeRead (int32 handle, void *buffer, int32 count) { unsigned iocount; while (count) { iocount = count > 0x8000 ? 0x8000 : count; if (read (handle,buffer,iocount) != (int)iocount) Error (EXIT_FAILURE, "File read failure reading %ld bytes",count); buffer = (void *)( (byte *)buffer + iocount ); count -= iocount; } } void SafeWrite (int32 handle, void *buffer, int32 count) { unsigned iocount; while (count) { iocount = count > 0x8000 ? 0x8000 : count; if (write (handle,buffer,iocount) != (int)iocount) Error (EXIT_FAILURE, "File write failure writing %ld bytes",count); buffer = (void *)( (byte *)buffer + iocount ); count -= iocount; } } void SafeWriteString (int handle, char * buffer) { unsigned iocount; iocount=strlen(buffer); if (write (handle,buffer,iocount) != (int)iocount) Error (EXIT_FAILURE, "File write string failure writing %s\n",buffer); } void *SafeMalloc (int32_t size) { void *ptr; #if 0 if (zonememorystarted==false) Error(EXIT_FAILURE, "Called SafeMalloc without starting zone memory\n"); ptr = Z_Malloc (size,PU_STATIC,NULL); #else ptr = malloc(size); #endif if (!ptr) Error (EXIT_FAILURE, "SafeMalloc failure for %lu bytes",size); return ptr; } void SafeRealloc (void **x, int32 size) { void *ptr; #if 0 if (zonememorystarted==false) Error(EXIT_FAILURE, "Called SafeMalloc without starting zone memory\n"); ptr = Z_Malloc (size,PU_STATIC,NULL); #else ptr = realloc(*x, size); #endif if (!ptr) Error (EXIT_FAILURE, "SafeRealloc failure for %lu bytes",size); *x = ptr; } void *SafeLevelMalloc (int32_t size) { void *ptr; #if 0 if (zonememorystarted==false) Error(EXIT_FAILURE, "Called SafeLevelMalloc without starting zone memory\n"); ptr = Z_LevelMalloc (size,PU_STATIC,NULL); #else ptr = malloc(size); #endif if (!ptr) Error (EXIT_FAILURE, "SafeLevelMalloc failure for %lu bytes",size); return ptr; } void SafeFree (void * ptr) { if ( ptr == NULL ) Error (EXIT_FAILURE, "SafeFree : Tried to free a freed pointer\n"); #if 0 Z_Free (ptr); #else free(ptr); #endif } #ifndef LITTLE_ENDIAN #define LITTLE_ENDIAN 1234 #endif #ifndef BIG_ENDIAN #define BIG_ENDIAN 4321 #endif #if PLATFORM_DOS #ifndef BYTE_ORDER #define BYTE_ORDER LITTLE_ENDIAN #endif #endif #if PLATFORM_WIN32 #ifndef BYTE_ORDER #define BYTE_ORDER LITTLE_ENDIAN #endif #endif #ifndef BYTE_ORDER #error Please define your platform. #endif #if (BYTE_ORDER == LITTLE_ENDIAN) #define KeepShort IntelShort #define SwapShort MotoShort #define Keepint32_t IntelLong #define Swapint32_t MotoLong #else #define KeepShort MotoShort #define SwapShort IntelShort #define Keepint32_t MotoLong #define Swapint32_t IntelLong #endif short SwapShort (short l) { byte b1,b2; b1 = l&255; b2 = (l>>8)&255; return (b1<<8) + b2; } short KeepShort (short l) { return l; } int32_t Swapint32_t (int32_t 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; } int32_t Keepint32_t (int32_t l) { return l; } #undef KeepShort #undef KeepLong #undef SwapShort #undef SwapLong void SwapIntelLong(int32_t *l) { *l = IntelLong(*l); } void SwapIntelShort(short *s) { *s = IntelShort(*s); } void SwapIntelLongArray(int32_t *l, int num) { while (num--) { SwapIntelLong(l); l++; } } void SwapIntelShortArray(short *s, int num) { while (num--) { SwapIntelShort(s); s++; } } /* Copied over from Wolf3D Linux: http://www.icculus.org/wolf3d/ Modified for ROTT. Stolen for Duke3D, too. */ #if PLATFORM_UNIX uint8_t *strlwr(uint8_t *s) { uint8_t *p = s; while (*p) { *p = tolower(*p); p++; } return s; } uint8_t *strupr(uint8_t *s) { uint8_t *p = s; while (*p) { *p = toupper(*p); p++; } return s; } uint8_t *itoa(int value, uint8_t *string, int radix) { switch (radix) { case 10: sprintf(string, "%d", value); break; case 16: sprintf(string, "%x", value); break; default: STUBBED("unknown radix"); break; } return string; } uint8_t *ltoa(int32_t value, uint8_t *string, int radix) { switch (radix) { case 10: sprintf(string, "%ld", value); break; case 16: sprintf(string, "%lx", value); break; default: STUBBED("unknown radix"); break; } return string; } uint8_t *ultoa(unsigned int32_t value, uint8_t *string, int radix) { switch (radix) { case 10: sprintf(string, "%lu", value); break; case 16: sprintf(string, "%lux", value); break; default: STUBBED("unknown radix"); break; } return string; } #endif char ApogeePath[256]; int setup_homedir (void) { #if PLATFORM_UNIX int err; snprintf (ApogeePath, sizeof (ApogeePath), "%s/.duke3d/", getenv ("HOME")); err = mkdir (ApogeePath, S_IRWXU); if (err == -1 && errno != EEXIST) { fprintf (stderr, "Couldn't create preferences directory: %s\n", strerror (errno)); return -1; } #else sprintf(ApogeePath, ".%s", PATH_SEP_STR); #endif return 0; } uint8_t CheckParm (char *check) { int i; for (i = 1; i < _argc; i++) { if ((*(_argv[i]) == '-') && (strcmpi(_argv[i] + 1, check) == 0)) return(i); } return(0); } static void (*shutdown_func)(void) = NULL; void RegisterShutdownFunction( void (* shutdown) (void) ) { shutdown_func = shutdown; } void Shutdown(void) { if (shutdown_func != NULL) { shutdown_func(); shutdown_func = NULL; } } /* * From Ryan's buildengine CHANGELOG: * Removed global var: cachedebug in engine.c, and put #define * BUILD_CACHEDEBUG 0 at the top of the source. Flip it to 1 if you ever * need to tinker in the cache code. */ uint8_t cachedebug = 0;