Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

common.c (34055B)


      1 /*
      2 Copyright (C) 1997-2001 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 // common.c -- misc functions used in client and server
     21 #include "qcommon.h"
     22 #include <setjmp.h>
     23 
     24 #define	MAXPRINTMSG	4096
     25 
     26 #define MAX_NUM_ARGVS	50
     27 
     28 
     29 int		com_argc;
     30 char	*com_argv[MAX_NUM_ARGVS+1];
     31 
     32 int		realtime;
     33 
     34 jmp_buf abortframe;		// an ERR_DROP occured, exit the entire frame
     35 
     36 
     37 FILE	*log_stats_file;
     38 
     39 cvar_t	*host_speeds;
     40 cvar_t	*log_stats;
     41 cvar_t	*developer;
     42 cvar_t	*timescale;
     43 cvar_t	*fixedtime;
     44 cvar_t	*logfile_active;	// 1 = buffer log, 2 = flush after each print
     45 cvar_t	*showtrace;
     46 cvar_t	*dedicated;
     47 
     48 FILE	*logfile;
     49 
     50 int			server_state;
     51 
     52 // host_speeds times
     53 int		time_before_game;
     54 int		time_after_game;
     55 int		time_before_ref;
     56 int		time_after_ref;
     57 
     58 /*
     59 ============================================================================
     60 
     61 CLIENT / SERVER interactions
     62 
     63 ============================================================================
     64 */
     65 
     66 static int	rd_target;
     67 static char	*rd_buffer;
     68 static int	rd_buffersize;
     69 static void	(*rd_flush)(int target, char *buffer);
     70 
     71 void Com_BeginRedirect (int target, char *buffer, int buffersize, void (*flush))
     72 {
     73 	if (!target || !buffer || !buffersize || !flush)
     74 		return;
     75 	rd_target = target;
     76 	rd_buffer = buffer;
     77 	rd_buffersize = buffersize;
     78 	rd_flush = flush;
     79 
     80 	*rd_buffer = 0;
     81 }
     82 
     83 void Com_EndRedirect (void)
     84 {
     85 	rd_flush(rd_target, rd_buffer);
     86 
     87 	rd_target = 0;
     88 	rd_buffer = NULL;
     89 	rd_buffersize = 0;
     90 	rd_flush = NULL;
     91 }
     92 
     93 /*
     94 =============
     95 Com_Printf
     96 
     97 Both client and server can use this, and it will output
     98 to the apropriate place.
     99 =============
    100 */
    101 void Com_Printf (char *fmt, ...)
    102 {
    103 	va_list		argptr;
    104 	char		msg[MAXPRINTMSG];
    105 
    106 	va_start (argptr,fmt);
    107 	vsprintf (msg,fmt,argptr);
    108 	va_end (argptr);
    109 
    110 	if (rd_target)
    111 	{
    112 		if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1))
    113 		{
    114 			rd_flush(rd_target, rd_buffer);
    115 			*rd_buffer = 0;
    116 		}
    117 		strcat (rd_buffer, msg);
    118 		return;
    119 	}
    120 
    121 	Con_Print (msg);
    122 		
    123 	// also echo to debugging console
    124 	Sys_ConsoleOutput (msg);
    125 
    126 	// logfile
    127 	if (logfile_active && logfile_active->value)
    128 	{
    129 		char	name[MAX_QPATH];
    130 		
    131 		if (!logfile)
    132 		{
    133 			Com_sprintf (name, sizeof(name), "%s/qconsole.log", FS_Gamedir ());
    134 			logfile = fopen (name, "w");
    135 		}
    136 		if (logfile)
    137 			fprintf (logfile, "%s", msg);
    138 		if (logfile_active->value > 1)
    139 			fflush (logfile);		// force it to save every time
    140 	}
    141 }
    142 
    143 
    144 /*
    145 ================
    146 Com_DPrintf
    147 
    148 A Com_Printf that only shows up if the "developer" cvar is set
    149 ================
    150 */
    151 void Com_DPrintf (char *fmt, ...)
    152 {
    153 	va_list		argptr;
    154 	char		msg[MAXPRINTMSG];
    155 		
    156 	if (!developer || !developer->value)
    157 		return;			// don't confuse non-developers with techie stuff...
    158 
    159 	va_start (argptr,fmt);
    160 	vsprintf (msg,fmt,argptr);
    161 	va_end (argptr);
    162 	
    163 	Com_Printf ("%s", msg);
    164 }
    165 
    166 
    167 /*
    168 =============
    169 Com_Error
    170 
    171 Both client and server can use this, and it will
    172 do the apropriate things.
    173 =============
    174 */
    175 void Com_Error (int code, char *fmt, ...)
    176 {
    177 	va_list		argptr;
    178 	static char		msg[MAXPRINTMSG];
    179 	static	qboolean	recursive;
    180 
    181 	if (recursive)
    182 		Sys_Error ("recursive error after: %s", msg);
    183 	recursive = true;
    184 
    185 	va_start (argptr,fmt);
    186 	vsprintf (msg,fmt,argptr);
    187 	va_end (argptr);
    188 	
    189 	if (code == ERR_DISCONNECT)
    190 	{
    191 		CL_Drop ();
    192 		recursive = false;
    193 		longjmp (abortframe, -1);
    194 	}
    195 	else if (code == ERR_DROP)
    196 	{
    197 		Com_Printf ("********************\nERROR: %s\n********************\n", msg);
    198 		SV_Shutdown (va("Server crashed: %s\n", msg), false);
    199 		CL_Drop ();
    200 		recursive = false;
    201 		longjmp (abortframe, -1);
    202 	}
    203 	else
    204 	{
    205 		SV_Shutdown (va("Server fatal crashed: %s\n", msg), false);
    206 		CL_Shutdown ();
    207 	}
    208 
    209 	if (logfile)
    210 	{
    211 		fclose (logfile);
    212 		logfile = NULL;
    213 	}
    214 
    215 	Sys_Error ("%s", msg);
    216 }
    217 
    218 
    219 /*
    220 =============
    221 Com_Quit
    222 
    223 Both client and server can use this, and it will
    224 do the apropriate things.
    225 =============
    226 */
    227 void Com_Quit (void)
    228 {
    229 	SV_Shutdown ("Server quit\n", false);
    230 	CL_Shutdown ();
    231 
    232 	if (logfile)
    233 	{
    234 		fclose (logfile);
    235 		logfile = NULL;
    236 	}
    237 
    238 	Sys_Quit ();
    239 }
    240 
    241 
    242 /*
    243 ==================
    244 Com_ServerState
    245 ==================
    246 */
    247 int Com_ServerState (void)
    248 {
    249 	return server_state;
    250 }
    251 
    252 /*
    253 ==================
    254 Com_SetServerState
    255 ==================
    256 */
    257 void Com_SetServerState (int state)
    258 {
    259 	server_state = state;
    260 }
    261 
    262 
    263 /*
    264 ==============================================================================
    265 
    266 			MESSAGE IO FUNCTIONS
    267 
    268 Handles byte ordering and avoids alignment errors
    269 ==============================================================================
    270 */
    271 
    272 vec3_t	bytedirs[NUMVERTEXNORMALS] =
    273 {
    274 #include "../client/anorms.h"
    275 };
    276 
    277 //
    278 // writing functions
    279 //
    280 
    281 void MSG_WriteChar (sizebuf_t *sb, int c)
    282 {
    283 	byte	*buf;
    284 	
    285 #ifdef PARANOID
    286 	if (c < -128 || c > 127)
    287 		Com_Error (ERR_FATAL, "MSG_WriteChar: range error");
    288 #endif
    289 
    290 	buf = SZ_GetSpace (sb, 1);
    291 	buf[0] = c;
    292 }
    293 
    294 void MSG_WriteByte (sizebuf_t *sb, int c)
    295 {
    296 	byte	*buf;
    297 	
    298 #ifdef PARANOID
    299 	if (c < 0 || c > 255)
    300 		Com_Error (ERR_FATAL, "MSG_WriteByte: range error");
    301 #endif
    302 
    303 	buf = SZ_GetSpace (sb, 1);
    304 	buf[0] = c;
    305 }
    306 
    307 void MSG_WriteShort (sizebuf_t *sb, int c)
    308 {
    309 	byte	*buf;
    310 	
    311 #ifdef PARANOID
    312 	if (c < ((short)0x8000) || c > (short)0x7fff)
    313 		Com_Error (ERR_FATAL, "MSG_WriteShort: range error");
    314 #endif
    315 
    316 	buf = SZ_GetSpace (sb, 2);
    317 	buf[0] = c&0xff;
    318 	buf[1] = c>>8;
    319 }
    320 
    321 void MSG_WriteLong (sizebuf_t *sb, int c)
    322 {
    323 	byte	*buf;
    324 	
    325 	buf = SZ_GetSpace (sb, 4);
    326 	buf[0] = c&0xff;
    327 	buf[1] = (c>>8)&0xff;
    328 	buf[2] = (c>>16)&0xff;
    329 	buf[3] = c>>24;
    330 }
    331 
    332 void MSG_WriteFloat (sizebuf_t *sb, float f)
    333 {
    334 	union
    335 	{
    336 		float	f;
    337 		int	l;
    338 	} dat;
    339 	
    340 	
    341 	dat.f = f;
    342 	dat.l = LittleLong (dat.l);
    343 	
    344 	SZ_Write (sb, &dat.l, 4);
    345 }
    346 
    347 void MSG_WriteString (sizebuf_t *sb, char *s)
    348 {
    349 	if (!s)
    350 		SZ_Write (sb, "", 1);
    351 	else
    352 		SZ_Write (sb, s, strlen(s)+1);
    353 }
    354 
    355 void MSG_WriteCoord (sizebuf_t *sb, float f)
    356 {
    357 	MSG_WriteShort (sb, (int)(f*8));
    358 }
    359 
    360 void MSG_WritePos (sizebuf_t *sb, vec3_t pos)
    361 {
    362 	MSG_WriteShort (sb, (int)(pos[0]*8));
    363 	MSG_WriteShort (sb, (int)(pos[1]*8));
    364 	MSG_WriteShort (sb, (int)(pos[2]*8));
    365 }
    366 
    367 void MSG_WriteAngle (sizebuf_t *sb, float f)
    368 {
    369 	MSG_WriteByte (sb, (int)(f*256/360) & 255);
    370 }
    371 
    372 void MSG_WriteAngle16 (sizebuf_t *sb, float f)
    373 {
    374 	MSG_WriteShort (sb, ANGLE2SHORT(f));
    375 }
    376 
    377 
    378 void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd)
    379 {
    380 	int		bits;
    381 
    382 //
    383 // send the movement message
    384 //
    385 	bits = 0;
    386 	if (cmd->angles[0] != from->angles[0])
    387 		bits |= CM_ANGLE1;
    388 	if (cmd->angles[1] != from->angles[1])
    389 		bits |= CM_ANGLE2;
    390 	if (cmd->angles[2] != from->angles[2])
    391 		bits |= CM_ANGLE3;
    392 	if (cmd->forwardmove != from->forwardmove)
    393 		bits |= CM_FORWARD;
    394 	if (cmd->sidemove != from->sidemove)
    395 		bits |= CM_SIDE;
    396 	if (cmd->upmove != from->upmove)
    397 		bits |= CM_UP;
    398 	if (cmd->buttons != from->buttons)
    399 		bits |= CM_BUTTONS;
    400 	if (cmd->impulse != from->impulse)
    401 		bits |= CM_IMPULSE;
    402 
    403     MSG_WriteByte (buf, bits);
    404 
    405 	if (bits & CM_ANGLE1)
    406 		MSG_WriteShort (buf, cmd->angles[0]);
    407 	if (bits & CM_ANGLE2)
    408 		MSG_WriteShort (buf, cmd->angles[1]);
    409 	if (bits & CM_ANGLE3)
    410 		MSG_WriteShort (buf, cmd->angles[2]);
    411 	
    412 	if (bits & CM_FORWARD)
    413 		MSG_WriteShort (buf, cmd->forwardmove);
    414 	if (bits & CM_SIDE)
    415 	  	MSG_WriteShort (buf, cmd->sidemove);
    416 	if (bits & CM_UP)
    417 		MSG_WriteShort (buf, cmd->upmove);
    418 
    419  	if (bits & CM_BUTTONS)
    420 	  	MSG_WriteByte (buf, cmd->buttons);
    421  	if (bits & CM_IMPULSE)
    422 	    MSG_WriteByte (buf, cmd->impulse);
    423 
    424     MSG_WriteByte (buf, cmd->msec);
    425 	MSG_WriteByte (buf, cmd->lightlevel);
    426 }
    427 
    428 
    429 void MSG_WriteDir (sizebuf_t *sb, vec3_t dir)
    430 {
    431 	int		i, best;
    432 	float	d, bestd;
    433 	
    434 	if (!dir)
    435 	{
    436 		MSG_WriteByte (sb, 0);
    437 		return;
    438 	}
    439 
    440 	bestd = 0;
    441 	best = 0;
    442 	for (i=0 ; i<NUMVERTEXNORMALS ; i++)
    443 	{
    444 		d = DotProduct (dir, bytedirs[i]);
    445 		if (d > bestd)
    446 		{
    447 			bestd = d;
    448 			best = i;
    449 		}
    450 	}
    451 	MSG_WriteByte (sb, best);
    452 }
    453 
    454 
    455 void MSG_ReadDir (sizebuf_t *sb, vec3_t dir)
    456 {
    457 	int		b;
    458 
    459 	b = MSG_ReadByte (sb);
    460 	if (b >= NUMVERTEXNORMALS)
    461 		Com_Error (ERR_DROP, "MSF_ReadDir: out of range");
    462 	VectorCopy (bytedirs[b], dir);
    463 }
    464 
    465 
    466 /*
    467 ==================
    468 MSG_WriteDeltaEntity
    469 
    470 Writes part of a packetentities message.
    471 Can delta from either a baseline or a previous packet_entity
    472 ==================
    473 */
    474 void MSG_WriteDeltaEntity (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean newentity)
    475 {
    476 	int		bits;
    477 
    478 	if (!to->number)
    479 		Com_Error (ERR_FATAL, "Unset entity number");
    480 	if (to->number >= MAX_EDICTS)
    481 		Com_Error (ERR_FATAL, "Entity number >= MAX_EDICTS");
    482 
    483 // send an update
    484 	bits = 0;
    485 
    486 	if (to->number >= 256)
    487 		bits |= U_NUMBER16;		// number8 is implicit otherwise
    488 
    489 	if (to->origin[0] != from->origin[0])
    490 		bits |= U_ORIGIN1;
    491 	if (to->origin[1] != from->origin[1])
    492 		bits |= U_ORIGIN2;
    493 	if (to->origin[2] != from->origin[2])
    494 		bits |= U_ORIGIN3;
    495 
    496 	if ( to->angles[0] != from->angles[0] )
    497 		bits |= U_ANGLE1;		
    498 	if ( to->angles[1] != from->angles[1] )
    499 		bits |= U_ANGLE2;
    500 	if ( to->angles[2] != from->angles[2] )
    501 		bits |= U_ANGLE3;
    502 		
    503 	if ( to->skinnum != from->skinnum )
    504 	{
    505 		if ((unsigned)to->skinnum < 256)
    506 			bits |= U_SKIN8;
    507 		else if ((unsigned)to->skinnum < 0x10000)
    508 			bits |= U_SKIN16;
    509 		else
    510 			bits |= (U_SKIN8|U_SKIN16);
    511 	}
    512 		
    513 	if ( to->frame != from->frame )
    514 	{
    515 		if (to->frame < 256)
    516 			bits |= U_FRAME8;
    517 		else
    518 			bits |= U_FRAME16;
    519 	}
    520 
    521 	if ( to->effects != from->effects )
    522 	{
    523 		if (to->effects < 256)
    524 			bits |= U_EFFECTS8;
    525 		else if (to->effects < 0x8000)
    526 			bits |= U_EFFECTS16;
    527 		else
    528 			bits |= U_EFFECTS8|U_EFFECTS16;
    529 	}
    530 	
    531 	if ( to->renderfx != from->renderfx )
    532 	{
    533 		if (to->renderfx < 256)
    534 			bits |= U_RENDERFX8;
    535 		else if (to->renderfx < 0x8000)
    536 			bits |= U_RENDERFX16;
    537 		else
    538 			bits |= U_RENDERFX8|U_RENDERFX16;
    539 	}
    540 	
    541 	if ( to->solid != from->solid )
    542 		bits |= U_SOLID;
    543 
    544 	// event is not delta compressed, just 0 compressed
    545 	if ( to->event  )
    546 		bits |= U_EVENT;
    547 	
    548 	if ( to->modelindex != from->modelindex )
    549 		bits |= U_MODEL;
    550 	if ( to->modelindex2 != from->modelindex2 )
    551 		bits |= U_MODEL2;
    552 	if ( to->modelindex3 != from->modelindex3 )
    553 		bits |= U_MODEL3;
    554 	if ( to->modelindex4 != from->modelindex4 )
    555 		bits |= U_MODEL4;
    556 
    557 	if ( to->sound != from->sound )
    558 		bits |= U_SOUND;
    559 
    560 	if (newentity || (to->renderfx & RF_BEAM))
    561 		bits |= U_OLDORIGIN;
    562 
    563 	//
    564 	// write the message
    565 	//
    566 	if (!bits && !force)
    567 		return;		// nothing to send!
    568 
    569 	//----------
    570 
    571 	if (bits & 0xff000000)
    572 		bits |= U_MOREBITS3 | U_MOREBITS2 | U_MOREBITS1;
    573 	else if (bits & 0x00ff0000)
    574 		bits |= U_MOREBITS2 | U_MOREBITS1;
    575 	else if (bits & 0x0000ff00)
    576 		bits |= U_MOREBITS1;
    577 
    578 	MSG_WriteByte (msg,	bits&255 );
    579 
    580 	if (bits & 0xff000000)
    581 	{
    582 		MSG_WriteByte (msg,	(bits>>8)&255 );
    583 		MSG_WriteByte (msg,	(bits>>16)&255 );
    584 		MSG_WriteByte (msg,	(bits>>24)&255 );
    585 	}
    586 	else if (bits & 0x00ff0000)
    587 	{
    588 		MSG_WriteByte (msg,	(bits>>8)&255 );
    589 		MSG_WriteByte (msg,	(bits>>16)&255 );
    590 	}
    591 	else if (bits & 0x0000ff00)
    592 	{
    593 		MSG_WriteByte (msg,	(bits>>8)&255 );
    594 	}
    595 
    596 	//----------
    597 
    598 	if (bits & U_NUMBER16)
    599 		MSG_WriteShort (msg, to->number);
    600 	else
    601 		MSG_WriteByte (msg,	to->number);
    602 
    603 	if (bits & U_MODEL)
    604 		MSG_WriteByte (msg,	to->modelindex);
    605 	if (bits & U_MODEL2)
    606 		MSG_WriteByte (msg,	to->modelindex2);
    607 	if (bits & U_MODEL3)
    608 		MSG_WriteByte (msg,	to->modelindex3);
    609 	if (bits & U_MODEL4)
    610 		MSG_WriteByte (msg,	to->modelindex4);
    611 
    612 	if (bits & U_FRAME8)
    613 		MSG_WriteByte (msg, to->frame);
    614 	if (bits & U_FRAME16)
    615 		MSG_WriteShort (msg, to->frame);
    616 
    617 	if ((bits & U_SKIN8) && (bits & U_SKIN16))		//used for laser colors
    618 		MSG_WriteLong (msg, to->skinnum);
    619 	else if (bits & U_SKIN8)
    620 		MSG_WriteByte (msg, to->skinnum);
    621 	else if (bits & U_SKIN16)
    622 		MSG_WriteShort (msg, to->skinnum);
    623 
    624 
    625 	if ( (bits & (U_EFFECTS8|U_EFFECTS16)) == (U_EFFECTS8|U_EFFECTS16) )
    626 		MSG_WriteLong (msg, to->effects);
    627 	else if (bits & U_EFFECTS8)
    628 		MSG_WriteByte (msg, to->effects);
    629 	else if (bits & U_EFFECTS16)
    630 		MSG_WriteShort (msg, to->effects);
    631 
    632 	if ( (bits & (U_RENDERFX8|U_RENDERFX16)) == (U_RENDERFX8|U_RENDERFX16) )
    633 		MSG_WriteLong (msg, to->renderfx);
    634 	else if (bits & U_RENDERFX8)
    635 		MSG_WriteByte (msg, to->renderfx);
    636 	else if (bits & U_RENDERFX16)
    637 		MSG_WriteShort (msg, to->renderfx);
    638 
    639 	if (bits & U_ORIGIN1)
    640 		MSG_WriteCoord (msg, to->origin[0]);		
    641 	if (bits & U_ORIGIN2)
    642 		MSG_WriteCoord (msg, to->origin[1]);
    643 	if (bits & U_ORIGIN3)
    644 		MSG_WriteCoord (msg, to->origin[2]);
    645 
    646 	if (bits & U_ANGLE1)
    647 		MSG_WriteAngle(msg, to->angles[0]);
    648 	if (bits & U_ANGLE2)
    649 		MSG_WriteAngle(msg, to->angles[1]);
    650 	if (bits & U_ANGLE3)
    651 		MSG_WriteAngle(msg, to->angles[2]);
    652 
    653 	if (bits & U_OLDORIGIN)
    654 	{
    655 		MSG_WriteCoord (msg, to->old_origin[0]);
    656 		MSG_WriteCoord (msg, to->old_origin[1]);
    657 		MSG_WriteCoord (msg, to->old_origin[2]);
    658 	}
    659 
    660 	if (bits & U_SOUND)
    661 		MSG_WriteByte (msg, to->sound);
    662 	if (bits & U_EVENT)
    663 		MSG_WriteByte (msg, to->event);
    664 	if (bits & U_SOLID)
    665 		MSG_WriteShort (msg, to->solid);
    666 }
    667 
    668 
    669 //============================================================
    670 
    671 //
    672 // reading functions
    673 //
    674 
    675 void MSG_BeginReading (sizebuf_t *msg)
    676 {
    677 	msg->readcount = 0;
    678 }
    679 
    680 // returns -1 if no more characters are available
    681 int MSG_ReadChar (sizebuf_t *msg_read)
    682 {
    683 	int	c;
    684 	
    685 	if (msg_read->readcount+1 > msg_read->cursize)
    686 		c = -1;
    687 	else
    688 		c = (signed char)msg_read->data[msg_read->readcount];
    689 	msg_read->readcount++;
    690 	
    691 	return c;
    692 }
    693 
    694 int MSG_ReadByte (sizebuf_t *msg_read)
    695 {
    696 	int	c;
    697 	
    698 	if (msg_read->readcount+1 > msg_read->cursize)
    699 		c = -1;
    700 	else
    701 		c = (unsigned char)msg_read->data[msg_read->readcount];
    702 	msg_read->readcount++;
    703 	
    704 	return c;
    705 }
    706 
    707 int MSG_ReadShort (sizebuf_t *msg_read)
    708 {
    709 	int	c;
    710 	
    711 	if (msg_read->readcount+2 > msg_read->cursize)
    712 		c = -1;
    713 	else		
    714 		c = (short)(msg_read->data[msg_read->readcount]
    715 		+ (msg_read->data[msg_read->readcount+1]<<8));
    716 	
    717 	msg_read->readcount += 2;
    718 	
    719 	return c;
    720 }
    721 
    722 int MSG_ReadLong (sizebuf_t *msg_read)
    723 {
    724 	int	c;
    725 	
    726 	if (msg_read->readcount+4 > msg_read->cursize)
    727 		c = -1;
    728 	else
    729 		c = msg_read->data[msg_read->readcount]
    730 		+ (msg_read->data[msg_read->readcount+1]<<8)
    731 		+ (msg_read->data[msg_read->readcount+2]<<16)
    732 		+ (msg_read->data[msg_read->readcount+3]<<24);
    733 	
    734 	msg_read->readcount += 4;
    735 	
    736 	return c;
    737 }
    738 
    739 float MSG_ReadFloat (sizebuf_t *msg_read)
    740 {
    741 	union
    742 	{
    743 		byte	b[4];
    744 		float	f;
    745 		int	l;
    746 	} dat;
    747 	
    748 	if (msg_read->readcount+4 > msg_read->cursize)
    749 		dat.f = -1;
    750 	else
    751 	{
    752 		dat.b[0] =	msg_read->data[msg_read->readcount];
    753 		dat.b[1] =	msg_read->data[msg_read->readcount+1];
    754 		dat.b[2] =	msg_read->data[msg_read->readcount+2];
    755 		dat.b[3] =	msg_read->data[msg_read->readcount+3];
    756 	}
    757 	msg_read->readcount += 4;
    758 	
    759 	dat.l = LittleLong (dat.l);
    760 
    761 	return dat.f;	
    762 }
    763 
    764 char *MSG_ReadString (sizebuf_t *msg_read)
    765 {
    766 	static char	string[2048];
    767 	int		l,c;
    768 	
    769 	l = 0;
    770 	do
    771 	{
    772 		c = MSG_ReadChar (msg_read);
    773 		if (c == -1 || c == 0)
    774 			break;
    775 		string[l] = c;
    776 		l++;
    777 	} while (l < sizeof(string)-1);
    778 	
    779 	string[l] = 0;
    780 	
    781 	return string;
    782 }
    783 
    784 char *MSG_ReadStringLine (sizebuf_t *msg_read)
    785 {
    786 	static char	string[2048];
    787 	int		l,c;
    788 	
    789 	l = 0;
    790 	do
    791 	{
    792 		c = MSG_ReadChar (msg_read);
    793 		if (c == -1 || c == 0 || c == '\n')
    794 			break;
    795 		string[l] = c;
    796 		l++;
    797 	} while (l < sizeof(string)-1);
    798 	
    799 	string[l] = 0;
    800 	
    801 	return string;
    802 }
    803 
    804 float MSG_ReadCoord (sizebuf_t *msg_read)
    805 {
    806 	return MSG_ReadShort(msg_read) * (1.0/8);
    807 }
    808 
    809 void MSG_ReadPos (sizebuf_t *msg_read, vec3_t pos)
    810 {
    811 	pos[0] = MSG_ReadShort(msg_read) * (1.0/8);
    812 	pos[1] = MSG_ReadShort(msg_read) * (1.0/8);
    813 	pos[2] = MSG_ReadShort(msg_read) * (1.0/8);
    814 }
    815 
    816 float MSG_ReadAngle (sizebuf_t *msg_read)
    817 {
    818 	return MSG_ReadChar(msg_read) * (360.0/256);
    819 }
    820 
    821 float MSG_ReadAngle16 (sizebuf_t *msg_read)
    822 {
    823 	return SHORT2ANGLE(MSG_ReadShort(msg_read));
    824 }
    825 
    826 void MSG_ReadDeltaUsercmd (sizebuf_t *msg_read, usercmd_t *from, usercmd_t *move)
    827 {
    828 	int bits;
    829 
    830 	memcpy (move, from, sizeof(*move));
    831 
    832 	bits = MSG_ReadByte (msg_read);
    833 		
    834 // read current angles
    835 	if (bits & CM_ANGLE1)
    836 		move->angles[0] = MSG_ReadShort (msg_read);
    837 	if (bits & CM_ANGLE2)
    838 		move->angles[1] = MSG_ReadShort (msg_read);
    839 	if (bits & CM_ANGLE3)
    840 		move->angles[2] = MSG_ReadShort (msg_read);
    841 		
    842 // read movement
    843 	if (bits & CM_FORWARD)
    844 		move->forwardmove = MSG_ReadShort (msg_read);
    845 	if (bits & CM_SIDE)
    846 		move->sidemove = MSG_ReadShort (msg_read);
    847 	if (bits & CM_UP)
    848 		move->upmove = MSG_ReadShort (msg_read);
    849 	
    850 // read buttons
    851 	if (bits & CM_BUTTONS)
    852 		move->buttons = MSG_ReadByte (msg_read);
    853 
    854 	if (bits & CM_IMPULSE)
    855 		move->impulse = MSG_ReadByte (msg_read);
    856 
    857 // read time to run command
    858 	move->msec = MSG_ReadByte (msg_read);
    859 
    860 // read the light level
    861 	move->lightlevel = MSG_ReadByte (msg_read);
    862 }
    863 
    864 
    865 void MSG_ReadData (sizebuf_t *msg_read, void *data, int len)
    866 {
    867 	int		i;
    868 
    869 	for (i=0 ; i<len ; i++)
    870 		((byte *)data)[i] = MSG_ReadByte (msg_read);
    871 }
    872 
    873 
    874 //===========================================================================
    875 
    876 void SZ_Init (sizebuf_t *buf, byte *data, int length)
    877 {
    878 	memset (buf, 0, sizeof(*buf));
    879 	buf->data = data;
    880 	buf->maxsize = length;
    881 }
    882 
    883 void SZ_Clear (sizebuf_t *buf)
    884 {
    885 	buf->cursize = 0;
    886 	buf->overflowed = false;
    887 }
    888 
    889 void *SZ_GetSpace (sizebuf_t *buf, int length)
    890 {
    891 	void	*data;
    892 	
    893 	if (buf->cursize + length > buf->maxsize)
    894 	{
    895 		if (!buf->allowoverflow)
    896 			Com_Error (ERR_FATAL, "SZ_GetSpace: overflow without allowoverflow set");
    897 		
    898 		if (length > buf->maxsize)
    899 			Com_Error (ERR_FATAL, "SZ_GetSpace: %i is > full buffer size", length);
    900 			
    901 		Com_Printf ("SZ_GetSpace: overflow\n");
    902 		SZ_Clear (buf); 
    903 		buf->overflowed = true;
    904 	}
    905 
    906 	data = buf->data + buf->cursize;
    907 	buf->cursize += length;
    908 	
    909 	return data;
    910 }
    911 
    912 void SZ_Write (sizebuf_t *buf, void *data, int length)
    913 {
    914 	memcpy (SZ_GetSpace(buf,length),data,length);		
    915 }
    916 
    917 void SZ_Print (sizebuf_t *buf, char *data)
    918 {
    919 	int		len;
    920 	
    921 	len = strlen(data)+1;
    922 
    923 	if (buf->cursize)
    924 	{
    925 		if (buf->data[buf->cursize-1])
    926 			memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
    927 		else
    928 			memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
    929 	}
    930 	else
    931 		memcpy ((byte *)SZ_GetSpace(buf, len),data,len);
    932 }
    933 
    934 
    935 //============================================================================
    936 
    937 
    938 /*
    939 ================
    940 COM_CheckParm
    941 
    942 Returns the position (1 to argc-1) in the program's argument list
    943 where the given parameter apears, or 0 if not present
    944 ================
    945 */
    946 int COM_CheckParm (char *parm)
    947 {
    948 	int		i;
    949 	
    950 	for (i=1 ; i<com_argc ; i++)
    951 	{
    952 		if (!strcmp (parm,com_argv[i]))
    953 			return i;
    954 	}
    955 		
    956 	return 0;
    957 }
    958 
    959 int COM_Argc (void)
    960 {
    961 	return com_argc;
    962 }
    963 
    964 char *COM_Argv (int arg)
    965 {
    966 	if (arg < 0 || arg >= com_argc || !com_argv[arg])
    967 		return "";
    968 	return com_argv[arg];
    969 }
    970 
    971 void COM_ClearArgv (int arg)
    972 {
    973 	if (arg < 0 || arg >= com_argc || !com_argv[arg])
    974 		return;
    975 	com_argv[arg] = "";
    976 }
    977 
    978 
    979 /*
    980 ================
    981 COM_InitArgv
    982 ================
    983 */
    984 void COM_InitArgv (int argc, char **argv)
    985 {
    986 	int		i;
    987 
    988 	if (argc > MAX_NUM_ARGVS)
    989 		Com_Error (ERR_FATAL, "argc > MAX_NUM_ARGVS");
    990 	com_argc = argc;
    991 	for (i=0 ; i<argc ; i++)
    992 	{
    993 		if (!argv[i] || strlen(argv[i]) >= MAX_TOKEN_CHARS )
    994 			com_argv[i] = "";
    995 		else
    996 			com_argv[i] = argv[i];
    997 	}
    998 }
    999 
   1000 /*
   1001 ================
   1002 COM_AddParm
   1003 
   1004 Adds the given string at the end of the current argument list
   1005 ================
   1006 */
   1007 void COM_AddParm (char *parm)
   1008 {
   1009 	if (com_argc == MAX_NUM_ARGVS)
   1010 		Com_Error (ERR_FATAL, "COM_AddParm: MAX_NUM)ARGS");
   1011 	com_argv[com_argc++] = parm;
   1012 }
   1013 
   1014 
   1015 
   1016 
   1017 /// just for debugging
   1018 int	memsearch (byte *start, int count, int search)
   1019 {
   1020 	int		i;
   1021 	
   1022 	for (i=0 ; i<count ; i++)
   1023 		if (start[i] == search)
   1024 			return i;
   1025 	return -1;
   1026 }
   1027 
   1028 
   1029 char *CopyString (char *in)
   1030 {
   1031 	char	*out;
   1032 	
   1033 	out = Z_Malloc (strlen(in)+1);
   1034 	strcpy (out, in);
   1035 	return out;
   1036 }
   1037 
   1038 
   1039 
   1040 void Info_Print (char *s)
   1041 {
   1042 	char	key[512];
   1043 	char	value[512];
   1044 	char	*o;
   1045 	int		l;
   1046 
   1047 	if (*s == '\\')
   1048 		s++;
   1049 	while (*s)
   1050 	{
   1051 		o = key;
   1052 		while (*s && *s != '\\')
   1053 			*o++ = *s++;
   1054 
   1055 		l = o - key;
   1056 		if (l < 20)
   1057 		{
   1058 			memset (o, ' ', 20-l);
   1059 			key[20] = 0;
   1060 		}
   1061 		else
   1062 			*o = 0;
   1063 		Com_Printf ("%s", key);
   1064 
   1065 		if (!*s)
   1066 		{
   1067 			Com_Printf ("MISSING VALUE\n");
   1068 			return;
   1069 		}
   1070 
   1071 		o = value;
   1072 		s++;
   1073 		while (*s && *s != '\\')
   1074 			*o++ = *s++;
   1075 		*o = 0;
   1076 
   1077 		if (*s)
   1078 			s++;
   1079 		Com_Printf ("%s\n", value);
   1080 	}
   1081 }
   1082 
   1083 
   1084 /*
   1085 ==============================================================================
   1086 
   1087 						ZONE MEMORY ALLOCATION
   1088 
   1089 just cleared malloc with counters now...
   1090 
   1091 ==============================================================================
   1092 */
   1093 
   1094 #define	Z_MAGIC		0x1d1d
   1095 
   1096 
   1097 typedef struct zhead_s
   1098 {
   1099 	struct zhead_s	*prev, *next;
   1100 	short	magic;
   1101 	short	tag;			// for group free
   1102 	int		size;
   1103 } zhead_t;
   1104 
   1105 zhead_t		z_chain;
   1106 int		z_count, z_bytes;
   1107 
   1108 /*
   1109 ========================
   1110 Z_Free
   1111 ========================
   1112 */
   1113 void Z_Free (void *ptr)
   1114 {
   1115 	zhead_t	*z;
   1116 
   1117 	z = ((zhead_t *)ptr) - 1;
   1118 
   1119 	if (z->magic != Z_MAGIC)
   1120 		Com_Error (ERR_FATAL, "Z_Free: bad magic");
   1121 
   1122 	z->prev->next = z->next;
   1123 	z->next->prev = z->prev;
   1124 
   1125 	z_count--;
   1126 	z_bytes -= z->size;
   1127 	free (z);
   1128 }
   1129 
   1130 
   1131 /*
   1132 ========================
   1133 Z_Stats_f
   1134 ========================
   1135 */
   1136 void Z_Stats_f (void)
   1137 {
   1138 	Com_Printf ("%i bytes in %i blocks\n", z_bytes, z_count);
   1139 }
   1140 
   1141 /*
   1142 ========================
   1143 Z_FreeTags
   1144 ========================
   1145 */
   1146 void Z_FreeTags (int tag)
   1147 {
   1148 	zhead_t	*z, *next;
   1149 
   1150 	for (z=z_chain.next ; z != &z_chain ; z=next)
   1151 	{
   1152 		next = z->next;
   1153 		if (z->tag == tag)
   1154 			Z_Free ((void *)(z+1));
   1155 	}
   1156 }
   1157 
   1158 /*
   1159 ========================
   1160 Z_TagMalloc
   1161 ========================
   1162 */
   1163 void *Z_TagMalloc (int size, int tag)
   1164 {
   1165 	zhead_t	*z;
   1166 	
   1167 	size = size + sizeof(zhead_t);
   1168 	z = malloc(size);
   1169 	if (!z)
   1170 		Com_Error (ERR_FATAL, "Z_Malloc: failed on allocation of %i bytes",size);
   1171 	memset (z, 0, size);
   1172 	z_count++;
   1173 	z_bytes += size;
   1174 	z->magic = Z_MAGIC;
   1175 	z->tag = tag;
   1176 	z->size = size;
   1177 
   1178 	z->next = z_chain.next;
   1179 	z->prev = &z_chain;
   1180 	z_chain.next->prev = z;
   1181 	z_chain.next = z;
   1182 
   1183 	return (void *)(z+1);
   1184 }
   1185 
   1186 /*
   1187 ========================
   1188 Z_Malloc
   1189 ========================
   1190 */
   1191 void *Z_Malloc (int size)
   1192 {
   1193 	return Z_TagMalloc (size, 0);
   1194 }
   1195 
   1196 
   1197 //============================================================================
   1198 
   1199 
   1200 /*
   1201 ====================
   1202 COM_BlockSequenceCheckByte
   1203 
   1204 For proxy protecting
   1205 
   1206 // THIS IS MASSIVELY BROKEN!  CHALLENGE MAY BE NEGATIVE
   1207 // DON'T USE THIS FUNCTION!!!!!
   1208 
   1209 ====================
   1210 */
   1211 byte	COM_BlockSequenceCheckByte (byte *base, int length, int sequence, int challenge)
   1212 {
   1213 	Sys_Error("COM_BlockSequenceCheckByte called\n");
   1214 
   1215 #if 0
   1216 	int		checksum;
   1217 	byte	buf[68];
   1218 	byte	*p;
   1219 	float temp;
   1220 	byte c;
   1221 
   1222 	temp = bytedirs[(sequence/3) % NUMVERTEXNORMALS][sequence % 3];
   1223 	temp = LittleFloat(temp);
   1224 	p = ((byte *)&temp);
   1225 
   1226 	if (length > 60)
   1227 		length = 60;
   1228 	memcpy (buf, base, length);
   1229 
   1230 	buf[length] = (sequence & 0xff) ^ p[0];
   1231 	buf[length+1] = p[1];
   1232 	buf[length+2] = ((sequence>>8) & 0xff) ^ p[2];
   1233 	buf[length+3] = p[3];
   1234 
   1235 	temp = bytedirs[((sequence+challenge)/3) % NUMVERTEXNORMALS][(sequence+challenge) % 3];
   1236 	temp = LittleFloat(temp);
   1237 	p = ((byte *)&temp);
   1238 
   1239 	buf[length+4] = (sequence & 0xff) ^ p[3];
   1240 	buf[length+5] = (challenge & 0xff) ^ p[2];
   1241 	buf[length+6] = ((sequence>>8) & 0xff) ^ p[1];
   1242 	buf[length+7] = ((challenge >> 7) & 0xff) ^ p[0];
   1243 
   1244 	length += 8;
   1245 
   1246 	checksum = LittleLong(Com_BlockChecksum (buf, length));
   1247 
   1248 	checksum &= 0xff;
   1249 
   1250 	return checksum;
   1251 #endif
   1252 	return 0;
   1253 }
   1254 
   1255 static byte chktbl[1024] = {
   1256 0x84, 0x47, 0x51, 0xc1, 0x93, 0x22, 0x21, 0x24, 0x2f, 0x66, 0x60, 0x4d, 0xb0, 0x7c, 0xda,
   1257 0x88, 0x54, 0x15, 0x2b, 0xc6, 0x6c, 0x89, 0xc5, 0x9d, 0x48, 0xee, 0xe6, 0x8a, 0xb5, 0xf4,
   1258 0xcb, 0xfb, 0xf1, 0x0c, 0x2e, 0xa0, 0xd7, 0xc9, 0x1f, 0xd6, 0x06, 0x9a, 0x09, 0x41, 0x54,
   1259 0x67, 0x46, 0xc7, 0x74, 0xe3, 0xc8, 0xb6, 0x5d, 0xa6, 0x36, 0xc4, 0xab, 0x2c, 0x7e, 0x85,
   1260 0xa8, 0xa4, 0xa6, 0x4d, 0x96, 0x19, 0x19, 0x9a, 0xcc, 0xd8, 0xac, 0x39, 0x5e, 0x3c, 0xf2,
   1261 0xf5, 0x5a, 0x72, 0xe5, 0xa9, 0xd1, 0xb3, 0x23, 0x82, 0x6f, 0x29, 0xcb, 0xd1, 0xcc, 0x71,
   1262 0xfb, 0xea, 0x92, 0xeb, 0x1c, 0xca, 0x4c, 0x70, 0xfe, 0x4d, 0xc9, 0x67, 0x43, 0x47, 0x94,
   1263 0xb9, 0x47, 0xbc, 0x3f, 0x01, 0xab, 0x7b, 0xa6, 0xe2, 0x76, 0xef, 0x5a, 0x7a, 0x29, 0x0b,
   1264 0x51, 0x54, 0x67, 0xd8, 0x1c, 0x14, 0x3e, 0x29, 0xec, 0xe9, 0x2d, 0x48, 0x67, 0xff, 0xed,
   1265 0x54, 0x4f, 0x48, 0xc0, 0xaa, 0x61, 0xf7, 0x78, 0x12, 0x03, 0x7a, 0x9e, 0x8b, 0xcf, 0x83,
   1266 0x7b, 0xae, 0xca, 0x7b, 0xd9, 0xe9, 0x53, 0x2a, 0xeb, 0xd2, 0xd8, 0xcd, 0xa3, 0x10, 0x25,
   1267 0x78, 0x5a, 0xb5, 0x23, 0x06, 0x93, 0xb7, 0x84, 0xd2, 0xbd, 0x96, 0x75, 0xa5, 0x5e, 0xcf,
   1268 0x4e, 0xe9, 0x50, 0xa1, 0xe6, 0x9d, 0xb1, 0xe3, 0x85, 0x66, 0x28, 0x4e, 0x43, 0xdc, 0x6e,
   1269 0xbb, 0x33, 0x9e, 0xf3, 0x0d, 0x00, 0xc1, 0xcf, 0x67, 0x34, 0x06, 0x7c, 0x71, 0xe3, 0x63,
   1270 0xb7, 0xb7, 0xdf, 0x92, 0xc4, 0xc2, 0x25, 0x5c, 0xff, 0xc3, 0x6e, 0xfc, 0xaa, 0x1e, 0x2a,
   1271 0x48, 0x11, 0x1c, 0x36, 0x68, 0x78, 0x86, 0x79, 0x30, 0xc3, 0xd6, 0xde, 0xbc, 0x3a, 0x2a,
   1272 0x6d, 0x1e, 0x46, 0xdd, 0xe0, 0x80, 0x1e, 0x44, 0x3b, 0x6f, 0xaf, 0x31, 0xda, 0xa2, 0xbd,
   1273 0x77, 0x06, 0x56, 0xc0, 0xb7, 0x92, 0x4b, 0x37, 0xc0, 0xfc, 0xc2, 0xd5, 0xfb, 0xa8, 0xda,
   1274 0xf5, 0x57, 0xa8, 0x18, 0xc0, 0xdf, 0xe7, 0xaa, 0x2a, 0xe0, 0x7c, 0x6f, 0x77, 0xb1, 0x26,
   1275 0xba, 0xf9, 0x2e, 0x1d, 0x16, 0xcb, 0xb8, 0xa2, 0x44, 0xd5, 0x2f, 0x1a, 0x79, 0x74, 0x87,
   1276 0x4b, 0x00, 0xc9, 0x4a, 0x3a, 0x65, 0x8f, 0xe6, 0x5d, 0xe5, 0x0a, 0x77, 0xd8, 0x1a, 0x14,
   1277 0x41, 0x75, 0xb1, 0xe2, 0x50, 0x2c, 0x93, 0x38, 0x2b, 0x6d, 0xf3, 0xf6, 0xdb, 0x1f, 0xcd,
   1278 0xff, 0x14, 0x70, 0xe7, 0x16, 0xe8, 0x3d, 0xf0, 0xe3, 0xbc, 0x5e, 0xb6, 0x3f, 0xcc, 0x81,
   1279 0x24, 0x67, 0xf3, 0x97, 0x3b, 0xfe, 0x3a, 0x96, 0x85, 0xdf, 0xe4, 0x6e, 0x3c, 0x85, 0x05,
   1280 0x0e, 0xa3, 0x2b, 0x07, 0xc8, 0xbf, 0xe5, 0x13, 0x82, 0x62, 0x08, 0x61, 0x69, 0x4b, 0x47,
   1281 0x62, 0x73, 0x44, 0x64, 0x8e, 0xe2, 0x91, 0xa6, 0x9a, 0xb7, 0xe9, 0x04, 0xb6, 0x54, 0x0c,
   1282 0xc5, 0xa9, 0x47, 0xa6, 0xc9, 0x08, 0xfe, 0x4e, 0xa6, 0xcc, 0x8a, 0x5b, 0x90, 0x6f, 0x2b,
   1283 0x3f, 0xb6, 0x0a, 0x96, 0xc0, 0x78, 0x58, 0x3c, 0x76, 0x6d, 0x94, 0x1a, 0xe4, 0x4e, 0xb8,
   1284 0x38, 0xbb, 0xf5, 0xeb, 0x29, 0xd8, 0xb0, 0xf3, 0x15, 0x1e, 0x99, 0x96, 0x3c, 0x5d, 0x63,
   1285 0xd5, 0xb1, 0xad, 0x52, 0xb8, 0x55, 0x70, 0x75, 0x3e, 0x1a, 0xd5, 0xda, 0xf6, 0x7a, 0x48,
   1286 0x7d, 0x44, 0x41, 0xf9, 0x11, 0xce, 0xd7, 0xca, 0xa5, 0x3d, 0x7a, 0x79, 0x7e, 0x7d, 0x25,
   1287 0x1b, 0x77, 0xbc, 0xf7, 0xc7, 0x0f, 0x84, 0x95, 0x10, 0x92, 0x67, 0x15, 0x11, 0x5a, 0x5e,
   1288 0x41, 0x66, 0x0f, 0x38, 0x03, 0xb2, 0xf1, 0x5d, 0xf8, 0xab, 0xc0, 0x02, 0x76, 0x84, 0x28,
   1289 0xf4, 0x9d, 0x56, 0x46, 0x60, 0x20, 0xdb, 0x68, 0xa7, 0xbb, 0xee, 0xac, 0x15, 0x01, 0x2f,
   1290 0x20, 0x09, 0xdb, 0xc0, 0x16, 0xa1, 0x89, 0xf9, 0x94, 0x59, 0x00, 0xc1, 0x76, 0xbf, 0xc1,
   1291 0x4d, 0x5d, 0x2d, 0xa9, 0x85, 0x2c, 0xd6, 0xd3, 0x14, 0xcc, 0x02, 0xc3, 0xc2, 0xfa, 0x6b,
   1292 0xb7, 0xa6, 0xef, 0xdd, 0x12, 0x26, 0xa4, 0x63, 0xe3, 0x62, 0xbd, 0x56, 0x8a, 0x52, 0x2b,
   1293 0xb9, 0xdf, 0x09, 0xbc, 0x0e, 0x97, 0xa9, 0xb0, 0x82, 0x46, 0x08, 0xd5, 0x1a, 0x8e, 0x1b,
   1294 0xa7, 0x90, 0x98, 0xb9, 0xbb, 0x3c, 0x17, 0x9a, 0xf2, 0x82, 0xba, 0x64, 0x0a, 0x7f, 0xca,
   1295 0x5a, 0x8c, 0x7c, 0xd3, 0x79, 0x09, 0x5b, 0x26, 0xbb, 0xbd, 0x25, 0xdf, 0x3d, 0x6f, 0x9a,
   1296 0x8f, 0xee, 0x21, 0x66, 0xb0, 0x8d, 0x84, 0x4c, 0x91, 0x45, 0xd4, 0x77, 0x4f, 0xb3, 0x8c,
   1297 0xbc, 0xa8, 0x99, 0xaa, 0x19, 0x53, 0x7c, 0x02, 0x87, 0xbb, 0x0b, 0x7c, 0x1a, 0x2d, 0xdf,
   1298 0x48, 0x44, 0x06, 0xd6, 0x7d, 0x0c, 0x2d, 0x35, 0x76, 0xae, 0xc4, 0x5f, 0x71, 0x85, 0x97,
   1299 0xc4, 0x3d, 0xef, 0x52, 0xbe, 0x00, 0xe4, 0xcd, 0x49, 0xd1, 0xd1, 0x1c, 0x3c, 0xd0, 0x1c,
   1300 0x42, 0xaf, 0xd4, 0xbd, 0x58, 0x34, 0x07, 0x32, 0xee, 0xb9, 0xb5, 0xea, 0xff, 0xd7, 0x8c,
   1301 0x0d, 0x2e, 0x2f, 0xaf, 0x87, 0xbb, 0xe6, 0x52, 0x71, 0x22, 0xf5, 0x25, 0x17, 0xa1, 0x82,
   1302 0x04, 0xc2, 0x4a, 0xbd, 0x57, 0xc6, 0xab, 0xc8, 0x35, 0x0c, 0x3c, 0xd9, 0xc2, 0x43, 0xdb,
   1303 0x27, 0x92, 0xcf, 0xb8, 0x25, 0x60, 0xfa, 0x21, 0x3b, 0x04, 0x52, 0xc8, 0x96, 0xba, 0x74,
   1304 0xe3, 0x67, 0x3e, 0x8e, 0x8d, 0x61, 0x90, 0x92, 0x59, 0xb6, 0x1a, 0x1c, 0x5e, 0x21, 0xc1,
   1305 0x65, 0xe5, 0xa6, 0x34, 0x05, 0x6f, 0xc5, 0x60, 0xb1, 0x83, 0xc1, 0xd5, 0xd5, 0xed, 0xd9,
   1306 0xc7, 0x11, 0x7b, 0x49, 0x7a, 0xf9, 0xf9, 0x84, 0x47, 0x9b, 0xe2, 0xa5, 0x82, 0xe0, 0xc2,
   1307 0x88, 0xd0, 0xb2, 0x58, 0x88, 0x7f, 0x45, 0x09, 0x67, 0x74, 0x61, 0xbf, 0xe6, 0x40, 0xe2,
   1308 0x9d, 0xc2, 0x47, 0x05, 0x89, 0xed, 0xcb, 0xbb, 0xb7, 0x27, 0xe7, 0xdc, 0x7a, 0xfd, 0xbf,
   1309 0xa8, 0xd0, 0xaa, 0x10, 0x39, 0x3c, 0x20, 0xf0, 0xd3, 0x6e, 0xb1, 0x72, 0xf8, 0xe6, 0x0f,
   1310 0xef, 0x37, 0xe5, 0x09, 0x33, 0x5a, 0x83, 0x43, 0x80, 0x4f, 0x65, 0x2f, 0x7c, 0x8c, 0x6a,
   1311 0xa0, 0x82, 0x0c, 0xd4, 0xd4, 0xfa, 0x81, 0x60, 0x3d, 0xdf, 0x06, 0xf1, 0x5f, 0x08, 0x0d,
   1312 0x6d, 0x43, 0xf2, 0xe3, 0x11, 0x7d, 0x80, 0x32, 0xc5, 0xfb, 0xc5, 0xd9, 0x27, 0xec, 0xc6,
   1313 0x4e, 0x65, 0x27, 0x76, 0x87, 0xa6, 0xee, 0xee, 0xd7, 0x8b, 0xd1, 0xa0, 0x5c, 0xb0, 0x42,
   1314 0x13, 0x0e, 0x95, 0x4a, 0xf2, 0x06, 0xc6, 0x43, 0x33, 0xf4, 0xc7, 0xf8, 0xe7, 0x1f, 0xdd,
   1315 0xe4, 0x46, 0x4a, 0x70, 0x39, 0x6c, 0xd0, 0xed, 0xca, 0xbe, 0x60, 0x3b, 0xd1, 0x7b, 0x57,
   1316 0x48, 0xe5, 0x3a, 0x79, 0xc1, 0x69, 0x33, 0x53, 0x1b, 0x80, 0xb8, 0x91, 0x7d, 0xb4, 0xf6,
   1317 0x17, 0x1a, 0x1d, 0x5a, 0x32, 0xd6, 0xcc, 0x71, 0x29, 0x3f, 0x28, 0xbb, 0xf3, 0x5e, 0x71,
   1318 0xb8, 0x43, 0xaf, 0xf8, 0xb9, 0x64, 0xef, 0xc4, 0xa5, 0x6c, 0x08, 0x53, 0xc7, 0x00, 0x10,
   1319 0x39, 0x4f, 0xdd, 0xe4, 0xb6, 0x19, 0x27, 0xfb, 0xb8, 0xf5, 0x32, 0x73, 0xe5, 0xcb, 0x32
   1320 };
   1321 
   1322 /*
   1323 ====================
   1324 COM_BlockSequenceCRCByte
   1325 
   1326 For proxy protecting
   1327 ====================
   1328 */
   1329 byte	COM_BlockSequenceCRCByte (byte *base, int length, int sequence)
   1330 {
   1331 	int		n;
   1332 	byte	*p;
   1333 	int		x;
   1334 	byte chkb[60 + 4];
   1335 	unsigned short crc;
   1336 
   1337 
   1338 	if (sequence < 0)
   1339 		Sys_Error("sequence < 0, this shouldn't happen\n");
   1340 
   1341 	p = chktbl + (sequence % (sizeof(chktbl) - 4));
   1342 
   1343 	if (length > 60)
   1344 		length = 60;
   1345 	memcpy (chkb, base, length);
   1346 
   1347 	chkb[length] = p[0];
   1348 	chkb[length+1] = p[1];
   1349 	chkb[length+2] = p[2];
   1350 	chkb[length+3] = p[3];
   1351 
   1352 	length += 4;
   1353 
   1354 	crc = CRC_Block(chkb, length);
   1355 
   1356 	for (x=0, n=0; n<length; n++)
   1357 		x += chkb[n];
   1358 
   1359 	crc = (crc ^ x) & 0xff;
   1360 
   1361 	return crc;
   1362 }
   1363 
   1364 //========================================================
   1365 
   1366 float	frand(void)
   1367 {
   1368 	return (rand()&32767)* (1.0/32767);
   1369 }
   1370 
   1371 float	crand(void)
   1372 {
   1373 	return (rand()&32767)* (2.0/32767) - 1;
   1374 }
   1375 
   1376 void Key_Init (void);
   1377 void SCR_EndLoadingPlaque (void);
   1378 
   1379 /*
   1380 =============
   1381 Com_Error_f
   1382 
   1383 Just throw a fatal error to
   1384 test error shutdown procedures
   1385 =============
   1386 */
   1387 void Com_Error_f (void)
   1388 {
   1389 	Com_Error (ERR_FATAL, "%s", Cmd_Argv(1));
   1390 }
   1391 
   1392 
   1393 /*
   1394 =================
   1395 Qcommon_Init
   1396 =================
   1397 */
   1398 void Qcommon_Init (int argc, char **argv)
   1399 {
   1400 	char	*s;
   1401 
   1402 	if (setjmp (abortframe) )
   1403 		Sys_Error ("Error during initialization");
   1404 
   1405 	z_chain.next = z_chain.prev = &z_chain;
   1406 
   1407 	// prepare enough of the subsystems to handle
   1408 	// cvar and command buffer management
   1409 	COM_InitArgv (argc, argv);
   1410 
   1411 	Swap_Init ();
   1412 	Cbuf_Init ();
   1413 
   1414 	Cmd_Init ();
   1415 	Cvar_Init ();
   1416 
   1417 	Key_Init ();
   1418 
   1419 	// we need to add the early commands twice, because
   1420 	// a basedir or cddir needs to be set before execing
   1421 	// config files, but we want other parms to override
   1422 	// the settings of the config files
   1423 	Cbuf_AddEarlyCommands (false);
   1424 	Cbuf_Execute ();
   1425 
   1426 	FS_InitFilesystem ();
   1427 
   1428 	Cbuf_AddText ("exec default.cfg\n");
   1429 	Cbuf_AddText ("exec config.cfg\n");
   1430 
   1431 	Cbuf_AddEarlyCommands (true);
   1432 	Cbuf_Execute ();
   1433 
   1434 	//
   1435 	// init commands and vars
   1436 	//
   1437     Cmd_AddCommand ("z_stats", Z_Stats_f);
   1438     Cmd_AddCommand ("error", Com_Error_f);
   1439 
   1440 	host_speeds = Cvar_Get ("host_speeds", "0", 0);
   1441 	log_stats = Cvar_Get ("log_stats", "0", 0);
   1442 	developer = Cvar_Get ("developer", "0", 0);
   1443 	timescale = Cvar_Get ("timescale", "1", 0);
   1444 	fixedtime = Cvar_Get ("fixedtime", "0", 0);
   1445 	logfile_active = Cvar_Get ("logfile", "0", 0);
   1446 	showtrace = Cvar_Get ("showtrace", "0", 0);
   1447 #ifdef DEDICATED_ONLY
   1448 	dedicated = Cvar_Get ("dedicated", "1", CVAR_NOSET);
   1449 #else
   1450 	dedicated = Cvar_Get ("dedicated", "0", CVAR_NOSET);
   1451 #endif
   1452 
   1453 	s = va("%4.2f %s %s %s", VERSION, CPUSTRING, __DATE__, BUILDSTRING);
   1454 	Cvar_Get ("version", s, CVAR_SERVERINFO|CVAR_NOSET);
   1455 
   1456 
   1457 	if (dedicated->value)
   1458 		Cmd_AddCommand ("quit", Com_Quit);
   1459 
   1460 	Sys_Init ();
   1461 
   1462 	NET_Init ();
   1463 	Netchan_Init ();
   1464 
   1465 	SV_Init ();
   1466 	CL_Init ();
   1467 
   1468 	// add + commands from command line
   1469 	if (!Cbuf_AddLateCommands ())
   1470 	{	// if the user didn't give any commands, run default action
   1471 		if (!dedicated->value)
   1472 			Cbuf_AddText ("d1\n");
   1473 		else
   1474 			Cbuf_AddText ("dedicated_start\n");
   1475 		Cbuf_Execute ();
   1476 	}
   1477 	else
   1478 	{	// the user asked for something explicit
   1479 		// so drop the loading plaque
   1480 		SCR_EndLoadingPlaque ();
   1481 	}
   1482 
   1483 	Com_Printf ("====== Quake2 Initialized ======\n\n");	
   1484 }
   1485 
   1486 /*
   1487 =================
   1488 Qcommon_Frame
   1489 =================
   1490 */
   1491 void Qcommon_Frame (int msec)
   1492 {
   1493 	char	*s;
   1494 	int		time_before, time_between, time_after;
   1495 
   1496 	if (setjmp (abortframe) )
   1497 		return;			// an ERR_DROP was thrown
   1498 
   1499 	if ( log_stats->modified )
   1500 	{
   1501 		log_stats->modified = false;
   1502 		if ( log_stats->value )
   1503 		{
   1504 			if ( log_stats_file )
   1505 			{
   1506 				fclose( log_stats_file );
   1507 				log_stats_file = 0;
   1508 			}
   1509 			log_stats_file = fopen( "stats.log", "w" );
   1510 			if ( log_stats_file )
   1511 				fprintf( log_stats_file, "entities,dlights,parts,frame time\n" );
   1512 		}
   1513 		else
   1514 		{
   1515 			if ( log_stats_file )
   1516 			{
   1517 				fclose( log_stats_file );
   1518 				log_stats_file = 0;
   1519 			}
   1520 		}
   1521 	}
   1522 
   1523 	if (fixedtime->value)
   1524 		msec = fixedtime->value;
   1525 	else if (timescale->value)
   1526 	{
   1527 		msec *= timescale->value;
   1528 		if (msec < 1)
   1529 			msec = 1;
   1530 	}
   1531 
   1532 	if (showtrace->value)
   1533 	{
   1534 		extern	int c_traces, c_brush_traces;
   1535 		extern	int	c_pointcontents;
   1536 
   1537 		Com_Printf ("%4i traces  %4i points\n", c_traces, c_pointcontents);
   1538 		c_traces = 0;
   1539 		c_brush_traces = 0;
   1540 		c_pointcontents = 0;
   1541 	}
   1542 
   1543 	do
   1544 	{
   1545 		s = Sys_ConsoleInput ();
   1546 		if (s)
   1547 			Cbuf_AddText (va("%s\n",s));
   1548 	} while (s);
   1549 	Cbuf_Execute ();
   1550 
   1551 	if (host_speeds->value)
   1552 		time_before = Sys_Milliseconds ();
   1553 
   1554 	SV_Frame (msec);
   1555 
   1556 	if (host_speeds->value)
   1557 		time_between = Sys_Milliseconds ();		
   1558 
   1559 	CL_Frame (msec);
   1560 
   1561 	if (host_speeds->value)
   1562 		time_after = Sys_Milliseconds ();		
   1563 
   1564 
   1565 	if (host_speeds->value)
   1566 	{
   1567 		int			all, sv, gm, cl, rf;
   1568 
   1569 		all = time_after - time_before;
   1570 		sv = time_between - time_before;
   1571 		cl = time_after - time_between;
   1572 		gm = time_after_game - time_before_game;
   1573 		rf = time_after_ref - time_before_ref;
   1574 		sv -= gm;
   1575 		cl -= rf;
   1576 		Com_Printf ("all:%3i sv:%3i gm:%3i cl:%3i rf:%3i\n",
   1577 			all, sv, gm, cl, rf);
   1578 	}	
   1579 }
   1580 
   1581 /*
   1582 =================
   1583 Qcommon_Shutdown
   1584 =================
   1585 */
   1586 void Qcommon_Shutdown (void)
   1587 {
   1588 }