diff options
34 files changed, 756 insertions, 183 deletions
@@ -136,8 +136,8 @@ LIBSDIR=$(MOUNT_DIR)/libs MASTERDIR=$(MOUNT_DIR)/master # extract version info -VERSION=$(shell grep Q3_VERSION $(CMDIR)/q_shared.h | \ - sed -e 's/.*tremulous\ \(.*\)"/\1/') +VERSION=$(shell grep "#define VERSION_NUMBER" $(CMDIR)/q_shared.h | \ + sed -e 's/[^"]*"\(.*\)"/\1/') ifeq ($(wildcard .svn),.svn) SVN_VERSION=$(VERSION)_SVN$(shell LANG=C svnversion .) @@ -778,6 +778,7 @@ Q3OBJ = \ $(B)/client/cvar.o \ $(B)/client/files.o \ $(B)/client/md4.o \ + $(B)/client/md5.o \ $(B)/client/msg.o \ $(B)/client/net_chan.o \ $(B)/client/huffman.o \ @@ -1021,6 +1022,7 @@ $(B)/client/common.o : $(CMDIR)/common.c; $(DO_CC) $(B)/client/cvar.o : $(CMDIR)/cvar.c; $(DO_CC) $(B)/client/files.o : $(CMDIR)/files.c; $(DO_CC) $(B)/client/md4.o : $(CMDIR)/md4.c; $(DO_CC) +$(B)/client/md5.o : $(CMDIR)/md5.c; $(DO_CC) $(B)/client/msg.o : $(CMDIR)/msg.c; $(DO_CC) $(B)/client/net_chan.o : $(CMDIR)/net_chan.c; $(DO_CC) $(B)/client/huffman.o : $(CMDIR)/huffman.c; $(DO_CC) diff --git a/src/botlib/be_interface.c b/src/botlib/be_interface.c index e70a6d4a..2980674e 100644 --- a/src/botlib/be_interface.c +++ b/src/botlib/be_interface.c @@ -138,12 +138,24 @@ int Export_BotLibSetup(void) { int errnum; char logfilename[MAX_QPATH]; + char *homedir, *gamedir; bot_developer = LibVarGetValue("bot_developer"); memset( &botlibglobals, 0, sizeof(botlibglobals) ); // bk001207 - init //initialize byte swapping (litte endian etc.) // Swap_Init(); - Com_sprintf(logfilename, sizeof(logfilename), "%s%cbotlib.log", LibVarGetString("homedir"), PATH_SEP); + homedir = LibVarGetString("homedir"); + gamedir = LibVarGetString("gamedir"); + if (homedir[0]) { + if (gamedir[0]) { + Com_sprintf(logfilename, sizeof(logfilename), "%s%c%s%cbotlib.log", homedir, PATH_SEP, gamedir, PATH_SEP); + } + else { + /*Com_sprintf(logfilename, sizeof(logfilename), "%s%c" BASEGAME "%cbotlib.log", homedir, PATH_SEP, PATH_SEP);*/ + } + } else { + Com_sprintf(logfilename, sizeof(logfilename), "botlib.log"); + } Log_Open(logfilename); // botimport.Print(PRT_MESSAGE, "------- BotLib Initialization -------\n"); diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c index ecb2499b..671bc4ae 100644 --- a/src/cgame/cg_weapons.c +++ b/src/cgame/cg_weapons.c @@ -503,17 +503,17 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi ) CG_Printf( S_COLOR_RED "ERROR: weapon model not found %s\n", token ); strcpy( path, token ); - COM_StripExtension( path, path ); + COM_StripExtension( path, path, MAX_QPATH ); strcat( path, "_flash.md3" ); wi->flashModel = trap_R_RegisterModel( path ); strcpy( path, token ); - COM_StripExtension( path, path ); + COM_StripExtension( path, path, MAX_QPATH ); strcat( path, "_barrel.md3" ); wi->barrelModel = trap_R_RegisterModel( path ); strcpy( path, token ); - COM_StripExtension( path, path ); + COM_StripExtension( path, path, MAX_QPATH ); strcat( path, "_hand.md3" ); wi->handsModel = trap_R_RegisterModel( path ); diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 28e5021f..af8c1d76 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -2012,7 +2012,7 @@ void CL_Frame ( int msec ) { } Q_strncpyz( mapName, COM_SkipPath( cl.mapname ), sizeof( cl.mapname ) ); - COM_StripExtension( mapName, mapName ); + COM_StripExtension(mapName, mapName, sizeof(mapName)); Cbuf_ExecuteText( EXEC_NOW, va( "record %s-%s-%s", nowString, serverName, mapName ) ); @@ -2324,6 +2324,28 @@ void CL_StopVideo_f( void ) CL_CloseAVI( ); } +static void CL_GenerateQKey(void) +{ + int len = 0; + unsigned char buff[2048]; + + len = FS_ReadFile(QKEY_FILE, NULL); + if(len >= (int)sizeof(buff)) { + Com_Printf("QKEY found.\n"); + return; + } + else { + int i; + srand(time(0)); + for(i = 0; i < sizeof(buff) - 1; i++) { + buff[i] = (unsigned char)(rand() % 255); + } + buff[i] = 0; + Com_Printf("QKEY generated\n"); + FS_WriteFile(QKEY_FILE, buff, sizeof(buff)); + } +} + /* ==================== CL_Init @@ -2472,6 +2494,9 @@ void CL_Init( void ) { Cvar_Set( "cl_running", "1" ); + CL_GenerateQKey(); + Cvar_Get("cl_guid", Com_MD5File(QKEY_FILE, 0), CVAR_USERINFO | CVAR_ROM); + Com_Printf( "----- Client Initialization Complete -----\n" ); } @@ -2485,6 +2510,10 @@ CL_Shutdown void CL_Shutdown( void ) { static qboolean recursive = qfalse; + // check whether the client is running at all. + if(!(com_cl_running && com_cl_running->integer)) + return; + Com_Printf( "----- CL_Shutdown -----\n" ); if ( recursive ) { diff --git a/src/client/client.h b/src/client/client.h index a7db023f..e5f5d596 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -31,6 +31,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../cgame/cg_public.h" #include "../game/bg_public.h" +// tjw: file full of random crap that gets used to create cl_guid +#define QKEY_FILE "qkey" + #define RETRANSMIT_TIMEOUT 3000 // time between connection packet retransmits diff --git a/src/qcommon/common.c b/src/qcommon/common.c index 5c3726ff..44174ead 100644 --- a/src/qcommon/common.c +++ b/src/qcommon/common.c @@ -181,11 +181,22 @@ void QDECL Com_Printf( const char *fmt, ... ) { newtime = localtime( &aclock ); logfile = FS_FOpenFileWrite( "qconsole.log" ); - Com_Printf( "logfile opened on %s\n", asctime( newtime ) ); - if ( com_logfile->integer > 1 ) { - // force it to not buffer so we get valid - // data even if we are crashing - FS_ForceFlush(logfile); + + if(logfile) + { + Com_Printf( "logfile opened on %s\n", asctime( newtime ) ); + + if ( com_logfile->integer > 1 ) + { + // force it to not buffer so we get valid + // data even if we are crashing + FS_ForceFlush(logfile); + } + } + else + { + Com_Printf("Opening qconsole.log failed!\n"); + Cvar_SetValue("logfile", 0); } opening_qconsole = qfalse; diff --git a/src/qcommon/files.c b/src/qcommon/files.c index 84db5b18..ce380438 100644 --- a/src/qcommon/files.c +++ b/src/qcommon/files.c @@ -2175,8 +2175,8 @@ int FS_GetModList( char *listbuf, int bufsize ) { if (bDrop) { continue; } - // we drop "base" "." and ".." - if (Q_stricmp(name, "base") && Q_stricmpn(name, ".", 1)) { + // we drop BASEGAME "." and ".." + if (Q_stricmp(name, BASEGAME) && Q_stricmpn(name, ".", 1)) { // now we need to find some .pk3 files to validate the mod // NOTE TTimo: (actually I'm not sure why .. what if it's a mod under developement with no .pk3?) // we didn't keep the information when we merged the directory names, as to what OS Path it was found under @@ -2550,9 +2550,16 @@ FS_idPak */ qboolean FS_idPak( char *pak, char *base ) { int i; + char pakbuf[MAX_QPATH], *pakptr; + + // Chop off filename extension if necessary. + Com_sprintf(pakbuf, sizeof(pakbuf), "%s", pak); + pakptr = Q_strrchr(pakbuf, '.'); + if(pakptr) + *pakptr = '\0'; for (i = 0; i < NUM_ID_PAKS; i++) { - if ( !FS_FilenameCompare(pak, va("%s/pak%d", base, i)) ) { + if ( !FS_FilenameCompare(pakbuf, va("%s/pak%d", base, i)) ) { break; } } @@ -2605,7 +2612,7 @@ qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring ) { havepak = qfalse; // never autodownload any of the tremulous paks - if ( FS_idPak(fs_serverReferencedPakNames[i], "base") ) { + if ( FS_idPak(fs_serverReferencedPakNames[i], BASEGAME) ) { continue; } @@ -3377,7 +3384,7 @@ void FS_FilenameCompletion( const char *dir, const char *ext, Q_strncpyz( filename, filenames[ i ], MAX_STRING_CHARS ); if( stripExt ) { - COM_StripExtension( filename, filename ); + COM_StripExtension(filename, filename, sizeof(filename)); } callback( filename ); diff --git a/src/qcommon/md4.c b/src/qcommon/md4.c index 1b491be8..2501b2b6 100644 --- a/src/qcommon/md4.c +++ b/src/qcommon/md4.c @@ -30,21 +30,9 @@ #include "q_shared.h" #include "qcommon.h" -#ifndef int32 -#define int32 int -#endif - -#if SIZEOF_INT > 4 -#define LARGE_INT32 -#endif - -#ifndef uint32 -#define uint32 unsigned int32 -#endif - struct mdfour { - uint32 A, B, C, D; - uint32 totalN; + uint32_t A, B, C, D; + uint32_t totalN; }; @@ -58,23 +46,19 @@ static struct mdfour *m; #define F(X,Y,Z) (((X)&(Y)) | ((~(X))&(Z))) #define G(X,Y,Z) (((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z))) #define H(X,Y,Z) ((X)^(Y)^(Z)) -#ifdef LARGE_INT32 -#define lshift(x,s) ((((x)<<(s))&0xFFFFFFFF) | (((x)>>(32-(s)))&0xFFFFFFFF)) -#else #define lshift(x,s) (((x)<<(s)) | ((x)>>(32-(s)))) -#endif #define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s) #define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + 0x5A827999,s) #define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + 0x6ED9EBA1,s) /* this applies md4 to 64 byte chunks */ -static void mdfour64(uint32 *M) +static void mdfour64(uint32_t *M) { int j; - uint32 AA, BB, CC, DD; - uint32 X[16]; - uint32 A,B,C,D; + uint32_t AA, BB, CC, DD; + uint32_t X[16]; + uint32_t A,B,C,D; for (j=0;j<16;j++) X[j] = M[j]; @@ -111,18 +95,13 @@ static void mdfour64(uint32 *M) A += AA; B += BB; C += CC; D += DD; -#ifdef LARGE_INT32 - A &= 0xFFFFFFFF; B &= 0xFFFFFFFF; - C &= 0xFFFFFFFF; D &= 0xFFFFFFFF; -#endif - for (j=0;j<16;j++) X[j] = 0; m->A = A; m->B = B; m->C = C; m->D = D; } -static void copy64(uint32 *M, byte *in) +static void copy64(uint32_t *M, byte *in) { int i; @@ -131,7 +110,7 @@ static void copy64(uint32 *M, byte *in) (in[i*4+1]<<8) | (in[i*4+0]<<0); } -static void copy4(byte *out,uint32 x) +static void copy4(byte *out,uint32_t x) { out[0] = x&0xFF; out[1] = (x>>8)&0xFF; @@ -152,8 +131,8 @@ void mdfour_begin(struct mdfour *md) static void mdfour_tail(byte *in, int n) { byte buf[128]; - uint32 M[16]; - uint32 b; + uint32_t M[16]; + uint32_t b; m->totalN += n; @@ -178,7 +157,7 @@ static void mdfour_tail(byte *in, int n) static void mdfour_update(struct mdfour *md, byte *in, int n) { - uint32 M[16]; + uint32_t M[16]; if (n == 0) mdfour_tail(in, n); diff --git a/src/qcommon/md5.c b/src/qcommon/md5.c new file mode 100644 index 00000000..ffe77527 --- /dev/null +++ b/src/qcommon/md5.c @@ -0,0 +1,299 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ +#include "q_shared.h" +#include "qcommon.h" + +typedef struct MD5Context { + uint32_t buf[4]; + uint32_t bits[2]; + unsigned char in[64]; +} MD5_CTX; + +#ifndef Q3_BIG_ENDIAN + #define byteReverse(buf, len) /* Nothing */ +#else + static void byteReverse(unsigned char *buf, unsigned longs); + + /* + * Note: this code is harmless on little-endian machines. + */ + static void byteReverse(unsigned char *buf, unsigned longs) + { + uint32_t t; + do { + t = (uint32_t) + ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32_t *) buf = t; + buf += 4; + } while (--longs); + } +#endif // Q3_BIG_ENDIAN + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +static void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(uint32_t buf[4], + uint32_t const in[16]) +{ + register uint32_t a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +static void MD5Update(struct MD5Context *ctx, unsigned char const *buf, + unsigned len) +{ + uint32_t t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +static void MD5Final(struct MD5Context *ctx, unsigned char *digest) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32_t *) ctx->in)[14] = ctx->bits[0]; + ((uint32_t *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + + if (digest!=NULL) + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + + +char *Com_MD5File(const char *fn, int length) +{ + static char final[33] = {"unknown"}; + unsigned char digest[16] = {""}; + fileHandle_t f; + MD5_CTX md5; + char buffer[2048]; + int i; + int filelen = 0; + int r = 0; + int total = 0; + + filelen = FS_FOpenFileRead(fn, &f, qtrue); + if(filelen < 1) { + return final; + } + if(filelen < length || !length) { + length = filelen; + } + + MD5Init(&md5); + for(;;) { + r = FS_Read2(buffer, sizeof(buffer), f); + if(r < 1) + break; + if(r + total > length) + r = length - total; + total += r; + MD5Update(&md5 , (unsigned char *)buffer, r); + if(r < sizeof(buffer) || total >= length) + break; + } + FS_FCloseFile(f); + MD5Final(&md5, digest); + final[0] = '\0'; + for(i = 0; i < 16; i++) { + Q_strcat(final, sizeof(final), va("%02X", digest[i])); + } + return final; +} diff --git a/src/qcommon/q_shared.c b/src/qcommon/q_shared.c index 9f152d62..93c1dc20 100644 --- a/src/qcommon/q_shared.c +++ b/src/qcommon/q_shared.c @@ -59,10 +59,10 @@ char *COM_SkipPath (char *pathname) COM_StripExtension ============ */ -void COM_StripExtension( const char *in, char *out ) { +void COM_StripExtension( const char *in, char *out, int destsize ) { int length; - strcpy( out, in ); + Q_strncpyz(out, in, destsize); length = strlen(out)-1; while (length > 0 && out[length] != '.') diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h index 6d276630..0127fd90 100644 --- a/src/qcommon/q_shared.h +++ b/src/qcommon/q_shared.h @@ -108,10 +108,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA //============================================================= #ifdef Q3_VM -typedef int intptr_t; + typedef int intptr_t; #else # ifndef _MSC_VER # include <stdint.h> +# else + typedef __int64 int64_t; + typedef __int32 int32_t; + typedef __int16 int16_t; + typedef __int8 int8_t; + typedef unsigned __int64 uint64_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int8 uint8_t; # endif #endif @@ -633,7 +642,7 @@ vec_t DistanceBetweenLineSegments( float Com_Clamp( float min, float max, float value ); char *COM_SkipPath( char *pathname ); -void COM_StripExtension( const char *in, char *out ); +void COM_StripExtension(const char *in, char *out, int destsize); void COM_DefaultExtension( char *path, int maxSize, const char *extension ); void COM_BeginParseSession( const char *name ); diff --git a/src/qcommon/qcommon.h b/src/qcommon/qcommon.h index eb89de47..f9ca82fc 100644 --- a/src/qcommon/qcommon.h +++ b/src/qcommon/qcommon.h @@ -720,6 +720,7 @@ void Com_Quit_f( void ); int Com_EventLoop( void ); int Com_Milliseconds( void ); // will be journaled properly unsigned Com_BlockChecksum( const void *buffer, int length ); +char *Com_MD5File(const char *filename, int length); int Com_HashKey(char *string, int maxlen); int Com_Filter(char *filter, char *name, int casesensitive); int Com_FilterPath(char *filter, char *name, int casesensitive); diff --git a/src/qcommon/vm.c b/src/qcommon/vm.c index 0235ffea..8fb588db 100644 --- a/src/qcommon/vm.c +++ b/src/qcommon/vm.c @@ -231,7 +231,7 @@ void VM_LoadSymbols( vm_t *vm ) { return; } - COM_StripExtension( vm->name, name ); + COM_StripExtension(vm->name, name, sizeof(name)); Com_sprintf( symbols, sizeof( symbols ), "vm/%s.map", name ); len = FS_ReadFile( symbols, (void **)&mapfile ); if ( !mapfile ) { diff --git a/src/renderer/qgl.h b/src/renderer/qgl.h index e1945f8b..5bf52e13 100644 --- a/src/renderer/qgl.h +++ b/src/renderer/qgl.h @@ -92,11 +92,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA //=========================================================================== +// <Timbo> I hate this section so much /* ** multitexture extension definitions */ #if !defined(__sun) + #define GL_ACTIVE_TEXTURE_ARB 0x84E0 #define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 #define GL_MAX_ACTIVE_TEXTURES_ARB 0x84E2 @@ -105,10 +107,24 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define GL_TEXTURE1_ARB 0x84C1 #define GL_TEXTURE2_ARB 0x84C2 #define GL_TEXTURE3_ARB 0x84C3 + #else + #define GL_MAX_ACTIVE_TEXTURES_ARB 0x84E2 + #endif /* defined(__sun) */ +// anisotropic filtering constants +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF + +// define for skyboxes without black seams on non SDL-versions. +#if !defined(GL_VERSION_1_2) && !defined(GL_CLAMP_TO_EDGE) + #define GL_CLAMP_TO_EDGE 0x812F +#endif + +//=========================================================================== + // NOTE: some Linux platforms would need those prototypes #if defined(MACOS_X) || ( defined(__sun) && defined(__sparc) ) typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); @@ -175,7 +191,7 @@ extern void ( APIENTRY * qglUnlockArraysEXT) (void); //=========================================================================== -// non-windows systems will just redefine qgl* to gl* +// non-dlopening systems will just redefine qgl* to gl* #if !defined( _WIN32 ) && !defined(MACOS_X) && !defined( __linux__ ) && !defined( __FreeBSD__ ) && !defined(__sun) // rb010123 #include "qgl_linked.h" diff --git a/src/renderer/tr_bsp.c b/src/renderer/tr_bsp.c index eb57da8f..2eff8349 100644 --- a/src/renderer/tr_bsp.c +++ b/src/renderer/tr_bsp.c @@ -1824,7 +1824,7 @@ void RE_LoadWorldMap( const char *name ) { Q_strncpyz( s_worldData.name, name, sizeof( s_worldData.name ) ); Q_strncpyz( s_worldData.baseName, COM_SkipPath( s_worldData.name ), sizeof( s_worldData.name ) ); - COM_StripExtension( s_worldData.baseName, s_worldData.baseName ); + COM_StripExtension(s_worldData.baseName, s_worldData.baseName, sizeof(s_worldData.baseName)); startMarker = ri.Hunk_Alloc(0, h_low); c_gridVerts = 0; diff --git a/src/renderer/tr_flares.c b/src/renderer/tr_flares.c index 17e21976..f8fb222d 100644 --- a/src/renderer/tr_flares.c +++ b/src/renderer/tr_flares.c @@ -76,6 +76,7 @@ typedef struct flare_s { int windowX, windowY; float eyeZ; + vec3_t origin; vec3_t color; } flare_t; @@ -84,6 +85,8 @@ typedef struct flare_s { flare_t r_flareStructs[MAX_FLARES]; flare_t *r_activeFlares, *r_inactiveFlares; +int flareCoeff; + /* ================== R_ClearFlares @@ -114,11 +117,22 @@ void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t int i; flare_t *f, *oldest; vec3_t local; - float d; + float d = 1; vec4_t eye, clip, normalized, window; backEnd.pc.c_flareAdds++; + if(normal && (normal[0] || normal[1] || normal[2])) + { + VectorSubtract( backEnd.viewParms.or.origin, point, local ); + VectorNormalizeFast(local); + d = DotProduct(local, normal); + + // If the viewer is behind the flare don't add it. + if(d < 0) + return; + } + // if the point is off the screen, don't bother adding it // calculate screen coordinates and depth R_TransformModelToClip( point, backEnd.or.modelMatrix, @@ -172,16 +186,12 @@ void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t f->addedFrame = backEnd.viewParms.frameCount; f->fogNum = fogNum; + VectorCopy(point, f->origin); VectorCopy( color, f->color ); // fade the intensity of the flare down as the // light surface turns away from the viewer - if ( normal ) { - VectorSubtract( backEnd.viewParms.or.origin, point, local ); - VectorNormalizeFast( local ); - d = DotProduct( local, normal ); - VectorScale( f->color, d, f->color ); - } + VectorScale( f->color, d, f->color ); // save info needed to test f->windowX = backEnd.viewParms.viewportX + window[0]; @@ -198,31 +208,39 @@ RB_AddDlightFlares void RB_AddDlightFlares( void ) { dlight_t *l; int i, j, k; - fog_t *fog; + fog_t *fog = NULL; if ( !r_flares->integer ) { return; } l = backEnd.refdef.dlights; - fog = tr.world->fogs; + + if(tr.world) + fog = tr.world->fogs; + for (i=0 ; i<backEnd.refdef.num_dlights ; i++, l++) { - // find which fog volume the light is in - for ( j = 1 ; j < tr.world->numfogs ; j++ ) { - fog = &tr.world->fogs[j]; - for ( k = 0 ; k < 3 ; k++ ) { - if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) { + if(fog) + { + // find which fog volume the light is in + for ( j = 1 ; j < tr.world->numfogs ; j++ ) { + fog = &tr.world->fogs[j]; + for ( k = 0 ; k < 3 ; k++ ) { + if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) { + break; + } + } + if ( k == 3 ) { break; } } - if ( k == 3 ) { - break; + if ( j == tr.world->numfogs ) { + j = 0; } } - if ( j == tr.world->numfogs ) { + else j = 0; - } RB_AddFlare( (void *)l, j, l->origin, l->color, NULL ); } @@ -295,16 +313,65 @@ void RB_RenderFlare( flare_t *f ) { float size; vec3_t color; int iColor[3]; + float distance, intensity, factor; + byte fogFactors[3] = {255, 255, 255}; backEnd.pc.c_flareRenders++; - VectorScale( f->color, f->drawIntensity*tr.identityLight, color ); - iColor[0] = color[0] * 255; - iColor[1] = color[1] * 255; - iColor[2] = color[2] * 255; + // We don't want too big values anyways when dividing by distance. + if(f->eyeZ > -1.0f) + distance = 1.0f; + else + distance = -f->eyeZ; + + // calculate the flare size.. + size = backEnd.viewParms.viewportWidth * ( r_flareSize->value/640.0f + 8 / distance ); - size = backEnd.viewParms.viewportWidth * ( r_flareSize->value/640.0f + 8 / -f->eyeZ ); +/* + * This is an alternative to intensity scaling. It changes the size of the flare on screen instead + * with growing distance. See in the description at the top why this is not the way to go. + // size will change ~ 1/r. + size = backEnd.viewParms.viewportWidth * (r_flareSize->value / (distance * -2.0f)); +*/ +/* + * As flare sizes stay nearly constant with increasing distance we must decrease the intensity + * to achieve a reasonable visual result. The intensity is ~ (size^2 / distance^2) which can be + * got by considering the ratio of + * (flaresurface on screen) : (Surface of sphere defined by flare origin and distance from flare) + * An important requirement is: + * intensity <= 1 for all distances. + * + * The formula used here to compute the intensity is as follows: + * intensity = flareCoeff * size^2 / (distance + size*sqrt(flareCoeff))^2 + * As you can see, the intensity will have a max. of 1 when the distance is 0. + * The coefficient flareCoeff will determine the falloff speed with increasing distance. + */ + + factor = distance + size * sqrt(flareCoeff); + + intensity = flareCoeff * size * size / (factor * factor); + + VectorScale(f->color, f->drawIntensity * intensity, color); + +// Calculations for fogging + if(tr.world && f->fogNum < tr.world->numfogs) + { + tess.numVertexes = 1; + VectorCopy(f->origin, tess.xyz[0]); + tess.fogNum = f->fogNum; + + RB_CalcModulateColorsByFog(fogFactors); + + // We don't need to render the flare if colors are 0 anyways. + if(!(fogFactors[0] || fogFactors[1] || fogFactors[2])) + return; + } + + iColor[0] = color[0] * fogFactors[0]; + iColor[1] = color[1] * fogFactors[1]; + iColor[2] = color[2] * fogFactors[2]; + RB_BeginSurface( tr.flareShader, f->fogNum ); // FIXME: use quadstamp? @@ -383,6 +450,21 @@ void RB_RenderFlares (void) { return; } + if(r_flareCoeff->modified) + { + if(r_flareCoeff->value == 0.0f) + flareCoeff = atof(FLARE_STDCOEFF); + else + flareCoeff = r_flareCoeff->value; + + r_flareCoeff->modified = qfalse; + } + + // Reset currentEntity to world so that any previously referenced entities + // don't have influence on the rendering of these flares (i.e. RF_ renderer flags). + backEnd.currentEntity = &tr.worldEntity; + backEnd.or = backEnd.viewParms.world; + // RB_AddDlightFlares(); // perform z buffer readback on each flare in this view diff --git a/src/renderer/tr_image.c b/src/renderer/tr_image.c index 692f00c6..d4beacd8 100644 --- a/src/renderer/tr_image.c +++ b/src/renderer/tr_image.c @@ -700,11 +700,18 @@ done: if (mipmap) { + if ( glConfig.textureFilterAnisotropic ) + qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, + (GLint)Com_Clamp( 1, glConfig.maxAnisotropy, r_ext_max_anisotropy->integer ) ); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } else { + if ( glConfig.textureFilterAnisotropic ) + qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 ); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); } diff --git a/src/renderer/tr_init.c b/src/renderer/tr_init.c index 475a37c6..f9cdc911 100644 --- a/src/renderer/tr_init.c +++ b/src/renderer/tr_init.c @@ -25,12 +25,16 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" glconfig_t glConfig; +qboolean textureFilterAnisotropic = qfalse; +int maxAnisotropy = 0; + glstate_t glState; static void GfxInfo_f( void ); cvar_t *r_flareSize; cvar_t *r_flareFade; +cvar_t *r_flareCoeff; cvar_t *r_railWidth; cvar_t *r_railCoreWidth; @@ -81,6 +85,8 @@ cvar_t *r_ext_gamma_control; cvar_t *r_ext_multitexture; cvar_t *r_ext_compiled_vertex_array; cvar_t *r_ext_texture_env_add; +cvar_t *r_ext_texture_filter_anisotropic; +cvar_t *r_ext_max_anisotropy; cvar_t *r_ignoreGLErrors; cvar_t *r_logFile; @@ -995,6 +1001,10 @@ void R_Register( void ) r_picmip = ri.Cvar_Get ("r_picmip", GENERIC_HW_R_PICMIP_DEFAULT, CVAR_ARCHIVE | CVAR_LATCH ); + r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic", + "0", CVAR_ARCHIVE | CVAR_LATCH ); + r_ext_max_anisotropy = ri.Cvar_Get( "r_ext_max_anisotropy", "2", CVAR_ARCHIVE | CVAR_LATCH ); + r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH ); AssertCvarRange( r_picmip, 0, 16, qtrue ); @@ -1079,6 +1089,7 @@ void R_Register( void ) r_flareSize = ri.Cvar_Get ("r_flareSize", "40", CVAR_CHEAT); r_flareFade = ri.Cvar_Get ("r_flareFade", "7", CVAR_CHEAT); + r_flareCoeff = ri.Cvar_Get ("r_flareCoeff", FLARE_STDCOEFF, CVAR_CHEAT); r_showSmp = ri.Cvar_Get ("r_showSmp", "0", CVAR_CHEAT); r_skipBackEnd = ri.Cvar_Get ("r_skipBackEnd", "0", CVAR_CHEAT); @@ -1141,6 +1152,11 @@ void R_Init( void ) { Com_Memset( &backEnd, 0, sizeof( backEnd ) ); Com_Memset( &tess, 0, sizeof( tess ) ); + if(sizeof(glconfig_t) != 11332) + { + ri.Error( ERR_FATAL, "Mod ABI incompatible: sizeof(glconfig_t) == %zd != 11332", sizeof(glconfig_t)); + } + // Swap_Init(); if ( (int)tess.xyz & 15 ) { diff --git a/src/renderer/tr_local.h b/src/renderer/tr_local.h index a80590ca..7c694759 100644 --- a/src/renderer/tr_local.h +++ b/src/renderer/tr_local.h @@ -971,12 +971,14 @@ extern trGlobals_t tr; extern glconfig_t glConfig; // outside of TR since it shouldn't be cleared during ref re-init extern glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init - // // cvars // extern cvar_t *r_flareSize; extern cvar_t *r_flareFade; +// coefficient for the flare intensity falloff function. +#define FLARE_STDCOEFF "150" +extern cvar_t *r_flareCoeff; extern cvar_t *r_railWidth; extern cvar_t *r_railCoreWidth; @@ -1039,6 +1041,9 @@ extern cvar_t *r_ext_multitexture; extern cvar_t *r_ext_compiled_vertex_array; extern cvar_t *r_ext_texture_env_add; +extern cvar_t *r_ext_texture_filter_anisotropic; +extern cvar_t *r_ext_max_anisotropy; + extern cvar_t *r_nobind; // turns off binding to appropriate textures extern cvar_t *r_singleShader; // make most world faces use default shader extern cvar_t *r_roundImagesDown; diff --git a/src/renderer/tr_shader.c b/src/renderer/tr_shader.c index 380f9bf6..0e4504ef 100644 --- a/src/renderer/tr_shader.c +++ b/src/renderer/tr_shader.c @@ -96,7 +96,7 @@ void R_RemapShader(const char *shaderName, const char *newShaderName, const char // remap all the shaders with the given name // even tho they might have different lightmaps - COM_StripExtension( shaderName, strippedName ); + COM_StripExtension(shaderName, strippedName, sizeof(strippedName)); hash = generateHashValue(strippedName, FILE_HASH_SIZE); for (sh = hashTable[hash]; sh; sh = sh->next) { if (Q_stricmp(sh->name, strippedName) == 0) { @@ -2366,7 +2366,7 @@ shader_t *R_FindShaderByName( const char *name ) { return tr.defaultShader; } - COM_StripExtension( name, strippedName ); + COM_StripExtension(name, strippedName, sizeof(strippedName)); hash = generateHashValue(strippedName, FILE_HASH_SIZE); @@ -2434,7 +2434,7 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag lightmapIndex = LIGHTMAP_BY_VERTEX; } - COM_StripExtension( name, strippedName ); + COM_StripExtension(name, strippedName, sizeof(strippedName)); hash = generateHashValue(strippedName, FILE_HASH_SIZE); @@ -3010,8 +3010,22 @@ static void CreateInternalShaders( void ) { static void CreateExternalShaders( void ) { tr.projectionShadowShader = R_FindShader( "projectionShadow", LIGHTMAP_NONE, qtrue ); - //tr.flareShader = R_FindShader( "flareShader", LIGHTMAP_NONE, qtrue ); - //tr.sunShader = R_FindShader( "sun", LIGHTMAP_NONE, qtrue ); + tr.flareShader = R_FindShader( "flareShader", LIGHTMAP_NONE, qtrue ); + + // Hack to make fogging work correctly on flares. Fog colors are calculated + // in tr_flare.c already. + if(!tr.flareShader->defaultShader) + { + int index; + + for(index = 0; index < tr.flareShader->numUnfoggedPasses; index++) + { + tr.flareShader->stages[index]->adjustColorsForFog = ACFF_NONE; + tr.flareShader->stages[index]->stateBits |= GLS_DEPTHTEST_DISABLE; + } + } + + tr.sunShader = R_FindShader( "sun", LIGHTMAP_NONE, qtrue ); } /* diff --git a/src/renderer/tr_surface.c b/src/renderer/tr_surface.c index a65b17db..2a291c84 100644 --- a/src/renderer/tr_surface.c +++ b/src/renderer/tr_surface.c @@ -1215,71 +1215,12 @@ void RB_SurfaceBad( surfaceType_t *surfType ) { ri.Printf( PRINT_ALL, "Bad surface tesselated.\n" ); } -#if 0 - -void RB_SurfaceFlare( srfFlare_t *surf ) { - vec3_t left, up; - float radius; - byte color[4]; - vec3_t dir; - vec3_t origin; - float d; - - // calculate the xyz locations for the four corners - radius = 30; - VectorScale( backEnd.viewParms.or.axis[1], radius, left ); - VectorScale( backEnd.viewParms.or.axis[2], radius, up ); - if ( backEnd.viewParms.isMirror ) { - VectorSubtract( vec3_origin, left, left ); - } - - color[0] = color[1] = color[2] = color[3] = 255; - - VectorMA( surf->origin, 3, surf->normal, origin ); - VectorSubtract( origin, backEnd.viewParms.or.origin, dir ); - VectorNormalize( dir ); - VectorMA( origin, r_ignore->value, dir, origin ); - - d = -DotProduct( dir, surf->normal ); - if ( d < 0 ) { - return; - } -#if 0 - color[0] *= d; - color[1] *= d; - color[2] *= d; -#endif - - RB_AddQuadStamp( origin, left, up, color ); -} - -#else - -void RB_SurfaceFlare( srfFlare_t *surf ) { -#if 0 - vec3_t left, up; - byte color[4]; - - color[0] = surf->color[0] * 255; - color[1] = surf->color[1] * 255; - color[2] = surf->color[2] * 255; - color[3] = 255; - - VectorClear( left ); - VectorClear( up ); - - left[0] = r_ignore->value; - - up[1] = r_ignore->value; - - RB_AddQuadStampExt( surf->origin, left, up, color, 0, 0, 1, 1 ); -#endif +void RB_SurfaceFlare(srfFlare_t *surf) +{ + if (r_flares->integer) + RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal); } -#endif - - - void RB_SurfaceDisplayList( srfDisplayList_t *surf ) { // all apropriate state must be set in RB_BeginSurface // this isn't implemented yet... diff --git a/src/renderer/tr_types.h b/src/renderer/tr_types.h index e3aabc3b..5aa08aed 100644 --- a/src/renderer/tr_types.h +++ b/src/renderer/tr_types.h @@ -201,6 +201,10 @@ typedef struct { qboolean isFullscreen; qboolean stereoEnabled; qboolean smpActive; // dual processor + + qboolean textureFilterAnisotropic; + int maxAnisotropy; + } glconfig_t; // FIXME: VM should be OS agnostic .. in theory diff --git a/src/server/sv_ccmds.c b/src/server/sv_ccmds.c index 55ee62fd..0e016056 100644 --- a/src/server/sv_ccmds.c +++ b/src/server/sv_ccmds.c @@ -35,12 +35,12 @@ These commands can only be entered from stdin or by a remote operator datagram /* ================== -SV_GetPlayerByName +SV_GetPlayerByHandle -Returns the player with name from Cmd_Argv(1) +Returns the player with player id or name from Cmd_Argv(1) ================== */ -static client_t *SV_GetPlayerByName( void ) { +static client_t *SV_GetPlayerByHandle( void ) { client_t *cl; int i; char *s; @@ -58,6 +58,23 @@ static client_t *SV_GetPlayerByName( void ) { s = Cmd_Argv(1); + // Check whether this is a numeric player handle + for(i = 0; s[i] >= '0' && s[i] <= '9'; i++); + + if(!s[i]) + { + int plid = atoi(s); + + // Check for numeric playerid match + if(plid >= 0 && plid < sv_maxclients->integer) + { + cl = &svs.clients[plid]; + + if(cl->state) + return cl; + } + } + // check for a name match for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) { if ( !cl->state ) { @@ -218,7 +235,7 @@ static void SV_MapRestart_f( void ) { delay = 5; } if( delay && !Cvar_VariableValue("g_doWarmup") ) { - sv.restartTime = svs.time + delay * 1000; + sv.restartTime = sv.time + delay * 1000; SV_SetConfigstring( CS_WARMUP, va("%i", sv.restartTime) ); return; } @@ -355,7 +372,7 @@ static void SV_Kick_f( void ) { return; } - cl = SV_GetPlayerByName(); + cl = SV_GetPlayerByHandle(); if ( !cl ) { return; } @@ -390,7 +407,7 @@ static void SV_Ban_f( void ) { return; } - cl = SV_GetPlayerByName(); + cl = SV_GetPlayerByHandle(); if (!cl) { return; @@ -675,7 +692,7 @@ static void SV_DumpUser_f( void ) { return; } - cl = SV_GetPlayerByName(); + cl = SV_GetPlayerByHandle(); if ( !cl ) { return; } diff --git a/src/server/sv_client.c b/src/server/sv_client.c index 92a91bb7..fe7cc905 100644 --- a/src/server/sv_client.c +++ b/src/server/sv_client.c @@ -340,7 +340,7 @@ void SV_DropClient( client_t *drop, const char *reason ) { return; // already dropped } - if ( !drop->gentity || !(drop->gentity->r.svFlags & SVF_BOT) ) { + if (drop->netchan.remoteAddress.type != NA_BOT) { // see if we already have a challenge for this ip challenge = &svs.challenges[0]; @@ -630,7 +630,7 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg ) Com_Printf( "clientDownload: %d : begining \"%s\"\n", cl - svs.clients, cl->downloadName ); missionPack = FS_idPak(cl->downloadName, "missionpack"); - idPack = missionPack || FS_idPak(cl->downloadName, "baseq3"); + idPack = missionPack || FS_idPak(cl->downloadName, BASEGAME); if ( !sv_allowDownload->integer || idPack || ( cl->downloadSize = FS_SV_FOpenFileRead( cl->downloadName, &cl->download ) ) <= 0 ) { diff --git a/src/server/sv_init.c b/src/server/sv_init.c index d0a6a3c0..76cb8297 100644 --- a/src/server/sv_init.c +++ b/src/server/sv_init.c @@ -634,7 +634,7 @@ void SV_FinalMessage( char *message ) { if (cl->state >= CS_CONNECTED) { // don't send a disconnect to a local client if ( cl->netchan.remoteAddress.type != NA_LOOPBACK ) { - SV_SendServerCommand( cl, "print \"%s\"\n", message ); + SV_SendServerCommand( cl, "print \"%s\n\"\n", message ); SV_SendServerCommand( cl, "disconnect" ); } // force a snapshot to be sent diff --git a/src/server/sv_main.c b/src/server/sv_main.c index b40d173f..2e3135b6 100644 --- a/src/server/sv_main.c +++ b/src/server/sv_main.c @@ -834,7 +834,7 @@ void SV_Frame( int msec ) { return; } - if( sv.restartTime && svs.time >= sv.restartTime ) { + if( sv.restartTime && sv.time >= sv.restartTime ) { sv.restartTime = 0; Cbuf_AddText( "map_restart 0\n" ); return; diff --git a/src/tools/asm/Makefile b/src/tools/asm/Makefile index f03025ca..df355719 100644 --- a/src/tools/asm/Makefile +++ b/src/tools/asm/Makefile @@ -6,7 +6,7 @@ else BINEXT= endif -ifeq ($(PLATFORM),SunOS) +ifeq ($(PLATFORM),sunos) INSTALL=ginstall else INSTALL=install diff --git a/src/tools/lcc/Makefile b/src/tools/lcc/Makefile index 381b48ee..8dd5fb2b 100644 --- a/src/tools/lcc/Makefile +++ b/src/tools/lcc/Makefile @@ -30,7 +30,7 @@ ifeq ($(PLATFORM),darwin) LCC_CFLAGS += -DMACOS_X endif -ifeq ($(PLATFORM),SunOS) +ifeq ($(PLATFORM),sunos) INSTALL=ginstall else INSTALL=install diff --git a/src/ui/ui_main.c b/src/ui/ui_main.c index c7b90a6a..7873fb63 100644 --- a/src/ui/ui_main.c +++ b/src/ui/ui_main.c @@ -5371,7 +5371,7 @@ static void UI_BuildQ3Model_List( void ) { filelen = strlen(fileptr); - COM_StripExtension(fileptr,skinname); + COM_StripExtension(fileptr,skinname,2048); // look for icon_???? if (Q_stricmpn(skinname, "icon_", 5) == 0 && !(Q_stricmp(skinname,"icon_blue") == 0 || Q_stricmp(skinname,"icon_red") == 0)) diff --git a/src/unix/linux_glimp.c b/src/unix/linux_glimp.c index e6a86997..36e3dc36 100644 --- a/src/unix/linux_glimp.c +++ b/src/unix/linux_glimp.c @@ -1324,6 +1324,30 @@ static void GLW_InitExtensions( void ) ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" ); } + glConfig.textureFilterAnisotropic = qfalse; + if ( strstr( glConfig.extensions_string, "GL_EXT_texture_filter_anisotropic" ) ) + { + if ( r_ext_texture_filter_anisotropic->integer ) { + qglGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.maxAnisotropy ); + if ( glConfig.maxAnisotropy <= 0 ) { + ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not properly supported!\n" ); + glConfig.maxAnisotropy = 0; + } + else + { + ri.Printf( PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic (max: %i)\n", glConfig.maxAnisotropy ); + glConfig.textureFilterAnisotropic = qtrue; + } + } + else + { + ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_filter_anisotropic\n" ); + } + } + else + { + ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not found\n" ); + } } static void GLW_InitGamma(void) diff --git a/src/unix/linux_signals.c b/src/unix/linux_signals.c index 5d94f68b..72c5a522 100644 --- a/src/unix/linux_signals.c +++ b/src/unix/linux_signals.c @@ -47,6 +47,7 @@ static void signal_handler(int sig) // bk010104 - replace this... (NOTE TTimo hu // rcg08312005 Agreed: changed to CL_Shutdown... --ryan. CL_Shutdown(); #endif + SV_Shutdown("Signal caught"); Sys_Exit(0); // bk010104 - abstraction NOTE TTimo send a 0 to avoid DOUBLE SIGNAL FAULT } diff --git a/src/unix/sdl_glimp.c b/src/unix/sdl_glimp.c index f7720790..4469f9e0 100644 --- a/src/unix/sdl_glimp.c +++ b/src/unix/sdl_glimp.c @@ -439,15 +439,35 @@ void IN_DeactivateMouse( void ) */ void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned char blue[256] ) { - // NOTE TTimo we get the gamma value from cvar, because we can't work with the s_gammatable - // the API wasn't changed to avoid breaking other OSes - float g; + Uint16 table[3][256]; + int i, j; +// float g; - if ( r_ignorehwgamma->integer ) - return; + if(r_ignorehwgamma->integer) + return; + + // taken from win_gamma.c: + for (i = 0; i < 256; i++) + { + table[0][i] = ( ( ( Uint16 ) red[i] ) << 8 ) | red[i]; + table[1][i] = ( ( ( Uint16 ) green[i] ) << 8 ) | green[i]; + table[2][i] = ( ( ( Uint16 ) blue[i] ) << 8 ) | blue[i]; + } - g = Cvar_Get("r_gamma", "1.0", 0)->value; - SDL_SetGamma(g, g, g); + // enforce constantly increasing + for (j = 0; j < 3; j++) + { + for (i = 1; i < 256; i++) + { + if (table[j][i] < table[j][i-1]) + table[j][i] = table[j][i-1]; + } + } + + SDL_SetGammaRamp(table[0], table[1], table[2]); + +// g = Cvar_Get("r_gamma", "1.0", 0)->value; +// SDL_SetGamma(g, g, g); } /* @@ -554,7 +574,12 @@ static int GLW_SetMode( const char *drivername, int mode, qboolean fullscreen ) Uint32 flags = SDL_OPENGL; if (fullscreen) + { flags |= SDL_FULLSCREEN; + glConfig.isFullscreen = qtrue; + } + else + glConfig.isFullscreen = qfalse; if (!r_colorbits->value) colorbits = 24; @@ -626,7 +651,6 @@ static int GLW_SetMode( const char *drivername, int mode, qboolean fullscreen ) tstencilbits = 0; } - sdlcolorbits = 4; if (tcolorbits == 24) sdlcolorbits = 8; @@ -804,6 +828,30 @@ static void GLW_InitExtensions( void ) ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" ); } + glConfig.textureFilterAnisotropic = qfalse; + if ( strstr( glConfig.extensions_string, "GL_EXT_texture_filter_anisotropic" ) ) + { + if ( r_ext_texture_filter_anisotropic->integer ) { + qglGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.maxAnisotropy ); + if ( glConfig.maxAnisotropy <= 0 ) { + ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not properly supported!\n" ); + glConfig.maxAnisotropy = 0; + } + else + { + ri.Printf( PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic (max: %i)\n", glConfig.maxAnisotropy ); + glConfig.textureFilterAnisotropic = qtrue; + } + } + else + { + ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_filter_anisotropic\n" ); + } + } + else + { + ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not found\n" ); + } } static void GLW_InitGamma( void ) diff --git a/src/win32/win_glimp.c b/src/win32/win_glimp.c index 187fd7b9..22e98e5f 100644 --- a/src/win32/win_glimp.c +++ b/src/win32/win_glimp.c @@ -1112,6 +1112,31 @@ static void GLW_InitExtensions( void ) { ri.Printf( PRINT_ALL, "...WGL_3DFX_gamma_control not found\n" ); } + + glConfig.textureFilterAnisotropic = qfalse; + if ( strstr( glConfig.extensions_string, "GL_EXT_texture_filter_anisotropic" ) ) + { + if ( r_ext_texture_filter_anisotropic->integer ) { + qglGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.maxAnisotropy ); + if ( glConfig.maxAnisotropy <= 0 ) { + ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not properly supported!\n" ); + glConfig.maxAnisotropy = 0; + } + else + { + ri.Printf( PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic (max: %i)\n", glConfig.maxAnisotropy ); + glConfig.textureFilterAnisotropic = qtrue; + } + } + else + { + ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_filter_anisotropic\n" ); + } + } + else + { + ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not found\n" ); + } } /* diff --git a/ui/ingame_options.menu b/ui/ingame_options.menu index 75adbd3d..47914b4a 100644 --- a/ui/ingame_options.menu +++ b/ui/ingame_options.menu @@ -1255,7 +1255,7 @@ text "Quality:" cvar "ui_glCustom" cvarFloatList { "High Quality" 0 "Normal" 1 "Fast" 2 "Fastest" 3 "Custom" 4 } - rect 96 55 192 15 + rect 96 50 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1277,7 +1277,7 @@ text "GL Driver:" cvar "r_gldriver" //cvarFloatList { } - rect 96 70 192 15 + rect 96 65 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1294,7 +1294,7 @@ type ITEM_TYPE_YESNO text "GL Extensions:" cvar "r_allowExtensions" - rect 96 85 192 15 + rect 96 80 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1318,7 +1318,7 @@ cvarFloatList { "320x240" 0 "400x300" 1 "512x384" 2 "640x480" 3 "800x600" 4 "960x720" 5 "1024x768" 6 "1152x864" 7 "1280x1024" 8 "1600x1200" 9 "2048x1536" 10 "856x480 wide screen" 11 } - rect 96 100 192 15 + rect 96 95 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1340,7 +1340,7 @@ text "Color Depth:" cvar "r_colorbits" cvarFloatList { "Default" 0 "16 bit" 16 "32 bit" 32 } - rect 96 115 192 15 + rect 96 110 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1362,7 +1362,7 @@ type ITEM_TYPE_YESNO text "Fullscreen:" cvar "r_fullscreen" - rect 96 130 192 15 + rect 96 125 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1384,7 +1384,7 @@ text "Lighting:" cvar "r_vertexlight" cvarFloatList { "Light Map (high)" 0 "Vertex (low)" 1 } - rect 96 145 192 15 + rect 96 140 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1406,7 +1406,7 @@ text "Geometric Detail:" cvar "r_lodbias" cvarFloatList { "High" 0 "Medium" 1 "Low" 2 } - rect 96 160 192 15 + rect 96 155 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1429,7 +1429,7 @@ text "Texture Detail:" cvar "r_picmip" cvarFloatList { "Low" 2 "Normal" 1 "High" 0 } - rect 96 175 192 15 + rect 96 170 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1451,7 +1451,7 @@ text "Texture Quality:" cvar "r_texturebits" cvarFloatList { "Default" 0 "16 bit" 16 "32 bit" 32 } - rect 96 190 192 15 + rect 96 185 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1472,7 +1472,28 @@ text "Texture Filter:" cvar "r_texturemode" cvarStrList { "Bilinear", "GL_LINEAR_MIPMAP_NEAREST", "Trilinear", "GL_LINEAR_MIPMAP_LINEAR" } - rect 96 205 192 15 + rect 96 200 192 15 + textalign ITEM_ALIGN_RIGHT + textalignx 100 + textaligny 12 + textscale .25 + forecolor 1 1 1 1 + visible 0 + action + { + play "sound/misc/menu1.wav"; + uiScript glCustom + } + } + + itemDef + { + name ghardware + group optionsGrp + type ITEM_TYPE_YESNO + text "Anisotropic Filtering:" + cvar "r_ext_texture_filter_anisotropic" + rect 96 215 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1493,7 +1514,7 @@ type ITEM_TYPE_YESNO text "Compress Textures:" cvar "r_ext_compressed_textures " - rect 96 220 192 15 + rect 96 230 192 15 textalign ITEM_ALIGN_RIGHT textalignx 100 textaligny 12 @@ -1515,7 +1536,7 @@ text "APPLY" textscale .25 style WINDOW_STYLE_EMPTY - rect 144 240 75 20 + rect 144 245 75 20 textalign ITEM_ALIGN_CENTER textalignx 37 textaligny 15 |