/* Copyright (C) 1997-2001 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // common.c -- misc functions used in client and server #include "qcommon.h" #include #include "md5.h" #define MAX_NUM_ARGVS 50 qboolean com_initialized; int com_argc; char *com_argv[MAX_NUM_ARGVS+1]; int realtime; jmp_buf abortframe; // an ERR_DROP occured, exit the entire frame int log_stats_file; cvar_t *host_speeds; cvar_t *log_stats; cvar_t *developer; cvar_t *timescale; cvar_t *fixedtime; cvar_t *logconsole = NULL; cvar_t *logconsole_append; cvar_t *logconsole_flush; cvar_t *com_showtrace; cvar_t *dedicated; cvar_t *sv_defaultmap; cvar_t *versioncvar; int logfile; static int server_state = CA_UNINITIALIZED; static int client_state = CA_UNINITIALIZED; static qboolean demo_playing = qfalse; // host_speeds times unsigned int time_before_game; unsigned int time_after_game; unsigned int time_before_ref; unsigned int time_after_ref; /* ============================================================== BSP FORMATS ============================================================== */ bspFormatDesc_t bspFormats[] = { { QFBSPHEADER, QFBSPVERSION, QF_LIGHTMAP_WIDTH, QF_LIGHTMAP_HEIGHT, BSP_RAVEN }, { IDBSPHEADER, Q3BSPVERSION, LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT, BSP_NONE }, { IDBSPHEADER, RTCWBSPVERSION, LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT, BSP_NONE }, { RBSPHEADER, RBSPVERSION, LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT, BSP_RAVEN } }; int numBspFormats = sizeof( bspFormats ) / sizeof( bspFormats[0] ); /* ============================================================================ CLIENT / SERVER interactions ============================================================================ */ static int rd_target; static char *rd_buffer; static int rd_buffersize; static void (*rd_flush)( int target, char *buffer ); void Com_BeginRedirect( int target, char *buffer, int buffersize, void (*flush) ) { if( !target || !buffer || !buffersize || !flush ) return; rd_target = target; rd_buffer = buffer; rd_buffersize = buffersize; rd_flush = flush; *rd_buffer = 0; } void Com_EndRedirect( void ) { rd_flush( rd_target, rd_buffer ); rd_target = 0; rd_buffer = NULL; rd_buffersize = 0; rd_flush = NULL; } /* ============= Com_Printf Both client and server can use this, and it will output to the apropriate place. ============= */ void Com_Printf( char *fmt, ... ) { va_list argptr; char msg[MAX_PRINTMSG]; va_start( argptr, fmt ); vsnprintf( msg, sizeof(msg), fmt, argptr ); va_end( argptr ); if( rd_target ) { if( (int)(strlen(msg) + strlen(rd_buffer)) > (rd_buffersize - 1) ) { rd_flush( rd_target, rd_buffer ); *rd_buffer = 0; } strcat( rd_buffer, msg ); return; } Con_Print( msg ); // also echo to debugging console Sys_ConsoleOutput( msg ); // logfile if( logconsole && logconsole->string && strlen(logconsole->string) ) { if( !logfile ) { int length; char name[MAX_QPATH]; Q_strncpyz( name, logconsole->string, sizeof(name) ); COM_DefaultExtension( name, ".log", sizeof(name) ); if( logconsole_append->integer ) length = FS_FOpenFile( name, &logfile, FS_APPEND ); else length = FS_FOpenFile( name, &logfile, FS_WRITE ); if( length == -1 ) { logfile = -1; // only try to open it once Com_Printf( "Couldn't open: %s\n", name ); } } if( logfile > 0 ) { FS_Printf( logfile, "%s", msg ); if( logconsole_flush->integer ) FS_Flush( logfile ); // force it to save every time } } } /* ================ Com_DPrintf A Com_Printf that only shows up if the "developer" cvar is set ================ */ void Com_DPrintf( char *fmt, ... ) { va_list argptr; char msg[MAX_PRINTMSG]; if (!developer || !developer->integer) return; // don't confuse non-developers with techie stuff... va_start( argptr,fmt ); vsnprintf( msg, sizeof(msg), fmt, argptr ); va_end( argptr ); Com_Printf( "%s", msg ); } /* ============= Com_Error Both client and server can use this, and it will do the apropriate things. ============= */ void Com_Error( int code, char *fmt, ... ) { va_list argptr; static char msg[MAX_PRINTMSG]; static qboolean recursive; // wsw: pb: miss initialisation of recursive recursive = qfalse; if( recursive ) { Com_Printf( "recursive error after: %s", msg ); // wsw : jal : log it Sys_Error ( "recursive error after: %s", msg ); } recursive = qtrue; va_start( argptr, fmt ); vsnprintf( msg, sizeof(msg), fmt, argptr ); va_end( argptr ); if( code == ERR_DISCONNECT ) { CL_Disconnect( msg ); recursive = qfalse; if( !com_initialized ) Sys_Error( "%s", msg ); else Com_Printf( "Disconnected: %s\n", msg ); longjmp( abortframe, -1 ); } else if( code == ERR_DROP ) { Com_Printf( "********************\nERROR: %s\n********************\n", msg ); SV_Shutdown( va("Server crashed: %s\n", msg), qfalse ); CL_Disconnect( msg ); recursive = qfalse; if( !com_initialized ) Sys_Error( "%s", msg ); longjmp( abortframe, -1 ); } else { Com_Printf( "********************\nERROR: %s\n********************\n", msg ); SV_Shutdown( va("Server fatal crashed: %s\n", msg), qfalse ); CL_Shutdown(); } if( logfile ) { FS_FCloseFile( logfile ); logfile = 0; } Sys_Error( "%s", msg ); } /* ============= Com_Quit Both client and server can use this, and it will do the apropriate things. ============= */ void Com_Quit( void ) { SV_Shutdown( "Server quit\n", qfalse ); CL_Shutdown(); if( logfile ) { FS_FCloseFile( logfile ); logfile = 0; } Sys_Quit(); } /* ================== Com_ServerState ================== */ int Com_ServerState( void ) { return server_state; } /* ================== Com_SetServerState ================== */ void Com_SetServerState( int state ) { server_state = state; } int Com_ClientState( void ) { return client_state; } void Com_SetClientState( int state ) { client_state = state; } qboolean Com_DemoPlaying( void ) { return demo_playing; } void Com_SetDemoPlaying( qboolean state ) { demo_playing = state; } /* ========== Com_HashKey Returns hash key for a string ========== */ unsigned int Com_HashKey( char *name, int hashsize ) { int i; unsigned int v; unsigned int c; v = 0; for( i = 0; name[i]; i++ ) { c = name[i]; if( c == '\\' ) c = '/'; v = (v + i) * 37 + tolower( c ); // case insensitivity } return v % hashsize; } //============================================================================ /* ================ COM_CheckParm Returns the position (1 to argc-1) in the program's argument list where the given parameter apears, or 0 if not present ================ */ int COM_CheckParm( char *parm ) { int i; for( i=1 ; i= com_argc || !com_argv[arg] ) return ""; return com_argv[arg]; } void COM_ClearArgv( int arg ) { if( arg < 0 || arg >= com_argc || !com_argv[arg] ) return; com_argv[arg] = ""; } /* ================ COM_InitArgv ================ */ void COM_InitArgv( int argc, char **argv ) { int i; if( argc > MAX_NUM_ARGVS ) Com_Error( ERR_FATAL, "argc > MAX_NUM_ARGVS" ); com_argc = argc; for( i = 0 ; i < argc ; i++ ) { if( !argv[i] || strlen(argv[i]) >= MAX_TOKEN_CHARS ) com_argv[i] = ""; else com_argv[i] = argv[i]; } } /* ================ COM_AddParm Adds the given string at the end of the current argument list ================ */ void COM_AddParm( char *parm ) { if( com_argc == MAX_NUM_ARGVS ) Com_Error( ERR_FATAL, "COM_AddParm: MAX_NUM_ARGVS" ); com_argv[com_argc++] = parm; } char *CopyString( char *in ) { char *out; out = Mem_ZoneMallocExt( (int)strlen(in)+1, 0 ); strcpy( out, in ); return out; } void Info_Print( char *s ) { char key[512]; char value[512]; char *o; int l; if( *s == '\\' ) s++; while(*s) { o = key; while( *s && *s != '\\' ) *o++ = *s++; l = o - key; if( l < 20 ) { memset( o, ' ', 20-l ); key[20] = 0; } else *o = 0; Com_Printf( "%s", key ); if(!*s) { Com_Printf( "MISSING VALUE\n" ); return; } o = value; s++; while( *s && *s != '\\' ) *o++ = *s++; *o = 0; if(*s) s++; Com_Printf( "%s\n", value ); } } //============================================================================ // this is a 16 bit, non-reflected CRC using the polynomial 0x1021 // and the initial and final xor values shown below... in other words, the // CCITT standard CRC used by XMODEM #define CRC_INIT_VALUE 0xffff #define CRC_XOR_VALUE 0x0000 static unsigned short crctable[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; unsigned short CRC_Block( qbyte *start, int count ) { unsigned short crc; crc = CRC_INIT_VALUE; while (count--) crc = (crc << 8) ^ crctable[(crc >> 8) ^ *start++]; return crc ^ CRC_XOR_VALUE; } static qbyte chktbl[1024] = { 0x84, 0x47, 0x51, 0xc1, 0x93, 0x22, 0x21, 0x24, 0x2f, 0x66, 0x60, 0x4d, 0xb0, 0x7c, 0xda, 0x88, 0x54, 0x15, 0x2b, 0xc6, 0x6c, 0x89, 0xc5, 0x9d, 0x48, 0xee, 0xe6, 0x8a, 0xb5, 0xf4, 0xcb, 0xfb, 0xf1, 0x0c, 0x2e, 0xa0, 0xd7, 0xc9, 0x1f, 0xd6, 0x06, 0x9a, 0x09, 0x41, 0x54, 0x67, 0x46, 0xc7, 0x74, 0xe3, 0xc8, 0xb6, 0x5d, 0xa6, 0x36, 0xc4, 0xab, 0x2c, 0x7e, 0x85, 0xa8, 0xa4, 0xa6, 0x4d, 0x96, 0x19, 0x19, 0x9a, 0xcc, 0xd8, 0xac, 0x39, 0x5e, 0x3c, 0xf2, 0xf5, 0x5a, 0x72, 0xe5, 0xa9, 0xd1, 0xb3, 0x23, 0x82, 0x6f, 0x29, 0xcb, 0xd1, 0xcc, 0x71, 0xfb, 0xea, 0x92, 0xeb, 0x1c, 0xca, 0x4c, 0x70, 0xfe, 0x4d, 0xc9, 0x67, 0x43, 0x47, 0x94, 0xb9, 0x47, 0xbc, 0x3f, 0x01, 0xab, 0x7b, 0xa6, 0xe2, 0x76, 0xef, 0x5a, 0x7a, 0x29, 0x0b, 0x51, 0x54, 0x67, 0xd8, 0x1c, 0x14, 0x3e, 0x29, 0xec, 0xe9, 0x2d, 0x48, 0x67, 0xff, 0xed, 0x54, 0x4f, 0x48, 0xc0, 0xaa, 0x61, 0xf7, 0x78, 0x12, 0x03, 0x7a, 0x9e, 0x8b, 0xcf, 0x83, 0x7b, 0xae, 0xca, 0x7b, 0xd9, 0xe9, 0x53, 0x2a, 0xeb, 0xd2, 0xd8, 0xcd, 0xa3, 0x10, 0x25, 0x78, 0x5a, 0xb5, 0x23, 0x06, 0x93, 0xb7, 0x84, 0xd2, 0xbd, 0x96, 0x75, 0xa5, 0x5e, 0xcf, 0x4e, 0xe9, 0x50, 0xa1, 0xe6, 0x9d, 0xb1, 0xe3, 0x85, 0x66, 0x28, 0x4e, 0x43, 0xdc, 0x6e, 0xbb, 0x33, 0x9e, 0xf3, 0x0d, 0x00, 0xc1, 0xcf, 0x67, 0x34, 0x06, 0x7c, 0x71, 0xe3, 0x63, 0xb7, 0xb7, 0xdf, 0x92, 0xc4, 0xc2, 0x25, 0x5c, 0xff, 0xc3, 0x6e, 0xfc, 0xaa, 0x1e, 0x2a, 0x48, 0x11, 0x1c, 0x36, 0x68, 0x78, 0x86, 0x79, 0x30, 0xc3, 0xd6, 0xde, 0xbc, 0x3a, 0x2a, 0x6d, 0x1e, 0x46, 0xdd, 0xe0, 0x80, 0x1e, 0x44, 0x3b, 0x6f, 0xaf, 0x31, 0xda, 0xa2, 0xbd, 0x77, 0x06, 0x56, 0xc0, 0xb7, 0x92, 0x4b, 0x37, 0xc0, 0xfc, 0xc2, 0xd5, 0xfb, 0xa8, 0xda, 0xf5, 0x57, 0xa8, 0x18, 0xc0, 0xdf, 0xe7, 0xaa, 0x2a, 0xe0, 0x7c, 0x6f, 0x77, 0xb1, 0x26, 0xba, 0xf9, 0x2e, 0x1d, 0x16, 0xcb, 0xb8, 0xa2, 0x44, 0xd5, 0x2f, 0x1a, 0x79, 0x74, 0x87, 0x4b, 0x00, 0xc9, 0x4a, 0x3a, 0x65, 0x8f, 0xe6, 0x5d, 0xe5, 0x0a, 0x77, 0xd8, 0x1a, 0x14, 0x41, 0x75, 0xb1, 0xe2, 0x50, 0x2c, 0x93, 0x38, 0x2b, 0x6d, 0xf3, 0xf6, 0xdb, 0x1f, 0xcd, 0xff, 0x14, 0x70, 0xe7, 0x16, 0xe8, 0x3d, 0xf0, 0xe3, 0xbc, 0x5e, 0xb6, 0x3f, 0xcc, 0x81, 0x24, 0x67, 0xf3, 0x97, 0x3b, 0xfe, 0x3a, 0x96, 0x85, 0xdf, 0xe4, 0x6e, 0x3c, 0x85, 0x05, 0x0e, 0xa3, 0x2b, 0x07, 0xc8, 0xbf, 0xe5, 0x13, 0x82, 0x62, 0x08, 0x61, 0x69, 0x4b, 0x47, 0x62, 0x73, 0x44, 0x64, 0x8e, 0xe2, 0x91, 0xa6, 0x9a, 0xb7, 0xe9, 0x04, 0xb6, 0x54, 0x0c, 0xc5, 0xa9, 0x47, 0xa6, 0xc9, 0x08, 0xfe, 0x4e, 0xa6, 0xcc, 0x8a, 0x5b, 0x90, 0x6f, 0x2b, 0x3f, 0xb6, 0x0a, 0x96, 0xc0, 0x78, 0x58, 0x3c, 0x76, 0x6d, 0x94, 0x1a, 0xe4, 0x4e, 0xb8, 0x38, 0xbb, 0xf5, 0xeb, 0x29, 0xd8, 0xb0, 0xf3, 0x15, 0x1e, 0x99, 0x96, 0x3c, 0x5d, 0x63, 0xd5, 0xb1, 0xad, 0x52, 0xb8, 0x55, 0x70, 0x75, 0x3e, 0x1a, 0xd5, 0xda, 0xf6, 0x7a, 0x48, 0x7d, 0x44, 0x41, 0xf9, 0x11, 0xce, 0xd7, 0xca, 0xa5, 0x3d, 0x7a, 0x79, 0x7e, 0x7d, 0x25, 0x1b, 0x77, 0xbc, 0xf7, 0xc7, 0x0f, 0x84, 0x95, 0x10, 0x92, 0x67, 0x15, 0x11, 0x5a, 0x5e, 0x41, 0x66, 0x0f, 0x38, 0x03, 0xb2, 0xf1, 0x5d, 0xf8, 0xab, 0xc0, 0x02, 0x76, 0x84, 0x28, 0xf4, 0x9d, 0x56, 0x46, 0x60, 0x20, 0xdb, 0x68, 0xa7, 0xbb, 0xee, 0xac, 0x15, 0x01, 0x2f, 0x20, 0x09, 0xdb, 0xc0, 0x16, 0xa1, 0x89, 0xf9, 0x94, 0x59, 0x00, 0xc1, 0x76, 0xbf, 0xc1, 0x4d, 0x5d, 0x2d, 0xa9, 0x85, 0x2c, 0xd6, 0xd3, 0x14, 0xcc, 0x02, 0xc3, 0xc2, 0xfa, 0x6b, 0xb7, 0xa6, 0xef, 0xdd, 0x12, 0x26, 0xa4, 0x63, 0xe3, 0x62, 0xbd, 0x56, 0x8a, 0x52, 0x2b, 0xb9, 0xdf, 0x09, 0xbc, 0x0e, 0x97, 0xa9, 0xb0, 0x82, 0x46, 0x08, 0xd5, 0x1a, 0x8e, 0x1b, 0xa7, 0x90, 0x98, 0xb9, 0xbb, 0x3c, 0x17, 0x9a, 0xf2, 0x82, 0xba, 0x64, 0x0a, 0x7f, 0xca, 0x5a, 0x8c, 0x7c, 0xd3, 0x79, 0x09, 0x5b, 0x26, 0xbb, 0xbd, 0x25, 0xdf, 0x3d, 0x6f, 0x9a, 0x8f, 0xee, 0x21, 0x66, 0xb0, 0x8d, 0x84, 0x4c, 0x91, 0x45, 0xd4, 0x77, 0x4f, 0xb3, 0x8c, 0xbc, 0xa8, 0x99, 0xaa, 0x19, 0x53, 0x7c, 0x02, 0x87, 0xbb, 0x0b, 0x7c, 0x1a, 0x2d, 0xdf, 0x48, 0x44, 0x06, 0xd6, 0x7d, 0x0c, 0x2d, 0x35, 0x76, 0xae, 0xc4, 0x5f, 0x71, 0x85, 0x97, 0xc4, 0x3d, 0xef, 0x52, 0xbe, 0x00, 0xe4, 0xcd, 0x49, 0xd1, 0xd1, 0x1c, 0x3c, 0xd0, 0x1c, 0x42, 0xaf, 0xd4, 0xbd, 0x58, 0x34, 0x07, 0x32, 0xee, 0xb9, 0xb5, 0xea, 0xff, 0xd7, 0x8c, 0x0d, 0x2e, 0x2f, 0xaf, 0x87, 0xbb, 0xe6, 0x52, 0x71, 0x22, 0xf5, 0x25, 0x17, 0xa1, 0x82, 0x04, 0xc2, 0x4a, 0xbd, 0x57, 0xc6, 0xab, 0xc8, 0x35, 0x0c, 0x3c, 0xd9, 0xc2, 0x43, 0xdb, 0x27, 0x92, 0xcf, 0xb8, 0x25, 0x60, 0xfa, 0x21, 0x3b, 0x04, 0x52, 0xc8, 0x96, 0xba, 0x74, 0xe3, 0x67, 0x3e, 0x8e, 0x8d, 0x61, 0x90, 0x92, 0x59, 0xb6, 0x1a, 0x1c, 0x5e, 0x21, 0xc1, 0x65, 0xe5, 0xa6, 0x34, 0x05, 0x6f, 0xc5, 0x60, 0xb1, 0x83, 0xc1, 0xd5, 0xd5, 0xed, 0xd9, 0xc7, 0x11, 0x7b, 0x49, 0x7a, 0xf9, 0xf9, 0x84, 0x47, 0x9b, 0xe2, 0xa5, 0x82, 0xe0, 0xc2, 0x88, 0xd0, 0xb2, 0x58, 0x88, 0x7f, 0x45, 0x09, 0x67, 0x74, 0x61, 0xbf, 0xe6, 0x40, 0xe2, 0x9d, 0xc2, 0x47, 0x05, 0x89, 0xed, 0xcb, 0xbb, 0xb7, 0x27, 0xe7, 0xdc, 0x7a, 0xfd, 0xbf, 0xa8, 0xd0, 0xaa, 0x10, 0x39, 0x3c, 0x20, 0xf0, 0xd3, 0x6e, 0xb1, 0x72, 0xf8, 0xe6, 0x0f, 0xef, 0x37, 0xe5, 0x09, 0x33, 0x5a, 0x83, 0x43, 0x80, 0x4f, 0x65, 0x2f, 0x7c, 0x8c, 0x6a, 0xa0, 0x82, 0x0c, 0xd4, 0xd4, 0xfa, 0x81, 0x60, 0x3d, 0xdf, 0x06, 0xf1, 0x5f, 0x08, 0x0d, 0x6d, 0x43, 0xf2, 0xe3, 0x11, 0x7d, 0x80, 0x32, 0xc5, 0xfb, 0xc5, 0xd9, 0x27, 0xec, 0xc6, 0x4e, 0x65, 0x27, 0x76, 0x87, 0xa6, 0xee, 0xee, 0xd7, 0x8b, 0xd1, 0xa0, 0x5c, 0xb0, 0x42, 0x13, 0x0e, 0x95, 0x4a, 0xf2, 0x06, 0xc6, 0x43, 0x33, 0xf4, 0xc7, 0xf8, 0xe7, 0x1f, 0xdd, 0xe4, 0x46, 0x4a, 0x70, 0x39, 0x6c, 0xd0, 0xed, 0xca, 0xbe, 0x60, 0x3b, 0xd1, 0x7b, 0x57, 0x48, 0xe5, 0x3a, 0x79, 0xc1, 0x69, 0x33, 0x53, 0x1b, 0x80, 0xb8, 0x91, 0x7d, 0xb4, 0xf6, 0x17, 0x1a, 0x1d, 0x5a, 0x32, 0xd6, 0xcc, 0x71, 0x29, 0x3f, 0x28, 0xbb, 0xf3, 0x5e, 0x71, 0xb8, 0x43, 0xaf, 0xf8, 0xb9, 0x64, 0xef, 0xc4, 0xa5, 0x6c, 0x08, 0x53, 0xc7, 0x00, 0x10, 0x39, 0x4f, 0xdd, 0xe4, 0xb6, 0x19, 0x27, 0xfb, 0xb8, 0xf5, 0x32, 0x73, 0xe5, 0xcb, 0x32 }; /* ==================== COM_BlockSequenceCRCByte For proxy protecting ==================== */ qbyte COM_BlockSequenceCRCByte( qbyte *base, int length, int sequence ) { int n; qbyte *p; int x; qbyte chkb[60 + 4]; unsigned short crc; if( sequence < 0 ) Sys_Error( "sequence < 0, this shouldn't happen" ); p = chktbl + ( sequence % (sizeof(chktbl) - 4) ); if( length > 60 ) length = 60; memcpy( chkb, base, length ); chkb[length] = p[0]; chkb[length+1] = p[1]; chkb[length+2] = p[2]; chkb[length+3] = p[3]; length += 4; crc = CRC_Block( chkb, length ); for( x = 0, n = 0; n < length; n++ ) x += chkb[n]; crc = (crc ^ x) & 0xff; return crc; } /////////////////////////////////////////////////////////////// // MD4-based checksum utility functions // // Copyright (C) 2000 Jeff Teunissen // // Author: Jeff Teunissen // Date: 01 Jan 2000 /* unsigned Com_BlockChecksum( void *buffer, int length ) { int digest[4]; unsigned val; mdfour ( (unsigned char *) digest, (unsigned char *) buffer, length ); val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3]; return val; } */ unsigned Com_BlockChecksum(void *buffer, int length) { int digest[4]; unsigned val; MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, (unsigned char *)buffer, length); MD5_Final(&ctx, (unsigned char *)digest); val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3]; return val; } /* =============== Com_PageInMemory =============== */ int paged_total; void Com_PageInMemory( qbyte *buffer, int size ) { int i; for( i = size-1; i > 0; i -= 4096 ) paged_total += buffer[i]; } //======================================================== void Key_Init( void ); void SCR_EndLoadingPlaque( void ); /* ============= Com_Error_f Just throw a fatal error to test error shutdown procedures ============= */ void Com_Error_f( void ) { Com_Error( ERR_FATAL, "%s", Cmd_Argv(1) ); } /* ================= Q_malloc ================= */ void *Q_malloc( int cnt ) { void *buf = (void *)malloc( cnt ); if( !buf ) { Com_Printf( "Q_malloc: failed on allocation of %i bytes.\n", cnt ); return NULL; } memset( buf, 0, cnt ); return buf; } /* ================= Q_free ================= */ void Q_free( void *buf ) { if( buf ) free( buf ); } /* ================= Qcommon_Init ================= */ void Qcommon_Init( int argc, char **argv ) { char *s; if( setjmp(abortframe) ) Sys_Error( "Error during initialization" ); // initialize memory manager Memory_Init(); // prepare enough of the subsystems to handle // cvar and command buffer management COM_InitArgv( argc, argv ); Swap_Init(); Cbuf_Init(); Cmd_Init(); Cvar_Init(); Key_Init(); Huff_Init(); // we need to add the early commands twice, because // a basedir or cddir needs to be set before execing // config files, but we want other parms to override // the settings of the config files Cbuf_AddEarlyCommands( qfalse ); Cbuf_Execute(); #ifdef DEDICATED_ONLY dedicated = Cvar_Get( "dedicated", "1", CVAR_NOSET ); Cvar_ForceSet( "dedicated", "1" ); #else dedicated = Cvar_Get( "dedicated", "0", CVAR_NOSET ); #endif FS_InitFilesystem(); // Kurim : default file won't exist anymore Cbuf_AddText( "exec default.cfg\n" ); if( !dedicated->integer ) { Cbuf_AddText( "exec config.cfg\n" ); Cbuf_AddText( "exec autoexec.cfg\n" ); } else { Cbuf_AddText( "exec dedicated_autoexec.cfg\n" ); } Cbuf_AddEarlyCommands( qtrue ); Cbuf_Execute(); // // init commands and vars // Memory_InitCommands(); Cmd_AddCommand( "error", Com_Error_f ); host_speeds = Cvar_Get( "host_speeds", "0", 0 ); log_stats = Cvar_Get( "log_stats", "0", 0 ); developer = Cvar_Get( "developer", "0", 0 ); timescale = Cvar_Get( "timescale", "1.0", CVAR_CHEAT ); fixedtime = Cvar_Get( "fixedtime", "0", CVAR_CHEAT ); if( dedicated->integer ) logconsole = Cvar_Get( "logconsole", "wswconsole.log", CVAR_ARCHIVE ); else logconsole = Cvar_Get( "logconsole", "", CVAR_ARCHIVE ); logconsole_append = Cvar_Get( "logconsole_append", "1", CVAR_ARCHIVE ); logconsole_flush = Cvar_Get( "logconsole_flush", "0", CVAR_ARCHIVE ); com_showtrace = Cvar_Get( "com_showtrace", "0", 0 ); cm_noAreas = Cvar_Get( "cm_noAreas", "0", CVAR_CHEAT ); cm_noCurves = Cvar_Get( "cm_noCurves", "0", CVAR_CHEAT ); s = va( "%4.2f %s %s %s", VERSION, CPUSTRING, __DATE__, BUILDSTRING ); versioncvar = Cvar_Get( "version", s, CVAR_SERVERINFO|CVAR_READONLY ); if( dedicated->integer ) { sv_defaultmap = Cvar_Get( "sv_defaultmap", "wdm1", CVAR_ARCHIVE ); Cmd_AddCommand( "quit", Com_Quit ); } Sys_Init(); NET_Init(); Netchan_Init(); SV_Init(); CL_Init(); SCR_EndLoadingPlaque(); // add + commands from command line if( !Cbuf_AddLateCommands() ) { // if the user didn't give any commands, run default action if( dedicated->integer ) { Cbuf_AddText( va("map %s\n", sv_defaultmap->string) ); } } else { // the user asked for something explicit // so drop the loading plaque SCR_EndLoadingPlaque(); } Com_Printf( "====== %s Initialized ======\n", APPLICATION ); com_initialized = qtrue; Cbuf_Execute(); } /* ================= Qcommon_Frame ================= */ void Qcommon_Frame( int msec ) { char *s; int time_before = 0, time_between = 0, time_after = 0; if( setjmp (abortframe) ) return; // an ERR_DROP was thrown if( log_stats->modified ) { log_stats->modified = qfalse; if( log_stats->integer ) { if( log_stats_file ) { FS_FCloseFile( log_stats_file ); log_stats_file = 0; } if( FS_FOpenFile( "stats.log", &log_stats_file, FS_WRITE ) != -1 ) FS_Printf( log_stats_file, "entities,dlights,parts,frame time\n" ); else log_stats_file = 0; } else { if( log_stats_file ) { FS_FCloseFile( log_stats_file ); log_stats_file = 0; } } } if( fixedtime->integer ) msec = fixedtime->integer; else if( timescale->value ) { msec *= timescale->value; if( msec < 1 ) msec = 1; } if( com_showtrace->integer ) { Com_Printf( "%4i traces %4i brush traces %4i points\n", c_traces, c_brush_traces, c_pointcontents ); c_traces = 0; c_brush_traces = 0; c_pointcontents = 0; } if( dedicated->integer ) { do { s = Sys_ConsoleInput(); if(s) Cbuf_AddText( va("%s\n",s) ); } while(s); Cbuf_Execute(); } // keep the random time dependent rand(); if( host_speeds->integer ) time_before = Sys_Milliseconds(); SV_Frame( msec ); if( host_speeds->integer ) time_between = Sys_Milliseconds(); CL_Frame( msec ); if( host_speeds->integer ) time_after = Sys_Milliseconds (); if( host_speeds->integer ) { int all, sv, gm, cl, rf; all = time_after - time_before; sv = time_between - time_before; cl = time_after - time_between; gm = time_after_game - time_before_game; rf = time_after_ref - time_before_ref; sv -= gm; cl -= rf; Com_Printf( "all:%3i sv:%3i gm:%3i cl:%3i rf:%3i\n", all, sv, gm, cl, rf ); } } /* ================= Qcommon_Shutdown ================= */ void Qcommon_Shutdown( void ) { NET_Shutdown(); Memory_Shutdown(); }