diff options
author | Andrey Nazarov <skuller@skuller.net> | 2008-06-29 12:32:32 +0000 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2008-06-29 12:32:32 +0000 |
commit | e826e5f176f21cd18b3bbc22887a266835ada57c (patch) | |
tree | d25a84a84f9168b16a77fe4ed8b169c9611bbb02 | |
parent | 491f1c100e860c45a5d2aa358d58f777cd1cf895 (diff) |
Added client and server side support for 32-bit solids.
New R1Q2 and Q2PRO minor protocol versions, 1905 and 1014.
Use environment variables for game and server features negotiation.
Relax restrictions on quake paths when searching inside pak files.
Made OSS subsystem cvar names consistent with core sound system conventions.
Misc latched cvar handling changes.
42 files changed, 2890 insertions, 2871 deletions
diff --git a/source/cl_console.c b/source/cl_console.c index 7f6846e..4e4ac72 100644 --- a/source/cl_console.c +++ b/source/cl_console.c @@ -693,6 +693,7 @@ void Con_DrawSolidConsole( void ) { int vislines; float alpha; clipRect_t clip; + int widths[2]; vislines = con.vidHeight * con.currentHeight; if( vislines <= 0 ) @@ -757,11 +758,13 @@ void Con_DrawSolidConsole( void ) { text = con.text[row & CON_TOTALLINES_MASK]; - ref.DrawString( CHAR_WIDTH, y, 0, con.linewidth, text, con.charsetImage ); + x = ref.DrawString( CHAR_WIDTH, y, 0, con.linewidth, text, con.charsetImage ); + if( i < 2 ) { + widths[i] = x; + } y -= CHAR_HEIGHT; row--; - } //ZOID @@ -836,17 +839,21 @@ void Con_DrawSolidConsole( void ) { } y = vislines - CON_PRESTEP + CHAR_HEIGHT; + row = 0; if( x > con.vidWidth - 12 * CHAR_WIDTH ) { y -= CHAR_HEIGHT; + row++; } ref.SetColor( DRAW_COLOR_RGBA, colorCyan ); // draw clock if( con_clock->integer ) { - Com_Time_m( buffer, sizeof( buffer ) ); - SCR_DrawStringEx( con.vidWidth - CHAR_WIDTH, y - CHAR_HEIGHT, - UI_RIGHT, MAX_STRING_CHARS, buffer, con.charsetImage ); + x = Com_Time_m( buffer, sizeof( buffer ) ) * CHAR_WIDTH; + if( widths[row] + x + CHAR_WIDTH <= con.vidWidth ) { + ref.DrawString( con.vidWidth - CHAR_WIDTH - x, y - CHAR_HEIGHT, + UI_RIGHT, MAX_STRING_CHARS, buffer, con.charsetImage ); + } } // draw version @@ -1000,7 +1007,7 @@ void Key_Console( int key ) { { char *cbd, *s; - if( ( cbd = Sys_GetClipboardData() ) != NULL ) { + if( ( cbd = VID_GetClipboardData() ) != NULL ) { s = cbd; while( *s ) { int c = *s++; diff --git a/source/cl_ents.c b/source/cl_ents.c index 2dc8c46..7f63640 100644 --- a/source/cl_ents.c +++ b/source/cl_ents.c @@ -45,9 +45,28 @@ static void CL_SetEntityState( entity_state_t *state ) { if( state->number == cl.frame.clientNum + 1 ) { VectorCopy( cl.playerEntityOrigin, state->origin ); VectorCopy( cl.playerEntityAngles, state->angles ); - } + } else if( state->solid ) { + cl.solidEntities[cl.numSolidEntities++] = ent; + if( state->solid != 31 ) { + int x, zd, zu; + + // encoded bbox + if( LONG_SOLID_SUPPORTED( cls.serverProtocol, cls.protocolVersion ) ) { + x = (state->solid & 255); + zd = ((state->solid>>8) & 255); + zu = ((state->solid>>16) & 65535) - 32768; + } else { + x = 8*(state->solid & 31); + zd = 8*((state->solid>>5) & 31); + zu = 8*((state->solid>>10) & 63) - 32; + } - ent = &cl_entities[state->number]; + ent->mins[0] = ent->mins[1] = -x; + ent->maxs[0] = ent->maxs[1] = x; + ent->mins[2] = -zd; + ent->maxs[2] = zu; + } + } if( ent->serverframe != cl.oldframe.number ) { // wasn't in last update, so initialize some things @@ -101,7 +120,7 @@ void CL_DeltaFrame( void ) { VectorScale( cl.frame.ps.pmove.origin, 0.125f, cl.playerEntityOrigin ); - CL_BuildSolidList(); + cl.numSolidEntities = 0; for( i = 0; i < cl.frame.numEntities; i++ ) { j = ( cl.frame.firstEntity + i ) & PARSE_ENTITIES_MASK; diff --git a/source/cl_keys.c b/source/cl_keys.c index 7ccd659..1a403ed 100644 --- a/source/cl_keys.c +++ b/source/cl_keys.c @@ -824,7 +824,7 @@ void Key_Event( unsigned key, qboolean down, unsigned time ) { #ifndef USE_CHAR_EVENTS if( keydown[K_CTRL] || keydown[K_ALT] ) { - // return; + return; } switch( key ) { diff --git a/source/cl_local.h b/source/cl_local.h index bd768c0..e5a15d2 100644 --- a/source/cl_local.h +++ b/source/cl_local.h @@ -37,6 +37,8 @@ typedef struct centity_s { entity_state_t current; entity_state_t prev; // will always be valid, but might just be a copy of current + vec3_t mins, maxs; + int serverframe; // if not current, this ent isn't in the frame int trailcount; // for diminishing grenade trails @@ -117,7 +119,7 @@ typedef struct client_state_s { vec3_t prediction_error; // rebuilt each valid frame - entity_state_t *solidEntities[MAX_PACKET_ENTITIES]; + centity_t *solidEntities[MAX_PACKET_ENTITIES]; int numSolidEntities; entity_state_t baselines[MAX_EDICTS]; @@ -176,7 +178,6 @@ typedef struct client_state_s { // // server state information // - gametype_t gametype; int servercount; // server identification for prespawns char gamedir[MAX_QPATH]; int clientNum; // never changed during gameplay, set by serverdata packet @@ -579,7 +580,6 @@ laser_t *CL_AllocLaser( void ); // void CL_PredictMovement (void); void CL_CheckPredictionError (void); -void CL_BuildSolidList( void ); // // cl_fx.c diff --git a/source/cl_main.c b/source/cl_main.c index e339ce0..2a6b22a 100644 --- a/source/cl_main.c +++ b/source/cl_main.c @@ -2275,7 +2275,6 @@ static void CL_RestartRefresh_f( void ) { // switch back to original state cls.state = cls_state; - } /* diff --git a/source/cl_parse.c b/source/cl_parse.c index 20df0b3..28d52bb 100644 --- a/source/cl_parse.c +++ b/source/cl_parse.c @@ -271,6 +271,9 @@ static inline void CL_ParseDeltaEntity( server_frame_t *frame, MSG_ShowDeltaEntityBits( bits ); } + if( LONG_SOLID_SUPPORTED( cls.serverProtocol, cls.protocolVersion ) ) { + bits |= U_SOLID32; + } MSG_ParseDeltaEntity( old, state, newnum, bits ); } @@ -744,9 +747,12 @@ static void CL_ParseGamestate( void ) { break; } if( index < 1 || index >= MAX_EDICTS ) { - Com_Error( ERR_DROP, "%s: bad baseline index: %d", + Com_Error( ERR_DROP, "%s: bad entity number: %d", __func__, index ); } + if( LONG_SOLID_SUPPORTED( cls.serverProtocol, cls.protocolVersion ) ) { + bits |= U_SOLID32; + } MSG_ParseDeltaEntity( NULL, &cl.baselines[index], index, bits ); } } @@ -817,7 +823,6 @@ static void CL_ParseServerData( void ) { cl.pmp.waterfriction = 1; cl.pmp.flyfriction = 9; cl.pmp.airaccelerate = 0; - cl.gametype = GT_DEATHMATCH; #ifdef PMOVE_HACK cl.pmp.highprec = qtrue; #endif @@ -853,7 +858,7 @@ static void CL_ParseServerData( void ) { "Current client version is %d.", i, PROTOCOL_VERSION_Q2PRO_CURRENT ); } cls.protocolVersion = i; - cl.gametype = MSG_ReadByte(); + MSG_ReadByte(); // used to be gametype cl.pmp.strafeHack = MSG_ReadByte(); cl.pmp.qwmod = MSG_ReadByte(); //atu QWMod cl.pmp.speedMultiplier = 2; @@ -903,7 +908,14 @@ static void CL_ParseBaseline( void ) { newnum = MSG_ParseEntityBits( &bits ); if( newnum < 1 || newnum >= MAX_EDICTS ) { - Com_Error( ERR_DROP, "CL_ParseBaseline: bad entity number %i", newnum ); + Com_Error( ERR_DROP, "%s: bad entity number: %d", __func__, newnum ); + } + if( cl_shownet->integer > 2 ) { + MSG_ShowDeltaEntityBits( bits ); + Com_Printf( "\n" ); + } + if( LONG_SOLID_SUPPORTED( cls.serverProtocol, cls.protocolVersion ) ) { + bits |= U_SOLID32; } MSG_ParseDeltaEntity( NULL, &cl.baselines[newnum], newnum, bits ); } @@ -1135,7 +1147,7 @@ static void CL_ParseStartSoundPacket( void ) { Com_DPrintf( "SERVER BUG: sound on entity %d last seen %d frames ago\n", ent, cl.frame.number - cl_entities[ent].serverframe ); } else { - Com_DPrintf( "SERVER BUG: sound on entity %d we have never seen\n", ent ); + Com_DPrintf( "SERVER BUG: sound on entity %d never seen before\n", ent ); } } // use entity number @@ -1478,7 +1490,7 @@ void CL_ParseServerMessage( void ) { case svc_serverdata: CL_ParseServerData(); - break; + continue; case svc_configstring: CL_ParseConfigString(); diff --git a/source/cl_pred.c b/source/cl_pred.c index 5b56a9f..edf43dc 100644 --- a/source/cl_pred.c +++ b/source/cl_pred.c @@ -27,124 +27,92 @@ CL_CheckPredictionError =================== */ void CL_CheckPredictionError( void ) { - int frame; - int delta[3]; - unsigned cmd; - int len; - player_state_t *ps; - - if( !cls.netchan ) { - return; - } + int frame; + int delta[3]; + unsigned cmd; + int len; + player_state_t *ps; + + if( !cls.netchan ) { + return; + } - if( sv_paused->integer ) { - VectorClear( cl.prediction_error ); - return; - } + if( sv_paused->integer ) { + VectorClear( cl.prediction_error ); + return; + } - ps = &cl.frame.ps; + ps = &cl.frame.ps; - if( !cl_predict->integer || ( ps->pmove.pm_flags & PMF_NO_PREDICTION ) ) - return; + if( !cl_predict->integer || ( ps->pmove.pm_flags & PMF_NO_PREDICTION ) ) + return; - // calculate the last usercmd_t we sent that the server has processed - frame = cls.netchan->incoming_acknowledged & CMD_MASK; - cmd = cl.history[frame].cmdNumber; + // calculate the last usercmd_t we sent that the server has processed + frame = cls.netchan->incoming_acknowledged & CMD_MASK; + cmd = cl.history[frame].cmdNumber; // don't predict steps against server returned data if( cl.predicted_step_frame < cmd + 1 ) { cl.predicted_step_frame = cmd + 1; } - cmd &= CMD_MASK; + cmd &= CMD_MASK; - // compare what the server returned with what we had predicted it to be - VectorSubtract( ps->pmove.origin, cl.predicted_origins[cmd], delta ); + // compare what the server returned with what we had predicted it to be + VectorSubtract( ps->pmove.origin, cl.predicted_origins[cmd], delta ); - // save the prediction error for interpolation - len = abs( delta[0] ) + abs( delta[1] ) + abs( delta[2] ); - if( len > 640 ) { // 80 world units - // a teleport or something - VectorClear( cl.prediction_error ); - } else { - if( cl_showmiss->integer && ( delta[0] || delta[1] || delta[2] ) ) { - Com_Printf( "prediction miss on %i: %i\n", cl.frame.number, len ); - } + // save the prediction error for interpolation + len = abs( delta[0] ) + abs( delta[1] ) + abs( delta[2] ); + if( len > 640 ) { // 80 world units + // a teleport or something + VectorClear( cl.prediction_error ); + } else { + if( cl_showmiss->integer && ( delta[0] || delta[1] || delta[2] ) ) { + Com_Printf( "prediction miss on %i: %i\n", cl.frame.number, len ); + } - VectorCopy( ps->pmove.origin, cl.predicted_origins[cmd] ); - - // save for error interpolation - VectorScale( delta, 0.125f, cl.prediction_error ); - } -} + VectorCopy( ps->pmove.origin, cl.predicted_origins[cmd] ); -void CL_BuildSolidList( void ) { - int i, num; - entity_state_t *ent; - - cl.numSolidEntities = 0; - for( i = 0; i < cl.frame.numEntities; i++ ) { - num = ( cl.frame.firstEntity + i ) & PARSE_ENTITIES_MASK; - ent = &cl.entityStates[num]; - - if( ent->number == cl.frame.clientNum + 1 ) { - continue; - } - if( !ent->solid ) { - continue; - } - - cl.solidEntities[cl.numSolidEntities++] = ent; - } + // save for error interpolation + VectorScale( delta, 0.125f, cl.prediction_error ); + } } - /* ==================== CL_ClipMoveToEntities ==================== */ -static void CL_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t *tr ) { - int i, x, zd, zu; - trace_t trace; - cnode_t *headnode; - entity_state_t *ent; - cmodel_t *cmodel; - vec3_t bmins, bmaxs; - - for (i=0 ; i<cl.numSolidEntities ; i++) { - ent = cl.solidEntities[i]; - - if (ent->solid == 31) { +static void CL_ClipMoveToEntities( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t *tr ) { + int i; + trace_t trace; + cnode_t *headnode; + centity_t *ent; + cmodel_t *cmodel; + + for( i = 0; i < cl.numSolidEntities; i++ ) { + ent = cl.solidEntities[i]; + + if( ent->current.solid == 31 ) { // special value for bmodel - cmodel = cl.model_clip[ent->modelindex]; - if (!cmodel) - continue; - headnode = cmodel->headnode; - } else { - // encoded bbox - x = 8*(ent->solid & 31); - zd = 8*((ent->solid>>5) & 31); - zu = 8*((ent->solid>>10) & 63) - 32; - - bmins[0] = bmins[1] = -x; - bmaxs[0] = bmaxs[1] = x; - bmins[2] = -zd; - bmaxs[2] = zu; - - headnode = CM_HeadnodeForBox (bmins, bmaxs); - } - - if (tr->allsolid) - return; - - CM_TransformedBoxTrace (&trace, start, end, - mins, maxs, headnode, MASK_PLAYERSOLID, - ent->origin, ent->angles); - - CM_ClipEntity( tr, &trace, ( struct edict_s * )ent ); - } + cmodel = cl.model_clip[ent->current.modelindex]; + if( !cmodel ) + continue; + headnode = cmodel->headnode; + } else { + headnode = CM_HeadnodeForBox( ent->mins, ent->maxs ); + } + + if( tr->allsolid ) + return; + + CM_TransformedBoxTrace( &trace, start, end, + mins, maxs, headnode, MASK_PLAYERSOLID, + ent->current.origin, ent->current.angles ); + + CM_ClipEntity( tr, &trace, ( struct edict_s * )ent ); + } } @@ -154,41 +122,44 @@ CL_PMTrace ================ */ static trace_t CL_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end) { - trace_t t; + trace_t t; - // check against world - CM_BoxTrace (&t, start, end, mins, maxs, cl.cm.cache->nodes, MASK_PLAYERSOLID); - if (t.fraction < 1.0) - t.ent = (struct edict_s *)1; + // check against world + CM_BoxTrace (&t, start, end, mins, maxs, cl.cm.cache->nodes, MASK_PLAYERSOLID); + if (t.fraction < 1.0) + t.ent = (struct edict_s *)1; - // check all other solid models - CL_ClipMoveToEntities (start, mins, maxs, end, &t); + // check all other solid models + CL_ClipMoveToEntities (start, mins, maxs, end, &t); - return t; + return t; } static int CL_PointContents (vec3_t point) { - int i; - entity_state_t *ent; - cmodel_t *cmodel; - int contents; + int i; + centity_t *ent; + cmodel_t *cmodel; + int contents; - contents = CM_PointContents (point, cl.cm.cache->nodes); + contents = CM_PointContents (point, cl.cm.cache->nodes); - for (i=0 ; i<cl.numSolidEntities ; i++) { - ent = cl.solidEntities[i]; + for (i=0 ; i<cl.numSolidEntities ; i++) { + ent = cl.solidEntities[i]; - if (ent->solid != 31) // special value for bmodel - continue; + if (ent->current.solid != 31) // special value for bmodel + continue; - cmodel = cl.model_clip[ent->modelindex]; - if (!cmodel) - continue; + cmodel = cl.model_clip[ent->current.modelindex]; + if (!cmodel) + continue; - contents |= CM_TransformedPointContents (point, cmodel->headnode, ent->origin, ent->angles); - } + contents |= CM_TransformedPointContents( + point, cmodel->headnode, + ent->current.origin, + ent->current.angles ); + } - return contents; + return contents; } @@ -200,96 +171,96 @@ Sets cl.predicted_origin and cl.predicted_angles ================= */ void CL_PredictMovement( void ) { - unsigned ack, current, frame; - pmove_t pm; - int step, oldz; - player_state_t *ps; - - if( cls.state != ca_active ) { - return; - } - - if( cls.demo.playback ) { - return; - } - - if( sv_paused->integer ) { - return; - } - - ps = &cl.frame.ps; - - if( !cl_predict->integer || ( ps->pmove.pm_flags & PMF_NO_PREDICTION ) ) { - // just set angles - cl.predicted_angles[0] = cl.viewangles[0] + SHORT2ANGLE( ps->pmove.delta_angles[0] ); - cl.predicted_angles[1] = cl.viewangles[1] + SHORT2ANGLE( ps->pmove.delta_angles[1] ); - cl.predicted_angles[2] = cl.viewangles[2] + SHORT2ANGLE( ps->pmove.delta_angles[2] ); - return; - } - - ack = cl.history[cls.netchan->incoming_acknowledged & CMD_MASK].cmdNumber; - current = cl.cmdNumber; - - // if we are too far out of date, just freeze - if( current - ack > CMD_BACKUP - 1 ) { - if( cl_showmiss->integer ) { - Com_Printf( "%i: exceeded CMD_BACKUP\n", cl.frame.number ); - } - return; - } - - if( !cl.cmd.msec && current == ack ) { - if( cl_showmiss->integer ) { - Com_Printf( "%i: not moved\n", cl.frame.number ); - } - return; - } - - // copy current state to pmove - memset( &pm, 0, sizeof( pm ) ); - pm.trace = CL_Trace; - pm.pointcontents = CL_PointContents; - - pm.s = ps->pmove; + unsigned ack, current, frame; + pmove_t pm; + int step, oldz; + player_state_t *ps; + + if( cls.state != ca_active ) { + return; + } + + if( cls.demo.playback ) { + return; + } + + if( sv_paused->integer ) { + return; + } + + ps = &cl.frame.ps; + + if( !cl_predict->integer || ( ps->pmove.pm_flags & PMF_NO_PREDICTION ) ) { + // just set angles + cl.predicted_angles[0] = cl.viewangles[0] + SHORT2ANGLE( ps->pmove.delta_angles[0] ); + cl.predicted_angles[1] = cl.viewangles[1] + SHORT2ANGLE( ps->pmove.delta_angles[1] ); + cl.predicted_angles[2] = cl.viewangles[2] + SHORT2ANGLE( ps->pmove.delta_angles[2] ); + return; + } + + ack = cl.history[cls.netchan->incoming_acknowledged & CMD_MASK].cmdNumber; + current = cl.cmdNumber; + + // if we are too far out of date, just freeze + if( current - ack > CMD_BACKUP - 1 ) { + if( cl_showmiss->integer ) { + Com_Printf( "%i: exceeded CMD_BACKUP\n", cl.frame.number ); + } + return; + } + + if( !cl.cmd.msec && current == ack ) { + if( cl_showmiss->integer ) { + Com_Printf( "%i: not moved\n", cl.frame.number ); + } + return; + } + + // copy current state to pmove + memset( &pm, 0, sizeof( pm ) ); + pm.trace = CL_Trace; + pm.pointcontents = CL_PointContents; + + pm.s = ps->pmove; #if USE_SMOOTH_DELTA_ANGLES VectorCopy( cl.delta_angles, pm.s.delta_angles ); #endif - // run frames - while( ++ack <= current ) { - pm.cmd = cl.cmds[ack & CMD_MASK]; - Pmove( &pm, &cl.pmp ); + // run frames + while( ++ack <= current ) { + pm.cmd = cl.cmds[ack & CMD_MASK]; + Pmove( &pm, &cl.pmp ); - // save for debug checking - VectorCopy( pm.s.origin, cl.predicted_origins[ack & CMD_MASK] ); - } + // save for debug checking + VectorCopy( pm.s.origin, cl.predicted_origins[ack & CMD_MASK] ); + } - // run pending cmd + // run pending cmd if( cl.cmd.msec ) { pm.cmd = cl.cmd; pm.cmd.forwardmove = cl.move[0]; pm.cmd.sidemove = cl.move[1]; pm.cmd.upmove = cl.move[2]; Pmove( &pm, &cl.pmp ); - frame = current; - - // save for debug checking - VectorCopy( pm.s.origin, cl.predicted_origins[( current + 1 ) & CMD_MASK] ); - } else { - frame = current - 1; - } - - oldz = cl.predicted_origins[cl.predicted_step_frame & CMD_MASK][2]; - step = pm.s.origin[2] - oldz; - if( step > 63 && step < 160 && ( pm.s.pm_flags & PMF_ON_GROUND ) ) { - cl.predicted_step = step * 0.125f; - cl.predicted_step_time = cls.realtime;/// - cls.frametime * 500; - } - cl.predicted_step_frame = frame; - - // copy results out for rendering - VectorScale( pm.s.origin, 0.125f, cl.predicted_origin ); - VectorScale( pm.s.velocity, 0.125f, cl.predicted_velocity ); - VectorCopy( pm.viewangles, cl.predicted_angles ); + frame = current; + + // save for debug checking + VectorCopy( pm.s.origin, cl.predicted_origins[( current + 1 ) & CMD_MASK] ); + } else { + frame = current - 1; + } + + oldz = cl.predicted_origins[cl.predicted_step_frame & CMD_MASK][2]; + step = pm.s.origin[2] - oldz; + if( step > 63 && step < 160 && ( pm.s.pm_flags & PMF_ON_GROUND ) ) { + cl.predicted_step = step * 0.125f; + cl.predicted_step_time = cls.realtime;/// - cls.frametime * 500; + } + cl.predicted_step_frame = frame; + + // copy results out for rendering + VectorScale( pm.s.origin, 0.125f, cl.predicted_origin ); + VectorScale( pm.s.velocity, 0.125f, cl.predicted_velocity ); + VectorCopy( pm.viewangles, cl.predicted_angles ); } diff --git a/source/cl_ref.c b/source/cl_ref.c index fe959bc..7c130b7 100644 --- a/source/cl_ref.c +++ b/source/cl_ref.c @@ -337,7 +337,7 @@ void CL_PumpEvents( void ) { #endif if( mode_changed & MODE_FULLSCREEN ) { if( vid_fullscreen->integer ) { - Cbuf_AddText( "set _vid_fullscreen $vid_fullscreen\n" ); + Cvar_Set( "_vid_fullscreen", vid_fullscreen->string ); } VID_ModeChanged(); } else { @@ -387,7 +387,7 @@ void CL_InitRefresh( void ) { vid_geometry = Cvar_Get( "vid_geometry", "640x480", CVAR_ARCHIVE ); vid_fullscreen = Cvar_Get( "vid_fullscreen", "0", CVAR_ARCHIVE ); _vid_fullscreen = Cvar_Get( "_vid_fullscreen", "1", CVAR_ARCHIVE ); - vid_modelist = Cvar_Get( "vid_modelist", "640x480 800x600 1024x768", CVAR_ARCHIVE ); + vid_modelist = Cvar_Get( "vid_modelist", "640x480 800x600 1024x768", 0 ); if( vid_fullscreen->integer ) { Cvar_Set( "_vid_fullscreen", vid_fullscreen->string ); diff --git a/source/com_local.h b/source/com_local.h index e93539d..30ce0d9 100644 --- a/source/com_local.h +++ b/source/com_local.h @@ -237,8 +237,7 @@ typedef enum { } cvarSetSource_t; extern cvar_t *cvar_vars; -extern int cvar_latchedModified; -extern int cvar_infoModified; +extern int cvar_modified; void Cvar_SetByVar( cvar_t *var, const char *value, cvarSetSource_t source ); @@ -1037,10 +1036,7 @@ void Sys_FreeLibrary( void *handle ); void *Sys_GetProcAddress( void *handle, const char *sym ); unsigned Sys_Milliseconds( void ); -char *Sys_GetClipboardData( void ); -void Sys_SetClipboardData( const char *data ); void Sys_Sleep( int msec ); -void Sys_Setenv( const char *name, const char *value ); void Hunk_Begin( mempool_t *pool, size_t maxsize ); void *Hunk_Alloc( mempool_t *pool, size_t size ); @@ -1059,9 +1055,6 @@ void Sys_Quit( void ); void **Sys_ListFiles( const char *path, const char *extension, int flags, size_t length, int *numFiles ); -qboolean Sys_Mkdir( const char *path ); -qboolean Sys_RemoveFile( const char *path ); -qboolean Sys_RenameFile( const char *from, const char *to ); qboolean Sys_GetPathInfo( const char *path, fsFileInfo_t *info ); qboolean Sys_GetFileInfo( FILE *fp, fsFileInfo_t *info ); @@ -1125,12 +1118,17 @@ void CL_UpdateUserinfo( cvar_t *var, cvarSetSource_t source ); void IN_Frame( void ); void IN_Activate( void ); void IN_MouseEvent( int x, int y ); +void IN_WarpMouse( int x, int y ); void Key_Init( void ); void Key_Event( unsigned key, qboolean down, unsigned time ); void Key_CharEvent( int key ); void Key_WriteBindings( fileHandle_t f ); +char *VID_GetClipboardData( void ); +void VID_SetClipboardData( const char *data ); +void VID_FatalShutdown( void ); + typedef enum { ss_dead, // no map loaded ss_loading, // spawning level edicts diff --git a/source/com_public.h b/source/com_public.h index cfdd492..8f79815 100644 --- a/source/com_public.h +++ b/source/com_public.h @@ -129,12 +129,15 @@ CVAR #define CVAR_CHEAT ( 1 << 5 ) #define CVAR_PRIVATE ( 1 << 6 ) #define CVAR_ROM ( 1 << 7 ) -#define CVAR_LATCHED ( 1 << 8 ) #define CVAR_CUSTOM ( 1 << 9 ) #define CVAR_VOLATILE ( 1 << 10 ) #define CVAR_GAME ( 1 << 11 ) +#define CVAR_FILES ( 1 << 13 ) +#define CVAR_REFRESH ( 1 << 14 ) +#define CVAR_SOUND ( 1 << 15 ) #define CVAR_INFOMASK (CVAR_USERINFO|CVAR_SERVERINFO) +#define CVAR_MODIFYMASK (CVAR_INFOMASK|CVAR_FILES|CVAR_REFRESH|CVAR_SOUND) #define CVAR_EXTENDED_MASK (~31) typedef struct cvarAPI_s { @@ -246,8 +249,6 @@ typedef struct { typedef struct sysAPI_s { unsigned (*Milliseconds)( void ); - char *(*GetClipboardData)( void ); - void (*SetClipboardData)( const char *data ); void (*HunkBegin)( mempool_t *pool, size_t maxsize ); void *(*HunkAlloc)( mempool_t *pool, size_t size ); void (*HunkEnd)( mempool_t *pool ); @@ -265,7 +266,7 @@ MODULES */ // if api_version is different, the dll cannot be used -#define MODULES_APIVERSION 317 +#define MODULES_APIVERSION 318 typedef enum moduleQuery_e { MQ_GETINFO, diff --git a/source/common.c b/source/common.c index 08a9dd0..1ef854b 100644 --- a/source/common.c +++ b/source/common.c @@ -1054,7 +1054,7 @@ static void Com_Setenv_f( void ) { int argc = Cmd_Argc(); if( argc > 2 ) { - Sys_Setenv( Cmd_Argv( 1 ), Cmd_ArgsFrom( 2 ) ); + Q_setenv( Cmd_Argv( 1 ), Cmd_ArgsFrom( 2 ) ); } else if( argc == 2 ) { char *env = getenv( Cmd_Argv( 1 ) ); @@ -1574,8 +1574,12 @@ void Qcommon_Frame( void ) { all, ev, sv, gm, cl, rf ); } #endif + + if( cvar_modified & CVAR_FILES ) { + Cbuf_ExecuteText( EXEC_NOW, "fs_restart" ); + } - cvar_infoModified = 0; + cvar_modified = 0; com_localTime += msec; com_framenum++; diff --git a/source/cvar.c b/source/cvar.c index c7f8fe6..564c989 100644 --- a/source/cvar.c +++ b/source/cvar.c @@ -25,8 +25,7 @@ cvarAPI_t cvar; cvar_t *cvar_vars; -//int cvar_latchedModified; -int cvar_infoModified; +int cvar_modified; #define Cvar_Malloc( size ) Z_TagMalloc( size, TAG_CVAR ) @@ -170,15 +169,17 @@ static void Cvar_ChangeString( cvar_t *var, const char *value, cvarSetSource_t s Cvar_ParseString( var ); if( var->flags & CVAR_INFOMASK ) { - cvar_infoModified |= var->flags & CVAR_INFOMASK; if( var->flags & CVAR_USERINFO ) { CL_UpdateUserinfo( var, source ); } } var->modified = qtrue; - if( source != CVAR_SET_DIRECT && var->changed ) { - var->changed( var ); + if( source != CVAR_SET_DIRECT ) { + cvar_modified |= var->flags & CVAR_MODIFYMASK; + if( var->changed ) { + var->changed( var ); + } } } @@ -190,15 +191,6 @@ Cvar_Get has been called from subsystem initialization routine. ============ */ static void Cvar_EngineGet( cvar_t *var, const char *var_value, int flags ) { - if( ( var->flags & CVAR_LATCHED ) && var->latched_string ) { - // update latched cvar - Z_Free( var->string ); - var->string = var->latched_string; - var->latched_string = NULL; - Cvar_ParseString( var ); - var->modified = qtrue; - } - if( var->flags & (CVAR_CUSTOM|CVAR_VOLATILE) ) { // update default string if cvar was set from command line Z_Free( var->default_string ); @@ -216,7 +208,7 @@ static void Cvar_EngineGet( cvar_t *var, const char *var_value, int flags ) { } // some flags are not saved - var->flags &= ~(CVAR_LATCHED|CVAR_GAME|CVAR_CUSTOM|CVAR_VOLATILE); + var->flags &= ~(CVAR_GAME|CVAR_CUSTOM|CVAR_VOLATILE); var->flags |= flags; } @@ -309,9 +301,7 @@ void Cvar_SetByVar( cvar_t *var, const char *value, cvarSetSource_t source ) { if( !value ) { value = ""; } - if( !strcmp( value, var->string ) && - !( var->flags & (CVAR_LATCHED|CVAR_LATCH) ) ) - { + if( !strcmp( value, var->string ) && !( var->flags & CVAR_LATCH ) ) { return; // not changed } @@ -344,7 +334,7 @@ void Cvar_SetByVar( cvar_t *var, const char *value, cvarSetSource_t source ) { return; } - if( var->flags & (CVAR_LATCHED|CVAR_LATCH) ) { + if( var->flags & CVAR_LATCH ) { if( !strcmp( var->string, value ) ) { // set back to current value if( var->latched_string ) { @@ -466,7 +456,6 @@ cvar_t *Cvar_FullSet( const char *var_name, const char *value, int flags, cvarSe // force retransmit of userinfo variables // needed for compatibility with q2admin if( ( var->flags | flags ) & CVAR_USERINFO ) { - cvar_infoModified |= CVAR_USERINFO; CL_UpdateUserinfo( var, source ); } @@ -585,14 +574,14 @@ Cvar_FixCheats ================== */ void Cvar_FixCheats( void ) { - cvar_t *var; + cvar_t *var; - if ( CL_CheatsOK() ) { + if( CL_CheatsOK() ) { return; } // fix any cheating cvars - for( var = cvar_vars ; var ; var = var->next ) { + for( var = cvar_vars; var; var = var->next ) { if( var->flags & CVAR_CHEAT ) { Cvar_SetByVar( var, var->default_string, CVAR_SET_DIRECT ); } @@ -615,8 +604,6 @@ void Cvar_GetLatchedVars( void ) { var->flags &= ~CVAR_SERVERINFO; if( !(var->flags & CVAR_LATCH) ) continue; - if( var->flags & CVAR_LATCHED ) - continue; // don't update engine cvars if( !var->latched_string ) continue; Z_Free( var->string ); @@ -624,6 +611,7 @@ void Cvar_GetLatchedVars( void ) { var->latched_string = NULL; Cvar_ParseString( var ); var->modified = qtrue; + cvar_modified |= var->flags & CVAR_MODIFYMASK; } } @@ -757,7 +745,7 @@ void Cvar_WriteVariables( fileHandle_t f, int mask, qboolean modified ) { continue; } if( var->flags & mask ) { - if( ( var->flags & CVAR_LATCHED ) && var->latched_string ) { + if( var->latched_string ) { string = var->latched_string; } else { string = var->string; @@ -827,8 +815,7 @@ static void Cvar_List_f( void ) { "S: included in serverinfo\n" "N: set from command line only\n" "R: read-only variable\n" - "L: latched (requires subsystem restart)\n" - "G: latched (requires game map restart)\n" + "L: latched\n" "?: created by user\n" ); return; case 'l': @@ -900,10 +887,8 @@ static void Cvar_List_f( void ) { buffer[4] = 'R'; else if( var->flags & CVAR_NOSET ) buffer[4] = 'N'; - else if( var->flags & CVAR_LATCHED ) - buffer[4] = 'L'; else if( var->flags & CVAR_LATCH ) - buffer[4] = 'G'; + buffer[4] = 'L'; else if( var->flags & CVAR_CUSTOM ) buffer[4] = '?'; diff --git a/source/files.c b/source/files.c index b6a8871..120d564 100644 --- a/source/files.c +++ b/source/files.c @@ -39,8 +39,8 @@ QUAKE FILESYSTEM ============================================================================= */ -#define MAX_FILES_IN_PK2 0x4000 -#define MAX_FILE_HANDLES 8 +#define MAX_FILES_IN_PK2 0x4000 +#define MAX_FILE_HANDLES 8 // macros for dealing portably with files at OS level #ifdef _WIN32 @@ -51,8 +51,8 @@ QUAKE FILESYSTEM #define FS_strncmp strncmp #endif -#define MAX_READ 0x40000 // read in blocks of 256k -#define MAX_WRITE 0x40000 // write in blocks of 256k +#define MAX_READ 0x40000 // read in blocks of 256k +#define MAX_WRITE 0x40000 // write in blocks of 256k // @@ -60,54 +60,54 @@ QUAKE FILESYSTEM // typedef struct packfile_s { - char *name; - size_t filepos; - size_t filelen; + char *name; + size_t filepos; + size_t filelen; - struct packfile_s *hashNext; + struct packfile_s *hashNext; } packfile_t; typedef struct pack_s { #if USE_ZLIB - unzFile zFile; + unzFile zFile; #endif - FILE *fp; - int numfiles; - packfile_t *files; - packfile_t **fileHash; - int hashSize; - char filename[1]; + FILE *fp; + int numfiles; + packfile_t *files; + packfile_t **fileHash; + int hashSize; + char filename[1]; } pack_t; typedef struct searchpath_s { - struct searchpath_s *next; + struct searchpath_s *next; int mode; - struct pack_s *pack; // only one of filename / pack will be used - char filename[1]; + struct pack_s *pack; // only one of filename / pack will be used + char filename[1]; } searchpath_t; typedef enum fsFileType_e { - FS_FREE, - FS_REAL, - FS_PAK, + FS_FREE, + FS_REAL, + FS_PAK, #if USE_ZLIB - FS_PK2, - FS_GZIP, + FS_PK2, + FS_GZIP, #endif - FS_BAD + FS_BAD } fsFileType_t; typedef struct fsFile_s { - char fullpath[MAX_OSPATH]; - fsFileType_t type; - unsigned mode; - FILE *fp; + char fullpath[MAX_OSPATH]; + fsFileType_t type; + unsigned mode; + FILE *fp; #if USE_ZLIB - void *zfp; + void *zfp; #endif - packfile_t *pak; - qboolean unique; - size_t length; + packfile_t *pak; + qboolean unique; + size_t length; } fsFile_t; typedef struct fsLink_s { @@ -118,26 +118,26 @@ typedef struct fsLink_s { } fsLink_t; // these point to user home directory -static char fs_gamedir[MAX_OSPATH]; -//static char fs_basedir[MAX_OSPATH]; +static char fs_gamedir[MAX_OSPATH]; +//static char fs_basedir[MAX_OSPATH]; -static cvar_t *fs_debug; -static cvar_t *fs_restrict_mask; +static cvar_t *fs_debug; +static cvar_t *fs_restrict_mask; -static searchpath_t *fs_searchpaths; -static searchpath_t *fs_base_searchpaths; +static searchpath_t *fs_searchpaths; +static searchpath_t *fs_base_searchpaths; static fsLink_t *fs_links; -static fsFile_t fs_files[MAX_FILE_HANDLES]; +static fsFile_t fs_files[MAX_FILE_HANDLES]; -static qboolean fs_fileFromPak; +static qboolean fs_fileFromPak; static int fs_count_read, fs_count_strcmp, fs_count_open; -cvar_t *fs_game; +cvar_t *fs_game; -fsAPI_t fs; +fsAPI_t fs; /* @@ -159,22 +159,72 @@ This is a precacution against having a malicious server instruct clients to writ /* ================ +FS_pathcmp + +Portably compares quake paths +================ +*/ +static int FS_pathcmp( const char *s1, const char *s2 ) { + int c1, c2; + + do { + c1 = *s1++; + c2 = *s2++; + + if( c1 != c2 ) { + c1 = c1 == '\\' ? '/' : Q_tolower( c1 ); + c2 = c2 == '\\' ? '/' : Q_tolower( c2 ); + if( c1 < c2 ) + return -1; + if( c1 > c2 ) + return 1; /* strings not equal */ + } + } while( c1 ); + + return 0; /* strings are equal */ +} + +static int FS_pathcmpn( const char *s1, const char *s2, size_t n ) { + int c1, c2; + + do { + c1 = *s1++; + c2 = *s2++; + + if( !n-- ) + return 0; /* strings are equal until end point */ + + if( c1 != c2 ) { + c1 = c1 == '\\' ? '/' : Q_tolower( c1 ); + c2 = c2 == '\\' ? '/' : Q_tolower( c2 ); + if( c1 < c2 ) + return -1; + if( c1 > c2 ) + return 1; /* strings not equal */ + } + } while( c1 ); + + return 0; /* strings are equal */ +} + +/* +================ FS_DPrintf ================ */ static void FS_DPrintf( char *format, ... ) { - va_list argptr; - char string[MAXPRINTMSG]; + va_list argptr; + char string[MAXPRINTMSG]; - if( !fs_debug || !fs_debug->integer ) { - return; - } + if( !fs_debug || !fs_debug->integer ) { + return; + } - va_start( argptr, format ); - Q_vsnprintf( string, sizeof( string ), format, argptr ); - va_end( argptr ); + va_start( argptr, format ); + Q_vsnprintf( string, sizeof( string ), format, argptr ); + va_end( argptr ); - Com_Printf( S_COLOR_CYAN "%s", string ); + Com_Printf( S_COLOR_CYAN "%s", string ); } /* @@ -183,21 +233,21 @@ FS_AllocHandle ================ */ static fsFile_t *FS_AllocHandle( fileHandle_t *f ) { - fsFile_t *file; - int i; + fsFile_t *file; + int i; - for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) { - if( file->type == FS_FREE ) { - break; - } - } + for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) { + if( file->type == FS_FREE ) { + break; + } + } - if( i == MAX_FILE_HANDLES ) { - Com_Error( ERR_FATAL, "%s: none free", __func__ ); - } + if( i == MAX_FILE_HANDLES ) { + Com_Error( ERR_FATAL, "%s: none free", __func__ ); + } - *f = i + 1; - return file; + *f = i + 1; + return file; } /* @@ -206,22 +256,22 @@ FS_FileForHandle ================ */ static fsFile_t *FS_FileForHandle( fileHandle_t f ) { - fsFile_t *file; + fsFile_t *file; - if( f <= 0 || f >= MAX_FILE_HANDLES + 1 ) { - Com_Error( ERR_FATAL, "%s: invalid handle: %i", __func__, f ); - } + if( f <= 0 || f >= MAX_FILE_HANDLES + 1 ) { + Com_Error( ERR_FATAL, "%s: invalid handle: %i", __func__, f ); + } - file = &fs_files[f - 1]; - if( file->type == FS_FREE ) { - Com_Error( ERR_FATAL, "%s: free handle: %i", __func__, f ); - } + file = &fs_files[f - 1]; + if( file->type == FS_FREE ) { + Com_Error( ERR_FATAL, "%s: free handle: %i", __func__, f ); + } - if( file->type < FS_FREE || file->type >= FS_BAD ) { - Com_Error( ERR_FATAL, "%s: invalid file type: %i", __func__, file->type ); - } + if( file->type < FS_FREE || file->type >= FS_BAD ) { + Com_Error( ERR_FATAL, "%s: invalid file type: %i", __func__, file->type ); + } - return file; + return file; } /* @@ -230,42 +280,42 @@ FS_ValidatePath ================ */ static qboolean FS_ValidatePath( const char *s ) { - const char *start; - - // check for leading slash - // check for empty path - if( *s == '/' || *s == '\\' /*|| *s == 0*/ ) { - return qfalse; - } - - start = s; - while( *s ) { - // check for ".." - if( *s == '.' && s[1] == '.' ) { - return qfalse; - } - if( *s == '/' || *s == '\\' ) { - // check for two slashes in a row - // check for trailing slash - if( ( s[1] == '/' || s[1] == '\\' || s[1] == 0 ) ) { - return qfalse; - } - } - if( *s == ':' ) { - // check for "X:\" - if( s[1] == '\\' || s[1] == '/' ) { - return qfalse; - } - } - s++; - } + const char *start; + + // check for leading slash + // check for empty path + if( *s == '/' || *s == '\\' /*|| *s == 0*/ ) { + return qfalse; + } + + start = s; + while( *s ) { + // check for ".." + if( *s == '.' && s[1] == '.' ) { + return qfalse; + } + if( *s == '/' || *s == '\\' ) { + // check for two slashes in a row + // check for trailing slash + if( ( s[1] == '/' || s[1] == '\\' || s[1] == 0 ) ) { + return qfalse; + } + } + if( *s == ':' ) { + // check for "X:\" + if( s[1] == '\\' || s[1] == '/' ) { + return qfalse; + } + } + s++; + } // check length - if( s - start > MAX_OSPATH ) { - return qfalse; - } + if( s - start > MAX_OSPATH ) { + return qfalse; + } - return qtrue; + return qtrue; } /* @@ -274,17 +324,17 @@ FS_ReplaceSeparators ================ */ char *FS_ReplaceSeparators( char *s, int separator ) { - char *p; + char *p; - p = s; - while( *p ) { - if( *p == '/' || *p == '\\' ) { - *p = separator; - } - p++; - } + p = s; + while( *p ) { + if( *p == '/' || *p == '\\' ) { + *p = separator; + } + p++; + } - return s; + return s; } @@ -298,32 +348,32 @@ Returns compressed length for GZIP files. ================ */ size_t FS_GetFileLength( fileHandle_t f ) { - fsFile_t *file = FS_FileForHandle( f ); + fsFile_t *file = FS_FileForHandle( f ); fsFileInfo_t info; - switch( file->type ) { - case FS_REAL: + switch( file->type ) { + case FS_REAL: if( !Sys_GetFileInfo( file->fp, &info ) ) { return INVALID_LENGTH; } - return info.size; - case FS_PAK: - return file->length; + return info.size; + case FS_PAK: + return file->length; #if USE_ZLIB - case FS_PK2: - return file->length; - case FS_GZIP: + case FS_PK2: + return file->length; + case FS_GZIP: return INVALID_LENGTH; #endif default: - Com_Error( ERR_FATAL, "%s: bad file type", __func__ ); - } + Com_Error( ERR_FATAL, "%s: bad file type", __func__ ); + } return INVALID_LENGTH; } const char *FS_GetFileFullPath( fileHandle_t f ) { - return ( FS_FileForHandle( f ) )->fullpath; + return ( FS_FileForHandle( f ) )->fullpath; } /* @@ -335,29 +385,29 @@ Expects a fully qualified quake path (i.e. with / separators). ============ */ void FS_CreatePath( const char *path ) { - char buffer[MAX_OSPATH]; - char *ofs; + char buffer[MAX_OSPATH]; + char *ofs; - Q_strncpyz( buffer, path, sizeof( buffer ) ); + Q_strncpyz( buffer, path, sizeof( buffer ) ); - FS_DPrintf( "%s: %s\n", __func__, buffer ); - - for( ofs = buffer + 1; *ofs; ofs++ ) { - if( *ofs == '/' ) { - // create the directory - *ofs = 0; - Sys_Mkdir( buffer ); - *ofs = '/'; - } - } + FS_DPrintf( "%s: %s\n", __func__, buffer ); + + for( ofs = buffer + 1; *ofs; ofs++ ) { + if( *ofs == '/' ) { + // create the directory + *ofs = 0; + Q_mkdir( buffer ); + *ofs = '/'; + } + } } qboolean FS_FilterFile( fileHandle_t f ) { #if USE_ZLIB - fsFile_t *file = FS_FileForHandle( f ); + fsFile_t *file = FS_FileForHandle( f ); int mode; char *modeStr; - void *zfp; + void *zfp; switch( file->type ) { case FS_GZIP: @@ -368,17 +418,17 @@ qboolean FS_FilterFile( fileHandle_t f ) { return qfalse; } - mode = file->mode & FS_MODE_MASK; - switch( mode ) { - case FS_MODE_READ: + mode = file->mode & FS_MODE_MASK; + switch( mode ) { + case FS_MODE_READ: modeStr = "rb"; break; - case FS_MODE_WRITE: - modeStr = "wb"; - break; - default: + case FS_MODE_WRITE: + modeStr = "wb"; + break; + default: return qfalse; - } + } fseek( file->fp, 0, SEEK_SET ); zfp = gzdopen( fileno( file->fp ), modeStr ); @@ -401,43 +451,43 @@ FS_FCloseFile ============== */ void FS_FCloseFile( fileHandle_t f ) { - fsFile_t *file = FS_FileForHandle( f ); - - FS_DPrintf( "%s: %s\n", __func__, file->fullpath ); - - switch( file->type ) { - case FS_REAL: - fclose( file->fp ); - break; - case FS_PAK: - if( file->unique ) { - fclose( file->fp ); - } - break; + fsFile_t *file = FS_FileForHandle( f ); + + FS_DPrintf( "%s: %s\n", __func__, file->fullpath ); + + switch( file->type ) { + case FS_REAL: + fclose( file->fp ); + break; + case FS_PAK: + if( file->unique ) { + fclose( file->fp ); + } + break; #if USE_ZLIB - case FS_GZIP: - gzclose( file->zfp ); - break; - case FS_PK2: - unzCloseCurrentFile( file->zfp ); - if( file->unique ) { - unzClose( file->zfp ); - } - break; + case FS_GZIP: + gzclose( file->zfp ); + break; + case FS_PK2: + unzCloseCurrentFile( file->zfp ); + if( file->unique ) { + unzClose( file->zfp ); + } + break; #endif - default: - break; - } + default: + break; + } - // don't clear name and mode, in case + // don't clear name and mode, in case // this handle will be reopened later - file->type = FS_FREE; - file->fp = NULL; + file->type = FS_FREE; + file->fp = NULL; #if USE_ZLIB - file->zfp = NULL; + file->zfp = NULL; #endif - file->pak = NULL; - file->unique = qfalse; + file->pak = NULL; + file->unique = qfalse; } /* @@ -446,49 +496,54 @@ FS_FOpenFileWrite ============ */ static size_t FS_FOpenFileWrite( fsFile_t *file, const char *name ) { - FILE *fp; - char *modeStr; - unsigned mode; + FILE *fp; + char *modeStr; + unsigned mode; - if( ( file->mode & FS_PATH_MASK ) == FS_PATH_BASE ) { + if( !FS_ValidatePath( name ) ) { + FS_DPrintf( "%s: refusing invalid path: %s\n", __func__, name ); + return INVALID_LENGTH; + } + + if( ( file->mode & FS_PATH_MASK ) == FS_PATH_BASE ) { if( sys_homedir->string[0] ) { - Q_concat( file->fullpath, sizeof( file->fullpath ), - sys_homedir->string, "/" BASEGAME "/", name, NULL ); + Q_concat( file->fullpath, sizeof( file->fullpath ), + sys_homedir->string, "/" BASEGAME "/", name, NULL ); } else { - Q_concat( file->fullpath, sizeof( file->fullpath ), - sys_basedir->string, "/" BASEGAME "/", name, NULL ); - } - } else { - Q_concat( file->fullpath, sizeof( file->fullpath ), - fs_gamedir, "/", name, NULL ); - } - - mode = file->mode & FS_MODE_MASK; - switch( mode ) { - case FS_MODE_APPEND: - modeStr = "ab"; - break; - case FS_MODE_WRITE: - modeStr = "wb"; - break; - case FS_MODE_RDWR: - modeStr = "r+b"; - break; - default: - Com_Error( ERR_FATAL, "%s: %s: invalid mode mask", + Q_concat( file->fullpath, sizeof( file->fullpath ), + sys_basedir->string, "/" BASEGAME "/", name, NULL ); + } + } else { + Q_concat( file->fullpath, sizeof( file->fullpath ), + fs_gamedir, "/", name, NULL ); + } + + mode = file->mode & FS_MODE_MASK; + switch( mode ) { + case FS_MODE_APPEND: + modeStr = "ab"; + break; + case FS_MODE_WRITE: + modeStr = "wb"; + break; + case FS_MODE_RDWR: + modeStr = "r+b"; + break; + default: + Com_Error( ERR_FATAL, "%s: %s: invalid mode mask", __func__, file->fullpath ); - modeStr = NULL; - break; - } + modeStr = NULL; + break; + } - FS_CreatePath( file->fullpath ); + FS_CreatePath( file->fullpath ); - fp = fopen( file->fullpath, modeStr ); - if( !fp ) { - FS_DPrintf( "%s: %s: fopen(%s): %s\n", - __func__, file->fullpath, modeStr, strerror( errno ) ); - return INVALID_LENGTH; - } + fp = fopen( file->fullpath, modeStr ); + if( !fp ) { + FS_DPrintf( "%s: %s: fopen(%s): %s\n", + __func__, file->fullpath, modeStr, strerror( errno ) ); + return INVALID_LENGTH; + } #ifdef __unix__ if( !Sys_GetFileInfo( fp, NULL ) ) { @@ -499,22 +554,88 @@ static size_t FS_FOpenFileWrite( fsFile_t *file, const char *name ) { } #endif - FS_DPrintf( "%s: %s: succeeded\n", __func__, file->fullpath ); + FS_DPrintf( "%s: %s: succeeded\n", __func__, file->fullpath ); + + file->fp = fp; + file->type = FS_REAL; + file->length = 0; + file->unique = qtrue; + + if( mode == FS_MODE_WRITE ) { + return 0; + } + + if( mode == FS_MODE_RDWR ) { + fseek( fp, 0, SEEK_END ); + } + + return ( size_t )ftell( fp ); +} + +static size_t FS_FOpenFromPak( fsFile_t *file, pack_t *pak, packfile_t *entry, qboolean unique ) { + // found it! + fs_fileFromPak = qtrue; + + Q_concat( file->fullpath, sizeof( file->fullpath ), + pak->filename, "/", entry->name, NULL ); + + // open a new file on the pakfile +#if USE_ZLIB + if( pak->zFile ) { + void *zfp; + + if( unique ) { + zfp = unzReOpen( pak->filename, pak->zFile ); + if( !zfp ) { + Com_Error( ERR_FATAL, "%s: couldn't reopen %s", + __func__, pak->filename ); + } + } else { + zfp = pak->zFile; + } + if( unzSetCurrentFileInfoPosition( zfp, entry->filepos ) == -1 ) { + Com_Error( ERR_FATAL, "%s: couldn't seek into %s", + __func__, pak->filename ); + } + if( unzOpenCurrentFile( zfp ) != UNZ_OK ) { + Com_Error( ERR_FATAL, "%s: couldn't open curfile from %s", + __func__, pak->filename ); + } + + file->zfp = zfp; + file->type = FS_PK2; + } else +#endif + { + FILE *fp; + + if( unique ) { + fp = fopen( pak->filename, "rb" ); + if( !fp ) { + Com_Error( ERR_FATAL, "%s: couldn't reopen %s", + __func__, pak->filename ); + } + } else { + fp = pak->fp; + } + + if( fseek( fp, entry->filepos, SEEK_SET ) == -1 ) { + Com_Error( ERR_FATAL, "%s: couldn't seek into %s", + __func__, pak->filename ); + } + + file->fp = fp; + file->type = FS_PAK; + } - file->fp = fp; - file->type = FS_REAL; - file->length = 0; - file->unique = qtrue; + file->pak = entry; + file->length = entry->filelen; + file->unique = unique; - if( mode == FS_MODE_WRITE ) { - return 0; - } + FS_DPrintf( "%s: %s/%s: succeeded\n", + __func__, pak->filename, entry->name ); - if( mode == FS_MODE_RDWR ) { - fseek( fp, 0, SEEK_END ); - } - - return ( size_t )ftell( fp ); + return file->length; } /* @@ -530,105 +651,65 @@ a seperate file. */ static size_t FS_FOpenFileRead( fsFile_t *file, const char *name, qboolean unique ) { searchpath_t *search; - pack_t *pak; - unsigned hash; - packfile_t *entry; - FILE *fp; + pack_t *pak; + unsigned hash; + packfile_t *entry; + FILE *fp; fsFileInfo_t info; + int valid = -1; - fs_fileFromPak = qfalse; + fs_fileFromPak = qfalse; fs_count_read++; // // search through the path, one element at a time // - hash = Com_HashPath( name, 0 ); - - for( search = fs_searchpaths; search; search = search->next ) { - if( file->mode & FS_PATH_MASK ) { - if( ( file->mode & search->mode & FS_PATH_MASK ) == 0 ) { - continue; - } - } - - // is the element a pak file? - if( search->pack ) { - if( ( file->mode & FS_TYPE_MASK ) == FS_TYPE_REAL ) { - continue; - } - // look through all the pak file elements - pak = search->pack; - entry = pak->fileHash[ hash & ( pak->hashSize - 1 ) ]; - for( ; entry; entry = entry->hashNext ) { - fs_count_strcmp++; - if( !Q_stricmp( entry->name, name ) ) { - // found it! - fs_fileFromPak = qtrue; - - Q_concat( file->fullpath, sizeof( file->fullpath ), pak->filename, "/", entry->name, NULL ); + hash = Com_HashPath( name, 0 ); - // open a new file on the pakfile -#if USE_ZLIB - if( pak->zFile ) { - void *zfp; - - if( unique ) { - zfp = unzReOpen( pak->filename, pak->zFile ); - if( !zfp ) { - Com_Error( ERR_FATAL, "%s: %s: unzReOpen failed", __func__, pak->filename ); - } - } else { - zfp = pak->zFile; - } - if( unzSetCurrentFileInfoPosition( zfp, entry->filepos ) == -1 ) { - Com_Error( ERR_FATAL, "%s: %s/%s: unzSetCurrentFileInfoPosition failed", __func__, pak->filename, entry->name ); - } - if( unzOpenCurrentFile( zfp ) != UNZ_OK ) { - Com_Error( ERR_FATAL, "%s: %s/%s: unzReOpen failed", __func__, pak->filename, entry->name ); - } - - file->zfp = zfp; - file->type = FS_PK2; - } else -#endif - { - if( unique ) { - fp = fopen( pak->filename, "rb" ); - if( !fp ) { - Com_Error( ERR_FATAL, "%s: couldn't reopen %s", __func__, pak->filename ); - } - } else { - fp = pak->fp; - } - - fseek( fp, entry->filepos, SEEK_SET ); - - file->fp = fp; - file->type = FS_PAK; - } - - file->pak = entry; - file->length = entry->filelen; - file->unique = unique; - - FS_DPrintf( "%s: %s/%s: succeeded\n", __func__, pak->filename, entry->name ); - - return file->length; - } - } - } else { - if( ( file->mode & FS_TYPE_MASK ) == FS_TYPE_PAK ) { - continue; - } - // check a file in the directory tree - Q_concat( file->fullpath, sizeof( file->fullpath ), - search->filename, "/", name, NULL ); + for( search = fs_searchpaths; search; search = search->next ) { + if( file->mode & FS_PATH_MASK ) { + if( ( file->mode & search->mode & FS_PATH_MASK ) == 0 ) { + continue; + } + } + + // is the element a pak file? + if( search->pack ) { + if( ( file->mode & FS_TYPE_MASK ) == FS_TYPE_REAL ) { + continue; + } + // look through all the pak file elements + pak = search->pack; + entry = pak->fileHash[ hash & ( pak->hashSize - 1 ) ]; + for( ; entry; entry = entry->hashNext ) { + fs_count_strcmp++; + if( !FS_pathcmp( entry->name, name ) ) { + return FS_FOpenFromPak( file, pak, entry, unique ); + } + } + } else { + if( ( file->mode & FS_TYPE_MASK ) == FS_TYPE_PAK ) { + continue; + } + if( valid == -1 ) { + if( !FS_ValidatePath( name ) ) { + FS_DPrintf( "%s: refusing invalid path: %s\n", + __func__, name ); + valid = 0; + } + } + if( valid == 0 ) { + continue; + } + // check a file in the directory tree + Q_concat( file->fullpath, sizeof( file->fullpath ), + search->filename, "/", name, NULL ); fs_count_open++; - fp = fopen( file->fullpath, "rb" ); - if( !fp ) { - continue; - } + fp = fopen( file->fullpath, "rb" ); + if( !fp ) { + continue; + } if( !Sys_GetFileInfo( fp, &info ) ) { FS_DPrintf( "%s: %s: couldn't get info\n", @@ -637,20 +718,20 @@ static size_t FS_FOpenFileRead( fsFile_t *file, const char *name, qboolean uniqu continue; } - file->fp = fp; - file->type = FS_REAL; - file->unique = qtrue; - file->length = info.size; + file->fp = fp; + file->type = FS_REAL; + file->unique = qtrue; + file->length = info.size; - FS_DPrintf( "%s: %s: succeeded\n", __func__, file->fullpath ); + FS_DPrintf( "%s: %s: succeeded\n", __func__, file->fullpath ); - return file->length; - } - } - - FS_DPrintf( "%s: %s: not found\n", __func__, name ); - - return INVALID_LENGTH; + return file->length; + } + } + + FS_DPrintf( "%s: %s: not found\n", __func__, name ); + + return INVALID_LENGTH; } /* @@ -659,7 +740,7 @@ FS_LastFileFromPak ================= */ qboolean FS_LastFileFromPak( void ) { - return fs_fileFromPak; + return fs_fileFromPak; } @@ -671,51 +752,51 @@ Properly handles partial reads ================= */ size_t FS_Read( void *buffer, size_t len, fileHandle_t hFile ) { - size_t block, remaining = len, read = 0; - byte *buf = (byte *)buffer; - fsFile_t *file = FS_FileForHandle( hFile ); - - // read in chunks for progress bar - while( remaining ) { - block = remaining; - if( block > MAX_READ ) - block = MAX_READ; - switch( file->type ) { - case FS_REAL: - case FS_PAK: - read = fread( buf, 1, block, file->fp ); - break; + size_t block, remaining = len, read = 0; + byte *buf = (byte *)buffer; + fsFile_t *file = FS_FileForHandle( hFile ); + + // read in chunks for progress bar + while( remaining ) { + block = remaining; + if( block > MAX_READ ) + block = MAX_READ; + switch( file->type ) { + case FS_REAL: + case FS_PAK: + read = fread( buf, 1, block, file->fp ); + break; #if USE_ZLIB - case FS_GZIP: - read = gzread( file->zfp, buf, block ); - break; - case FS_PK2: - read = unzReadCurrentFile( file->zfp, buf, block ); - break; + case FS_GZIP: + read = gzread( file->zfp, buf, block ); + break; + case FS_PK2: + read = unzReadCurrentFile( file->zfp, buf, block ); + break; #endif - default: - break; - } - if( read == 0 ) { - return len - remaining; - } - if( read > block ) { - Com_Error( ERR_FATAL, "FS_Read: %"PRIz" bytes read", read ); + default: + break; + } + if( read == 0 ) { + return len - remaining; + } + if( read > block ) { + Com_Error( ERR_FATAL, "FS_Read: %"PRIz" bytes read", read ); } - remaining -= read; - buf += read; - } + remaining -= read; + buf += read; + } - return len; + return len; } size_t FS_ReadLine( fileHandle_t f, char *buffer, int size ) { - fsFile_t *file = FS_FileForHandle( f ); + fsFile_t *file = FS_FileForHandle( f ); char *s; size_t len; - if( file->type != FS_REAL ) { + if( file->type != FS_REAL ) { return 0; } do { @@ -731,7 +812,7 @@ size_t FS_ReadLine( fileHandle_t f, char *buffer, int size ) { } void FS_Flush( fileHandle_t f ) { - fsFile_t *file = FS_FileForHandle( f ); + fsFile_t *file = FS_FileForHandle( f ); switch( file->type ) { case FS_REAL: @@ -755,55 +836,55 @@ Properly handles partial writes ================= */ size_t FS_Write( const void *buffer, size_t len, fileHandle_t hFile ) { - size_t block, remaining = len, write = 0; - byte *buf = (byte *)buffer; - fsFile_t *file = FS_FileForHandle( hFile ); - - // read in chunks for progress bar - while( remaining ) { - block = remaining; - if( block > MAX_WRITE ) - block = MAX_WRITE; - switch( file->type ) { - case FS_REAL: - write = fwrite( buf, 1, block, file->fp ); - break; + size_t block, remaining = len, write = 0; + byte *buf = (byte *)buffer; + fsFile_t *file = FS_FileForHandle( hFile ); + + // read in chunks for progress bar + while( remaining ) { + block = remaining; + if( block > MAX_WRITE ) + block = MAX_WRITE; + switch( file->type ) { + case FS_REAL: + write = fwrite( buf, 1, block, file->fp ); + break; #if USE_ZLIB - case FS_GZIP: - write = gzwrite( file->zfp, buf, block ); - break; + case FS_GZIP: + write = gzwrite( file->zfp, buf, block ); + break; #endif - default: - Com_Error( ERR_FATAL, "FS_Write: illegal file type" ); - break; - } - if( write == 0 ) { - return len - remaining; - } - if( write > block ) { - Com_Error( ERR_FATAL, "FS_Write: %"PRIz" bytes written", write ); - } - - remaining -= write; - buf += write; - } - - if( ( file->mode & FS_FLUSH_MASK ) == FS_FLUSH_SYNC ) { - switch( file->type ) { - case FS_REAL: - fflush( file->fp ); - break; + default: + Com_Error( ERR_FATAL, "FS_Write: illegal file type" ); + break; + } + if( write == 0 ) { + return len - remaining; + } + if( write > block ) { + Com_Error( ERR_FATAL, "FS_Write: %"PRIz" bytes written", write ); + } + + remaining -= write; + buf += write; + } + + if( ( file->mode & FS_FLUSH_MASK ) == FS_FLUSH_SYNC ) { + switch( file->type ) { + case FS_REAL: + fflush( file->fp ); + break; #if USE_ZLIB - case FS_GZIP: - gzflush( file->zfp, Z_SYNC_FLUSH ); - break; + case FS_GZIP: + gzflush( file->zfp, Z_SYNC_FLUSH ); + break; #endif - default: - break; - } - } + default: + break; + } + } - return len; + return len; } static char *FS_ExpandLinks( const char *filename ) { @@ -816,7 +897,7 @@ static char *FS_ExpandLinks( const char *filename ) { if( l->namelen > length ) { continue; } - if( !Q_stricmpn( l->name, filename, l->namelen ) ) { + if( !FS_pathcmpn( l->name, filename, l->namelen ) ) { if( l->targlen + length - l->namelen >= MAX_OSPATH ) { FS_DPrintf( "%s: %s: MAX_OSPATH exceeded\n", __func__, filename ); return ( char * )filename; @@ -838,19 +919,19 @@ FS_FOpenFile ============ */ size_t FS_FOpenFile( const char *name, fileHandle_t *f, int mode ) { - fsFile_t *file; - fileHandle_t hFile; - size_t ret = INVALID_LENGTH; + fsFile_t *file; + fileHandle_t hFile; + size_t ret = INVALID_LENGTH; - if( !name || !f ) { - Com_Error( ERR_FATAL, "FS_FOpenFile: NULL" ); - } + if( !name || !f ) { + Com_Error( ERR_FATAL, "%s: NULL", __func__ ); + } - *f = 0; + *f = 0; - if( !fs_searchpaths ) { - return ret; // not yet initialized - } + if( !fs_searchpaths ) { + return ret; // not yet initialized + } if( *name == '/' ) { name++; @@ -860,36 +941,31 @@ size_t FS_FOpenFile( const char *name, fileHandle_t *f, int mode ) { name = FS_ExpandLinks( name ); } - if( !FS_ValidatePath( name ) ) { - FS_DPrintf( "FS_FOpenFile: refusing invalid path: %s\n", name ); - return ret; - } + // allocate new file handle + file = FS_AllocHandle( &hFile ); + file->mode = mode; - // allocate new file handle - file = FS_AllocHandle( &hFile ); - file->mode = mode; - - mode &= FS_MODE_MASK; - switch( mode ) { - case FS_MODE_READ: - ret = FS_FOpenFileRead( file, name, qtrue ); - break; - case FS_MODE_WRITE: - case FS_MODE_APPEND: - case FS_MODE_RDWR: - ret = FS_FOpenFileWrite( file, name ); - break; - default: - Com_Error( ERR_FATAL, "FS_FOpenFile: illegal mode: %u", mode ); - break; - } + mode &= FS_MODE_MASK; + switch( mode ) { + case FS_MODE_READ: + ret = FS_FOpenFileRead( file, name, qtrue ); + break; + case FS_MODE_WRITE: + case FS_MODE_APPEND: + case FS_MODE_RDWR: + ret = FS_FOpenFileWrite( file, name ); + break; + default: + Com_Error( ERR_FATAL, "%s: illegal mode: %u", __func__, mode ); + break; + } - // if succeeded, store file handle - if( ret != -1 ) { - *f = hFile; - } + // if succeeded, store file handle + if( ret != -1 ) { + *f = hFile; + } - return ret; + return ret; } @@ -899,30 +975,30 @@ FS_Tell ============ */ int FS_Tell( fileHandle_t f ) { - fsFile_t *file = FS_FileForHandle( f ); - int length; - - switch( file->type ) { - case FS_REAL: - length = ftell( file->fp ); - break; - case FS_PAK: - length = ftell( file->fp ) - file->pak->filepos; - break; + fsFile_t *file = FS_FileForHandle( f ); + int length; + + switch( file->type ) { + case FS_REAL: + length = ftell( file->fp ); + break; + case FS_PAK: + length = ftell( file->fp ) - file->pak->filepos; + break; #if USE_ZLIB - case FS_GZIP: - length = gztell( file->zfp ); - break; - case FS_PK2: - length = unztell( file->zfp ); - break; + case FS_GZIP: + length = gztell( file->zfp ); + break; + case FS_PK2: + length = unztell( file->zfp ); + break; #endif - default: - length = -1; - break; - } + default: + length = -1; + break; + } - return length; + return length; } /* @@ -931,33 +1007,33 @@ FS_RawTell ============ */ int FS_RawTell( fileHandle_t f ) { - fsFile_t *file = FS_FileForHandle( f ); - int length; - - switch( file->type ) { - case FS_REAL: - length = ftell( file->fp ); - break; - case FS_PAK: - length = ftell( file->fp ) - file->pak->filepos; - break; + fsFile_t *file = FS_FileForHandle( f ); + int length; + + switch( file->type ) { + case FS_REAL: + length = ftell( file->fp ); + break; + case FS_PAK: + length = ftell( file->fp ) - file->pak->filepos; + break; #if USE_ZLIB - case FS_GZIP: - length = ftell( file->fp ); - break; - case FS_PK2: - length = unztell( file->zfp ); - break; + case FS_GZIP: + length = ftell( file->fp ); + break; + case FS_PK2: + length = unztell( file->zfp ); + break; #endif - default: - length = -1; - break; - } + default: + length = -1; + break; + } - return length; + return length; } -#define MAX_LOAD_BUFFER 0x100000 // 1 MiB +#define MAX_LOAD_BUFFER 0x100000 // 1 MiB // static buffer for small, stacked file loads and temp allocations // the last allocation may be easily undone @@ -980,22 +1056,22 @@ a null buffer will just return the file length without loading ============ */ size_t FS_LoadFileEx( const char *path, void **buffer, int flags, memtag_t tag ) { - fsFile_t *file; - fileHandle_t f; - byte *buf; - size_t len; + fsFile_t *file; + fileHandle_t f; + byte *buf; + size_t len; - if( !path ) { - Com_Error( ERR_FATAL, "FS_LoadFile: NULL" ); - } + if( !path ) { + Com_Error( ERR_FATAL, "%s: NULL", __func__ ); + } - if( buffer ) { - *buffer = NULL; - } + if( buffer ) { + *buffer = NULL; + } - if( !fs_searchpaths ) { - return INVALID_LENGTH; // not yet initialized - } + if( !fs_searchpaths ) { + return INVALID_LENGTH; // not yet initialized + } if( *path == '/' ) { path++; @@ -1003,23 +1079,18 @@ size_t FS_LoadFileEx( const char *path, void **buffer, int flags, memtag_t tag ) path = FS_ExpandLinks( path ); - if( !FS_ValidatePath( path ) ) { - FS_DPrintf( "FS_LoadFile: refusing invalid path: %s\n", path ); - return INVALID_LENGTH; - } + // allocate new file handle + file = FS_AllocHandle( &f ); + flags &= ~FS_MODE_MASK; + file->mode = flags | FS_MODE_READ; - // allocate new file handle - file = FS_AllocHandle( &f ); - flags &= ~FS_MODE_MASK; - file->mode = flags | FS_MODE_READ; - - // look for it in the filesystem or pack files - len = FS_FOpenFileRead( file, path, qfalse ); - if( len == INVALID_LENGTH ) { - return len; - } + // look for it in the filesystem or pack files + len = FS_FOpenFileRead( file, path, qfalse ); + if( len == INVALID_LENGTH ) { + return len; + } - if( buffer ) { + if( buffer ) { #if USE_ZLIB if( file->type == FS_GZIP ) { len = INVALID_LENGTH; // unknown length @@ -1035,7 +1106,7 @@ size_t FS_LoadFileEx( const char *path, void **buffer, int flags, memtag_t tag ) *buffer = buf; buf[len] = 0; } else { - Com_EPrintf( "FS_LoadFile: error reading file: %s\n", path ); + Com_EPrintf( "%s: error reading file: %s\n", __func__, path ); if( tag == TAG_FREE ) { FS_FreeFile( buf ); } else { @@ -1044,15 +1115,15 @@ size_t FS_LoadFileEx( const char *path, void **buffer, int flags, memtag_t tag ) len = INVALID_LENGTH; } } - } + } - FS_FCloseFile( f ); + FS_FCloseFile( f ); - return len; + return len; } size_t FS_LoadFile( const char *path, void **buffer ) { - return FS_LoadFileEx( path, buffer, 0, TAG_FREE ); + return FS_LoadFileEx( path, buffer, 0, TAG_FREE ); } void *FS_AllocTempMem( size_t length ) { @@ -1069,7 +1140,7 @@ void *FS_AllocTempMem( size_t length ) { } else { // Com_Printf(S_COLOR_MAGENTA"alloc %d\n",length); buf = FS_Malloc( length ); - loadCount++; + loadCount++; } return buf; } @@ -1080,24 +1151,24 @@ FS_FreeFile ============= */ void FS_FreeFile( void *buffer ) { - if( !buffer ) { - Com_Error( ERR_FATAL, "FS_FreeFile: NULL" ); - } - if( ( byte * )buffer >= loadBuffer && ( byte * )buffer < loadBuffer + MAX_LOAD_BUFFER ) { - if( loadStack == 0 ) { - Com_Error( ERR_FATAL, "FS_FreeFile: loadStack is zero" ); - } - loadStack--; - if( loadStack == 0 ) { - loadInuse = 0; + if( !buffer ) { + Com_Error( ERR_FATAL, "%s: NULL", __func__ ); + } + if( ( byte * )buffer >= loadBuffer && ( byte * )buffer < loadBuffer + MAX_LOAD_BUFFER ) { + if( loadStack == 0 ) { + Com_Error( ERR_FATAL, "%s: empty load stack", __func__ ); + } + loadStack--; + if( loadStack == 0 ) { + loadInuse = 0; // Com_Printf(S_COLOR_MAGENTA"clear\n"); - } else if( buffer == loadLast ) { + } else if( buffer == loadLast ) { loadInuse = loadSaved; // Com_Printf(S_COLOR_MAGENTA"partial\n"); } - } else { - Z_Free( buffer ); - } + } else { + Z_Free( buffer ); + } } /* @@ -1106,43 +1177,41 @@ FS_CopyFile ============= */ qboolean FS_CopyFile( const char *src, const char *dst ) { - fileHandle_t hSrc, hDst; - byte buffer[MAX_READ]; - size_t len, size; + fileHandle_t hSrc, hDst; + byte buffer[MAX_READ]; + size_t len, size; - FS_DPrintf( "FS_CopyFile( '%s', '%s' )\n", src, dst ); - - size = FS_FOpenFile( src, &hSrc, FS_MODE_READ ); - if( !hSrc ) { - return qfalse; - } + size = FS_FOpenFile( src, &hSrc, FS_MODE_READ ); + if( !hSrc ) { + return qfalse; + } - FS_FOpenFile( dst, &hDst, FS_MODE_WRITE ); - if( !hDst ) { - FS_FCloseFile( hSrc ); - return qfalse; - } + FS_FOpenFile( dst, &hDst, FS_MODE_WRITE ); + if( !hDst ) { + FS_FCloseFile( hSrc ); + return qfalse; + } - while( size ) { - len = size; - if( len > sizeof( buffer ) ) { - len = sizeof( buffer ); - } - if( !( len = FS_Read( buffer, len, hSrc ) ) ) { - break; - } - FS_Write( buffer, len, hDst ); - size -= len; - } + while( size ) { + len = size; + if( len > sizeof( buffer ) ) { + len = sizeof( buffer ); + } + if( !( len = FS_Read( buffer, len, hSrc ) ) ) { + break; + } + FS_Write( buffer, len, hDst ); + size -= len; + } - FS_FCloseFile( hSrc ); - FS_FCloseFile( hDst ); + FS_FCloseFile( hSrc ); + FS_FCloseFile( hDst ); - if( size ) { - return qfalse; - } + if( size ) { + return qfalse; + } - return qtrue; + return qtrue; } /* @@ -1151,25 +1220,25 @@ FS_RemoveFile ================ */ qboolean FS_RemoveFile( const char *filename ) { - char path[MAX_OSPATH]; + char path[MAX_OSPATH]; if( *filename == '/' ) { filename++; } - if( !FS_ValidatePath( filename ) ) { - FS_DPrintf( "FS_RemoveFile: refusing invalid path: %s\n", filename ); - return qfalse; - } + if( !FS_ValidatePath( filename ) ) { + FS_DPrintf( "%s: refusing invalid path: %s\n", __func__, filename ); + return qfalse; + } - Q_concat( path, sizeof( path ), fs_gamedir, "/", filename, NULL ); - //FS_ConvertToSysPath( path ); + Q_concat( path, sizeof( path ), fs_gamedir, "/", filename, NULL ); + //FS_ConvertToSysPath( path ); - if( !Sys_RemoveFile( path ) ) { - return qfalse; - } + if( Q_unlink( path ) ) { + return qfalse; + } - return qtrue; + return qtrue; } /* @@ -1178,8 +1247,8 @@ FS_RemoveFile ================ */ qboolean FS_RenameFile( const char *from, const char *to ) { - char frompath[MAX_OSPATH]; - char topath[MAX_OSPATH]; + char frompath[MAX_OSPATH]; + char topath[MAX_OSPATH]; if( *from == '/' ) { from++; @@ -1188,20 +1257,22 @@ qboolean FS_RenameFile( const char *from, const char *to ) { to++; } - if( !FS_ValidatePath( from ) || !FS_ValidatePath( to ) ) { - FS_DPrintf( "FS_RenameFile: refusing invalid path: %s to %s\n", from, to ); - return qfalse; - } + if( !FS_ValidatePath( from ) || !FS_ValidatePath( to ) ) { + FS_DPrintf( "%s: refusing invalid path: %s to %s\n", + __func__, from, to ); + return qfalse; + } - Q_concat( frompath, sizeof( frompath ), fs_gamedir, "/", from, NULL ); - Q_concat( topath, sizeof( topath ), fs_gamedir, "/", to, NULL ); + Q_concat( frompath, sizeof( frompath ), fs_gamedir, "/", from, NULL ); + Q_concat( topath, sizeof( topath ), fs_gamedir, "/", to, NULL ); - if( !Sys_RenameFile( frompath, topath ) ) { - FS_DPrintf( "FS_RenameFile: rename failed: %s to %s\n", frompath, topath ); - return qfalse; - } + if( rename( frompath, topath ) ) { + FS_DPrintf( "%s: rename failed: %s to %s\n", + __func__, frompath, topath ); + return qfalse; + } - return qtrue; + return qtrue; } /* @@ -1210,15 +1281,15 @@ FS_FPrintf ================ */ void FS_FPrintf( fileHandle_t f, const char *format, ... ) { - va_list argptr; - char string[MAXPRINTMSG]; - size_t len; + va_list argptr; + char string[MAXPRINTMSG]; + size_t len; - va_start( argptr, format ); - len = Q_vsnprintf( string, sizeof( string ), format, argptr ); - va_end( argptr ); + va_start( argptr, format ); + len = Q_vsnprintf( string, sizeof( string ), format, argptr ); + va_end( argptr ); - FS_Write( string, len, f ); + FS_Write( string, len, f ); } /* @@ -1232,114 +1303,114 @@ of the list so they override previous pack files. ================= */ static pack_t *FS_LoadPakFile( const char *packfile ) { - dpackheader_t header; - int i; - packfile_t *file; - dpackfile_t *dfile; - int numpackfiles; - char *names; - size_t namesLength; - pack_t *pack; - FILE *packhandle; - dpackfile_t info[MAX_FILES_IN_PACK]; - int hashSize; - unsigned hash; - size_t len; - - packhandle = fopen( packfile, "rb" ); - if( !packhandle ) { - Com_WPrintf( "Couldn't open %s\n", packfile ); - return NULL; - } - - if( fread( &header, 1, sizeof( header ), packhandle ) != sizeof( header ) ) { - Com_WPrintf( "Reading header failed on %s\n", packfile ); - goto fail; - } - - if( LittleLong( header.ident ) != IDPAKHEADER ) { - Com_WPrintf( "%s is not a 'PACK' file\n", packfile ); - goto fail; - } - - header.dirlen = LittleLong( header.dirlen ); - if( header.dirlen % sizeof( dpackfile_t ) ) { - Com_WPrintf( "%s has bad directory length\n", packfile ); - goto fail; - } - - numpackfiles = header.dirlen / sizeof( dpackfile_t ); - if( numpackfiles < 1 ) { - Com_WPrintf( "%s has bad number of files: %i\n", packfile, numpackfiles ); - goto fail; - } - if( numpackfiles > MAX_FILES_IN_PACK ) { - Com_WPrintf( "%s has too many files: %i > %i\n", packfile, numpackfiles, MAX_FILES_IN_PACK ); - goto fail; - } - - header.dirofs = LittleLong( header.dirofs ); - if( fseek( packhandle, header.dirofs, SEEK_SET ) ) { - Com_WPrintf( "Seeking to directory failed on %s\n", packfile ); - goto fail; - } - if( fread( info, 1, header.dirlen, packhandle ) != header.dirlen ) { - Com_WPrintf( "Reading directory failed on %s\n", packfile ); - goto fail; - } - - namesLength = 0; - for( i = 0, dfile = info; i < numpackfiles; i++, dfile++ ) { - dfile->name[sizeof( dfile->name ) - 1] = 0; - namesLength += strlen( dfile->name ) + 1; - } - - hashSize = Q_CeilPowerOfTwo( numpackfiles ); - if( hashSize > 32 ) { - hashSize >>= 1; - } - - len = strlen( packfile ); - len = ( len + 3 ) & ~3; - pack = FS_Malloc( sizeof( pack_t ) + - numpackfiles * sizeof( packfile_t ) + - hashSize * sizeof( packfile_t * ) + - namesLength + len ); - strcpy( pack->filename, packfile ); - pack->fp = packhandle; + dpackheader_t header; + int i; + packfile_t *file; + dpackfile_t *dfile; + int numpackfiles; + char *names; + size_t namesLength; + pack_t *pack; + FILE *packhandle; + dpackfile_t info[MAX_FILES_IN_PACK]; + int hashSize; + unsigned hash; + size_t len; + + packhandle = fopen( packfile, "rb" ); + if( !packhandle ) { + Com_WPrintf( "Couldn't open %s\n", packfile ); + return NULL; + } + + if( fread( &header, 1, sizeof( header ), packhandle ) != sizeof( header ) ) { + Com_WPrintf( "Reading header failed on %s\n", packfile ); + goto fail; + } + + if( LittleLong( header.ident ) != IDPAKHEADER ) { + Com_WPrintf( "%s is not a 'PACK' file\n", packfile ); + goto fail; + } + + header.dirlen = LittleLong( header.dirlen ); + if( header.dirlen % sizeof( dpackfile_t ) ) { + Com_WPrintf( "%s has bad directory length\n", packfile ); + goto fail; + } + + numpackfiles = header.dirlen / sizeof( dpackfile_t ); + if( numpackfiles < 1 ) { + Com_WPrintf( "%s has bad number of files: %i\n", packfile, numpackfiles ); + goto fail; + } + if( numpackfiles > MAX_FILES_IN_PACK ) { + Com_WPrintf( "%s has too many files: %i > %i\n", packfile, numpackfiles, MAX_FILES_IN_PACK ); + goto fail; + } + + header.dirofs = LittleLong( header.dirofs ); + if( fseek( packhandle, header.dirofs, SEEK_SET ) ) { + Com_WPrintf( "Seeking to directory failed on %s\n", packfile ); + goto fail; + } + if( fread( info, 1, header.dirlen, packhandle ) != header.dirlen ) { + Com_WPrintf( "Reading directory failed on %s\n", packfile ); + goto fail; + } + + namesLength = 0; + for( i = 0, dfile = info; i < numpackfiles; i++, dfile++ ) { + dfile->name[sizeof( dfile->name ) - 1] = 0; + namesLength += strlen( dfile->name ) + 1; + } + + hashSize = Q_CeilPowerOfTwo( numpackfiles ); + if( hashSize > 32 ) { + hashSize >>= 1; + } + + len = strlen( packfile ); + len = ( len + 3 ) & ~3; + pack = FS_Malloc( sizeof( pack_t ) + + numpackfiles * sizeof( packfile_t ) + + hashSize * sizeof( packfile_t * ) + + namesLength + len ); + strcpy( pack->filename, packfile ); + pack->fp = packhandle; #if USE_ZLIB - pack->zFile = NULL; + pack->zFile = NULL; #endif - pack->numfiles = numpackfiles; - pack->hashSize = hashSize; - pack->files = ( packfile_t * )( ( byte * )pack + sizeof( pack_t ) + len ); - pack->fileHash = ( packfile_t ** )( pack->files + numpackfiles ); - names = ( char * )( pack->fileHash + hashSize ); - memset( pack->fileHash, 0, hashSize * sizeof( packfile_t * ) ); + pack->numfiles = numpackfiles; + pack->hashSize = hashSize; + pack->files = ( packfile_t * )( ( byte * )pack + sizeof( pack_t ) + len ); + pack->fileHash = ( packfile_t ** )( pack->files + numpackfiles ); + names = ( char * )( pack->fileHash + hashSize ); + memset( pack->fileHash, 0, hashSize * sizeof( packfile_t * ) ); // parse the directory - for( i = 0, file = pack->files, dfile = info; i < pack->numfiles; i++, file++, dfile++ ) { - len = strlen( dfile->name ) + 1; + for( i = 0, file = pack->files, dfile = info; i < pack->numfiles; i++, file++, dfile++ ) { + len = strlen( dfile->name ) + 1; - file->name = memcpy( names, dfile->name, len ); - names += len; + file->name = memcpy( names, dfile->name, len ); + names += len; - file->filepos = LittleLong( dfile->filepos ); - file->filelen = LittleLong( dfile->filelen ); + file->filepos = LittleLong( dfile->filepos ); + file->filelen = LittleLong( dfile->filelen ); - hash = Com_HashPath( file->name, hashSize ); - file->hashNext = pack->fileHash[hash]; - pack->fileHash[hash] = file; - } + hash = Com_HashPath( file->name, hashSize ); + file->hashNext = pack->fileHash[hash]; + pack->fileHash[hash] = file; + } - FS_DPrintf( "%s: %d files, %d hash table entries\n", - packfile, numpackfiles, hashSize ); + FS_DPrintf( "%s: %d files, %d hash table entries\n", + packfile, numpackfiles, hashSize ); - return pack; + return pack; fail: - fclose( packhandle ); - return NULL; + fclose( packhandle ); + return NULL; } #if USE_ZLIB @@ -1349,110 +1420,110 @@ FS_LoadZipFile ================= */ static pack_t *FS_LoadZipFile( const char *packfile ) { - int i; - packfile_t *file; - char *names; - int numFiles; - pack_t *pack; - unzFile zFile; - unz_global_info zGlobalInfo; - unz_file_info zInfo; - char name[MAX_QPATH]; - size_t namesLength; - int hashSize; - unsigned hash; - size_t len; - - zFile = unzOpen( packfile ); - if( !zFile ) { - Com_WPrintf( "unzOpen() failed on %s\n", packfile ); - return NULL; - } - - if( unzGetGlobalInfo( zFile, &zGlobalInfo ) != UNZ_OK ) { - Com_WPrintf( "unzGetGlobalInfo() failed on %s\n", packfile ); - goto fail; - } - - numFiles = zGlobalInfo.number_entry; - if( numFiles > MAX_FILES_IN_PK2 ) { - Com_WPrintf( "%s has too many files, %i > %i\n", packfile, numFiles, MAX_FILES_IN_PK2 ); - goto fail; - } - - if( unzGoToFirstFile( zFile ) != UNZ_OK ) { - Com_WPrintf( "unzGoToFirstFile() failed on %s\n", packfile ); - goto fail; - } - - namesLength = 0; - for( i = 0; i < numFiles; i++ ) { - if( unzGetCurrentFileInfo( zFile, &zInfo, name, sizeof( name ), NULL, 0, NULL, 0 ) != UNZ_OK ) { - Com_WPrintf( "unzGetCurrentFileInfo() failed on %s\n", packfile ); - goto fail; - } - - namesLength += strlen( name ) + 1; - - if( i != numFiles - 1 && unzGoToNextFile( zFile ) != UNZ_OK ) { - Com_WPrintf( "unzGoToNextFile() failed on %s\n", packfile ); - - } - } - - hashSize = Q_CeilPowerOfTwo( numFiles ); - if( hashSize > 32 ) { - hashSize >>= 1; - } - - len = strlen( packfile ); - len = ( len + 3 ) & ~3; - pack = FS_Malloc( sizeof( pack_t ) + - numFiles * sizeof( packfile_t ) + - hashSize * sizeof( packfile_t * ) + - namesLength + len ); - strcpy( pack->filename, packfile ); - pack->zFile = zFile; - pack->fp = NULL; - pack->numfiles = numFiles; - pack->hashSize = hashSize; - pack->files = ( packfile_t * )( ( byte * )pack + sizeof( pack_t ) + len ); - pack->fileHash = ( packfile_t ** )( pack->files + numFiles ); - names = ( char * )( pack->fileHash + hashSize ); - memset( pack->fileHash, 0, hashSize * sizeof( packfile_t * ) ); + int i; + packfile_t *file; + char *names; + int numFiles; + pack_t *pack; + unzFile zFile; + unz_global_info zGlobalInfo; + unz_file_info zInfo; + char name[MAX_QPATH]; + size_t namesLength; + int hashSize; + unsigned hash; + size_t len; + + zFile = unzOpen( packfile ); + if( !zFile ) { + Com_WPrintf( "unzOpen() failed on %s\n", packfile ); + return NULL; + } + + if( unzGetGlobalInfo( zFile, &zGlobalInfo ) != UNZ_OK ) { + Com_WPrintf( "unzGetGlobalInfo() failed on %s\n", packfile ); + goto fail; + } + + numFiles = zGlobalInfo.number_entry; + if( numFiles > MAX_FILES_IN_PK2 ) { + Com_WPrintf( "%s has too many files, %i > %i\n", packfile, numFiles, MAX_FILES_IN_PK2 ); + goto fail; + } + + if( unzGoToFirstFile( zFile ) != UNZ_OK ) { + Com_WPrintf( "unzGoToFirstFile() failed on %s\n", packfile ); + goto fail; + } + + namesLength = 0; + for( i = 0; i < numFiles; i++ ) { + if( unzGetCurrentFileInfo( zFile, &zInfo, name, sizeof( name ), NULL, 0, NULL, 0 ) != UNZ_OK ) { + Com_WPrintf( "unzGetCurrentFileInfo() failed on %s\n", packfile ); + goto fail; + } + + namesLength += strlen( name ) + 1; + + if( i != numFiles - 1 && unzGoToNextFile( zFile ) != UNZ_OK ) { + Com_WPrintf( "unzGoToNextFile() failed on %s\n", packfile ); + + } + } + + hashSize = Q_CeilPowerOfTwo( numFiles ); + if( hashSize > 32 ) { + hashSize >>= 1; + } + + len = strlen( packfile ); + len = ( len + 3 ) & ~3; + pack = FS_Malloc( sizeof( pack_t ) + + numFiles * sizeof( packfile_t ) + + hashSize * sizeof( packfile_t * ) + + namesLength + len ); + strcpy( pack->filename, packfile ); + pack->zFile = zFile; + pack->fp = NULL; + pack->numfiles = numFiles; + pack->hashSize = hashSize; + pack->files = ( packfile_t * )( ( byte * )pack + sizeof( pack_t ) + len ); + pack->fileHash = ( packfile_t ** )( pack->files + numFiles ); + names = ( char * )( pack->fileHash + hashSize ); + memset( pack->fileHash, 0, hashSize * sizeof( packfile_t * ) ); // parse the directory - unzGoToFirstFile( zFile ); + unzGoToFirstFile( zFile ); - for( i = 0, file = pack->files; i < numFiles; i++, file++ ) { - unzGetCurrentFileInfo( zFile, &zInfo, name, sizeof( name ), NULL, 0, NULL, 0 ); + for( i = 0, file = pack->files; i < numFiles; i++, file++ ) { + unzGetCurrentFileInfo( zFile, &zInfo, name, sizeof( name ), NULL, 0, NULL, 0 ); - len = strlen( name ) + 1; - file->name = names; + len = strlen( name ) + 1; + file->name = names; - strcpy( file->name, name ); - file->filepos = unzGetCurrentFileInfoPosition( zFile ); - file->filelen = zInfo.uncompressed_size; + strcpy( file->name, name ); + file->filepos = unzGetCurrentFileInfoPosition( zFile ); + file->filelen = zInfo.uncompressed_size; - hash = Com_HashPath( file->name, hashSize ); - file->hashNext = pack->fileHash[hash]; - pack->fileHash[hash] = file; + hash = Com_HashPath( file->name, hashSize ); + file->hashNext = pack->fileHash[hash]; + pack->fileHash[hash] = file; - names += len; - - if( i != numFiles - 1 ) { - unzGoToNextFile( zFile ); - } - } + names += len; + + if( i != numFiles - 1 ) { + unzGoToNextFile( zFile ); + } + } - FS_DPrintf( "%s: %d files, %d hash table entries\n", - packfile, numFiles, hashSize ); + FS_DPrintf( "%s: %d files, %d hash table entries\n", + packfile, numFiles, hashSize ); - return pack; + return pack; fail: - unzClose( zFile ); - return NULL; + unzClose( zFile ); + return NULL; } #endif @@ -1460,8 +1531,8 @@ fail: // sorted in numerical order, then the rest of the paks in // alphabetical order, e.g. pak0.pak, pak2.pak, pak17.pak, abc.pak... static int QDECL pakcmp( const void *p1, const void *p2 ) { - char *s1 = *( char ** )p1; - char *s2 = *( char ** )p2; + char *s1 = *( char ** )p1; + char *s2 = *( char ** )p2; if( !FS_strncmp( s1, "pak", 3 ) ) { if( !FS_strncmp( s2, "pak", 3 ) ) { @@ -1482,36 +1553,36 @@ static int QDECL pakcmp( const void *p1, const void *p2 ) { } alphacmp: - return FS_strcmp( s1, s2 ); + return FS_strcmp( s1, s2 ); } static void FS_LoadPackFiles( int mode, const char *extension, pack_t *(loadfunc)( const char * ) ) { - int i; - searchpath_t *search; - pack_t *pak; - void **list; - int numFiles; + int i; + searchpath_t *search; + pack_t *pak; + void **list; + int numFiles; char path[MAX_OSPATH]; - list = Sys_ListFiles( fs_gamedir, extension, FS_SEARCH_NOSORT, 0, &numFiles ); - if( !list ) { - return; - } - qsort( list, numFiles, sizeof( list[0] ), pakcmp ); - for( i = 0; i < numFiles; i++ ) { + list = Sys_ListFiles( fs_gamedir, extension, FS_SEARCH_NOSORT, 0, &numFiles ); + if( !list ) { + return; + } + qsort( list, numFiles, sizeof( list[0] ), pakcmp ); + for( i = 0; i < numFiles; i++ ) { Q_concat( path, sizeof( path ), fs_gamedir, "/", list[i], NULL ); - pak = (*loadfunc)( path ); - if( !pak ) - continue; - search = FS_Malloc( sizeof( searchpath_t ) ); + pak = (*loadfunc)( path ); + if( !pak ) + continue; + search = FS_Malloc( sizeof( searchpath_t ) ); search->mode = mode; - search->filename[0] = 0; - search->pack = pak; - search->next = fs_searchpaths; - fs_searchpaths = search; - } + search->filename[0] = 0; + search->pack = pak; + search->next = fs_searchpaths; + fs_searchpaths = search; + } - FS_FreeList( list ); + FS_FreeList( list ); } /* @@ -1524,43 +1595,43 @@ then loads and adds pak*.pak, then anything else in alphabethical order. */ static void q_printf( 2, 3 ) FS_AddGameDirectory( int mode, const char *fmt, ... ) { va_list argptr; - searchpath_t *search; - size_t len; + searchpath_t *search; + size_t len; va_start( argptr, fmt ); - len = Q_vsnprintf( fs_gamedir, sizeof( fs_gamedir ), fmt, argptr ); + len = Q_vsnprintf( fs_gamedir, sizeof( fs_gamedir ), fmt, argptr ); va_end( argptr ); #ifdef _WIN32 - FS_ReplaceSeparators( fs_gamedir, '/' ); + FS_ReplaceSeparators( fs_gamedir, '/' ); #endif - // - // add the directory to the search path - // - if( !( fs_restrict_mask->integer & 1 ) ) { - search = FS_Malloc( sizeof( searchpath_t ) + len ); + // + // add the directory to the search path + // + if( !( fs_restrict_mask->integer & 1 ) ) { + search = FS_Malloc( sizeof( searchpath_t ) + len ); search->mode = mode; - search->pack = NULL; - memcpy( search->filename, fs_gamedir, len + 1 ); - search->next = fs_searchpaths; - fs_searchpaths = search; - } - - // - // add any pak files in the format *.pak - // - if( !( fs_restrict_mask->integer & 2 ) ) { - FS_LoadPackFiles( mode, ".pak", FS_LoadPakFile ); - } + search->pack = NULL; + memcpy( search->filename, fs_gamedir, len + 1 ); + search->next = fs_searchpaths; + fs_searchpaths = search; + } + + // + // add any pak files in the format *.pak + // + if( !( fs_restrict_mask->integer & 2 ) ) { + FS_LoadPackFiles( mode, ".pak", FS_LoadPakFile ); + } #if USE_ZLIB - // - // add any zip files in the format *.pkz - // - if( !( fs_restrict_mask->integer & 4 ) ) { - FS_LoadPackFiles( mode, ".pkz", FS_LoadZipFile ); - } + // + // add any zip files in the format *.pkz + // + if( !( fs_restrict_mask->integer & 4 ) ) { + FS_LoadPackFiles( mode, ".pkz", FS_LoadZipFile ); + } #endif } @@ -1570,32 +1641,32 @@ FS_CopyInfo ================= */ fsFileInfo_t *FS_CopyInfo( const char *name, size_t size, time_t ctime, time_t mtime ) { - fsFileInfo_t *out; - size_t len; + fsFileInfo_t *out; + size_t len; - if( !name ) { - return NULL; - } + if( !name ) { + return NULL; + } - len = strlen( name ); - out = FS_Mallocz( sizeof( *out ) + len ); + len = strlen( name ); + out = FS_Mallocz( sizeof( *out ) + len ); out->size = size; out->ctime = ctime; out->mtime = mtime; - memcpy( out->name, name, len + 1 ); + memcpy( out->name, name, len + 1 ); - return out; + return out; } void **FS_CopyList( void **list, int count ) { void **out; int i; - out = FS_Malloc( sizeof( void * ) * ( count + 1 ) ); - for( i = 0; i < count; i++ ) { - out[i] = list[i]; - } - out[i] = NULL; + out = FS_Malloc( sizeof( void * ) * ( count + 1 ) ); + for( i = 0; i < count; i++ ) { + out[i] = list[i]; + } + out[i] = NULL; return out; } @@ -1615,48 +1686,48 @@ static qboolean FS_WildCmp_r( const char *filter, const char *string ) { continue; } - if( *filter != '?' && Q_toupper( *filter ) != Q_toupper( *string ) ) { + if( *filter != '?' && Q_toupper( *filter ) != Q_toupper( *string ) ) { return qfalse; } filter++; string++; } - return !*string; + return !*string; } #endif static int FS_WildCmp_r( const char *filter, const char *string ) { - switch( *filter ) { - case '\0': - case ';': - return !*string; + switch( *filter ) { + case '\0': + case ';': + return !*string; - case '*': - return FS_WildCmp_r( filter + 1, string ) || (*string && FS_WildCmp_r( filter, string + 1 )); + case '*': + return FS_WildCmp_r( filter + 1, string ) || (*string && FS_WildCmp_r( filter, string + 1 )); - case '?': - return *string && FS_WildCmp_r( filter + 1, string + 1 ); + case '?': + return *string && FS_WildCmp_r( filter + 1, string + 1 ); - default: - return ((*filter == *string) || (Q_toupper( *filter ) == Q_toupper( *string ))) && FS_WildCmp_r( filter + 1, string + 1 ); - } + default: + return ((*filter == *string) || (Q_toupper( *filter ) == Q_toupper( *string ))) && FS_WildCmp_r( filter + 1, string + 1 ); + } } qboolean FS_WildCmp( const char *filter, const char *string ) { - do { - if( FS_WildCmp_r( filter, string ) ) { - return qtrue; - } - filter = strchr( filter, ';' ); - if( filter ) filter++; - } while( filter ); + do { + if( FS_WildCmp_r( filter, string ) ) { + return qtrue; + } + filter = strchr( filter, ';' ); + if( filter ) filter++; + } while( filter ); - return qfalse; + return qfalse; } qboolean FS_ExtCmp( const char *ext, const char *name ) { - int c1, c2; + int c1, c2; const char *e, *n, *l; if( !name[0] || !ext[0] ) { @@ -1704,14 +1775,14 @@ static int infocmp( const void *p1, const void *p2 ) { fsFileInfo_t *n1 = *( fsFileInfo_t ** )p1; fsFileInfo_t *n2 = *( fsFileInfo_t ** )p2; - return Q_stricmp( n1->name, n2->name ); + return FS_pathcmp( n1->name, n2->name ); } static int alphacmp( const void *p1, const void *p2 ) { char *s1 = *( char ** )p1; char *s2 = *( char ** )p2; - return Q_stricmp( s1, s2 ); + return FS_pathcmp( s1, s2 ); } /* @@ -1724,49 +1795,46 @@ void **FS_ListFiles( const char *path, int flags, int *numFiles ) { - searchpath_t *search; - void *listedFiles[MAX_LISTED_FILES]; - int count, total; - char buffer[MAX_OSPATH]; - void **dirlist; - int dircount; - void **list; - int i; - size_t len, pathlen; - char *s; - - if( flags & FS_SEARCH_BYFILTER ) { - if( !extension ) { - Com_Error( ERR_FATAL, "FS_ListFiles: NULL filter" ); - } - } - - count = 0; - - if( numFiles ) { - *numFiles = 0; - } - - if( !path ) { - path = ""; + searchpath_t *search; + void *listedFiles[MAX_LISTED_FILES]; + int count, total; + char buffer[MAX_OSPATH]; + void **dirlist; + int dircount; + void **list; + int i; + size_t len, pathlen; + char *s; + int valid = -1; + + if( flags & FS_SEARCH_BYFILTER ) { + if( !extension ) { + Com_Error( ERR_FATAL, "FS_ListFiles: NULL filter" ); + } + } + + count = 0; + + if( numFiles ) { + *numFiles = 0; + } + + if( !path ) { + path = ""; pathlen = 0; - } else { + } else { if( *path == '/' ) { path++; } - if( !FS_ValidatePath( path ) ) { - FS_DPrintf( "%s: refusing invalid path: %s\n", __func__, path ); - return NULL; - } pathlen = strlen( path ); } for( search = fs_searchpaths; search; search = search->next ) { - if( flags & FS_PATH_MASK ) { - if( ( flags & search->mode & FS_PATH_MASK ) == 0 ) { - continue; - } - } + if( flags & FS_PATH_MASK ) { + if( ( flags & search->mode & FS_PATH_MASK ) == 0 ) { + continue; + } + } if( search->pack ) { if( ( flags & FS_TYPE_MASK ) == FS_TYPE_REAL ) { // don't search in paks @@ -1784,7 +1852,7 @@ void **FS_ListFiles( const char *path, // check path if( pathlen ) { - if( Q_stricmpn( s, path, pathlen ) ) { + if( FS_pathcmpn( s, path, pathlen ) ) { continue; } s += pathlen + 1; @@ -1815,7 +1883,7 @@ void **FS_ListFiles( const char *path, s = search->pack->files[i].name; // check path - if( pathlen && Q_stricmpn( s, path, pathlen ) ) { + if( pathlen && FS_pathcmpn( s, path, pathlen ) ) { continue; } @@ -1851,6 +1919,16 @@ void **FS_ListFiles( const char *path, if( len + pathlen + 1 >= MAX_OSPATH ) { continue; } + if( valid == -1 ) { + if( !FS_ValidatePath( path ) ) { + FS_DPrintf( "%s: refusing invalid path: %s\n", + __func__, path ); + valid = 0; + } + } + if( valid == 0 ) { + continue; + } memcpy( buffer, search->filename, len ); buffer[len++] = '/'; memcpy( buffer + len, path, pathlen + 1 ); @@ -1884,9 +1962,9 @@ void **FS_ListFiles( const char *path, } } - if( !count ) { - return NULL; - } + if( !count ) { + return NULL; + } if( flags & FS_SEARCH_EXTRAINFO ) { // TODO @@ -1899,8 +1977,7 @@ void **FS_ListFiles( const char *path, // remove duplicates total = 1; for( i = 1; i < count; i++ ) { - // FIXME: use Q_stricmp instead of FS_strcmp here? - if( !Q_stricmp( listedFiles[ i - 1 ], listedFiles[i] ) ) { + if( !FS_pathcmp( listedFiles[ i - 1 ], listedFiles[i] ) ) { Z_Free( listedFiles[ i - 1 ] ); listedFiles[i-1] = NULL; } else { @@ -1909,21 +1986,21 @@ void **FS_ListFiles( const char *path, } } - list = FS_Malloc( sizeof( void * ) * ( total + 1 ) ); + list = FS_Malloc( sizeof( void * ) * ( total + 1 ) ); - total = 0; - for( i = 0; i < count; i++ ) { - if( listedFiles[i] ) { - list[total++] = listedFiles[i]; - } - } - list[total] = NULL; + total = 0; + for( i = 0; i < count; i++ ) { + if( listedFiles[i] ) { + list[total++] = listedFiles[i]; + } + } + list[total] = NULL; - if( numFiles ) { - *numFiles = total; - } + if( numFiles ) { + *numFiles = total; + } - return list; + return list; } /* @@ -1932,13 +2009,13 @@ FS_FreeList ================= */ void FS_FreeList( void **list ) { - void **p = list; + void **p = list; - while( *p ) { - Z_Free( *p++ ); - } + while( *p ) { + Z_Free( *p++ ); + } - Z_Free( list ); + Z_Free( list ); } void FS_File_g( const char *path, const char *ext, int flags, genctx_t *ctx ) { @@ -1953,10 +2030,10 @@ void FS_File_g( const char *path, const char *ext, int flags, genctx_t *ctx ) { for( i = 0; i < numFiles; i++ ) { s = list[i]; - if( flags & 0x80000000 ) { - p = COM_FileExtension( s ); - *p = 0; - } + if( flags & 0x80000000 ) { + p = COM_FileExtension( s ); + *p = 0; + } if( ctx->count < ctx->size && !strncmp( s, ctx->partial, ctx->length ) ) { ctx->matches[ctx->count++] = s; } else { @@ -1976,16 +2053,16 @@ extract file from *.pak, *.pk2 or *.gz ================= */ static void FS_CopyFile_f( void ) { - if( Cmd_Argc() < 2 ) { - Com_Printf( "Usage: %s <sourcePath> <destPath>\n", Cmd_Argv( 0 ) ); - return; - } + if( Cmd_Argc() < 2 ) { + Com_Printf( "Usage: %s <sourcePath> <destPath>\n", Cmd_Argv( 0 ) ); + return; + } - if( FS_CopyFile( Cmd_Argv( 1 ), Cmd_Argv( 2 ) ) ) { - Com_Printf( "File copied successfully\n" ); - } else { - Com_Printf( "Failed to copy file\n" ); - } + if( FS_CopyFile( Cmd_Argv( 1 ), Cmd_Argv( 2 ) ) ) { + Com_Printf( "File copied successfully\n" ); + } else { + Com_Printf( "Failed to copy file\n" ); + } } /* @@ -1994,30 +2071,30 @@ FS_FDir_f ============ */ static void FS_FDir_f( void ) { - void **list; - int ndirs = 0; - int i; + void **list; + int ndirs = 0; + int i; char *filter; - if( Cmd_Argc() < 2 ) { - Com_Printf( "Usage: %s <filter> [fullPath]\n", Cmd_Argv( 0 ) ); - return; - } + if( Cmd_Argc() < 2 ) { + Com_Printf( "Usage: %s <filter> [fullPath]\n", Cmd_Argv( 0 ) ); + return; + } filter = Cmd_Argv( 1 ); - i = FS_SEARCH_BYFILTER; - if( Cmd_Argc() > 2 ) { - i |= FS_SEARCH_SAVEPATH; - } + i = FS_SEARCH_BYFILTER; + if( Cmd_Argc() > 2 ) { + i |= FS_SEARCH_SAVEPATH; + } - if( ( list = FS_ListFiles( NULL, filter, i, &ndirs ) ) != NULL ) { - for( i = 0; i < ndirs; i++ ) { - Com_Printf( "%s\n", ( char * )list[i] ); - } - FS_FreeList( list ); - } - Com_Printf( "%i files listed\n", ndirs ); + if( ( list = FS_ListFiles( NULL, filter, i, &ndirs ) ) != NULL ) { + for( i = 0; i < ndirs; i++ ) { + Com_Printf( "%s\n", ( char * )list[i] ); + } + FS_FreeList( list ); + } + Com_Printf( "%i files listed\n", ndirs ); } /* @@ -2026,28 +2103,28 @@ FS_Dir_f ============ */ static void FS_Dir_f( void ) { - void **list; - int ndirs = 0; - int i; + void **list; + int ndirs = 0; + int i; char *ext; - if( Cmd_Argc() < 2 ) { - Com_Printf( "Usage: %s <directory> [.extension]\n", Cmd_Argv( 0 ) ); - return; - } + if( Cmd_Argc() < 2 ) { + Com_Printf( "Usage: %s <directory> [.extension]\n", Cmd_Argv( 0 ) ); + return; + } if( Cmd_Argc() > 2 ) { ext = Cmd_Argv( 2 ); } else { ext = NULL; } list = FS_ListFiles( Cmd_Argv( 1 ), ext, 0, &ndirs ); - if( list ) { - for( i = 0; i < ndirs; i++ ) { - Com_Printf( "%s\n", ( char * )list[i] ); - } - FS_FreeList( list ); - } - Com_Printf( "%i files listed\n", ndirs ); + if( list ) { + for( i = 0; i < ndirs; i++ ) { + Com_Printf( "%s\n", ( char * )list[i] ); + } + FS_FreeList( list ); + } + Com_Printf( "%i files listed\n", ndirs ); } /* @@ -2066,10 +2143,10 @@ static void FS_WhereIs_f( void ) { fsFileInfo_t info; int total; - if( Cmd_Argc() < 2 ) { - Com_Printf( "Usage: %s <path> [all]\n", Cmd_Argv( 0 ) ); - return; - } + if( Cmd_Argc() < 2 ) { + Com_Printf( "Usage: %s <path> [all]\n", Cmd_Argv( 0 ) ); + return; + } Cmd_ArgvBuffer( 1, filename, sizeof( filename ) ); @@ -2082,16 +2159,16 @@ static void FS_WhereIs_f( void ) { total = 0; for( search = fs_searchpaths; search; search = search->next ) { - // is the element a pak file? - if( search->pack ) { - // look through all the pak file elements - pak = search->pack; - entry = pak->fileHash[ hash & ( pak->hashSize - 1 ) ]; - for( ; entry; entry = entry->hashNext ) { - if( !Q_stricmp( entry->name, path ) ) { + // is the element a pak file? + if( search->pack ) { + // look through all the pak file elements + pak = search->pack; + entry = pak->fileHash[ hash & ( pak->hashSize - 1 ) ]; + for( ; entry; entry = entry->hashNext ) { + if( !FS_pathcmp( entry->name, path ) ) { Com_Printf( "%s/%s (%"PRIz" bytes)\n", pak->filename, path, entry->filelen ); - if( Cmd_Argc() < 3 ) { + if( Cmd_Argc() < 3 ) { return; } total++; @@ -2100,7 +2177,7 @@ static void FS_WhereIs_f( void ) { } else { Q_concat( fullpath, sizeof( fullpath ), search->filename, "/", path, NULL ); - //FS_ConvertToSysPath( fullpath ); + //FS_ConvertToSysPath( fullpath ); if( Sys_GetPathInfo( fullpath, &info ) ) { Com_Printf( "%s/%s (%"PRIz" bytes)\n", search->filename, filename, info.size ); if( Cmd_Argc() < 3 ) { @@ -2125,39 +2202,39 @@ FS_Path_f ============ */ void FS_Path_f( void ) { - searchpath_t *s; - int numFilesInPAK = 0; + searchpath_t *s; + int numFilesInPAK = 0; #if USE_ZLIB - int numFilesInPK2 = 0; + int numFilesInPK2 = 0; #endif - Com_Printf( "Current search path:\n" ); - for( s = fs_searchpaths; s; s = s->next ) { - if( s->pack ) { + Com_Printf( "Current search path:\n" ); + for( s = fs_searchpaths; s; s = s->next ) { + if( s->pack ) { #if USE_ZLIB - if( s->pack->zFile ) { - numFilesInPK2 += s->pack->numfiles; - } else + if( s->pack->zFile ) { + numFilesInPK2 += s->pack->numfiles; + } else #endif { - numFilesInPAK += s->pack->numfiles; - } - } + numFilesInPAK += s->pack->numfiles; + } + } - if( s->pack ) - Com_Printf( "%s (%i files)\n", s->pack->filename, s->pack->numfiles ); - else - Com_Printf( "%s\n", s->filename ); - } + if( s->pack ) + Com_Printf( "%s (%i files)\n", s->pack->filename, s->pack->numfiles ); + else + Com_Printf( "%s\n", s->filename ); + } - if( !( fs_restrict_mask->integer & 2 ) ) { - Com_Printf( "%i files in PAK files\n", numFilesInPAK ); - } + if( numFilesInPAK ) { + Com_Printf( "%i files in PAK files\n", numFilesInPAK ); + } #if USE_ZLIB - if( !( fs_restrict_mask->integer & 4 ) ) { - Com_Printf( "%i files in PKZ files\n", numFilesInPK2 ); - } + if( numFilesInPK2 ) { + Com_Printf( "%i files in PKZ files\n", numFilesInPK2 ); + } #endif } @@ -2167,55 +2244,55 @@ FS_Stats_f ================ */ static void FS_Stats_f( void ) { - searchpath_t *path; - pack_t *pack, *maxpack = NULL; - packfile_t *file, *max = NULL; - int i; - int len, maxLen = 0; - int totalHashSize, totalLen; - - totalHashSize = totalLen = 0; - for( path = fs_searchpaths; path; path = path->next ) { - if( !( pack = path->pack ) ) { - continue; - } - for( i = 0; i < pack->hashSize; i++ ) { - if( !( file = pack->fileHash[i] ) ) { - continue; - } - len = 0; - for( ; file ; file = file->hashNext ) { - len++; - } - if( maxLen < len ) { - max = pack->fileHash[i]; - maxpack = pack; - maxLen = len; - } - totalLen += len; - totalHashSize++; - } - //totalHashSize += pack->hashSize; - } - - Com_Printf( "LoadFile counter: %d\n", loadCount ); - Com_Printf( "Static LoadFile counter: %d\n", loadCountStatic ); - Com_Printf( "Total calls to OpenFileRead: %d\n", fs_count_read ); - Com_Printf( "Total path comparsions: %d\n", fs_count_strcmp ); - Com_Printf( "Total calls to fopen: %d\n", fs_count_open ); - - if( !totalHashSize ) { - Com_Printf( "No stats to display\n" ); - return; - } - - Com_Printf( "Maximum hash bucket length is %d, average is %.2f\n", maxLen, ( float )totalLen / totalHashSize ); - if( max ) { - Com_Printf( "Dumping longest bucket (%s):\n", maxpack->filename ); - for( file = max; file ; file = file->hashNext ) { - Com_Printf( "%s\n", file->name ); - } - } + searchpath_t *path; + pack_t *pack, *maxpack = NULL; + packfile_t *file, *max = NULL; + int i; + int len, maxLen = 0; + int totalHashSize, totalLen; + + totalHashSize = totalLen = 0; + for( path = fs_searchpaths; path; path = path->next ) { + if( !( pack = path->pack ) ) { + continue; + } + for( i = 0; i < pack->hashSize; i++ ) { + if( !( file = pack->fileHash[i] ) ) { + continue; + } + len = 0; + for( ; file ; file = file->hashNext ) { + len++; + } + if( maxLen < len ) { + max = pack->fileHash[i]; + maxpack = pack; + maxLen = len; + } + totalLen += len; + totalHashSize++; + } + //totalHashSize += pack->hashSize; + } + + Com_Printf( "LoadFile counter: %d\n", loadCount ); + Com_Printf( "Static LoadFile counter: %d\n", loadCountStatic ); + Com_Printf( "Total calls to OpenFileRead: %d\n", fs_count_read ); + Com_Printf( "Total path comparsions: %d\n", fs_count_strcmp ); + Com_Printf( "Total calls to fopen: %d\n", fs_count_open ); + + if( !totalHashSize ) { + Com_Printf( "No stats to display\n" ); + return; + } + + Com_Printf( "Maximum hash bucket length is %d, average is %.2f\n", maxLen, ( float )totalLen / totalHashSize ); + if( max ) { + Com_Printf( "Dumping longest bucket (%s):\n", maxpack->filename ); + for( file = max; file ; file = file->hashNext ) { + Com_Printf( "%s\n", file->name ); + } + } } static void FS_Link_g( genctx_t *ctx ) { @@ -2273,7 +2350,7 @@ static void FS_UnLink_f( void ) { } for( l = fs_links, back = &fs_links; l; l = l->next ) { - if( !Q_stricmp( l->name, name ) ) { + if( !FS_pathcmp( l->name, name ) ) { break; } back = &l->next; @@ -2290,7 +2367,7 @@ static void FS_UnLink_f( void ) { static void FS_Link_f( void ) { int argc, count; - size_t length; + size_t length; fsLink_t *l; char *name, *target; @@ -2314,7 +2391,7 @@ static void FS_Link_f( void ) { name = Cmd_Argv( 1 ); for( l = fs_links; l; l = l->next ) { - if( !Q_stricmp( l->name, name ) ) { + if( !FS_pathcmp( l->name, name ) ) { break; } } @@ -2336,21 +2413,21 @@ static void FS_Link_f( void ) { } static void FS_FreeSearchPath( searchpath_t *path ) { - pack_t *pak; + pack_t *pak; - if( ( pak = path->pack ) != NULL ) { + if( ( pak = path->pack ) != NULL ) { #if USE_ZLIB - if( pak->zFile ) { - unzClose( pak->zFile ); - } else + if( pak->zFile ) { + unzClose( pak->zFile ); + } else #endif { - fclose( pak->fp ); - } - Z_Free( pak ); - } + fclose( pak->fp ); + } + Z_Free( pak ); + } - Z_Free( path ); + Z_Free( path ); } /* @@ -2359,24 +2436,24 @@ FS_Shutdown ================ */ void FS_Shutdown( qboolean total ) { - searchpath_t *path, *next; + searchpath_t *path, *next; fsLink_t *l, *nextLink; - fsFile_t *file; - int i; - - if( !fs_searchpaths ) { - return; - } - - if( total ) { - // close file handles - for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) { - if( file->type != FS_FREE ) { - Com_WPrintf( "FS_Shutdown: closing handle %i: %s\n", + fsFile_t *file; + int i; + + if( !fs_searchpaths ) { + return; + } + + if( total ) { + // close file handles + for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) { + if( file->type != FS_FREE ) { + Com_WPrintf( "FS_Shutdown: closing handle %i: %s\n", i + 1, file->fullpath ); - FS_FCloseFile( i + 1 ); - } - } + FS_FCloseFile( i + 1 ); + } + } // free symbolic links for( l = fs_links; l; l = nextLink ) { @@ -2386,27 +2463,27 @@ void FS_Shutdown( qboolean total ) { } fs_links = NULL; - } + } - // free search paths - for( path = fs_searchpaths; path; path = next ) { - next = path->next; - FS_FreeSearchPath( path ); - } + // free search paths + for( path = fs_searchpaths; path; path = next ) { + next = path->next; + FS_FreeSearchPath( path ); + } - fs_searchpaths = NULL; + fs_searchpaths = NULL; if( total ) { - Z_LeakTest( TAG_FILESYSTEM ); + Z_LeakTest( TAG_FILESYSTEM ); } - Cmd_RemoveCommand( "path" ); - Cmd_RemoveCommand( "fdir" ); - Cmd_RemoveCommand( "dir" ); - Cmd_RemoveCommand( "copyfile" ); - Cmd_RemoveCommand( "fs_stats" ); - Cmd_RemoveCommand( "link" ); - Cmd_RemoveCommand( "unlink" ); + Cmd_RemoveCommand( "path" ); + Cmd_RemoveCommand( "fdir" ); + Cmd_RemoveCommand( "dir" ); + Cmd_RemoveCommand( "copyfile" ); + Cmd_RemoveCommand( "fs_stats" ); + Cmd_RemoveCommand( "link" ); + Cmd_RemoveCommand( "unlink" ); } /* @@ -2416,14 +2493,14 @@ FS_DefaultGamedir */ static void FS_DefaultGamedir( void ) { if( sys_homedir->string[0] ) { - FS_AddGameDirectory( FS_PATH_BASE|FS_PATH_GAME, + FS_AddGameDirectory( FS_PATH_BASE|FS_PATH_GAME, "%s/"BASEGAME, sys_homedir->string ); } - Cvar_Set( "game", "" ); - Cvar_Set( "gamedir", "" ); + Cvar_Set( "game", "" ); + Cvar_Set( "gamedir", "" ); - Sys_Setenv( "QUAKE2_HOME", fs_gamedir ); + Q_setenv( "QUAKE2_GAME_PATH", fs_gamedir ); } @@ -2435,27 +2512,29 @@ Sets the gamedir and path to a different directory. ================ */ static void FS_SetupGamedir( void ) { - fs_game = Cvar_Get( "game", "", CVAR_LATCHED|CVAR_SERVERINFO ); + fs_game = Cvar_Get( "game", "", CVAR_FILES|CVAR_LATCH|CVAR_SERVERINFO ); - if( !fs_game->string[0] || !FS_strcmp( fs_game->string, BASEGAME ) ) { - FS_DefaultGamedir(); - return; - } + cvar_modified &= ~CVAR_FILES; - if( !FS_ValidatePath( fs_game->string ) || + if( !fs_game->string[0] || !FS_strcmp( fs_game->string, BASEGAME ) ) { + FS_DefaultGamedir(); + return; + } + + if( !FS_ValidatePath( fs_game->string ) || strchr( fs_game->string, '/' ) || - strchr( fs_game->string, '\\' ) ) - { - Com_WPrintf( "Gamedir should be a single filename, not a path.\n" ); - FS_DefaultGamedir(); - return; - } - - // this one is left for compatibility with server browsers, etc - Cvar_FullSet( "gamedir", fs_game->string, CVAR_ROM|CVAR_SERVERINFO, + strchr( fs_game->string, '\\' ) ) + { + Com_WPrintf( "Gamedir should be a single filename, not a path.\n" ); + FS_DefaultGamedir(); + return; + } + + // this one is left for compatibility with server browsers, etc + Cvar_FullSet( "gamedir", fs_game->string, CVAR_ROM|CVAR_SERVERINFO, CVAR_SET_DIRECT ); - FS_AddGameDirectory( FS_PATH_GAME, "%s/%s", sys_basedir->string, fs_game->string ); + FS_AddGameDirectory( FS_PATH_GAME, "%s/%s", sys_basedir->string, fs_game->string ); // home paths override system paths if( sys_homedir->string[0] ) { @@ -2463,21 +2542,21 @@ static void FS_SetupGamedir( void ) { FS_AddGameDirectory( FS_PATH_GAME, "%s/%s", sys_homedir->string, fs_game->string ); } - Sys_Setenv( "QUAKE2_HOME", fs_gamedir ); + Q_setenv( "QUAKE2_GAME_PATH", fs_gamedir ); } qboolean FS_SafeToRestart( void ) { - fsFile_t *file; - int i; + fsFile_t *file; + int i; - // make sure no files are opened for reading - for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) { - if( file->type == FS_FREE ) { - continue; - } - if( file->mode == FS_MODE_READ ) { + // make sure no files are opened for reading + for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) { + if( file->type == FS_FREE ) { + continue; + } + if( file->mode == FS_MODE_READ ) { return qfalse; - } + } } return qtrue; @@ -2489,49 +2568,49 @@ FS_Restart ================ */ void FS_Restart( void ) { - fsFile_t *file; - int i; - fileHandle_t temp; - searchpath_t *path, *next; - - Com_Printf( "---------- FS_Restart ----------\n" ); - - // temporary disable logfile - temp = com_logFile; - com_logFile = 0; - - // make sure no files are opened for reading - for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) { - if( file->type == FS_FREE ) { - continue; - } - if( file->mode == FS_MODE_READ ) { - Com_Error( ERR_FATAL, "FS_Restart: closing handle %i: %s", + fsFile_t *file; + int i; + fileHandle_t temp; + searchpath_t *path, *next; + + Com_Printf( "---------- FS_Restart ----------\n" ); + + // temporary disable logfile + temp = com_logFile; + com_logFile = 0; + + // make sure no files are opened for reading + for( i = 0, file = fs_files; i < MAX_FILE_HANDLES; i++, file++ ) { + if( file->type == FS_FREE ) { + continue; + } + if( file->mode == FS_MODE_READ ) { + Com_Error( ERR_FATAL, "FS_Restart: closing handle %i: %s", i + 1, file->fullpath ); - } - } - - if( fs_restrict_mask->latched_string ) { - // perform full reset - FS_Shutdown( qfalse ); - FS_Init(); - } else { - // just change gamedir - for( path = fs_searchpaths; path != fs_base_searchpaths; path = next ) { - next = path->next; - FS_FreeSearchPath( path ); - } - - fs_searchpaths = fs_base_searchpaths; - - FS_SetupGamedir(); - FS_Path_f(); - } - - // re-enable logfile - com_logFile = temp; - - Com_Printf( "--------------------------------\n" ); + } + } + + if( fs_restrict_mask->latched_string ) { + // perform full reset + FS_Shutdown( qfalse ); + FS_Init(); + } else { + // just change gamedir + for( path = fs_searchpaths; path != fs_base_searchpaths; path = next ) { + next = path->next; + FS_FreeSearchPath( path ); + } + + fs_searchpaths = fs_base_searchpaths; + + FS_SetupGamedir(); + FS_Path_f(); + } + + // re-enable logfile + com_logFile = temp; + + Com_Printf( "--------------------------------\n" ); } /* @@ -2556,18 +2635,18 @@ FS_FillAPI ================ */ void FS_FillAPI( fsAPI_t *api ) { - api->LoadFile = FS_LoadFile; - api->LoadFileEx = FS_LoadFileEx; + api->LoadFile = FS_LoadFile; + api->LoadFileEx = FS_LoadFileEx; api->AllocTempMem = FS_AllocTempMem; - api->FreeFile = FS_FreeFile; - api->FOpenFile = FS_FOpenFile; - api->FCloseFile = FS_FCloseFile; - api->Tell = FS_Tell; - api->RawTell = FS_RawTell; - api->Read = FS_Read; - api->Write = FS_Write; - api->ListFiles = FS_ListFiles; - api->FreeList = FS_FreeList; + api->FreeFile = FS_FreeFile; + api->FOpenFile = FS_FOpenFile; + api->FCloseFile = FS_FCloseFile; + api->Tell = FS_Tell; + api->RawTell = FS_RawTell; + api->Read = FS_Read; + api->Write = FS_Write; + api->ListFiles = FS_ListFiles; + api->FreeList = FS_FreeList; api->FPrintf = FS_FPrintf; api->ReadLine = FS_ReadLine; } @@ -2581,7 +2660,7 @@ static const cmdreg_t c_fs[] = { { "whereis", FS_WhereIs_f }, { "link", FS_Link_f, FS_Link_c }, { "unlink", FS_UnLink_f, FS_Link_c }, - { "fs_restart", FS_Restart_f }, + { "fs_restart", FS_Restart_f }, { NULL } }; @@ -2592,39 +2671,39 @@ FS_Init ================ */ void FS_Init( void ) { - unsigned start, end; + unsigned start, end; - start = Sys_Milliseconds(); + start = Sys_Milliseconds(); - Com_Printf( "---------- FS_Init ----------\n" ); + Com_Printf( "---------- FS_Init ----------\n" ); Cmd_Register( c_fs ); - fs_debug = Cvar_Get( "fs_debug", "0", 0 ); - fs_restrict_mask = Cvar_Get( "fs_restrict_mask", "0", CVAR_NOSET ); + fs_debug = Cvar_Get( "fs_debug", "0", 0 ); + fs_restrict_mask = Cvar_Get( "fs_restrict_mask", "0", CVAR_NOSET ); - if( ( fs_restrict_mask->integer & 7 ) == 7 ) { - Com_WPrintf( "Invalid fs_restrict_mask value %d. " + if( ( fs_restrict_mask->integer & 7 ) == 7 ) { + Com_WPrintf( "Invalid fs_restrict_mask value %d. " "Falling back to default.\n", - fs_restrict_mask->integer ); - Cvar_Set( "fs_restrict_mask", "0" ); - } + fs_restrict_mask->integer ); + Cvar_Set( "fs_restrict_mask", "0" ); + } - // start up with baseq2 by default - FS_AddGameDirectory( FS_PATH_BASE|FS_PATH_GAME, "%s/"BASEGAME, sys_basedir->string ); + // start up with baseq2 by default + FS_AddGameDirectory( FS_PATH_BASE|FS_PATH_GAME, "%s/"BASEGAME, sys_basedir->string ); - fs_base_searchpaths = fs_searchpaths; + fs_base_searchpaths = fs_searchpaths; - // check for game override - FS_SetupGamedir(); + // check for game override + FS_SetupGamedir(); - FS_Path_f(); + FS_Path_f(); - FS_FillAPI( &fs ); - + FS_FillAPI( &fs ); + end = Sys_Milliseconds(); - Com_DPrintf( "%i msec to init filesystem\n", end - start ); - Com_Printf( "-----------------------------\n" ); + Com_DPrintf( "%i msec to init filesystem\n", end - start ); + Com_Printf( "-----------------------------\n" ); } /* @@ -2633,10 +2712,12 @@ FS_NeedRestart ================ */ qboolean FS_NeedRestart( void ) { - if( fs_game->latched_string || fs_restrict_mask->latched_string ) { - return qtrue; - } - - return qfalse; + if( cvar_modified & CVAR_FILES ) { + return qtrue; + } + if( fs_game->latched_string || fs_restrict_mask->latched_string ) { + return qtrue; + } + return qfalse; } diff --git a/source/g_public.h b/source/g_public.h index fac43a4..1384ff9 100644 --- a/source/g_public.h +++ b/source/g_public.h @@ -30,12 +30,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // edict->solid values -typedef enum -{ -SOLID_NOT, // no interaction with other objects -SOLID_TRIGGER, // only touch when inside, after moving -SOLID_BBOX, // touch on edge -SOLID_BSP // bsp clip, touch on edge +typedef enum { + SOLID_NOT, // no interaction with other objects + SOLID_TRIGGER, // only touch when inside, after moving + SOLID_BBOX, // touch on edge + SOLID_BSP // bsp clip, touch on edge } solid_t; // extended features diff --git a/source/gl_images.c b/source/gl_images.c index 3f3f5bc..489a6e7 100644 --- a/source/gl_images.c +++ b/source/gl_images.c @@ -1093,22 +1093,22 @@ void GL_InitImages( void ) { gl_texturemode->changed = gl_texturemode_changed; gl_anisotropy = cvar.Get( "gl_anisotropy", "1", CVAR_ARCHIVE ); gl_anisotropy->changed = gl_anisotropy_changed; - gl_noscrap = cvar.Get( "gl_noscrap", "0", CVAR_LATCHED ); - gl_round_down = cvar.Get( "gl_round_down", "0", CVAR_LATCHED ); - gl_picmip = cvar.Get( "gl_picmip", "0", CVAR_LATCHED ); - gl_gamma_scale_pics = cvar.Get( "gl_gamma_scale_pics", "0", CVAR_LATCHED ); + gl_noscrap = cvar.Get( "gl_noscrap", "0", CVAR_FILES ); + gl_round_down = cvar.Get( "gl_round_down", "0", CVAR_FILES ); + gl_picmip = cvar.Get( "gl_picmip", "0", CVAR_FILES ); + gl_gamma_scale_pics = cvar.Get( "gl_gamma_scale_pics", "0", CVAR_FILES ); gl_texturealphamode = cvar.Get( "gl_texturealphamode", - "default", CVAR_ARCHIVE|CVAR_LATCHED ); + "default", CVAR_ARCHIVE|CVAR_FILES ); gl_texturesolidmode = cvar.Get( "gl_texturesolidmode", - "default", CVAR_ARCHIVE|CVAR_LATCHED ); - gl_saturation = cvar.Get( "gl_saturation", "1", CVAR_ARCHIVE|CVAR_LATCHED ); - gl_intensity = cvar.Get( "intensity", "1", CVAR_ARCHIVE|CVAR_LATCHED ); - gl_invert = cvar.Get( "gl_invert", "0", CVAR_ARCHIVE|CVAR_LATCHED ); + "default", CVAR_ARCHIVE|CVAR_FILES ); + gl_saturation = cvar.Get( "gl_saturation", "1", CVAR_ARCHIVE|CVAR_FILES ); + gl_intensity = cvar.Get( "intensity", "1", CVAR_ARCHIVE|CVAR_FILES ); + gl_invert = cvar.Get( "gl_invert", "0", CVAR_ARCHIVE|CVAR_FILES ); if( gl_hwgamma->integer ) { - gl_gamma = cvar.Get( "vid_gamma", "1", 0 ); + gl_gamma = cvar.Get( "vid_gamma", "1", CVAR_ARCHIVE ); gl_gamma->changed = gl_gamma_changed; } else { - gl_gamma = cvar.Get( "vid_gamma", "1", CVAR_LATCHED ); + gl_gamma = cvar.Get( "vid_gamma", "1", CVAR_ARCHIVE|CVAR_FILES ); } R_InitImageManager(); diff --git a/source/gl_main.c b/source/gl_main.c index 31c67b6..b120f6f 100644 --- a/source/gl_main.c +++ b/source/gl_main.c @@ -689,7 +689,7 @@ static void GL_Register( void ) { #endif gl_celshading = cvar.Get( "gl_celshading", "0", 0 ); gl_modulate = cvar.Get( "gl_modulate", "1", CVAR_ARCHIVE ); - gl_hwgamma = cvar.Get( "vid_hwgamma", "0", CVAR_ARCHIVE|CVAR_LATCHED ); + gl_hwgamma = cvar.Get( "vid_hwgamma", "0", CVAR_ARCHIVE|CVAR_REFRESH ); /* development variables */ gl_znear = cvar.Get( "gl_znear", "2", CVAR_CHEAT ); @@ -713,8 +713,8 @@ static void GL_Register( void ) { gl_polyblend = cvar.Get( "gl_polyblend", "1", 0 ); gl_fullbright = cvar.Get( "r_fullbright", "0", CVAR_CHEAT ); gl_showerrors = cvar.Get( "gl_showerrors", "1", 0 ); - gl_fragment_program = cvar.Get( "gl_fragment_program", "0", CVAR_LATCHED ); - gl_vertex_buffer_object = cvar.Get( "gl_vertex_buffer_object", "0", CVAR_LATCHED ); + gl_fragment_program = cvar.Get( "gl_fragment_program", "0", CVAR_REFRESH ); + gl_vertex_buffer_object = cvar.Get( "gl_vertex_buffer_object", "0", CVAR_REFRESH ); cmd.AddCommand( "screenshot", GL_ScreenShot_f ); #if USE_JPEG diff --git a/source/gl_models.c b/source/gl_models.c index fa63470..7937512 100644 --- a/source/gl_models.c +++ b/source/gl_models.c @@ -987,8 +987,7 @@ void GL_InitModels( void ) { } gl_override_models = cvar.Get( "r_override_models", "0", - CVAR_ARCHIVE|CVAR_LATCHED ); - + CVAR_ARCHIVE|CVAR_FILES ); cmd.AddCommand( "modellist", Model_List_f ); } diff --git a/source/gl_surf.c b/source/gl_surf.c index c10bd34..488093c 100644 --- a/source/gl_surf.c +++ b/source/gl_surf.c @@ -358,9 +358,9 @@ void GL_BeginPostProcessing( void ) { lm.numMaps = 0; LM_InitBlock(); - gl_coloredlightmaps = cvar.Get( "gl_coloredlightmaps", "1", CVAR_ARCHIVE|CVAR_LATCHED ); - gl_brightness = cvar.Get( "gl_brightness", "0", CVAR_ARCHIVE|CVAR_LATCHED ); - gl_modulate_hack = cvar.Get( "gl_modulate_hack", "0", CVAR_LATCHED ); + gl_coloredlightmaps = cvar.Get( "gl_coloredlightmaps", "1", CVAR_ARCHIVE|CVAR_FILES ); + gl_brightness = cvar.Get( "gl_brightness", "0", CVAR_ARCHIVE|CVAR_FILES ); + gl_modulate_hack = cvar.Get( "gl_modulate_hack", "0", CVAR_FILES ); if( gl_coloredlightmaps->value < 0 ) { cvar.Set( "gl_coloredlightmaps", "0" ); diff --git a/source/mvd_game.c b/source/mvd_game.c index 3c9f2f0..c96c23f 100644 --- a/source/mvd_game.c +++ b/source/mvd_game.c @@ -1025,7 +1025,7 @@ static void MVD_GameInit( void ) { mvd_default_map = Cvar_Get( "mvd_default_map", "q2dm1", CVAR_LATCH ); mvd_stats_hack = Cvar_Get( "mvd_stats_hack", "0", 0 ); mvd_freeze_hack = Cvar_Get( "mvd_freeze_hack", "0", 0 ); - Cvar_Get( "g_features", va( "%d", GMF_CLIENTNUM|GMF_PROPERINUSE ), CVAR_ROM ); + svs.gameFeatures = GMF_CLIENTNUM|GMF_PROPERINUSE; Z_TagReserve( ( sizeof( edict_t ) + sizeof( udpClient_t ) ) * sv_maxclients->integer + diff --git a/source/protocol.h b/source/protocol.h index 926c8fd..1f46205 100644 --- a/source/protocol.h +++ b/source/protocol.h @@ -22,23 +22,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // protocol.h -- communications protocols // -#define MAX_MSGLEN 0x8000 // max length of a message, 32k - -#define PROTOCOL_VERSION_OLD 26 -#define PROTOCOL_VERSION_DEFAULT 34 -#define PROTOCOL_VERSION_R1Q2 35 -#define PROTOCOL_VERSION_Q2PRO 36 -#define PROTOCOL_VERSION_MVD 37 // not used for UDP connections - -#define PROTOCOL_VERSION_R1Q2_MINIMUM 1903 // b6377 -#define PROTOCOL_VERSION_R1Q2_UCMD 1904 // b7387 -#define PROTOCOL_VERSION_R1Q2_CURRENT 1904 // b7387 -#define PROTOCOL_VERSION_Q2PRO_MINIMUM 1011 // r161 -#define PROTOCOL_VERSION_Q2PRO_UCMD 1012 // r179 -#define PROTOCOL_VERSION_Q2PRO_CLIENTFIX 1013 // r226 -#define PROTOCOL_VERSION_Q2PRO_CURRENT 1013 // r226 -#define PROTOCOL_VERSION_MVD_MINIMUM 2009 // r168 -#define PROTOCOL_VERSION_MVD_CURRENT 2010 // r177 +#define MAX_MSGLEN 0x8000 // max length of a message, 32k + +#define PROTOCOL_VERSION_OLD 26 +#define PROTOCOL_VERSION_DEFAULT 34 +#define PROTOCOL_VERSION_R1Q2 35 +#define PROTOCOL_VERSION_Q2PRO 36 +#define PROTOCOL_VERSION_MVD 37 // not used for UDP connections + +#define PROTOCOL_VERSION_R1Q2_MINIMUM 1903 // b6377 +#define PROTOCOL_VERSION_R1Q2_UCMD 1904 // b7387 +#define PROTOCOL_VERSION_R1Q2_LONG_SOLID 1905 // b7759 +#define PROTOCOL_VERSION_R1Q2_CURRENT 1905 // b7387 +#define PROTOCOL_VERSION_Q2PRO_MINIMUM 1011 // r161 +#define PROTOCOL_VERSION_Q2PRO_UCMD 1012 // r179 +#define PROTOCOL_VERSION_Q2PRO_CLIENTNUM_FIX 1013 // r226 +#define PROTOCOL_VERSION_Q2PRO_LONG_SOLID 1014 // r243 +#define PROTOCOL_VERSION_Q2PRO_CURRENT 1014 // r243 +#define PROTOCOL_VERSION_MVD_MINIMUM 2009 // r168 +#define PROTOCOL_VERSION_MVD_CURRENT 2010 // r177 #define R1Q2_SUPPORTED( x ) ( (x) >= PROTOCOL_VERSION_R1Q2_MINIMUM && \ (x) <= PROTOCOL_VERSION_R1Q2_CURRENT ) @@ -47,48 +49,52 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (x) <= PROTOCOL_VERSION_Q2PRO_CURRENT ) #define MVD_SUPPORTED( x ) ( (x) >= PROTOCOL_VERSION_MVD_MINIMUM && \ - (x) <= PROTOCOL_VERSION_MVD_CURRENT ) + (x) <= PROTOCOL_VERSION_MVD_CURRENT ) + +#define LONG_SOLID_SUPPORTED( major, minor ) \ + ( ( (major) == PROTOCOL_VERSION_Q2PRO && (minor) >= PROTOCOL_VERSION_Q2PRO_LONG_SOLID ) || \ + ( (major) == PROTOCOL_VERSION_R1Q2 && (minor) >= PROTOCOL_VERSION_R1Q2_LONG_SOLID ) ) //========================================= -#define PORT_MASTER 27900 -#define PORT_CLIENT 27901 -#define PORT_SERVER 27910 -#define PORT_MAX_SEARCH 5 +#define PORT_MASTER 27900 +#define PORT_CLIENT 27901 +#define PORT_SERVER 27910 +#define PORT_MAX_SEARCH 5 //========================================= -#define UPDATE_BACKUP 16 // copies of entity_state_t to keep buffered - // must be power of two -#define UPDATE_MASK ( UPDATE_BACKUP - 1 ) +#define UPDATE_BACKUP 16 // copies of entity_state_t to keep buffered + // must be power of two +#define UPDATE_MASK ( UPDATE_BACKUP - 1 ) -#define CMD_BACKUP 128 // allow a lot of command backups for very fast systems - // increased from 64 -#define CMD_MASK ( CMD_BACKUP - 1 ) +#define CMD_BACKUP 128 // allow a lot of command backups for very fast systems + // increased from 64 +#define CMD_MASK ( CMD_BACKUP - 1 ) -#define SVCMD_BITS 5 -#define SVCMD_MASK ( ( 1 << SVCMD_BITS ) - 1 ) +#define SVCMD_BITS 5 +#define SVCMD_MASK ( ( 1 << SVCMD_BITS ) - 1 ) -#define FRAMENUM_BITS 27 -#define FRAMENUM_MASK ( ( 1 << FRAMENUM_BITS ) - 1 ) +#define FRAMENUM_BITS 27 +#define FRAMENUM_MASK ( ( 1 << FRAMENUM_BITS ) - 1 ) -#define SURPRESSCOUNT_BITS 4 -#define SURPRESSCOUNT_MASK ( ( 1 << SURPRESSCOUNT_BITS ) - 1 ) +#define SURPRESSCOUNT_BITS 4 +#define SURPRESSCOUNT_MASK ( ( 1 << SURPRESSCOUNT_BITS ) - 1 ) -#define MAX_PACKET_ENTITIES 128 -#define MAX_PARSE_ENTITIES 2048 // should be MAX_PACKET_ENTITIES * UPDATE_BACKUP -#define PARSE_ENTITIES_MASK ( MAX_PARSE_ENTITIES - 1 ) +#define MAX_PACKET_ENTITIES 128 +#define MAX_PARSE_ENTITIES 2048 // should be MAX_PACKET_ENTITIES * UPDATE_BACKUP +#define PARSE_ENTITIES_MASK ( MAX_PARSE_ENTITIES - 1 ) -#define MAX_PACKET_USERCMDS 32 -#define MAX_PACKET_FRAMES 4 +#define MAX_PACKET_USERCMDS 32 +#define MAX_PACKET_FRAMES 4 -#define MAX_PACKET_STRINGCMDS 8 -#define MAX_PACKET_USERINFOS 8 +#define MAX_PACKET_STRINGCMDS 8 +#define MAX_PACKET_USERINFOS 8 -#define CS_BITMAP_BYTES (MAX_CONFIGSTRINGS/8) // 260 -#define CS_BITMAP_LONGS (CS_BITMAP_BYTES/4) +#define CS_BITMAP_BYTES ( MAX_CONFIGSTRINGS / 8 ) // 260 +#define CS_BITMAP_LONGS ( CS_BITMAP_BYTES / 4 ) #define MVD_MAGIC MakeLong( 'M', 'V', 'D', '2' ) @@ -96,36 +102,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // server to client // typedef enum svc_ops_e { - svc_bad, - - // these ops are known to the game dll - svc_muzzleflash, - svc_muzzleflash2, - svc_temp_entity, - svc_layout, - svc_inventory, - - // the rest are private to the client and server - svc_nop, - svc_disconnect, - svc_reconnect, - svc_sound, // <see code> - svc_print, // [byte] id [string] null terminated string - svc_stufftext, // [string] stuffed into client's console buffer + svc_bad, + + // these ops are known to the game dll + svc_muzzleflash, + svc_muzzleflash2, + svc_temp_entity, + svc_layout, + svc_inventory, + + // the rest are private to the client and server + svc_nop, + svc_disconnect, + svc_reconnect, + svc_sound, // <see code> + svc_print, // [byte] id [string] null terminated string + svc_stufftext, // [string] stuffed into client's console buffer // should be \n terminated - svc_serverdata, // [long] protocol ... - svc_configstring, // [short] [string] - svc_spawnbaseline, - svc_centerprint, // [string] to put in center of the screen - svc_download, // [short] size [size bytes] - svc_playerinfo, // variable - svc_packetentities, // [...] - svc_deltapacketentities, // [...] - svc_frame, - - // r1q2 specific operations - svc_zpacket, - svc_zdownload, + svc_serverdata, // [long] protocol ... + svc_configstring, // [short] [string] + svc_spawnbaseline, + svc_centerprint, // [string] to put in center of the screen + svc_download, // [short] size [size bytes] + svc_playerinfo, // variable + svc_packetentities, // [...] + svc_deltapacketentities, // [...] + svc_frame, + + // r1q2 specific operations + svc_zpacket, + svc_zdownload, svc_gamestate, // q2pro specific, means svc_playerupdate in r1q2 svc_setting, @@ -142,14 +148,14 @@ typedef enum mvd_ops_e { mvd_configstring, mvd_frame, mvd_frame_nodelta, - mvd_unicast, + mvd_unicast, mvd_unicast_r, - mvd_multicast_all, - mvd_multicast_pvs, - mvd_multicast_phs, - mvd_multicast_all_r, - mvd_multicast_pvs_r, - mvd_multicast_phs_r, + mvd_multicast_all, + mvd_multicast_pvs, + mvd_multicast_phs, + mvd_multicast_all_r, + mvd_multicast_pvs_r, + mvd_multicast_phs_r, mvd_sound, mvd_print, // reserved mvd_stufftext, // reserved @@ -163,81 +169,81 @@ typedef enum mvd_ops_e { // client to server // typedef enum clc_ops_e { - clc_bad, - clc_nop, - clc_move, // [usercmd_t] - clc_userinfo, // [userinfo string] - clc_stringcmd, // [string] message - - // r1q2 specific operations - clc_setting, - - // q2pro specific operations - clc_move_nodelta = 10, - clc_move_batched, - clc_userinfo_delta + clc_bad, + clc_nop, + clc_move, // [usercmd_t] + clc_userinfo, // [userinfo string] + clc_stringcmd, // [string] message + + // r1q2 specific operations + clc_setting, + + // q2pro specific operations + clc_move_nodelta = 10, + clc_move_batched, + clc_userinfo_delta } clc_ops_t; //============================================== // player_state_t communication -#define PS_M_TYPE (1<<0) -#define PS_M_ORIGIN (1<<1) -#define PS_M_VELOCITY (1<<2) -#define PS_M_TIME (1<<3) -#define PS_M_FLAGS (1<<4) -#define PS_M_GRAVITY (1<<5) -#define PS_M_DELTA_ANGLES (1<<6) - -#define PS_VIEWOFFSET (1<<7) -#define PS_VIEWANGLES (1<<8) -#define PS_KICKANGLES (1<<9) -#define PS_BLEND (1<<10) -#define PS_FOV (1<<11) -#define PS_WEAPONINDEX (1<<12) -#define PS_WEAPONFRAME (1<<13) -#define PS_RDFLAGS (1<<14) -#define PS_RESERVED (1<<15) - -#define PS_BITS 16 -#define PS_MASK ( ( 1 << PS_BITS ) - 1 ) +#define PS_M_TYPE (1<<0) +#define PS_M_ORIGIN (1<<1) +#define PS_M_VELOCITY (1<<2) +#define PS_M_TIME (1<<3) +#define PS_M_FLAGS (1<<4) +#define PS_M_GRAVITY (1<<5) +#define PS_M_DELTA_ANGLES (1<<6) + +#define PS_VIEWOFFSET (1<<7) +#define PS_VIEWANGLES (1<<8) +#define PS_KICKANGLES (1<<9) +#define PS_BLEND (1<<10) +#define PS_FOV (1<<11) +#define PS_WEAPONINDEX (1<<12) +#define PS_WEAPONFRAME (1<<13) +#define PS_RDFLAGS (1<<14) +#define PS_RESERVED (1<<15) + +#define PS_BITS 16 +#define PS_MASK ( ( 1 << PS_BITS ) - 1 ) // r1q2 protocol specific extra flags -#define EPS_GUNOFFSET (1<<0) -#define EPS_GUNANGLES (1<<1) -#define EPS_M_VELOCITY2 (1<<2) -#define EPS_M_ORIGIN2 (1<<3) -#define EPS_VIEWANGLE2 (1<<4) -#define EPS_STATS (1<<5) +#define EPS_GUNOFFSET (1<<0) +#define EPS_GUNANGLES (1<<1) +#define EPS_M_VELOCITY2 (1<<2) +#define EPS_M_ORIGIN2 (1<<3) +#define EPS_VIEWANGLE2 (1<<4) +#define EPS_STATS (1<<5) // q2pro protocol specific extra flags -#define EPS_CLIENTNUM (1<<6) +#define EPS_CLIENTNUM (1<<6) -#define EPS_BITS 7 -#define EPS_MASK ( ( 1 << EPS_BITS ) - 1 ) +#define EPS_BITS 7 +#define EPS_MASK ( ( 1 << EPS_BITS ) - 1 ) //============================================== // packetized player_state_t communication (MVD specific) -#define PPS_M_TYPE (1<<0) -#define PPS_M_ORIGIN (1<<1) -#define PPS_M_ORIGIN2 (1<<2) - -#define PPS_VIEWOFFSET (1<<3) -#define PPS_VIEWANGLES (1<<4) -#define PPS_VIEWANGLE2 (1<<5) -#define PPS_KICKANGLES (1<<6) -#define PPS_BLEND (1<<7) -#define PPS_FOV (1<<8) -#define PPS_WEAPONINDEX (1<<9) -#define PPS_WEAPONFRAME (1<<10) -#define PPS_GUNOFFSET (1<<11) -#define PPS_GUNANGLES (1<<12) -#define PPS_RDFLAGS (1<<13) -#define PPS_STATS (1<<14) -#define PPS_REMOVE (1<<15) +#define PPS_M_TYPE (1<<0) +#define PPS_M_ORIGIN (1<<1) +#define PPS_M_ORIGIN2 (1<<2) + +#define PPS_VIEWOFFSET (1<<3) +#define PPS_VIEWANGLES (1<<4) +#define PPS_VIEWANGLE2 (1<<5) +#define PPS_KICKANGLES (1<<6) +#define PPS_BLEND (1<<7) +#define PPS_FOV (1<<8) +#define PPS_WEAPONINDEX (1<<9) +#define PPS_WEAPONFRAME (1<<10) +#define PPS_GUNOFFSET (1<<11) +#define PPS_GUNANGLES (1<<12) +#define PPS_RDFLAGS (1<<13) +#define PPS_STATS (1<<14) +#define PPS_REMOVE (1<<15) #define PPS_NUM( ps ) (ps)->pmove.pm_flags #define PPS_INUSE( ps ) (ps)->pmove.pm_time @@ -247,17 +253,17 @@ typedef enum clc_ops_e { // user_cmd_t communication // ms and light always sent, the others are optional -#define CM_ANGLE1 (1<<0) -#define CM_ANGLE2 (1<<1) -#define CM_ANGLE3 (1<<2) -#define CM_FORWARD (1<<3) -#define CM_SIDE (1<<4) -#define CM_UP (1<<5) -#define CM_BUTTONS (1<<6) -#define CM_IMPULSE (1<<7) +#define CM_ANGLE1 (1<<0) +#define CM_ANGLE2 (1<<1) +#define CM_ANGLE3 (1<<2) +#define CM_FORWARD (1<<3) +#define CM_SIDE (1<<4) +#define CM_UP (1<<5) +#define CM_BUTTONS (1<<6) +#define CM_IMPULSE (1<<7) // r1q2 button byte hacks -#define BUTTON_MASK (BUTTON_ATTACK|BUTTON_USE|BUTTON_ANY) +#define BUTTON_MASK (BUTTON_ATTACK|BUTTON_USE|BUTTON_ANY) #define BUTTON_FORWARD 4 #define BUTTON_SIDE 8 #define BUTTON_UP 16 @@ -267,13 +273,13 @@ typedef enum clc_ops_e { //============================================== // a sound without an ent or pos will be a local only sound -#define SND_VOLUME (1<<0) // a byte -#define SND_ATTENUATION (1<<1) // a byte -#define SND_POS (1<<2) // three coordinates -#define SND_ENT (1<<3) // a short 0-2: channel, 3-12: entity -#define SND_OFFSET (1<<4) // a byte, msec offset from frame start +#define SND_VOLUME (1<<0) // a byte +#define SND_ATTENUATION (1<<1) // a byte +#define SND_POS (1<<2) // three coordinates +#define SND_ENT (1<<3) // a short 0-2: channel, 3-12: entity +#define SND_OFFSET (1<<4) // a byte, msec offset from frame start -#define DEFAULT_SOUND_PACKET_VOLUME 1.0 +#define DEFAULT_SOUND_PACKET_VOLUME 1.0 #define DEFAULT_SOUND_PACKET_ATTENUATION 1.0 //============================================== @@ -281,59 +287,63 @@ typedef enum clc_ops_e { // entity_state_t communication // try to pack the common update flags into the first byte -#define U_ORIGIN1 (1<<0) -#define U_ORIGIN2 (1<<1) -#define U_ANGLE2 (1<<2) -#define U_ANGLE3 (1<<3) -#define U_FRAME8 (1<<4) // frame is a byte -#define U_EVENT (1<<5) -#define U_REMOVE (1<<6) // REMOVE this entity, don't add it -#define U_MOREBITS1 (1<<7) // read one additional byte +#define U_ORIGIN1 (1<<0) +#define U_ORIGIN2 (1<<1) +#define U_ANGLE2 (1<<2) +#define U_ANGLE3 (1<<3) +#define U_FRAME8 (1<<4) // frame is a byte +#define U_EVENT (1<<5) +#define U_REMOVE (1<<6) // REMOVE this entity, don't add it +#define U_MOREBITS1 (1<<7) // read one additional byte // second byte -#define U_NUMBER16 (1<<8) // NUMBER8 is implicit if not set -#define U_ORIGIN3 (1<<9) -#define U_ANGLE1 (1<<10) -#define U_MODEL (1<<11) -#define U_RENDERFX8 (1<<12) // fullbright, etc -#define U_EFFECTS8 (1<<14) // autorotate, trails, etc -#define U_MOREBITS2 (1<<15) // read one additional byte +#define U_NUMBER16 (1<<8) // NUMBER8 is implicit if not set +#define U_ORIGIN3 (1<<9) +#define U_ANGLE1 (1<<10) +#define U_MODEL (1<<11) +#define U_RENDERFX8 (1<<12) // fullbright, etc +#define U_EFFECTS8 (1<<14) // autorotate, trails, etc +#define U_MOREBITS2 (1<<15) // read one additional byte // third byte -#define U_SKIN8 (1<<16) -#define U_FRAME16 (1<<17) // frame is a short -#define U_RENDERFX16 (1<<18) // 8 + 16 = 32 -#define U_EFFECTS16 (1<<19) // 8 + 16 = 32 -#define U_MODEL2 (1<<20) // weapons, flags, etc -#define U_MODEL3 (1<<21) -#define U_MODEL4 (1<<22) -#define U_MOREBITS3 (1<<23) // read one additional byte +#define U_SKIN8 (1<<16) +#define U_FRAME16 (1<<17) // frame is a short +#define U_RENDERFX16 (1<<18) // 8 + 16 = 32 +#define U_EFFECTS16 (1<<19) // 8 + 16 = 32 +#define U_MODEL2 (1<<20) // weapons, flags, etc +#define U_MODEL3 (1<<21) +#define U_MODEL4 (1<<22) +#define U_MOREBITS3 (1<<23) // read one additional byte // fourth byte -#define U_OLDORIGIN (1<<24) // FIXME: get rid of this -#define U_SKIN16 (1<<25) -#define U_SOUND (1<<26) -#define U_SOLID (1<<27) +#define U_OLDORIGIN (1<<24) // FIXME: get rid of this +#define U_SKIN16 (1<<25) +#define U_SOUND (1<<26) +#define U_SOLID (1<<27) +#define U_MASK ((1<<28)-1) + +// not sent over the network +#define U_SOLID32 (1<<31) // ============================================================== -#define CLIENTNUM_NONE ( MAX_CLIENTS - 1 ) -#define CLIENTNUM_RESERVED ( MAX_CLIENTS - 1 ) +#define CLIENTNUM_NONE ( MAX_CLIENTS - 1 ) +#define CLIENTNUM_RESERVED ( MAX_CLIENTS - 1 ) typedef enum clientSetting_e { - // r1q2 specific - CLS_NOGUN, - CLS_NOBLEND, - CLS_RECORDING, + // r1q2 specific + CLS_NOGUN, + CLS_NOBLEND, + CLS_RECORDING, CLS_PLAYERUPDATES, CLS_FPS, - // q2pro specific - CLS_NOGIBS = 10, - CLS_NOFOOTSTEPS, - CLS_NOPREDICT, + // q2pro specific + CLS_NOGIBS = 10, + CLS_NOFOOTSTEPS, + CLS_NOPREDICT, - CLS_MAX + CLS_MAX } clientSetting_t; typedef enum serverSetting_e { @@ -344,12 +354,6 @@ typedef enum serverSetting_e { SVS_MAX } serverSetting_t; -typedef enum gametype_e { - GT_SINGLEPLAYER, - GT_COOP, - GT_DEATHMATCH -} gametype_t; - typedef enum { // these are sent by the server FF_SURPRESSED = ( 1 << 0 ), diff --git a/source/q_field.c b/source/q_field.c index 3e8105e..5f9554c 100644 --- a/source/q_field.c +++ b/source/q_field.c @@ -22,9 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // field.c // -#include <config.h> -#include "q_shared.h" -#include "com_public.h" +#include "com_local.h" #include "key_public.h" #include "ref_public.h" #include "q_field.h" @@ -36,13 +34,9 @@ IF_Init */ void IF_Init( inputField_t *field, size_t visibleChars, size_t maxChars, const char *text ) { memset( field, 0, sizeof( *field ) ); - - clamp( maxChars, 1, sizeof( field->text ) ); - clamp( visibleChars, 1, maxChars ); - - field->maxChars = maxChars; - field->visibleChars = visibleChars; + field->maxChars = clamp( maxChars, 1, sizeof( field->text ) ); + field->visibleChars = clamp( visibleChars, 1, maxChars ); if( text ) { field->cursorPos = Q_strncpyz( field->text, text, maxChars ); } @@ -69,7 +63,6 @@ void IF_Replace( inputField_t *field, const char *text ) { #ifndef DEDICATED_ONLY - /* ================ IF_KeyEvent @@ -125,7 +118,7 @@ qboolean IF_KeyEvent( inputField_t *field, int key ) { } if( key == 'c' && Key_IsDown( K_CTRL ) ) { - sys.SetClipboardData( field->text ); + VID_SetClipboardData( field->text ); return qtrue; } @@ -224,41 +217,34 @@ The input line scrolls horizontally if typing goes beyond the right edge. Returns x offset of the rightmost character drawn. ================ */ -int IF_Draw( inputField_t *field, int x, int y, int flags, qhandle_t hFont ) { - char *text; - size_t cursorPos, offset; +int IF_Draw( inputField_t *field, int x, int y, int flags, qhandle_t font ) { + char *text = field->text; + size_t cursorPos = field->cursorPos; + size_t offset = 0; int ret; - if( field->cursorPos > sizeof( field->text ) - 1 ) { + if( cursorPos >= sizeof( field->text ) ) { Com_Error( ERR_FATAL, "IF_Draw: bad field->cursorPos" ); } - text = field->text; - cursorPos = field->cursorPos; - offset = 0; - - /* scroll horizontally */ + // scroll horizontally if( cursorPos > field->visibleChars - 1 ) { cursorPos = field->visibleChars - 1; offset = field->cursorPos - cursorPos; } - - if( !( flags & UI_DRAWCURSOR ) ) { - /* just draw text and return */ - ret = ref.DrawString( x, y, flags, field->visibleChars, - text + offset, hFont ); - return ret; - } - /* draw text */ + // draw text ret = ref.DrawString( x, y, flags, field->visibleChars, - text + offset, hFont ); + text + offset, font ); - /* draw blinking cursor */ - if( ( sys.Milliseconds() >> 8 ) & 1 ) { - int c = Key_GetOverstrikeMode() ? 11 : '_'; - ref.DrawChar( x + cursorPos * CHAR_WIDTH, y, flags, c, hFont ); + if( flags & UI_DRAWCURSOR ) { + // draw blinking cursor + if( ( com_localTime >> 8 ) & 1 ) { + int c = Key_GetOverstrikeMode() ? 11 : '_'; + ref.DrawChar( x + cursorPos * CHAR_WIDTH, y, flags, c, font ); + } } + return ret; } diff --git a/source/q_msg.c b/source/q_msg.c index d78fb25..f734a35 100644 --- a/source/q_msg.c +++ b/source/q_msg.c @@ -713,8 +713,13 @@ void MSG_WriteDeltaEntity( const entity_state_t *from, MSG_WriteByte (to->sound); if (bits & U_EVENT) MSG_WriteByte (to->event); - if (bits & U_SOLID) - MSG_WriteShort (to->solid); + if (bits & U_SOLID) { + if( flags & MSG_ES_LONGSOLID ) { + MSG_WriteLong (to->solid); + } else { + MSG_WriteShort (to->solid); + } + } } /* @@ -1895,13 +1900,17 @@ MSG_ParseDeltaEntity Can go from either a baseline or a previous packet_entity ================== */ -void MSG_ParseDeltaEntity( const entity_state_t *from, entity_state_t *to, int number, int bits ) { +void MSG_ParseDeltaEntity( const entity_state_t *from, + entity_state_t *to, + int number, + int bits ) +{ if( !to ) { - Com_Error( ERR_DROP, "MSG_ParseDeltaEntity: NULL" ); + Com_Error( ERR_DROP, "%s: NULL", __func__ ); } if( number < 1 || number >= MAX_EDICTS ) { - Com_Error( ERR_DROP, "MSG_ParseDeltaEntity: bad entity number %i", number ); + Com_Error( ERR_DROP, "%s: bad entity number: %d", __func__, number ); } // set everything to the state we are delta'ing from @@ -1916,7 +1925,7 @@ void MSG_ParseDeltaEntity( const entity_state_t *from, entity_state_t *to, int n to->number = number; to->event = 0; - if( !bits ) { + if( ( bits & U_MASK ) == 0 ) { return; } @@ -1992,7 +2001,11 @@ void MSG_ParseDeltaEntity( const entity_state_t *from, entity_state_t *to, int n } if( bits & U_SOLID ) { - to->solid = MSG_ReadWord(); + if( bits & U_SOLID32 ) { + to->solid = MSG_ReadLong(); + } else { + to->solid = MSG_ReadWord(); + } } } @@ -2001,12 +2014,15 @@ void MSG_ParseDeltaEntity( const entity_state_t *from, entity_state_t *to, int n MSG_ParseDeltaPlayerstate_Default =================== */ -void MSG_ParseDeltaPlayerstate_Default( const player_state_t *from, player_state_t *to, int flags ) { +void MSG_ParseDeltaPlayerstate_Default( const player_state_t *from, + player_state_t *to, + int flags ) +{ int i; int statbits; if( !to ) { - Com_Error( ERR_DROP, "MSG_ParseDeltaPlayerstate_Default: NULL" ); + Com_Error( ERR_DROP, "%s: NULL", __func__ ); } // clear to old value before delta parsing @@ -2119,7 +2135,7 @@ void MSG_ParseDeltaPlayerstate_Enhanced( const player_state_t *from, int statbits; if( !to ) { - Com_Error( ERR_DROP, "MSG_ParseDeltaPlayerstate_Enhanced: NULL" ); + Com_Error( ERR_DROP, "%s: NULL", __func__ ); } // clear to old value before delta parsing @@ -2242,12 +2258,15 @@ void MSG_ParseDeltaPlayerstate_Enhanced( const player_state_t *from, MSG_ParseDeltaPlayerstate_Packet =================== */ -void MSG_ParseDeltaPlayerstate_Packet( const player_state_t *from, player_state_t *to, int flags ) { +void MSG_ParseDeltaPlayerstate_Packet( const player_state_t *from, + player_state_t *to, + int flags ) +{ int i; int statbits; if( !to ) { - Com_Error( ERR_DROP, "MSG_ParseDeltaPlayerstate_Packet: NULL" ); + Com_Error( ERR_DROP, "%s: NULL", __func__ ); } // clear to old value before delta parsing diff --git a/source/q_msg.h b/source/q_msg.h index 622d5f5..11df04a 100644 --- a/source/q_msg.h +++ b/source/q_msg.h @@ -69,7 +69,8 @@ typedef enum { MSG_ES_FORCE = ( 1 << 0 ), MSG_ES_NEWENTITY = ( 1 << 1 ), MSG_ES_FIRSTPERSON = ( 1 << 2 ), - MSG_ES_REMOVE = ( 1 << 3 ) + MSG_ES_LONGSOLID = ( 1 << 3 ), + MSG_ES_REMOVE = ( 1 << 4 ) } msgEsFlags_t; extern sizebuf_t msg_write; diff --git a/source/q_shared.c b/source/q_shared.c index 3fb40fb..9d1a81c 100644 --- a/source/q_shared.c +++ b/source/q_shared.c @@ -1838,10 +1838,8 @@ int Q_strncasecmp( const char *s1, const char *s2, size_t n ) { return 0; /* strings are equal until end point */ if( c1 != c2 ) { - if( c1 >= 'a' && c1 <= 'z' ) - c1 -= ( 'a' - 'A' ); - if( c2 >= 'a' && c2 <= 'z' ) - c2 -= ( 'a' - 'A' ); + c1 = Q_tolower( c1 ); + c2 = Q_tolower( c2 ); if( c1 < c2 ) return -1; if( c1 > c2 ) @@ -1860,10 +1858,8 @@ int Q_strcasecmp( const char *s1, const char *s2 ) { c2 = *s2++; if( c1 != c2 ) { - if( c1 >= 'a' && c1 <= 'z' ) - c1 -= ( 'a' - 'A' ); - if( c2 >= 'a' && c2 <= 'z' ) - c2 -= ( 'a' - 'A' ); + c1 = Q_tolower( c1 ); + c2 = Q_tolower( c2 ); if( c1 < c2 ) return -1; if( c1 > c2 ) @@ -2043,6 +2039,25 @@ char *Q_strchrnul( const char *s, int c ) { return ( char * )s; } +void Q_setenv( const char *name, const char *value ) { +#ifdef _WIN32 + if( !value ) { + value = ""; + } +#if( _MSC_VER >= 1400 ) + _putenv_s( name, value ); +#else + _putenv( va( "%s=%s", name, value ) ); +#endif +#else // _WIN32 + if( value ) { + setenv( name, value, 1 ); + } else { + unsetenv( name ); + } +#endif // !_WIN32 +} + /* ===================================================================== diff --git a/source/q_shared.h b/source/q_shared.h index d3f1765..23164fe 100644 --- a/source/q_shared.h +++ b/source/q_shared.h @@ -32,6 +32,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #if HAVE_ENDIAN_H #include <endian.h> #endif +#ifdef _WIN32 +#include <direct.h> +#else +#include <sys/stat.h> +#include <sys/types.h> +#endif #ifdef __GNUC__ @@ -465,9 +471,18 @@ int Q_strncasecmp( const char *s1, const char *s2, size_t n ); #define Q_stricmp Q_strcasecmp #define Q_stricmpn Q_strncasecmp +#ifdef _WIN32 +#define Q_mkdir( p ) _mkdir( p ) +#define Q_unlink( p ) _unlink( p ) +#else +#define Q_mkdir( p ) mkdir( p, 0775 ) +#define Q_unlink( p ) unlink( p ) +#endif + int QDECL SortStrcmp( const void *p1, const void *p2 ); char *Q_strchrnul( const char *s, int c ); +void Q_setenv( const char *name, const char *value ); char *COM_SkipPath( const char *pathname ); void COM_StripExtension( const char *in, char *out, size_t size ); diff --git a/source/r_images.c b/source/r_images.c index 567fdc3..5b92392 100644 --- a/source/r_images.c +++ b/source/r_images.c @@ -1841,7 +1841,7 @@ void R_InitImageManager( void ) { int i; #ifdef TRUECOLOR_RENDERER - r_override_textures = cvar.Get( "r_override_textures", "1", CVAR_ARCHIVE|CVAR_LATCHED ); + r_override_textures = cvar.Get( "r_override_textures", "1", CVAR_ARCHIVE|CVAR_FILES ); r_texture_formats = cvar.Get( "r_texture_formats", #if USE_PNG "p" diff --git a/source/snd_main.c b/source/snd_main.c index 4df6e01..4625722 100644 --- a/source/snd_main.c +++ b/source/snd_main.c @@ -36,7 +36,6 @@ int s_registration_sequence; channel_t channels[MAX_CHANNELS]; qboolean sound_started; -qboolean sound_modified; dma_t dma; @@ -156,10 +155,6 @@ static void S_SoundList_f( void ) { Com_Printf( "Total resident: %i\n", total ); } -static void s_param_changed( cvar_t *self ) { - sound_modified = qtrue; -} - static const cmdreg_t c_sound[] = { { "play", S_Play_f, S_Play_c }, { "stopsound", S_StopAllSounds }, @@ -177,8 +172,7 @@ S_Init void S_Init( void ) { sndinitstat_t ret = SIS_FAILURE; - s_enable = Cvar_Get( "s_enable", "1", 0 ); - s_enable->changed = s_param_changed; + s_enable = Cvar_Get( "s_enable", "1", CVAR_SOUND ); if( !s_enable->integer ) { Com_Printf( "Sound initialization disabled.\n" ); return; @@ -186,10 +180,10 @@ void S_Init( void ) { Com_Printf( "------- S_Init -------\n" ); - s_khz = Cvar_Get( "s_khz", "22", CVAR_ARCHIVE ); + s_khz = Cvar_Get( "s_khz", "22", CVAR_ARCHIVE|CVAR_SOUND ); #if USE_DSOUND - s_direct = Cvar_Get( "s_direct", "1", 0 ); + s_direct = Cvar_Get( "s_direct", "1", CVAR_ARCHIVE|CVAR_SOUND ); if( s_direct->integer ) { DS_FillAPI( &snddma ); ret = snddma.Init(); @@ -224,11 +218,6 @@ void S_Init( void ) { s_registration_sequence = 1; -#if USE_DSOUND - s_direct->changed = s_param_changed; -#endif - s_khz->changed = s_param_changed; - Com_Printf( "sound sampling rate: %i\n", dma.speed ); S_StopAllSounds(); @@ -1024,15 +1013,13 @@ S_Update Called once each time through the main loop ============ */ -void S_Update( void ) -{ +void S_Update( void ) { int i; int total; channel_t *ch; - if( sound_modified ) { + if( cvar_modified & CVAR_SOUND ) { Cbuf_AddText( "snd_restart\n" ); - sound_modified = qfalse; return; } diff --git a/source/snd_oss.c b/source/snd_oss.c index 2753326..1731619 100644 --- a/source/snd_oss.c +++ b/source/snd_oss.c @@ -37,13 +37,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "snd_local.h" static int audio_fd; -static int snd_inited; +static qboolean snd_inited; static struct audio_buf_info info; -static cvar_t *sndbits; -static cvar_t *sndspeed; -static cvar_t *sndchannels; -static cvar_t *snddevice; +static cvar_t *s_bits; +static cvar_t *s_channels; +static cvar_t *s_device; static const int tryrates[] = { 22050, 11025, 44100, 48000, 8000 }; @@ -57,23 +56,22 @@ static sndinitstat_t OSS_Init ( void ) { if ( snd_inited ) return SIS_SUCCESS; - sndbits = Cvar_Get ( "sndbits", "16", CVAR_ARCHIVE|CVAR_LATCHED ); - sndspeed = Cvar_Get ( "sndspeed", "22050", CVAR_ARCHIVE|CVAR_LATCHED ); - sndchannels = Cvar_Get ( "sndchannels", "2", CVAR_ARCHIVE|CVAR_LATCHED ); - snddevice = Cvar_Get ( "snddevice", "/dev/dsp", CVAR_ARCHIVE|CVAR_LATCHED ); + s_bits = Cvar_Get ( "s_bits", "16", CVAR_SOUND ); + s_channels = Cvar_Get ( "s_channels", "2", CVAR_SOUND ); + s_device = Cvar_Get ( "s_device", "/dev/dsp", CVAR_SOUND ); // open /dev/dsp, confirm capability to mmap, and get size of dma buffer - audio_fd = open ( snddevice->string, O_RDWR ); + audio_fd = open ( s_device->string, O_RDWR ); if ( audio_fd < 0 ) { - Com_WPrintf ( "Could not open %s: %s\n", snddevice->string, + Com_WPrintf ( "Could not open %s: %s\n", s_device->string, strerror ( errno ) ); return SIS_FAILURE; } if ( ioctl ( audio_fd, SNDCTL_DSP_GETCAPS, &caps ) == -1 ) { - Com_WPrintf ( "Could not get caps of %s: %s\n", snddevice->string, + Com_WPrintf ( "Could not get caps of %s: %s\n", s_device->string, strerror ( errno ) ); goto fail; } @@ -82,14 +80,14 @@ static sndinitstat_t OSS_Init ( void ) { (DSP_CAP_TRIGGER|DSP_CAP_MMAP) ) { Com_WPrintf ( "%s does not support TRIGGER and/or MMAP capabilities\n", - snddevice->string ); + s_device->string ); goto fail; } // set sample bits & speed - dma.samplebits = sndbits->integer; + dma.samplebits = s_bits->integer; if ( dma.samplebits != 16 && dma.samplebits != 8 ) { ioctl ( audio_fd, SNDCTL_DSP_GETFMTS, &fmt ); if ( fmt & AFMT_S16_LE ) { @@ -99,29 +97,40 @@ static sndinitstat_t OSS_Init ( void ) { } } - dma.speed = sndspeed->integer; - if ( !dma.speed ) { + switch( s_khz->integer ) { + case 48: + dma.speed = 48000; + break; + case 44: + dma.speed = 44100; + break; + case 22: + dma.speed = 22050; + break; + case 11: + dma.speed = 11025; + break; + default: for ( i = 0; i < sizeof ( tryrates ) / 4; i++ ) { if ( !ioctl ( audio_fd, SNDCTL_DSP_SPEED, &tryrates[i] ) ) break; } if ( i == sizeof ( tryrates ) / 4 ) { - Com_WPrintf ( "%s supports no valid bitrates\n", snddevice->string ); + Com_WPrintf ( "%s supports no valid bitrates\n", s_device->string ); goto fail; } dma.speed = tryrates[i]; + break; } - Cvar_ClampInteger ( sndchannels, 1, 2 ); - - dma.channels = sndchannels->integer; + dma.channels = s_channels->integer; tmp = 0; if ( dma.channels == 2 ) tmp = 1; rc = ioctl ( audio_fd, SNDCTL_DSP_STEREO, &tmp ); if ( rc < 0 ) { - Com_WPrintf ( "Could not set %s to %d channels: %s\n", snddevice->string, + Com_WPrintf ( "Could not set %s to %d channels: %s\n", s_device->string, dma.channels, strerror ( errno ) ); goto fail; } @@ -132,7 +141,7 @@ static sndinitstat_t OSS_Init ( void ) { rc = ioctl ( audio_fd, SNDCTL_DSP_SPEED, &dma.speed ); if ( rc < 0 ) { - Com_WPrintf ( "Could not set %s speed to %d: %s\n", snddevice->string, + Com_WPrintf ( "Could not set %s speed to %d: %s\n", s_device->string, dma.speed, strerror ( errno ) ); goto fail; } @@ -168,7 +177,7 @@ static sndinitstat_t OSS_Init ( void ) { dma.buffer = ( byte * ) mmap ( NULL, info.fragstotal * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0 ); if ( !dma.buffer ) { - Com_WPrintf ( "Could not mmap %s: %s\n", snddevice->string, + Com_WPrintf ( "Could not mmap %s: %s\n", s_device->string, strerror ( errno ) ); goto fail; } @@ -196,7 +205,7 @@ static sndinitstat_t OSS_Init ( void ) { dma.samplepos = 0; - snd_inited = 1; + snd_inited = qtrue; return SIS_SUCCESS; fail: @@ -222,7 +231,7 @@ static void OSS_BeginPainting ( void ) { if ( ioctl ( audio_fd, SNDCTL_DSP_GETOPTR, &count ) == -1 ) { Com_EPrintf ( "SNDCTL_DSP_GETOPTR failed on %s: %s\n", - snddevice->string, strerror ( errno ) ); + s_device->string, strerror ( errno ) ); OSS_Shutdown(); return; } diff --git a/source/sv_ents.c b/source/sv_ents.c index 616afc4..a662fee 100644 --- a/source/sv_ents.c +++ b/source/sv_ents.c @@ -35,10 +35,11 @@ SV_EmitPacketEntities Writes a delta update of an entity_state_t list to the message. ============= */ -static void SV_EmitPacketEntities( client_frame_t *from, - client_frame_t *to, - int clientEntityNum, - entity_state_t **baselines ) +static void SV_EmitPacketEntities( client_frame_t *from, + client_frame_t *to, + int clientEntityNum, + entity_state_t **baselines, + msgEsFlags_t baseflags ) { entity_state_t *oldent, *newent; const entity_state_t *base; @@ -79,7 +80,7 @@ static void SV_EmitPacketEntities( client_frame_t *from, // in any bytes being emited if the entity has not changed at all // note that players are always 'newentities', this updates their // oldorigin always and prevents warping - flags = 0; + flags = baseflags; //if( newent->number <= maxplayers ) { // flags |= MSG_ES_NEWENTITY; // FIXME: why? waste of bandwidth //} @@ -96,7 +97,7 @@ static void SV_EmitPacketEntities( client_frame_t *from, if( newnum < oldnum ) { // this is a new entity, send it from the baseline - flags = MSG_ES_FORCE|MSG_ES_NEWENTITY; + flags = baseflags|MSG_ES_FORCE|MSG_ES_NEWENTITY; base = baselines[newnum >> SV_BASELINES_SHIFT]; if( base ) { base += ( newnum & SV_BASELINES_MASK ); @@ -179,7 +180,7 @@ void SV_WriteFrameToClient_Default( client_t *client ) { // delta encode the entities MSG_WriteByte( svc_packetentities ); - SV_EmitPacketEntities( oldframe, frame, 0, client->baselines ); + SV_EmitPacketEntities( oldframe, frame, 0, client->baselines, 0 ); } /* @@ -195,6 +196,7 @@ void SV_WriteFrameToClient_Enhanced( client_t *client ) { byte *b1, *b2; msgPsFlags_t psFlags; int clientEntityNum; + int baseflags; // this is the frame we are creating frame = &client->frames[sv.framenum & UPDATE_MASK]; @@ -275,7 +277,7 @@ void SV_WriteFrameToClient_Enhanced( client_t *client ) { if( client->protocol == PROTOCOL_VERSION_Q2PRO ) { // delta encode the clientNum - if( client->version < PROTOCOL_VERSION_Q2PRO_CLIENTFIX ) { + if( client->version < PROTOCOL_VERSION_Q2PRO_CLIENTNUM_FIX ) { if( !oldframe || frame->clientNum != oldframe->clientNum ) { extraflags |= EPS_CLIENTNUM; MSG_WriteByte( frame->clientNum ); @@ -299,8 +301,14 @@ void SV_WriteFrameToClient_Enhanced( client_t *client ) { client->surpressCount = 0; client->frameflags = 0; + baseflags = 0; + if( LONG_SOLID_SUPPORTED( client->protocol, client->version ) ) { + baseflags |= MSG_ES_LONGSOLID; + } + // delta encode the entities - SV_EmitPacketEntities( oldframe, frame, clientEntityNum, client->baselines ); + SV_EmitPacketEntities( oldframe, frame, clientEntityNum, + client->baselines, baseflags ); } /* @@ -382,7 +390,7 @@ void SV_BuildClientFrame( client_t *client ) { frame->ps = *ps; // grab the current clientNum - if( g_features->integer & GMF_CLIENTNUM ) { + if( svs.gameFeatures & GMF_CLIENTNUM ) { frame->clientNum = clent->client->clientNum; } else { frame->clientNum = client->number; @@ -399,7 +407,7 @@ void SV_BuildClientFrame( client_t *client ) { ent = EDICT_POOL( client, e ); // ignore entities not in use - if( ( g_features->integer & GMF_PROPERINUSE ) && !ent->inuse ) { + if( ( svs.gameFeatures & GMF_PROPERINUSE ) && !ent->inuse ) { continue; } @@ -472,15 +480,18 @@ void SV_BuildClientFrame( client_t *client ) { // XXX: hide this enitity from renderer if( ( client->protocol != PROTOCOL_VERSION_Q2PRO || client->settings[CLS_RECORDING] ) && - ( g_features->integer & GMF_CLIENTNUM ) && + ( svs.gameFeatures & GMF_CLIENTNUM ) && e == frame->clientNum + 1 && ent != clent ) { state->modelindex = 0; } // don't mark players missiles as solid - if( ent->owner == client->edict ) + if( ent->owner == client->edict ) { state->solid = 0; + } else if( LONG_SOLID_SUPPORTED( client->protocol, client->version ) ) { + state->solid = sv.entities[e].solid32; + } svs.nextEntityStates++; diff --git a/source/sv_game.c b/source/sv_game.c index 58391d9..5a24858 100644 --- a/source/sv_game.c +++ b/source/sv_game.c @@ -763,10 +763,7 @@ void SV_ShutdownGameProgs (void) { Sys_FreeLibrary( game_library ); game_library = NULL; } - if( g_features ) { - Cvar_SetByVar( g_features, NULL, CVAR_SET_DIRECT ); - g_features->flags = CVAR_VOLATILE; - } + Q_setenv( "QUAKE2_GAME_FEATURES", NULL ); } /* @@ -780,6 +777,7 @@ void SV_InitGameProgs ( void ) { game_import_t import; char path[MAX_OSPATH]; game_export_t *(*entry)( game_import_t * ) = NULL; + char *s; // unload anything we have now SV_ShutdownGameProgs (); @@ -830,15 +828,15 @@ void SV_InitGameProgs ( void ) { import.BoxEdicts = SV_AreaEdicts; #ifdef _WIN32 #ifdef __GNUC__ - import.trace = ( sv_trace_t )SV_Trace_Old; + import.trace = ( sv_trace_t )SV_Trace; #else - import.trace = SV_Trace; + import.trace = SV_Trace_Native; #endif #else /* _WIN32 */ if( sv_oldgame_hack->integer ) { - import.trace = ( sv_trace_t )SV_Trace_Old; + import.trace = ( sv_trace_t )SV_Trace; } else { - import.trace = SV_Trace; + import.trace = SV_Trace_Native; } #endif /* !_WIN32 */ import.pointcontents = SV_PointContents; @@ -891,9 +889,18 @@ void SV_InitGameProgs ( void ) { ge->apiversion, GAME_API_VERSION); } + // export server features + Q_setenv( "QUAKE2_SERVER_FEATURES", va( "%d", GMF_CLIENTNUM|GMF_MVDSPEC ) ); + // initialize ge->Init (); + // get game features + s = getenv( "QUAKE2_GAME_FEATURES" ); + if( s && *s ) { + svs.gameFeatures = atoi( s ); + } + Sys_FixFPCW(); } diff --git a/source/sv_init.c b/source/sv_init.c index c562969..b3b062f 100644 --- a/source/sv_init.c +++ b/source/sv_init.c @@ -204,15 +204,12 @@ void SV_InitGame( qboolean ismvd ){ } else if( sv_maxclients->integer > CLIENTNUM_RESERVED ) { Cvar_SetInteger( sv_maxclients, CLIENTNUM_RESERVED, CVAR_SET_DIRECT ); } - svs.gametype = GT_DEATHMATCH; } else if( Cvar_VariableInteger( "coop" ) ) { if( sv_maxclients->integer <= 1 || sv_maxclients->integer > 4 ) Cvar_Set( "maxclients", "4" ); - svs.gametype = GT_COOP; } else { // non-deathmatch, non-coop is one player Cvar_FullSet( "maxclients", "1", CVAR_SERVERINFO|CVAR_LATCH, CVAR_SET_DIRECT ); - svs.gametype = GT_SINGLEPLAYER; } // enable networking diff --git a/source/sv_local.h b/source/sv_local.h index fec87df..39c0ecd 100644 --- a/source/sv_local.h +++ b/source/sv_local.h @@ -58,7 +58,11 @@ typedef struct { #define PAUSED_FRAMES 10 -typedef struct server_s { +typedef struct { + int solid32; +} server_entity_t; + +typedef struct { server_state_t state; // precache commands are only valid during load int spawncount; // random number generated each server spawn @@ -69,6 +73,8 @@ typedef struct server_s { char configstrings[MAX_CONFIGSTRINGS][MAX_QPATH]; + server_entity_t entities[MAX_EDICTS]; + struct { fileHandle_t file; int paused; @@ -324,9 +330,7 @@ typedef struct server_static_s { qboolean initialized; // sv_init has completed unsigned realtime, time; // always increasing, no clamping, etc - char mapcmd[MAX_TOKEN_CHARS]; // ie: *intro.cin+base - - gametype_t gametype; + int gameFeatures; client_t *udp_client_pool; // [maxclients] list_t udp_client_list; // linked list of non-free clients @@ -637,9 +641,10 @@ int SV_PointContents (vec3_t p); typedef trace_t (*sv_trace_t)( vec3_t, vec3_t, vec3_t, vec3_t, edict_t *, int ); -trace_t SV_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask); -trace_t *SV_Trace_Old (trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, - edict_t *passedict, int contentmask); +trace_t SV_Trace_Native (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, + edict_t *passedict, int contentmask); +trace_t *SV_Trace (trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, + edict_t *passedict, int contentmask); // mins and maxs are relative // if the entire move stays in a solid volume, trace.allsolid will be set, diff --git a/source/sv_main.c b/source/sv_main.c index 2beeb23..4ece3da 100644 --- a/source/sv_main.c +++ b/source/sv_main.c @@ -86,7 +86,7 @@ cvar_t *sv_status_show; cvar_t *sv_uptime; cvar_t *sv_badauth_time; -cvar_t *g_features; +//cvar_t *g_features; //============================================================================ @@ -1795,12 +1795,10 @@ void SV_Init( void ) { sv_badauth_time = Cvar_Get( "sv_badauth_time", "1", 0 ); sv_badauth_time->changed = sv_badauth_time_changed; - Cvar_Get( "sv_features", va( "%d", GMF_CLIENTNUM|GMF_MVDSPEC ), CVAR_ROM ); - g_features = Cvar_Ref( "g_features" ); + //Cvar_Get( "sv_features", va( "%d", GMF_CLIENTNUM|GMF_MVDSPEC ), CVAR_ROM ); + //g_features = Cvar_Ref( "g_features" ); - // // set up default pmove parameters - // sv_pmp.maxspeed = 300; //sv_pmp.upspeed = 350; sv_pmp.friction = 6; @@ -1824,6 +1822,7 @@ static void SV_FinalMessage( const char *message, int cmd ) { tcpClient_t *t, *tnext; netchan_t *netchan; uint16_t length; + int i; MSG_WriteByte( svc_print ); MSG_WriteByte( PRINT_HIGH ); @@ -1832,29 +1831,18 @@ static void SV_FinalMessage( const char *message, int cmd ) { // send it twice // stagger the packets to crutch operating system limited buffers - - FOR_EACH_CLIENT( client ) { - if( client->state == cs_zombie ) { - continue; - } - netchan = client->netchan; - while( netchan->fragment_pending ) { - netchan->TransmitNextFragment( netchan ); - } - netchan->Transmit( netchan, msg_write.cursize, msg_write.data ); - } - - FOR_EACH_CLIENT( client ) { - if( client->state == cs_zombie ) { - continue; - } - netchan = client->netchan; - while( netchan->fragment_pending ) { - netchan->TransmitNextFragment( netchan ); - } - netchan->Transmit( netchan, msg_write.cursize, msg_write.data ); - } - SZ_Clear( &msg_write ); + for( i = 0; i < 2; i++ ) { + FOR_EACH_CLIENT( client ) { + if( client->state == cs_zombie ) { + continue; + } + netchan = client->netchan; + while( netchan->fragment_pending ) { + netchan->TransmitNextFragment( netchan ); + } + netchan->Transmit( netchan, msg_write.cursize, msg_write.data ); + } + } // send EOF to MVD clients length = 0; diff --git a/source/sv_user.c b/source/sv_user.c index 3e7c845..0c29983 100644 --- a/source/sv_user.c +++ b/source/sv_user.c @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sv_local.h" #include "mvd_local.h" -edict_t *sv_player; +edict_t *sv_player; /* ============================================================ @@ -43,85 +43,94 @@ baseline will be transmitted ================ */ static void create_baselines( void ) { - int i; - edict_t *ent; - entity_state_t *base, **chunk; - - // clear baselines from previous level - for( i = 0; i < SV_BASELINES_CHUNKS; i++ ) { - base = sv_client->baselines[i]; - if( !base ) { - continue; - } - memset( base, 0, sizeof( *base ) * SV_BASELINES_PER_CHUNK ); - } - - for( i = 1; i < sv_client->pool->num_edicts; i++ ) { - ent = EDICT_POOL( sv_client, i ); - - if( ( g_features->integer & GMF_PROPERINUSE ) && !ent->inuse ) { + int i; + edict_t *ent; + entity_state_t *base, **chunk; + + // clear baselines from previous level + for( i = 0; i < SV_BASELINES_CHUNKS; i++ ) { + base = sv_client->baselines[i]; + if( !base ) { + continue; + } + memset( base, 0, sizeof( *base ) * SV_BASELINES_PER_CHUNK ); + } + + for( i = 1; i < sv_client->pool->num_edicts; i++ ) { + ent = EDICT_POOL( sv_client, i ); + + if( ( svs.gameFeatures & GMF_PROPERINUSE ) && !ent->inuse ) { continue; } - if( !ES_INUSE( &ent->s ) ) { - continue; - } + if( !ES_INUSE( &ent->s ) ) { + continue; + } - ent->s.number = i; + ent->s.number = i; - chunk = &sv_client->baselines[i >> SV_BASELINES_SHIFT]; - if( *chunk == NULL ) { - *chunk = SV_Mallocz( sizeof( *base ) * SV_BASELINES_PER_CHUNK ); - } + chunk = &sv_client->baselines[i >> SV_BASELINES_SHIFT]; + if( *chunk == NULL ) { + *chunk = SV_Mallocz( sizeof( *base ) * SV_BASELINES_PER_CHUNK ); + } - base = *chunk + ( i & SV_BASELINES_MASK ); + base = *chunk + ( i & SV_BASELINES_MASK ); - *base = ent->s; - } + *base = ent->s; + } } static void write_plain_configstrings( void ) { - int i; - char *string; - size_t length; - - // write a packet full of data - string = sv_client->configstrings; - for( i = 0; i < MAX_CONFIGSTRINGS; i++, string += MAX_QPATH ) { - if( !string[0] ) { - continue; - } - length = strlen( string ); - if( length > MAX_QPATH ) { - length = MAX_QPATH; - } - // check if this configstring will overflow - if( msg_write.cursize + length + 64 > sv_client->netchan->maxpacketlen ) + int i; + char *string; + size_t length; + + // write a packet full of data + string = sv_client->configstrings; + for( i = 0; i < MAX_CONFIGSTRINGS; i++, string += MAX_QPATH ) { + if( !string[0] ) { + continue; + } + length = strlen( string ); + if( length > MAX_QPATH ) { + length = MAX_QPATH; + } + // check if this configstring will overflow + if( msg_write.cursize + length + 64 > sv_client->netchan->maxpacketlen ) { - SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); + SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); } - MSG_WriteByte( svc_configstring ); - MSG_WriteShort( i ); - MSG_WriteData( string, length ); - MSG_WriteByte( 0 ); - } + MSG_WriteByte( svc_configstring ); + MSG_WriteShort( i ); + MSG_WriteData( string, length ); + MSG_WriteByte( 0 ); + } - SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); + SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); +} + +static void write_baseline( entity_state_t *base ) { + msgEsFlags_t flags = MSG_ES_FORCE; + + if( LONG_SOLID_SUPPORTED( sv_client->protocol, sv_client->version ) ) { + flags |= MSG_ES_LONGSOLID; + } + MSG_WriteDeltaEntity( NULL, base, flags ); } static void write_plain_baselines( void ) { - int i, j; - entity_state_t *base; + int i, j; + entity_state_t *base; - // write a packet full of data + // write a packet full of data for( i = 0; i < SV_BASELINES_CHUNKS; i++ ) { - base = sv_client->baselines[i]; - if( !base ) { - continue; - } - for( j = 0; j < SV_BASELINES_PER_CHUNK; j++ ) { + base = sv_client->baselines[i]; + if( !base ) { + continue; + } + for( j = 0; j < SV_BASELINES_PER_CHUNK; j++ ) { if( base->number ) { // check if this baseline will overflow if( msg_write.cursize + 64 > sv_client->netchan->maxpacketlen ) @@ -130,71 +139,71 @@ static void write_plain_baselines( void ) { } MSG_WriteByte( svc_spawnbaseline ); - MSG_WriteDeltaEntity( NULL, base, MSG_ES_FORCE ); + write_baseline( base ); } base++; } - } + } - SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); + SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); } #if USE_ZLIB static void write_compressed_gamestate( void ) { - sizebuf_t *buf = &sv_client->netchan->message; - entity_state_t *base; - int i, j; - size_t length; + sizebuf_t *buf = &sv_client->netchan->message; + entity_state_t *base; + int i, j; + size_t length; uint8_t *patch; char *string; MSG_WriteByte( svc_gamestate ); - // write configstrings + // write configstrings string = sv_client->configstrings; - for( i = 0; i < MAX_CONFIGSTRINGS; i++, string += MAX_QPATH ) { - if( !string[0] ) { - continue; - } - length = strlen( string ); - if( length > MAX_QPATH ) { - length = MAX_QPATH; - } - - MSG_WriteShort( i ); - MSG_WriteData( string, length ); - MSG_WriteByte( 0 ); - } + for( i = 0; i < MAX_CONFIGSTRINGS; i++, string += MAX_QPATH ) { + if( !string[0] ) { + continue; + } + length = strlen( string ); + if( length > MAX_QPATH ) { + length = MAX_QPATH; + } + + MSG_WriteShort( i ); + MSG_WriteData( string, length ); + MSG_WriteByte( 0 ); + } MSG_WriteShort( MAX_CONFIGSTRINGS ); // end of configstrings // write baselines for( i = 0; i < SV_BASELINES_CHUNKS; i++ ) { - base = sv_client->baselines[i]; - if( !base ) { - continue; - } - for( j = 0; j < SV_BASELINES_PER_CHUNK; j++ ) { + base = sv_client->baselines[i]; + if( !base ) { + continue; + } + for( j = 0; j < SV_BASELINES_PER_CHUNK; j++ ) { if( base->number ) { - MSG_WriteDeltaEntity( NULL, base, MSG_ES_FORCE ); + write_baseline( base ); } base++; } - } + } MSG_WriteShort( 0 ); // end of baselines - SZ_WriteByte( buf, svc_zpacket ); + SZ_WriteByte( buf, svc_zpacket ); patch = SZ_GetSpace( buf, 2 ); - SZ_WriteShort( buf, msg_write.cursize ); + SZ_WriteShort( buf, msg_write.cursize ); deflateReset( &svs.z ); svs.z.next_in = msg_write.data; svs.z.avail_in = ( uInt )msg_write.cursize; svs.z.next_out = buf->data + buf->cursize; svs.z.avail_out = ( uInt )( buf->maxsize - buf->cursize ); - SZ_Clear( &msg_write ); + SZ_Clear( &msg_write ); - if( deflate( &svs.z, Z_FINISH ) != Z_STREAM_END ) { + if( deflate( &svs.z, Z_FINISH ) != Z_STREAM_END ) { SV_DropClient( sv_client, "deflate() failed on gamestate" ); return; } @@ -213,23 +222,23 @@ static inline int z_flush( byte *buffer ) { int ret; ret = deflate( &svs.z, Z_FINISH ); - if( ret != Z_STREAM_END ) { - return ret; - } + if( ret != Z_STREAM_END ) { + return ret; + } if( sv_debug_send->integer ) { Com_Printf( S_COLOR_BLUE"%s: comp: %lu into %lu\n", sv_client->name, svs.z.total_in, svs.z.total_out ); } - MSG_WriteByte( svc_zpacket ); - MSG_WriteShort( svs.z.total_out ); - MSG_WriteShort( svs.z.total_in ); - MSG_WriteData( buffer, svs.z.total_out ); - - SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); + MSG_WriteByte( svc_zpacket ); + MSG_WriteShort( svs.z.total_out ); + MSG_WriteShort( svs.z.total_in ); + MSG_WriteData( buffer, svs.z.total_out ); + + SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); - return ret; + return ret; } static inline void z_reset( byte *buffer ) { @@ -239,52 +248,52 @@ static inline void z_reset( byte *buffer ) { } static void write_compressed_configstrings( void ) { - int i; - size_t length; - byte buffer[MAX_PACKETLEN_WRITABLE]; - char *string; + int i; + size_t length; + byte buffer[MAX_PACKETLEN_WRITABLE]; + char *string; z_reset( buffer ); - // write a packet full of data + // write a packet full of data string = sv_client->configstrings; - for( i = 0; i < MAX_CONFIGSTRINGS; i++, string += MAX_QPATH ) { - if( !string[0] ) { - continue; - } - length = strlen( string ); - if( length > MAX_QPATH ) { - length = MAX_QPATH; - } - - // check if this configstring will overflow - if( svs.z.avail_out < length + 32 ) { - // then flush compressed data - if( z_flush( buffer ) != Z_STREAM_END ) { + for( i = 0; i < MAX_CONFIGSTRINGS; i++, string += MAX_QPATH ) { + if( !string[0] ) { + continue; + } + length = strlen( string ); + if( length > MAX_QPATH ) { + length = MAX_QPATH; + } + + // check if this configstring will overflow + if( svs.z.avail_out < length + 32 ) { + // then flush compressed data + if( z_flush( buffer ) != Z_STREAM_END ) { goto fail; - } + } z_reset( buffer ); - } + } - MSG_WriteByte( svc_configstring ); - MSG_WriteShort( i ); - MSG_WriteData( string, length ); - MSG_WriteByte( 0 ); + MSG_WriteByte( svc_configstring ); + MSG_WriteShort( i ); + MSG_WriteData( string, length ); + MSG_WriteByte( 0 ); svs.z.next_in = msg_write.data; svs.z.avail_in = ( uInt )msg_write.cursize; SZ_Clear( &msg_write ); - if( deflate( &svs.z, Z_SYNC_FLUSH ) != Z_OK ) { + if( deflate( &svs.z, Z_SYNC_FLUSH ) != Z_OK ) { goto fail; } - } + } - // finally flush all remaining compressed data - if( z_flush( buffer ) != Z_STREAM_END ) { + // finally flush all remaining compressed data + if( z_flush( buffer ) != Z_STREAM_END ) { fail: SV_DropClient( sv_client, "deflate() failed on configstrings" ); - } + } } #endif // USE_ZLIB @@ -297,7 +306,7 @@ static void stuff_cmds( list_t *list ) { MSG_WriteData( stuff->string, stuff->len ); MSG_WriteByte( '\n' ); MSG_WriteByte( 0 ); - SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); + SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); } } @@ -316,18 +325,18 @@ void SV_New_f( void ) { char junk[8][16]; int i, j, c; - Com_DPrintf( "New() from %s\n", sv_client->name ); + Com_DPrintf( "New() from %s\n", sv_client->name ); if( sv_client->state < cs_connected ) { - Com_DPrintf( "Going from cs_assigned to cs_connected for %s\n", + Com_DPrintf( "Going from cs_assigned to cs_connected for %s\n", sv_client->name ); sv_client->state = cs_connected; sv_client->lastmessage = svs.realtime; // don't timeout time( &sv_client->connect_time ); } else if( sv_client->state > cs_connected ) { - Com_DPrintf( "New not valid -- already primed\n" ); - return; - } + Com_DPrintf( "New not valid -- already primed\n" ); + return; + } if( sv_force_reconnect->string[0] && !sv_client->reconnect_var[0] && !NET_IsLocalAddress( &sv_client->netchan->remote_address ) ) @@ -363,89 +372,89 @@ void SV_New_f( void ) { return; } - SV_ClientCommand( sv_client, "\n" ); + SV_ClientCommand( sv_client, "\n" ); - // - // serverdata needs to go over for all types of servers - // to make sure the protocol is right, and to set the gamedir - // + // + // serverdata needs to go over for all types of servers + // to make sure the protocol is right, and to set the gamedir + // // create baselines for this client create_baselines(); - // send the serverdata - MSG_WriteByte( svc_serverdata ); - MSG_WriteLong( sv_client->protocol ); - MSG_WriteLong( sv.spawncount ); - MSG_WriteByte( 0 ); // no attract loop - MSG_WriteString( sv_client->gamedir ); - MSG_WriteShort( sv_client->slot ); - MSG_WriteString( &sv_client->configstrings[CS_NAME*MAX_QPATH] ); - - // send protocol specific stuff - switch( sv_client->protocol ) { - case PROTOCOL_VERSION_R1Q2: - MSG_WriteByte( 0 ); // not enhanced - MSG_WriteShort( sv_client->version ); - MSG_WriteByte( 0 ); // no advanced deltas - MSG_WriteByte( sv_strafejump_hack->integer ? 1 : 0 ); - break; - case PROTOCOL_VERSION_Q2PRO: - MSG_WriteShort( sv_client->version ); - MSG_WriteByte( svs.gametype ); - MSG_WriteByte( sv_strafejump_hack->integer ? 1 : 0 ); - MSG_WriteByte( sv_qwmod->integer ); - break; - default: - break; - } - - SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); - - SV_ClientCommand( sv_client, "\n" ); - - // send version string request - if( !sv_client->versionString ) { - SV_ClientCommand( sv_client, "cmd \177c version $version\n" + // send the serverdata + MSG_WriteByte( svc_serverdata ); + MSG_WriteLong( sv_client->protocol ); + MSG_WriteLong( sv.spawncount ); + MSG_WriteByte( 0 ); // no attract loop + MSG_WriteString( sv_client->gamedir ); + MSG_WriteShort( sv_client->slot ); + MSG_WriteString( &sv_client->configstrings[CS_NAME*MAX_QPATH] ); + + // send protocol specific stuff + switch( sv_client->protocol ) { + case PROTOCOL_VERSION_R1Q2: + MSG_WriteByte( 0 ); // not enhanced + MSG_WriteShort( sv_client->version ); + MSG_WriteByte( 0 ); // no advanced deltas + MSG_WriteByte( sv_strafejump_hack->integer ? 1 : 0 ); + break; + case PROTOCOL_VERSION_Q2PRO: + MSG_WriteShort( sv_client->version ); + MSG_WriteByte( 2 ); // used to be GT_DEATHMATCH + MSG_WriteByte( sv_strafejump_hack->integer ? 1 : 0 ); + MSG_WriteByte( sv_qwmod->integer ); + break; + default: + break; + } + + SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); + + SV_ClientCommand( sv_client, "\n" ); + + // send version string request + if( !sv_client->versionString ) { + SV_ClientCommand( sv_client, "cmd \177c version $version\n" #if USE_ANTICHEAT & 2 "cmd \177c actoken $actoken\n" #endif ); stuff_cmds( &sv_cmdlist_connect ); - } + } // send reconnect var request if( sv_force_reconnect->string[0] && !( sv_client->flags & CF_RECONNECTED ) ) { - SV_ClientCommand( sv_client, "cmd \177c connect $%s\n", + SV_ClientCommand( sv_client, "cmd \177c connect $%s\n", sv_client->reconnect_var ); } - Com_DPrintf( "Going from cs_connected to cs_primed for %s\n", + Com_DPrintf( "Going from cs_connected to cs_primed for %s\n", sv_client->name ); - sv_client->state = cs_primed; + sv_client->state = cs_primed; - memset( &sv_client->lastcmd, 0, sizeof( sv_client->lastcmd ) ); + memset( &sv_client->lastcmd, 0, sizeof( sv_client->lastcmd ) ); #if USE_ZLIB if( !( sv_client->flags & CF_DEFLATE ) ) { - write_plain_configstrings(); - write_plain_baselines(); + write_plain_configstrings(); + write_plain_baselines(); } else { if( sv_client->netchan->type == NETCHAN_NEW ) { write_compressed_gamestate(); } else { // FIXME: Z_SYNC_FLUSH is not efficient for baselines write_compressed_configstrings(); - write_plain_baselines(); + write_plain_baselines(); } - } + } #else // USE_ZLIB - write_plain_configstrings(); - write_plain_baselines(); + write_plain_configstrings(); + write_plain_baselines(); #endif // !USE_ZLIB - // send next command - SV_ClientCommand( sv_client, "precache %i\n", sv.spawncount ); + // send next command + SV_ClientCommand( sv_client, "precache %i\n", sv.spawncount ); } /* @@ -454,18 +463,18 @@ SV_Begin_f ================== */ void SV_Begin_f( void ) { - Com_DPrintf( "Begin() from %s\n", sv_client->name ); - - // handle the case of a level changing while a client was connecting - if( sv_client->state < cs_primed ) { - Com_DPrintf( "Begin not valid -- not yet primed\n" ); - SV_New_f(); - return; - } - if( sv_client->state > cs_primed ) { - Com_DPrintf( "Begin not valid -- already spawned\n" ); - return; - } + Com_DPrintf( "Begin() from %s\n", sv_client->name ); + + // handle the case of a level changing while a client was connecting + if( sv_client->state < cs_primed ) { + Com_DPrintf( "Begin not valid -- not yet primed\n" ); + SV_New_f(); + return; + } + if( sv_client->state > cs_primed ) { + Com_DPrintf( "Begin not valid -- already spawned\n" ); + return; + } if( sv_force_reconnect->string[0] && !( sv_client->flags & CF_RECONNECTED ) ) { if( dedicated->integer ) { @@ -482,17 +491,17 @@ void SV_Begin_f( void ) { } #endif - Com_DPrintf( "Going from cs_primed to cs_spawned for %s\n", + Com_DPrintf( "Going from cs_primed to cs_spawned for %s\n", sv_client->name ); - sv_client->state = cs_spawned; - sv_client->send_delta = 0; - sv_client->commandMsec = 1800; + sv_client->state = cs_spawned; + sv_client->send_delta = 0; + sv_client->commandMsec = 1800; sv_client->surpressCount = 0; stuff_cmds( &sv_cmdlist_begin ); - - // call the game begin function - ge->ClientBegin( sv_player ); + + // call the game begin function + ge->ClientBegin( sv_player ); #if USE_ANTICHEAT & 2 AC_ClientAnnounce( sv_client ); @@ -501,7 +510,7 @@ void SV_Begin_f( void ) { //============================================================================= -#define MAX_DOWNLOAD_CHUNK 1024 +#define MAX_DOWNLOAD_CHUNK 1024 /* ================== @@ -509,42 +518,42 @@ SV_NextDownload_f ================== */ static void SV_NextDownload_f( void ) { - int r; - int percent; - int size; - - if ( !sv_client->download ) - return; - - r = sv_client->downloadsize - sv_client->downloadcount; - if ( r > MAX_DOWNLOAD_CHUNK ) - r = MAX_DOWNLOAD_CHUNK; - - MSG_WriteByte( svc_download ); - MSG_WriteShort( r ); - - sv_client->downloadcount += r; - size = sv_client->downloadsize; - if( !size ) - size = 1; - percent = sv_client->downloadcount*100/size; - MSG_WriteByte( percent ); - MSG_WriteData( sv_client->download + sv_client->downloadcount - r, r ); - - if( sv_client->downloadcount == sv_client->downloadsize ) { - Z_Free( sv_client->download ); - sv_client->download = NULL; - } - - SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); + int r; + int percent; + int size; + + if ( !sv_client->download ) + return; + + r = sv_client->downloadsize - sv_client->downloadcount; + if ( r > MAX_DOWNLOAD_CHUNK ) + r = MAX_DOWNLOAD_CHUNK; + + MSG_WriteByte( svc_download ); + MSG_WriteShort( r ); + + sv_client->downloadcount += r; + size = sv_client->downloadsize; + if( !size ) + size = 1; + percent = sv_client->downloadcount*100/size; + MSG_WriteByte( percent ); + MSG_WriteData( sv_client->download + sv_client->downloadcount - r, r ); + + if( sv_client->downloadcount == sv_client->downloadsize ) { + Z_Free( sv_client->download ); + sv_client->download = NULL; + } + + SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); } static void SV_DownloadFailed( void ) { - MSG_WriteByte( svc_download ); - MSG_WriteShort( -1 ); - MSG_WriteByte( 0 ); - SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); + MSG_WriteByte( svc_download ); + MSG_WriteShort( -1 ); + MSG_WriteByte( 0 ); + SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); } /* @@ -553,133 +562,133 @@ SV_BeginDownload_f ================== */ static void SV_BeginDownload_f( void ) { - char name[MAX_QPATH]; - int downloadsize; - int offset = 0; - cvar_t *allow; - int length; - char *filename; - - length = Q_ClearStr( name, Cmd_Argv( 1 ), sizeof( name ) ); - Q_strlwr( name ); - - if( Cmd_Argc() > 2 ) - offset = atoi( Cmd_Argv( 2 ) ); // downloaded offset - - // hacked by zoid to allow more conrol over download - // first off, no .. or global allow check - if( !allow_download->integer - // check for empty paths - || !length - // check for illegal negative offsets - || offset < 0 - // don't allow anything with .. path - || strstr( name, ".." ) - // leading dots, slashes, etc are no good - || !Q_ispath( name[0] ) - // trailing dots, slashes, etc are no good - || !Q_ispath( name[ length - 1 ] ) - // back slashes should be never sent - || strchr( name, '\\' ) - // colons are bad also - || strchr( name, ':' ) - // MUST be in a subdirectory - || !strchr( name, '/' ) ) - { - SV_DownloadFailed(); - return; - } - - if( strncmp( name, "players/", 8 ) == 0 ) { - allow = allow_download_players; - } else if( strncmp( name, "models/", 7 ) == 0 ) { - allow = allow_download_models; - } else if( strncmp( name, "sound/", 6 ) == 0 ) { - allow = allow_download_sounds; - } else if( strncmp( name, "maps/", 5 ) == 0 ) { - allow = allow_download_maps; - } else { - allow = allow_download_other; - } - - if( !allow->integer ) { - Com_DPrintf( "Refusing download of %s to %s\n", name, sv_client->name ); - SV_DownloadFailed(); - return; - } - - if( sv_client->download ) { - Com_DPrintf( "Closing existing download for %s (should not happen)\n", sv_client->name ); - FS_FreeFile( sv_client->download ); - sv_client->download = NULL; - } - - filename = name; - - downloadsize = FS_LoadFileEx( filename, NULL, 0, TAG_SERVER ); - - if( downloadsize == INVALID_LENGTH || downloadsize == 0 - // special check for maps, if it came from a pak file, don't allow - // download ZOID - || ( allow == allow_download_maps - && allow_download_maps->integer < 2 - && FS_LastFileFromPak() ) ) - { - Com_DPrintf( "Couldn't download %s to %s\n", name, sv_client->name ); - SV_DownloadFailed(); - return; - } - - if( offset > downloadsize ) { - Com_DPrintf( "Refusing download, %s has wrong version of %s (%d > %d)\n", - sv_client->name, name, offset, downloadsize ); - SV_ClientPrintf( sv_client, PRINT_HIGH, "File size differs from server.\n" - "Please delete the corresponding .tmp file from your system.\n" ); - SV_DownloadFailed(); - return; - } - - if( offset == downloadsize ) { - Com_DPrintf( "Refusing download, %s already has %s (%d bytes)\n", - sv_client->name, name, offset ); - MSG_WriteByte( svc_download ); - MSG_WriteShort( 0 ); - MSG_WriteByte( 100 ); - SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); - return; - } - - sv_client->downloadsize = FS_LoadFileEx( filename, + char name[MAX_QPATH]; + int downloadsize; + int offset = 0; + cvar_t *allow; + int length; + char *filename; + + length = Q_ClearStr( name, Cmd_Argv( 1 ), sizeof( name ) ); + Q_strlwr( name ); + + if( Cmd_Argc() > 2 ) + offset = atoi( Cmd_Argv( 2 ) ); // downloaded offset + + // hacked by zoid to allow more conrol over download + // first off, no .. or global allow check + if( !allow_download->integer + // check for empty paths + || !length + // check for illegal negative offsets + || offset < 0 + // don't allow anything with .. path + || strstr( name, ".." ) + // leading dots, slashes, etc are no good + || !Q_ispath( name[0] ) + // trailing dots, slashes, etc are no good + || !Q_ispath( name[ length - 1 ] ) + // back slashes should be never sent + || strchr( name, '\\' ) + // colons are bad also + || strchr( name, ':' ) + // MUST be in a subdirectory + || !strchr( name, '/' ) ) + { + SV_DownloadFailed(); + return; + } + + if( strncmp( name, "players/", 8 ) == 0 ) { + allow = allow_download_players; + } else if( strncmp( name, "models/", 7 ) == 0 ) { + allow = allow_download_models; + } else if( strncmp( name, "sound/", 6 ) == 0 ) { + allow = allow_download_sounds; + } else if( strncmp( name, "maps/", 5 ) == 0 ) { + allow = allow_download_maps; + } else { + allow = allow_download_other; + } + + if( !allow->integer ) { + Com_DPrintf( "Refusing download of %s to %s\n", name, sv_client->name ); + SV_DownloadFailed(); + return; + } + + if( sv_client->download ) { + Com_DPrintf( "Closing existing download for %s (should not happen)\n", sv_client->name ); + FS_FreeFile( sv_client->download ); + sv_client->download = NULL; + } + + filename = name; + + downloadsize = FS_LoadFileEx( filename, NULL, 0, TAG_SERVER ); + + if( downloadsize == INVALID_LENGTH || downloadsize == 0 + // special check for maps, if it came from a pak file, don't allow + // download ZOID + || ( allow == allow_download_maps + && allow_download_maps->integer < 2 + && FS_LastFileFromPak() ) ) + { + Com_DPrintf( "Couldn't download %s to %s\n", name, sv_client->name ); + SV_DownloadFailed(); + return; + } + + if( offset > downloadsize ) { + Com_DPrintf( "Refusing download, %s has wrong version of %s (%d > %d)\n", + sv_client->name, name, offset, downloadsize ); + SV_ClientPrintf( sv_client, PRINT_HIGH, "File size differs from server.\n" + "Please delete the corresponding .tmp file from your system.\n" ); + SV_DownloadFailed(); + return; + } + + if( offset == downloadsize ) { + Com_DPrintf( "Refusing download, %s already has %s (%d bytes)\n", + sv_client->name, name, offset ); + MSG_WriteByte( svc_download ); + MSG_WriteShort( 0 ); + MSG_WriteByte( 100 ); + SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); + return; + } + + sv_client->downloadsize = FS_LoadFileEx( filename, ( void ** )&sv_client->download, 0, TAG_SERVER ); - sv_client->downloadcount = offset; + sv_client->downloadcount = offset; - Com_DPrintf( "Downloading %s to %s\n", name, sv_client->name ); + Com_DPrintf( "Downloading %s to %s\n", name, sv_client->name ); - SV_NextDownload_f(); + SV_NextDownload_f(); } static void SV_StopDownload_f( void ) { - int size, percent; - - if( !sv_client->download ) { - return; - } - - size = sv_client->downloadsize; - if( !size ) { - percent = 0; - } else { - percent = sv_client->downloadcount*100/size; - } - - MSG_WriteByte( svc_download ); - MSG_WriteShort( -1 ); - MSG_WriteByte( percent ); - SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); - - Com_DPrintf( "Download for %s stopped by user request\n", sv_client->name ); - Z_Free( sv_client->download ); - sv_client->download = NULL; + int size, percent; + + if( !sv_client->download ) { + return; + } + + size = sv_client->downloadsize; + if( !size ) { + percent = 0; + } else { + percent = sv_client->downloadcount*100/size; + } + + MSG_WriteByte( svc_download ); + MSG_WriteShort( -1 ); + MSG_WriteByte( percent ); + SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR ); + + Com_DPrintf( "Download for %s stopped by user request\n", sv_client->name ); + Z_Free( sv_client->download ); + sv_client->download = NULL; } //============================================================================ @@ -697,7 +706,7 @@ static void SV_Disconnect_f( void ) { Com_Printf( "%s[%s] disconnected\n", sv_client->name, NET_AdrToString( &sv_client->netchan->remote_address ) ); } - SV_DropClient( sv_client, NULL ); + SV_DropClient( sv_client, NULL ); } @@ -713,21 +722,21 @@ static void SV_ShowServerinfo_f( void ) { Cvar_BitInfo( serverinfo, CVAR_SERVERINFO ); - SV_BeginRedirect( RD_CLIENT ); - Info_Print( serverinfo ); - Com_EndRedirect(); + SV_BeginRedirect( RD_CLIENT ); + Info_Print( serverinfo ); + Com_EndRedirect(); } static void SV_NoGameData_f( void ) { - sv_client->flags ^= CF_NODATA; + sv_client->flags ^= CF_NODATA; } static void SV_CvarResult_f( void ) { - char *c, *v; + char *c, *v; - c = Cmd_Argv( 1 ); - if( !strcmp( c, "version" ) ) { - if( !sv_client->versionString ) { + c = Cmd_Argv( 1 ); + if( !strcmp( c, "version" ) ) { + if( !sv_client->versionString ) { v = Cmd_RawArgsFrom( 2 ); if( dedicated->integer ) { Com_Printf( "%s[%s]: %s\n", sv_client->name, @@ -735,7 +744,7 @@ static void SV_CvarResult_f( void ) { } sv_client->versionString = SV_CopyString( v ); } - } else if( !strcmp( c, "connect" ) ) { + } else if( !strcmp( c, "connect" ) ) { if( sv_client->reconnect_var[0] ) { v = Cmd_Argv( 2 ); if( !strcmp( v, sv_client->reconnect_val ) ) { @@ -744,7 +753,7 @@ static void SV_CvarResult_f( void ) { } } #if USE_ANTICHEAT & 2 - else if( !strcmp( c, "actoken" ) ) { + else if( !strcmp( c, "actoken" ) ) { AC_ClientToken( sv_client, Cmd_Argv( 2 ) ); } #endif @@ -753,43 +762,43 @@ static void SV_CvarResult_f( void ) { #if USE_ANTICHEAT & 2 static void SV_AC_List_f( void ) { - SV_BeginRedirect( RD_CLIENT ); - AC_List_f(); - Com_EndRedirect(); + SV_BeginRedirect( RD_CLIENT ); + AC_List_f(); + Com_EndRedirect(); } static void SV_AC_Info_f( void ) { - SV_BeginRedirect( RD_CLIENT ); - AC_Info_f(); - Com_EndRedirect(); + SV_BeginRedirect( RD_CLIENT ); + AC_Info_f(); + Com_EndRedirect(); } #endif static const ucmd_t ucmds[] = { - // auto issued - { "new", SV_New_f }, - { "begin", SV_Begin_f }, - { "baselines", NULL }, - { "configstrings", NULL }, - { "nextserver", NULL }, - { "disconnect", SV_Disconnect_f }, - - // issued by hand at client consoles - { "info", SV_ShowServerinfo_f }, - - { "download", SV_BeginDownload_f }, - { "nextdl", SV_NextDownload_f }, - { "stopdl", SV_StopDownload_f }, - - { "\177c", SV_CvarResult_f }, - { "nogamedata", SV_NoGameData_f }, + // auto issued + { "new", SV_New_f }, + { "begin", SV_Begin_f }, + { "baselines", NULL }, + { "configstrings", NULL }, + { "nextserver", NULL }, + { "disconnect", SV_Disconnect_f }, + + // issued by hand at client consoles + { "info", SV_ShowServerinfo_f }, + + { "download", SV_BeginDownload_f }, + { "nextdl", SV_NextDownload_f }, + { "stopdl", SV_StopDownload_f }, + + { "\177c", SV_CvarResult_f }, + { "nogamedata", SV_NoGameData_f }, #if USE_ANTICHEAT & 2 - { "aclist", SV_AC_List_f }, - { "acinfo", SV_AC_Info_f }, + { "aclist", SV_AC_List_f }, + { "acinfo", SV_AC_Info_f }, #endif - { NULL, NULL } + { NULL, NULL } }; /* @@ -798,16 +807,16 @@ SV_ExecuteUserCommand ================== */ static void SV_ExecuteUserCommand( const char *s ) { - const ucmd_t *u; - char *c; - - Cmd_TokenizeString( s, qfalse ); - sv_player = sv_client->edict; + const ucmd_t *u; + char *c; + + Cmd_TokenizeString( s, qfalse ); + sv_player = sv_client->edict; - c = Cmd_Argv( 0 ); - if( !c[0] ) { - return; - } + c = Cmd_Argv( 0 ); + if( !c[0] ) { + return; + } if( ( u = Com_Find( ucmds, c ) ) != NULL ) { if( u->func ) { @@ -835,17 +844,17 @@ SV_ClientThink ================== */ static inline void SV_ClientThink( client_t *cl, usercmd_t *cmd ) { - cl->commandMsec -= cmd->msec; + cl->commandMsec -= cmd->msec; - if( cl->commandMsec < 0 && sv_enforcetime->integer ) { + if( cl->commandMsec < 0 && sv_enforcetime->integer ) { #ifdef _DEBUG - Com_DPrintf( "commandMsec underflow from %s: %d\n", - cl->name, cl->commandMsec ); + Com_DPrintf( "commandMsec underflow from %s: %d\n", + cl->name, cl->commandMsec ); #endif - return; - } + return; + } - ge->ClientThink( cl->edict, cmd ); + ge->ClientThink( cl->edict, cmd ); } static inline void SV_SetLastFrame( int lastframe ) { @@ -871,17 +880,17 @@ SV_OldClientExecuteMove ================== */ static void SV_OldClientExecuteMove( int net_drop ) { - usercmd_t oldest, oldcmd, newcmd; - int lastframe; + usercmd_t oldest, oldcmd, newcmd; + int lastframe; - if( sv_client->protocol == PROTOCOL_VERSION_DEFAULT ) { - MSG_ReadByte(); // skip over checksum - } - + if( sv_client->protocol == PROTOCOL_VERSION_DEFAULT ) { + MSG_ReadByte(); // skip over checksum + } + lastframe = MSG_ReadLong(); SV_SetLastFrame( lastframe ); - if( sv_client->protocol == PROTOCOL_VERSION_R1Q2 && + if( sv_client->protocol == PROTOCOL_VERSION_R1Q2 && sv_client->version >= PROTOCOL_VERSION_R1Q2_UCMD ) { MSG_ReadDeltaUsercmd_Hacked( NULL, &oldest ); @@ -893,31 +902,31 @@ static void SV_OldClientExecuteMove( int net_drop ) { MSG_ReadDeltaUsercmd( &oldcmd, &newcmd ); } - if( sv_client->state != cs_spawned ) { - sv_client->lastframe = -1; - return; - } + if( sv_client->state != cs_spawned ) { + sv_client->lastframe = -1; + return; + } - if( net_drop > 2 ) { + if( net_drop > 2 ) { sv_client->frameflags |= FF_CLIENTPRED; -// Com_DPrintf( "%s: net_drop %i\n", sv_client->name, net_drop ); - } - - if( net_drop < 20 ) { - while( net_drop > 2 ) { - SV_ClientThink( sv_client, &sv_client->lastcmd ); - net_drop--; - } - if( net_drop > 1 ) - SV_ClientThink( sv_client, &oldest ); - - if( net_drop > 0 ) - SV_ClientThink( sv_client, &oldcmd ); - - } - SV_ClientThink( sv_client, &newcmd ); - - sv_client->lastcmd = newcmd; +// Com_DPrintf( "%s: net_drop %i\n", sv_client->name, net_drop ); + } + + if( net_drop < 20 ) { + while( net_drop > 2 ) { + SV_ClientThink( sv_client, &sv_client->lastcmd ); + net_drop--; + } + if( net_drop > 1 ) + SV_ClientThink( sv_client, &oldest ); + + if( net_drop > 0 ) + SV_ClientThink( sv_client, &oldcmd ); + + } + SV_ClientThink( sv_client, &newcmd ); + + sv_client->lastcmd = newcmd; } @@ -928,91 +937,91 @@ SV_NewClientExecuteMove ================== */ static void SV_NewClientExecuteMove( int c, int net_drop ) { - usercmd_t cmds[MAX_PACKET_FRAMES][MAX_PACKET_USERCMDS]; - usercmd_t *lastcmd, *cmd; - int lastframe; - int numCmds[MAX_PACKET_FRAMES], numDups; - int i, j, lightlevel; - - numDups = c >> SVCMD_BITS; - c &= SVCMD_MASK; - - if( numDups >= MAX_PACKET_FRAMES ) { - SV_DropClient( sv_client, "too many frames in packet" ); - return; - } - - if( c == clc_move_nodelta ) { - lastframe = -1; - } else { - lastframe = MSG_ReadLong(); - } + usercmd_t cmds[MAX_PACKET_FRAMES][MAX_PACKET_USERCMDS]; + usercmd_t *lastcmd, *cmd; + int lastframe; + int numCmds[MAX_PACKET_FRAMES], numDups; + int i, j, lightlevel; + + numDups = c >> SVCMD_BITS; + c &= SVCMD_MASK; + + if( numDups >= MAX_PACKET_FRAMES ) { + SV_DropClient( sv_client, "too many frames in packet" ); + return; + } + + if( c == clc_move_nodelta ) { + lastframe = -1; + } else { + lastframe = MSG_ReadLong(); + } SV_SetLastFrame( lastframe ); - lightlevel = MSG_ReadByte(); - - // read all cmds - lastcmd = NULL; - for( i = 0; i <= numDups; i++ ) { - numCmds[i] = MSG_ReadBits( 5 ); - if( numCmds[i] == -1 ) { - SV_DropClient( sv_client, "read past end of message" ); - return; - } - if( numCmds[i] >= MAX_PACKET_USERCMDS ) { - SV_DropClient( sv_client, "too many usercmds in frame" ); - return; - } - for( j = 0; j < numCmds[i]; j++ ) { - if( msg_read.readcount > msg_read.cursize ) { - SV_DropClient( sv_client, "read past end of message" ); - return; - } - cmd = &cmds[i][j]; - MSG_ReadDeltaUsercmd_Enhanced( lastcmd, cmd, sv_client->version ); - cmd->lightlevel = lightlevel; - lastcmd = cmd; - } - } - if( sv_client->state != cs_spawned ) { - sv_client->lastframe = -1; - return; - } - - if( q_unlikely( !lastcmd ) ) { - return; // should never happen - } - - if( net_drop > numDups ) { + lightlevel = MSG_ReadByte(); + + // read all cmds + lastcmd = NULL; + for( i = 0; i <= numDups; i++ ) { + numCmds[i] = MSG_ReadBits( 5 ); + if( numCmds[i] == -1 ) { + SV_DropClient( sv_client, "read past end of message" ); + return; + } + if( numCmds[i] >= MAX_PACKET_USERCMDS ) { + SV_DropClient( sv_client, "too many usercmds in frame" ); + return; + } + for( j = 0; j < numCmds[i]; j++ ) { + if( msg_read.readcount > msg_read.cursize ) { + SV_DropClient( sv_client, "read past end of message" ); + return; + } + cmd = &cmds[i][j]; + MSG_ReadDeltaUsercmd_Enhanced( lastcmd, cmd, sv_client->version ); + cmd->lightlevel = lightlevel; + lastcmd = cmd; + } + } + if( sv_client->state != cs_spawned ) { + sv_client->lastframe = -1; + return; + } + + if( q_unlikely( !lastcmd ) ) { + return; // should never happen + } + + if( net_drop > numDups ) { sv_client->frameflags |= FF_CLIENTPRED; -// Com_DPrintf( "%s: net_drop %i\n", sv_client->name, net_drop ); - } - - if( net_drop < 20 ) { - // run lastcmd multiple times if no backups available - while( net_drop > numDups ) { - SV_ClientThink( sv_client, &sv_client->lastcmd ); - net_drop--; - } - - // run backup cmds, if any - while( net_drop > 0 ) { - i = numDups - net_drop; - for( j = 0; j < numCmds[i]; j++ ) { - SV_ClientThink( sv_client, &cmds[i][j] ); - } - net_drop--; - } - - } - - // run new cmds - for( j = 0; j < numCmds[numDups]; j++ ) { - SV_ClientThink( sv_client, &cmds[numDups][j] ); - } - - sv_client->lastcmd = *lastcmd; +// Com_DPrintf( "%s: net_drop %i\n", sv_client->name, net_drop ); + } + + if( net_drop < 20 ) { + // run lastcmd multiple times if no backups available + while( net_drop > numDups ) { + SV_ClientThink( sv_client, &sv_client->lastcmd ); + net_drop--; + } + + // run backup cmds, if any + while( net_drop > 0 ) { + i = numDups - net_drop; + for( j = 0; j < numCmds[i]; j++ ) { + SV_ClientThink( sv_client, &cmds[i][j] ); + } + net_drop--; + } + + } + + // run new cmds + for( j = 0; j < numCmds[numDups]; j++ ) { + SV_ClientThink( sv_client, &cmds[numDups][j] ); + } + + sv_client->lastcmd = *lastcmd; } /* @@ -1023,153 +1032,151 @@ The current net_message is parsed for the given client =================== */ void SV_ExecuteClientMessage( client_t *client ) { - int c; - char *s; - qboolean move_issued; - int stringCmdCount; - int userinfoUpdateCount; - int net_drop; - - sv_client = client; - sv_player = sv_client->edict; - - // only allow one move command - move_issued = qfalse; - stringCmdCount = 0; - userinfoUpdateCount = 0; - - net_drop = client->netchan->dropped; + int c; + char *s; + qboolean move_issued; + int stringCmdCount; + int userinfoUpdateCount; + int net_drop; + + sv_client = client; + sv_player = sv_client->edict; + + // only allow one move command + move_issued = qfalse; + stringCmdCount = 0; + userinfoUpdateCount = 0; + + net_drop = client->netchan->dropped; if( net_drop > 0 ) { client->frameflags |= FF_CLIENTDROP; } - while( 1 ) { - if( msg_read.readcount > msg_read.cursize ) { - SV_DropClient( client, "read past end of message" ); - break; - } - - c = MSG_ReadByte(); - if( c == -1 ) - break; - - switch( c & SVCMD_MASK ) { - default: - badbyte: - SV_DropClient( client, "unknown command byte" ); - break; - - case clc_nop: - break; - - case clc_userinfo: - s = MSG_ReadString(); - - // malicious users may try sending too many userinfo updates - if( userinfoUpdateCount == MAX_PACKET_USERINFOS ) { - Com_DPrintf( "Too many userinfos from %s\n", client->name ); - break; - } - - SV_UpdateUserinfo( s ); - userinfoUpdateCount++; - break; - - case clc_move: - if( move_issued ) { - SV_DropClient( client, "multiple clc_move commands in packet" ); - break; // someone is trying to cheat... - } - - move_issued = qtrue; - - SV_OldClientExecuteMove( net_drop ); - break; - - case clc_stringcmd: - s = MSG_ReadString(); - - Com_DPrintf( "ClientCommand( %s ): %s\n", client->name, s ); - - // malicious users may try using too many string commands - if( stringCmdCount == MAX_PACKET_STRINGCMDS ) { - Com_DPrintf( "Too many stringcmds from %s\n", client->name ); - break; - } - SV_ExecuteUserCommand( s ); - stringCmdCount++; - break; - - // r1q2 specific operations - case clc_setting: { - uint16_t idx, value; - - if( client->protocol < PROTOCOL_VERSION_R1Q2 ) { - goto badbyte; - } - - idx = MSG_ReadShort(); - value = MSG_ReadShort(); - if( idx < CLS_MAX ) { - client->settings[idx] = value; - } - } - break; - - - // q2pro specific operations - case clc_move_nodelta: - case clc_move_batched: - if( client->protocol != PROTOCOL_VERSION_Q2PRO ) { - goto badbyte; - } - - if( move_issued ) { - SV_DropClient( client, "multiple clc_move commands in packet" ); - break; // someone is trying to cheat... - } - - move_issued = qtrue; - SV_NewClientExecuteMove( c, net_drop ); - break; - - case clc_userinfo_delta: { - char *key, *value; - char buffer[MAX_INFO_STRING]; - - if( client->protocol != PROTOCOL_VERSION_Q2PRO ) { - goto badbyte; - } - - key = MSG_ReadString(); - value = MSG_ReadString(); - - // malicious users may try sending too many userinfo updates - if( userinfoUpdateCount == MAX_PACKET_USERINFOS ) { - Com_DPrintf( "Too many userinfos from %s\n", client->name ); - break; - } - userinfoUpdateCount++; - - strcpy( buffer, client->userinfo ); - if( !Info_SetValueForKey( buffer, key, value ) ) { - SV_DropClient( client, "malformed delta userinfo" ); - break; - } - - SV_UpdateUserinfo( buffer ); - } - break; - } - - if( client->state < cs_assigned ) { - break; // disconnect command - } - } - - sv_client = NULL; - sv_player = NULL; -} + while( 1 ) { + if( msg_read.readcount > msg_read.cursize ) { + SV_DropClient( client, "read past end of message" ); + break; + } + + c = MSG_ReadByte(); + if( c == -1 ) + break; + + switch( c & SVCMD_MASK ) { + default: + badbyte: + SV_DropClient( client, "unknown command byte" ); + break; + + case clc_nop: + break; + + case clc_userinfo: + s = MSG_ReadString(); + + // malicious users may try sending too many userinfo updates + if( userinfoUpdateCount == MAX_PACKET_USERINFOS ) { + Com_DPrintf( "Too many userinfos from %s\n", client->name ); + break; + } + + SV_UpdateUserinfo( s ); + userinfoUpdateCount++; + break; + + case clc_move: + if( move_issued ) { + SV_DropClient( client, "multiple clc_move commands in packet" ); + break; // someone is trying to cheat... + } + + move_issued = qtrue; + + SV_OldClientExecuteMove( net_drop ); + break; + + case clc_stringcmd: + s = MSG_ReadString(); + + Com_DPrintf( "ClientCommand( %s ): %s\n", client->name, s ); + + // malicious users may try using too many string commands + if( stringCmdCount == MAX_PACKET_STRINGCMDS ) { + Com_DPrintf( "Too many stringcmds from %s\n", client->name ); + break; + } + SV_ExecuteUserCommand( s ); + stringCmdCount++; + break; + + // r1q2 specific operations + case clc_setting: { + uint16_t idx, value; + + if( client->protocol < PROTOCOL_VERSION_R1Q2 ) { + goto badbyte; + } + idx = MSG_ReadShort(); + value = MSG_ReadShort(); + if( idx < CLS_MAX ) { + client->settings[idx] = value; + } + } + break; + + + // q2pro specific operations + case clc_move_nodelta: + case clc_move_batched: + if( client->protocol != PROTOCOL_VERSION_Q2PRO ) { + goto badbyte; + } + + if( move_issued ) { + SV_DropClient( client, "multiple clc_move commands in packet" ); + break; // someone is trying to cheat... + } + + move_issued = qtrue; + SV_NewClientExecuteMove( c, net_drop ); + break; + + case clc_userinfo_delta: { + char *key, *value; + char buffer[MAX_INFO_STRING]; + + if( client->protocol != PROTOCOL_VERSION_Q2PRO ) { + goto badbyte; + } + + key = MSG_ReadString(); + value = MSG_ReadString(); + // malicious users may try sending too many userinfo updates + if( userinfoUpdateCount == MAX_PACKET_USERINFOS ) { + Com_DPrintf( "Too many userinfos from %s\n", client->name ); + break; + } + userinfoUpdateCount++; + + strcpy( buffer, client->userinfo ); + if( !Info_SetValueForKey( buffer, key, value ) ) { + SV_DropClient( client, "malformed delta userinfo" ); + break; + } + + SV_UpdateUserinfo( buffer ); + } + break; + } + + if( client->state < cs_assigned ) { + break; // disconnect command + } + } + + sv_client = NULL; + sv_player = NULL; +} diff --git a/source/sv_world.c b/source/sv_world.c index 52c6b8b..54f5e30 100644 --- a/source/sv_world.c +++ b/source/sv_world.c @@ -243,10 +243,46 @@ void PF_UnlinkEdict (edict_t *ent) { ent->area.prev = ent->area.next = NULL; } +static int SV_CalcSolid( vec3_t mins, vec3_t maxs ) { + int i, j, k; + + // assume that x/y are equal and symetric + i = maxs[0] / 8; + clamp( i, 1, 31 ); + + // z is not symetric + j = ( -mins[2] ) / 8; + clamp( j, 1, 31 ); + + // and z maxs can be negative... + k = ( maxs[2] + 32 ) / 8; + clamp( k, 1, 63 ); + + return ( k << 10 ) | ( j << 5 ) | i; +} + +static int SV_CalcSolid32( vec3_t mins, vec3_t maxs ) { + int i, j, k; + + // assume that x/y are equal and symetric + i = maxs[0]; + clamp( i, 1, 255 ); + + // z is not symetric + j = -mins[2]; + clamp( j, 1, 255 ); + + // and z maxs can be negative... + k = maxs[2] + 32768; + clamp( k, 1, 65535 ); + + return ( k << 16 ) | ( j << 8 ) | i; +} void PF_LinkEdict (edict_t *ent) { areanode_t *node; - int i, j, k; + server_entity_t *sent; + int entnum; if (ent->area.prev) PF_UnlinkEdict (ent); // unlink from old position @@ -261,37 +297,29 @@ void PF_LinkEdict (edict_t *ent) { return; } + entnum = NUM_FOR_EDICT( ent ); + sent = &sv.entities[entnum]; + // encode the size into the entity_state for client prediction - if (ent->solid == SOLID_BBOX && !(ent->svflags & SVF_DEADMONSTER)) - { // assume that x/y are equal and symetric - i = ent->maxs[0]/8; - if (i<1) - i = 1; - if (i>31) - i = 31; - - // z is not symetric - j = (-ent->mins[2])/8; - if (j<1) - j = 1; - if (j>31) - j = 31; - - // and z maxs can be negative... - k = (ent->maxs[2]+32)/8; - if (k<1) - k = 1; - if (k>63) - k = 63; - - ent->s.solid = (k<<10) | (j<<5) | i; - } - else if (ent->solid == SOLID_BSP) - { + switch( ent->solid ) { + case SOLID_BBOX: + if( ( ent->svflags & SVF_DEADMONSTER ) || VectorCompare( ent->mins, ent->maxs ) ) { + ent->s.solid = 0; + sent->solid32 = 0; + } else { + ent->s.solid = SV_CalcSolid( ent->mins, ent->maxs ); + sent->solid32 = SV_CalcSolid32( ent->mins, ent->maxs ); + } + break; + case SOLID_BSP: ent->s.solid = 31; // a solid_bbox will never create this value - } - else + sent->solid32 = 31; // FIXME: use 255? + break; + default: ent->s.solid = 0; + sent->solid32 = 0; + break; + } SV_LinkEdict( &sv.cm, ent ); @@ -434,7 +462,7 @@ int SV_PointContents (vec3_t p) cnode_t *headnode; if( !sv.cm.cache ) { - Com_Error( ERR_DROP, "SV_PointContents: no map loaded" ); + Com_Error( ERR_DROP, "%s: no map loaded", __func__ ); } // get base contents from world @@ -545,80 +573,15 @@ SV_Trace Moves the given mins/maxs volume through the world from start to end. Passedict and edicts owned by passedict are explicitly not checked. - ================== */ -trace_t SV_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask) { - moveclip_t clip; - trace_t trace; - - if( !sv.cm.cache ) { - Com_Error( ERR_DROP, "SV_Trace: no map loaded" ); - } - - if( ++sv.tracecount > 10000 ) { - Com_EPrintf( "SV_Trace: game DLL caught in infinite loop!\n" ); - memset( &trace, 0, sizeof( trace ) ); - trace.fraction = 1; - trace.ent = ge->edicts; - VectorCopy( end, trace.endpos ); - sv.tracecount = 0; - return trace; - } - - if (!mins) - mins = vec3_origin; - if (!maxs) - maxs = vec3_origin; - - // clip to world - CM_BoxTrace ( &trace, start, end, mins, maxs, sv.cm.cache->nodes, contentmask); - trace.ent = ge->edicts; - if (trace.fraction == 0) { - return trace; // blocked by the world - } - - memset( &clip, 0, sizeof( clip ) ); - clip.trace = &trace; - clip.contentmask = contentmask; - clip.start = start; - clip.end = end; - clip.mins = mins; - clip.maxs = maxs; - clip.passedict = passedict; - - // create the bounding box of the entire move - SV_TraceBounds( &clip ); - - // clip to other solid entities - SV_ClipMoveToEntities( &clip ); - - return trace; -} - -/* -================== -SV_Trace_Old - -HACK: different compilers (and even different versions -of the same compiler) handle returning of structures differently. - -This function is intended to be binary-compatible with -game DLLs built by earlier versions of GCC. - -Game DLLs built by MSVC seems to behave similary to old GCC -(except they additionaly require pointer to destination -structure to be retured in EAX register), so this function is linked in -when building with MinGW, under assumption that no mods built with MinGW ever exist. -================== -*/ -trace_t *SV_Trace_Old (trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, +trace_t *SV_Trace(trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask) { moveclip_t clip; if( !sv.cm.cache ) { - Com_Error( ERR_DROP, "SV_Trace: no map loaded" ); + Com_Error( ERR_DROP, "%s: no map loaded", __func__ ); } if( ++sv.tracecount > 10000 ) { @@ -661,3 +624,18 @@ trace_t *SV_Trace_Old (trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, v return trace; } +/* +================== +SV_Trace_Native + +Variant of SV_Trace for native game ABI +================== +*/ +trace_t SV_Trace_Native (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask) { + trace_t trace; + + SV_Trace( &trace, start, mins, maxs, end, passedict, contentmask ); + + return trace; +} + diff --git a/source/sw_main.c b/source/sw_main.c index 7a63d7e..085c7cc 100644 --- a/source/sw_main.c +++ b/source/sw_main.c @@ -267,7 +267,7 @@ void R_Register (void) r_lerpmodels = cvar.Get( "r_lerpmodels", "1", 0 ); r_novis = cvar.Get( "r_novis", "0", 0 ); - vid_gamma = cvar.Get( "vid_gamma", "1.0", CVAR_ARCHIVE|CVAR_LATCHED ); + vid_gamma = cvar.Get( "vid_gamma", "1.0", CVAR_ARCHIVE|CVAR_FILES ); cmd.AddCommand ("modellist", Mod_Modellist_f); cmd.AddCommand( "screenshot", R_ScreenShot_f ); diff --git a/source/sys_unix.c b/source/sys_unix.c index 009cd4f..bfcf87b 100644 --- a/source/sys_unix.c +++ b/source/sys_unix.c @@ -49,17 +49,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "q_field.h" #include "prompt.h" -#ifdef DEDICATED_ONLY -#undef USE_SDL -#endif - -#if USE_SDL -#include <SDL.h> -#if USE_X11 -#include <SDL_syswm.h> -#endif -#endif - cvar_t *sys_basedir; cvar_t *sys_libdir; cvar_t *sys_refdir; @@ -497,32 +486,6 @@ unsigned Sys_Milliseconds( void ) { /* ================ -Sys_Mkdir -================ -*/ -qboolean Sys_Mkdir( const char *path ) { - if( mkdir( path, 0777 ) == -1 ) { - return qfalse; - } - return qtrue; -} - -qboolean Sys_RemoveFile( const char *path ) { - if( unlink( path ) == -1 ) { - return qfalse; - } - return qtrue; -} - -qboolean Sys_RenameFile( const char *from, const char *to ) { - if( rename( from, to ) == -1 ) { - return qfalse; - } - return qtrue; -} - -/* -================ Sys_GetPathInfo ================ */ @@ -578,79 +541,6 @@ void Sys_Quit( void ) { /* ================= -Sys_GetClipboardData -================= -*/ -char *Sys_GetClipboardData( void ) { -#if USE_SDL && USE_X11 - SDL_SysWMinfo info; - Display *dpy; - Window sowner, win; - Atom type, property; - unsigned long len, bytes_left; - unsigned char *data; - int format, result; - char *ret; - - if( SDL_WasInit( SDL_INIT_VIDEO ) != SDL_INIT_VIDEO ) { - return NULL; - } - SDL_VERSION( &info.version ); - if( !SDL_GetWMInfo( &info ) ) { - return NULL; - } - if( info.subsystem != SDL_SYSWM_X11 ) { - return NULL; - } - - dpy = info.info.x11.display; - win = info.info.x11.window; - - sowner = XGetSelectionOwner( dpy, XA_PRIMARY ); - if( sowner == None ) { - return NULL; - } - - property = XInternAtom( dpy, "GETCLIPBOARDDATA_PROP", False ); - - XConvertSelection( dpy, XA_PRIMARY, XA_STRING, property, win, CurrentTime ); - - XSync( dpy, False ); - - result = XGetWindowProperty( dpy, win, property, 0, 0, False, - AnyPropertyType, &type, &format, &len, &bytes_left, &data ); - - if( result != Success ) { - return NULL; - } - - ret = NULL; - if( bytes_left ) { - result = XGetWindowProperty( dpy, win, property, 0, bytes_left, True, - AnyPropertyType, &type, &format, &len, &bytes_left, &data ); - if( result == Success ) { - ret = Z_CopyString( ( char * )data ); - } - } - - XFree( data ); - - return ret; -#else - return NULL; -#endif -} - -/* -================= -Sys_SetClipboardData -================= -*/ -void Sys_SetClipboardData( const char *data ) { -} - -/* -================= Sys_GetCurrentDirectory ================= */ @@ -691,10 +581,6 @@ void Sys_Sleep( int msec ) { nanosleep( &req, NULL ); } -void Sys_Setenv( const char *name, const char *value ) { - setenv( name, value, 1 ); -} - #if USE_ANTICHEAT & 1 qboolean Sys_GetAntiCheatAPI( void ) { Sys_Sleep( 1500 ); @@ -709,8 +595,6 @@ Sys_FillAPI */ void Sys_FillAPI( sysAPI_t *api ) { api->Milliseconds = Sys_Milliseconds; - api->GetClipboardData = Sys_GetClipboardData; - api->SetClipboardData = Sys_SetClipboardData; api->HunkBegin = Hunk_Begin; api->HunkAlloc = Hunk_Alloc; api->HunkEnd = Hunk_End; @@ -760,10 +644,8 @@ Sys_Kill static void Sys_Kill( int signum ) { Sys_ShutdownTTY(); -#if USE_SDL - SDL_ShowCursor( SDL_ENABLE ); - SDL_WM_GrabInput( SDL_GRAB_OFF ); - SDL_Quit(); +#ifndef DEDICATED_ONLY + VID_FatalShutdown(); #endif #ifdef _GNU_SOURCE @@ -866,10 +748,8 @@ void Sys_Error( const char *error, ... ) { Sys_ShutdownTTY(); -#if USE_SDL - SDL_WM_GrabInput( SDL_GRAB_OFF ); - SDL_ShowCursor( SDL_ENABLE ); - SDL_Quit(); +#ifndef DEDICATED_ONLY + VID_FatalShutdown(); #endif va_start( argptr, error ); @@ -882,12 +762,6 @@ void Sys_Error( const char *error, ... ) { exit( 1 ); } - -/*void floating_point_exception_handler( int whatever ) { - signal( SIGFPE, floating_point_exception_handler ); -}*/ - - /* ======================================================================== diff --git a/source/sys_win.c b/source/sys_win.c index d145c45..2f12029 100644 --- a/source/sys_win.c +++ b/source/sys_win.c @@ -638,32 +638,6 @@ unsigned Sys_Milliseconds( void ) { return timeGetTime(); } -/* -================ -Sys_Mkdir -================ -*/ -qboolean Sys_Mkdir( const char *path ) { - if( !CreateDirectoryA( path, NULL ) ) { - return qfalse; - } - return qtrue; -} - -qboolean Sys_RemoveFile( const char *path ) { - if( !DeleteFileA( path ) ) { - return qfalse; - } - return qtrue; -} - -qboolean Sys_RenameFile( const char *from, const char *to ) { - if( !MoveFileA( from, to ) ) { - return qfalse; - } - return qtrue; -} - void Sys_AddDefaultConfig( void ) { } @@ -703,75 +677,11 @@ qboolean Sys_GetFileInfo( FILE *fp, fsFileInfo_t *info ) { /* ================ -Sys_GetClipboardData - -================ -*/ -char *Sys_GetClipboardData( void ) { - HANDLE clipdata; - char *data = NULL; - char *cliptext; - - if( OpenClipboard( NULL ) == FALSE ) { - Com_DPrintf( "Couldn't open clipboard.\n" ); - return data; - } - - if( ( clipdata = GetClipboardData( CF_TEXT ) ) != NULL ) { - if( ( cliptext = GlobalLock( clipdata ) ) != NULL ) { - data = Z_CopyString( cliptext ); - GlobalUnlock( clipdata ); - } - } - CloseClipboard(); - - return data; -} - -/* -================ -Sys_SetClipboardData - -================ -*/ -void Sys_SetClipboardData( const char *data ) { - HANDLE clipdata; - char *cliptext; - size_t length; - - if( !data[0] ) { - return; - } - - if( OpenClipboard( NULL ) == FALSE ) { - Com_DPrintf( "Couldn't open clipboard.\n" ); - return; - } - - EmptyClipboard(); - - length = strlen( data ) + 1; - if( ( clipdata = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE, length ) ) != NULL ) { - if( ( cliptext = GlobalLock( clipdata ) ) != NULL ) { - memcpy( cliptext, data, length ); - GlobalUnlock( clipdata ); - SetClipboardData( CF_TEXT, clipdata ); - } - } - - CloseClipboard(); -} - - -/* -================ Sys_FillAPI ================ */ void Sys_FillAPI( sysAPI_t *api ) { api->Milliseconds = Sys_Milliseconds; - api->GetClipboardData = Sys_GetClipboardData; - api->SetClipboardData = Sys_SetClipboardData; api->HunkBegin = Hunk_Begin; api->HunkAlloc = Hunk_Alloc; api->HunkEnd = Hunk_End; @@ -786,15 +696,6 @@ void Sys_Sleep( int msec ) { Sleep( msec ); } -void Sys_Setenv( const char *name, const char *value ) { -#if( _MSC_VER >= 1400 ) - _putenv_s( name, value ); -#else - _putenv( va( "%s=%s", name, value ) ); -#endif -} - - /* ================ Sys_Init diff --git a/source/ui_atoms.c b/source/ui_atoms.c index 20adc91..bafee89 100644 --- a/source/ui_atoms.c +++ b/source/ui_atoms.c @@ -51,8 +51,10 @@ void UI_PushMenu( menuFrameWork_t *menu ) { } if( i == uis.menuDepth ) { - if( uis.menuDepth >= MAX_MENU_DEPTH ) - Com_Error( ERR_FATAL, "UI_PushMenu: MAX_MENU_DEPTH" ); + if( uis.menuDepth >= MAX_MENU_DEPTH ) { + Com_EPrintf( "UI_PushMenu: MAX_MENU_DEPTH exceeded\n" ); + return; + } uis.layers[uis.menuDepth++] = menu; } else { for( j = i; j < uis.menuDepth; j++ ) { @@ -75,7 +77,7 @@ void UI_PushMenu( menuFrameWork_t *menu ) { if( !uis.activeMenu ) { uis.entersound = qtrue; - //CL_WarpMouse( 0, 0 ); + IN_WarpMouse( 0, menu->y1 ); } uis.transparent |= menu->transparent; diff --git a/source/vid_sdl.c b/source/vid_sdl.c index 68872c3..74d5cb1 100644 --- a/source/vid_sdl.c +++ b/source/vid_sdl.c @@ -91,6 +91,79 @@ static void SetHints( void ) { #endif } +/* +================= +VID_GetClipboardData +================= +*/ +char *VID_GetClipboardData( void ) { +#if USE_SDL && USE_X11 + SDL_SysWMinfo info; + Display *dpy; + Window sowner, win; + Atom type, property; + unsigned long len, bytes_left; + unsigned char *data; + int format, result; + char *ret; + + if( SDL_WasInit( SDL_INIT_VIDEO ) != SDL_INIT_VIDEO ) { + return NULL; + } + SDL_VERSION( &info.version ); + if( !SDL_GetWMInfo( &info ) ) { + return NULL; + } + if( info.subsystem != SDL_SYSWM_X11 ) { + return NULL; + } + + dpy = info.info.x11.display; + win = info.info.x11.window; + + sowner = XGetSelectionOwner( dpy, XA_PRIMARY ); + if( sowner == None ) { + return NULL; + } + + property = XInternAtom( dpy, "GETCLIPBOARDDATA_PROP", False ); + + XConvertSelection( dpy, XA_PRIMARY, XA_STRING, property, win, CurrentTime ); + + XSync( dpy, False ); + + result = XGetWindowProperty( dpy, win, property, 0, 0, False, + AnyPropertyType, &type, &format, &len, &bytes_left, &data ); + + if( result != Success ) { + return NULL; + } + + ret = NULL; + if( bytes_left ) { + result = XGetWindowProperty( dpy, win, property, 0, bytes_left, True, + AnyPropertyType, &type, &format, &len, &bytes_left, &data ); + if( result == Success ) { + ret = Z_CopyString( ( char * )data ); + } + } + + XFree( data ); + + return ret; +#else + return NULL; +#endif +} + +/* +================= +VID_SetClipboardData +================= +*/ +void VID_SetClipboardData( const char *data ) { +} + static qboolean SetMode( int flags, int forcedepth ) { SDL_Surface *surf; vrect_t rc; @@ -143,6 +216,12 @@ void VID_ModeChanged( void ) { } } +void VID_FatalShutdown( void ) { + SDL_ShowCursor( SDL_ENABLE ); + SDL_WM_GrabInput( SDL_GRAB_OFF ); + SDL_Quit(); +} + static qboolean InitVideo( void ) { SDL_Color color; byte *dst; diff --git a/source/vid_win.c b/source/vid_win.c index cbb0573..b5bb881 100644 --- a/source/vid_win.c +++ b/source/vid_win.c @@ -746,7 +746,7 @@ void Win_Init( void ) { // register variables vid_flip_on_switch = Cvar_Get( "vid_flip_on_switch", "0", 0 ); - vid_hwgamma = Cvar_Get( "vid_hwgamma", "0", CVAR_ARCHIVE|CVAR_LATCHED ); + vid_hwgamma = Cvar_Get( "vid_hwgamma", "0", CVAR_ARCHIVE|CVAR_REFRESH ); win_noalttab = Cvar_Get( "win_noalttab", "0", CVAR_ARCHIVE ); win_noalttab->changed = win_noalttab_changed; win_disablewinkey = Cvar_Get( "win_disablewinkey", "0", CVAR_ARCHIVE ); @@ -1003,6 +1003,65 @@ static void Win_GrabMouse( grab_t grab ) { } /* +================ +VID_GetClipboardData +================ +*/ +char *VID_GetClipboardData( void ) { + HANDLE clipdata; + char *data = NULL; + char *cliptext; + + if( OpenClipboard( NULL ) == FALSE ) { + Com_DPrintf( "Couldn't open clipboard.\n" ); + return data; + } + + if( ( clipdata = GetClipboardData( CF_TEXT ) ) != NULL ) { + if( ( cliptext = GlobalLock( clipdata ) ) != NULL ) { + data = Z_CopyString( cliptext ); + GlobalUnlock( clipdata ); + } + } + CloseClipboard(); + + return data; +} + +/* +================ +VID_SetClipboardData +================ +*/ +void VID_SetClipboardData( const char *data ) { + HANDLE clipdata; + char *cliptext; + size_t length; + + if( !data[0] ) { + return; + } + + if( OpenClipboard( NULL ) == FALSE ) { + Com_DPrintf( "Couldn't open clipboard.\n" ); + return; + } + + EmptyClipboard(); + + length = strlen( data ) + 1; + if( ( clipdata = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE, length ) ) != NULL ) { + if( ( cliptext = GlobalLock( clipdata ) ) != NULL ) { + memcpy( cliptext, data, length ); + GlobalUnlock( clipdata ); + SetClipboardData( CF_TEXT, clipdata ); + } + } + + CloseClipboard(); +} + +/* @@@@@@@@@@@@@@@@@@@ VID_FillInputAPI @@@@@@@@@@@@@@@@@@@ diff --git a/source/win_glimp.c b/source/win_glimp.c index 3393d0b..e5d8851 100644 --- a/source/win_glimp.c +++ b/source/win_glimp.c @@ -186,7 +186,7 @@ doing the wgl interface stuff. static qboolean GLimp_Init( void ) { const char *extensions; - gl_driver = Cvar_Get( "gl_driver", "opengl32", CVAR_ARCHIVE|CVAR_LATCHED ); + gl_driver = Cvar_Get( "gl_driver", "opengl32", CVAR_ARCHIVE|CVAR_REFRESH ); gl_drawbuffer = Cvar_Get( "gl_drawbuffer", "GL_BACK", 0 ); gl_swapinterval = Cvar_Get( "gl_swapinterval", "1", CVAR_ARCHIVE ); |