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 
23 #ifdef _WIN32
24 #define OPENSSLEXPORT __cdecl
25 #endif
26 #ifdef USE_OPENSSL
27 #include <openssl/md4.h>
28 #endif
29 
30 #include <setjmp.h>
31 
32 #define	MAXPRINTMSG	4096
33 
34 #define MAX_NUM_ARGVS	50
35 
36 qboolean		q2_initialized = false;
37 
38 entity_state_t	null_entity_state;
39 usercmd_t		null_usercmd;
40 cvar_t			uninitialized_cvar;
41 
42 cvar_t			*z_debug;
43 cvar_t			*z_buggygame;
44 cvar_t			*z_allowcorruption;
45 
46 cvar_t			*cl_quietstartup;
47 
48 static int		com_argc;
49 static char	*com_argv[MAX_NUM_ARGVS+1];
50 
51 char	*binary_name;
52 
53 //int		realtime;
54 jmp_buf abortframe;		// an ERR_DROP occured, exit the entire frame
55 
56 //static FILE	*log_stats_file;
57 
58 cvar_t	*host_speeds;
59 cvar_t	*log_stats;
60 cvar_t	*developer = &uninitialized_cvar;
61 
62 static cvar_t	*timescale;
63 static cvar_t	*fixedtime;
64 
65 static cvar_t	*logfile_active;	// 1 = buffer log, 2 = flush after each print
66 static cvar_t	*logfile_timestamp;
67 static cvar_t	*logfile_timestamp_format;
68 static cvar_t	*logfile_name;
69 static cvar_t	*logfile_filterlevel = &uninitialized_cvar;
70 static cvar_t	*con_filterlevel = &uninitialized_cvar;
71 
72 #ifndef DEDICATED_ONLY
73 cvar_t	*showtrace;
74 #endif
75 
76 #ifndef NO_SERVER
77 cvar_t	*dedicated = &uninitialized_cvar;
78 #endif
79 
80 cvar_t	*sys_loopstyle = &uninitialized_cvar;
81 
82 //r1: unload DLLs on crash?
83 cvar_t	*dbg_unload = &uninitialized_cvar;
84 
85 //r1: throw int3 on ERR_FATAL?
86 static cvar_t	*dbg_crash_on_fatal_error = &uninitialized_cvar;
87 
88 //r1: throw all err as fatal?
89 static cvar_t	*err_fatal = &uninitialized_cvar;
90 
91 static FILE	*logfile;
92 
93 int			server_state;
94 
95 // host_speeds times
96 unsigned int		time_before_game;
97 unsigned int		time_after_game;
98 unsigned int		time_before_ref;
99 unsigned int		time_after_ref;
100 
101 // for profiling
102 #ifndef NPROFILE
103 static int msg_local_hits;
104 static int msg_malloc_hits;
105 
106 static int messageSizes[1500];
107 #endif
108 
109 char *svc_strings[256] =
110 {
111 	"svc_bad",
112 
113 	"svc_muzzleflash",
114 	"svc_muzzlflash2",
115 	"svc_temp_entity",
116 	"svc_layout",
117 	"svc_inventory",
118 
119 	"svc_nop",
120 	"svc_disconnect",
121 	"svc_reconnect",
122 	"svc_sound",
123 	"svc_print",
124 	"svc_stufftext",
125 	"svc_serverdata",
126 	"svc_configstring",
127 	"svc_spawnbaseline",
128 	"svc_centerprint",
129 	"svc_download",
130 	"svc_playerinfo",
131 	"svc_packetentities",
132 	"svc_deltapacketentities",
133 	"svc_frame",
134 	"svc_zpacket",
135 	"svc_zdownload",
136 	"svc_playerupdate",
137 	"svc_setting",
138 };
139 
140 tagmalloc_tag_t tagmalloc_tags[] =
141 {
142 	{TAGMALLOC_NOT_TAGGED, "NOT_TAGGED", 0},
143 	{TAGMALLOC_CMDBUFF, "CMDBUFF", 0},
144 	{TAGMALLOC_CMDTOKEN, "CMDTOKEN", 0},
145 	{TAGMALLOC_CMD, "CMD", 0},
146 	{TAGMALLOC_LOADMAP, "LOADMAP", 0},
147 	{TAGMALLOC_ALIAS, "ALIAS", 0},
148 	{TAGMALLOC_TRIGGER, "TRIGGER", 0},
149 	{TAGMALLOC_CVAR, "CVAR", 0},
150 	{TAGMALLOC_FSCACHE, "FSCACHE", 0},
151 	{TAGMALLOC_FSLOADFILE, "FSLOADFILE", 0},
152 	{TAGMALLOC_FSLOADPAK, "FSLOADPAK", 0},
153 	{TAGMALLOC_SEARCHPATH, "SEARCHPATH", 0},
154 	{TAGMALLOC_LINK, "LINK", 0},
155 	{TAGMALLOC_CLIENTS, "CLIENTS", 0},
156 	{TAGMALLOC_CL_ENTS, "CL_ENTS", 0},
157 	{TAGMALLOC_CL_BASELINES, "CL_BASELINES", 0},
158 	{TAGMALLOC_CL_MESSAGES, "CL_MESSAGES", 0},
159 	{TAGMALLOC_CL_PARTICLES, "CL_PARTICLES", 0},
160 
161 	{TAGMALLOC_CLIENT_DOWNLOAD, "CLIENT_DOWNLOAD", 0},
162 	{TAGMALLOC_CLIENT_KEYBIND, "CLIENT_KEYBIND", 0},
163 	{TAGMALLOC_CLIENT_SFX, "CLIENT_SFX", 0},
164 	{TAGMALLOC_CLIENT_SOUNDCACHE, "CLIENT_SOUNDCACHE", 0},
165 	{TAGMALLOC_CLIENT_DLL, "CLIENT_DLL", 0},
166 	{TAGMALLOC_CLIENT_LOC, "CLIENT_LOC", 0},
167 	{TAGMALLOC_CLIENT_IGNORE, "CLIENT_IGNORE", 0},
168 	{TAGMALLOC_BLACKHOLE, "BLACKHOLE", 0},
169 	{TAGMALLOC_CVARBANS, "CVARBANS", 0},
170 	//{TAGMALLOC_MSG_QUEUE, "MSGQUEUE", 0},
171 	{TAGMALLOC_CMDBANS, "CMDBANS", 0},
172 	{TAGMALLOC_REDBLACK, "REDBLACK", 0},
173 	{TAGMALLOC_LRCON, "LRCON", 0},
174 #ifdef ANTICHEAT
175 	{TAGMALLOC_ANTICHEAT, "ANTICHEAT", 0},
176 #endif
177 	{TAGMALLOC_MAX_TAGS, "*** UNDEFINED ***", 0}
178 };
179 
180 void (EXPORT *Z_Free)(const void *buf);
181 void *(EXPORT *Z_TagMalloc)(int size, int tag);
182 
183 /*
184 ============================================================================
185 
186 CLIENT / SERVER interactions
187 
188 ============================================================================
189 */
190 
191 int	rd_target;
192 
193 static char	*rd_buffer;
194 static int	rd_buffersize;
195 static void	(*rd_flush)(int target, char *buffer);
196 
Com_BeginRedirect(int target,char * buffer,int buffersize,void * flush)197 void Com_BeginRedirect (int target, char *buffer, int buffersize, void *flush)
198 {
199 	if (!target || !buffer || !buffersize || !flush)
200 		return;
201 	rd_target = target;
202 	rd_buffer = buffer;
203 	rd_buffersize = buffersize;
204 	rd_flush = (void (*)(int, char *))flush;
205 
206 	*rd_buffer = 0;
207 }
208 
Com_EndRedirect(qboolean flush)209 void Com_EndRedirect (qboolean flush)
210 {
211 	if (!rd_target)
212 		return;
213 
214 	if (flush)
215 		rd_flush(rd_target, rd_buffer);
216 
217 	rd_target = 0;
218 	rd_buffer = NULL;
219 	rd_buffersize = 0;
220 	rd_flush = NULL;
221 }
222 
223 /*
224 =============
225 Com_Printf
226 
227 Both client and server can use this, and it will output
228 to the apropriate place.
229 =============
230 */
Com_Printf(const char * fmt,int level,...)231 void Com_Printf (const char *fmt, int level, ...)
232 {
233 	va_list		argptr;
234 	char		msg[MAXPRINTMSG];
235 
236 	if ((level & con_filterlevel->intvalue) && (level & logfile_filterlevel->intvalue))
237 		return;
238 
239 	va_start (argptr, level);
240 	if (Q_vsnprintf (msg, sizeof(msg)-1, fmt, argptr) < 0)
241 		Com_Printf ("WARNING: Com_Printf: message overflow.\n", LOG_GENERAL);
242 	va_end (argptr);
243 
244 	msg[sizeof(msg)-1] = 0;
245 
246 	if (rd_target)
247 	{
248 		if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1))
249 		{
250 			rd_flush(rd_target, rd_buffer);
251 			*rd_buffer = 0;
252 		}
253 		strcat (rd_buffer, msg);
254 		return;
255 	}
256 
257 	if (!(level & con_filterlevel->intvalue))
258 	{
259 #ifndef DEDICATED_ONLY
260 		Con_Print (msg);
261 #endif
262 
263 	// also echo to debugging console
264 #ifndef NO_SERVER
265 		Sys_ConsoleOutput (msg);
266 #endif
267 	}
268 
269 	// logfile
270 	if (logfile_active && logfile_active->intvalue && !(level & logfile_filterlevel->intvalue))
271 	{
272 		char	name[MAX_QPATH];
273 		char	timestamp[64];
274 		char	*p;
275 
276 		//r1: strip highbits and control chars
277 		p = msg;
278 		while (p[0])
279 		{
280 			p[0] &= ~128;
281 			if (p[0] < 32 && !isspace(p[0]))
282 				p[0] = '-';
283 			p++;
284 		}
285 
286 		if (!logfile)
287 		{
288 			//ensure someone malicious with rcon can't overwrite arbitrary files...
289 			if (strstr (logfile_name->string, "..") || strchr (logfile_name->string, '/') || strchr (logfile_name->string, '\\'))
290 			{
291 				Cvar_ForceSet ("logfile", "0");
292 				Com_Printf ("ALERT: Refusing to open logfile %s, illegal filename.\n", LOG_GENERAL|LOG_WARNING, logfile_name->string);
293 				return;
294 			}
295 			Com_sprintf (name, sizeof(name), "%s/%s", FS_Gamedir (), logfile_name->string);
296 
297 			if (logfile_active->intvalue > 2)
298 				logfile = fopen (name, "a");
299 			else
300 				logfile = fopen (name, "w");
301 
302 			if (!logfile)
303 			{
304 				Cvar_ForceSet ("logfile", "0");
305 				Com_Printf ("ALERT: Couldn't open logfile %s for writing, logfile disabled.\n", LOG_GENERAL|LOG_WARNING, logfile_name->string);
306 				return;
307 			}
308 		}
309 
310 		if (logfile)
311 		{
312 			if (logfile_timestamp->intvalue)
313 			{
314 				char		*line;
315 				char		*msgptr;
316 
317 				static qboolean	insert_timestamp = true;
318 
319 				time_t	tm;
320 				time(&tm);
321 				strftime (timestamp, sizeof(timestamp)-1, logfile_timestamp_format->string, localtime(&tm));
322 
323 				msgptr = msg;
324 				line = strchr (msgptr, '\n');
325 				while (line)
326 				{
327 					if (insert_timestamp)
328 					{
329 						fprintf (logfile, "%s ", timestamp);
330 						insert_timestamp = false;
331 					}
332 					*line = 0;
333 
334 					if (fprintf (logfile, "%s\n", msgptr) < 0)
335 					{
336 						fclose (logfile);
337 						logfile = NULL;
338 						Cvar_ForceSet ("logfile", "0");
339 						Com_Printf ("ALERT: Error writing to logfile %s, file closed.\n", LOG_GENERAL|LOG_WARNING, logfile_name->string);
340 						return;
341 					}
342 
343 					insert_timestamp = true;
344 					line++;
345 					msgptr = line;
346 
347 					if (!*line)
348 						break;
349 
350 					line = strchr (msgptr, '\n');
351 				}
352 
353 				if (insert_timestamp)
354 				{
355 					fprintf (logfile, "%s ", timestamp);
356 					insert_timestamp = false;
357 				}
358 
359 				fprintf (logfile, "%s", msgptr);
360 			}
361 			else
362 			{
363 				fwrite (msg, strlen(msg), 1, logfile);
364 			}
365 		}
366 
367 		//r1: allow logging > 2 (append) but not forcing flushing.
368 		if (logfile_active->intvalue & 1)
369 			fflush (logfile);
370 	}
371 }
372 
373 
374 /*
375 ================
376 Com_DPrintf
377 
378 A Com_Printf that only shows up if the "developer" cvar is set
379 ================
380 */
_Com_DPrintf(char const * fmt,...)381 void _Com_DPrintf (char const *fmt, ...)
382 {
383 #if !(__STDC_VERSION__ == 199901L || _MSC_VER >= 1400 && !defined _M_AMD64)
384 	if (!developer->intvalue)
385 	{
386 		return;
387 	}
388 	else
389 #endif
390 	{
391 		va_list		argptr;
392 		char		msg[MAXPRINTMSG];
393 
394 		va_start (argptr,fmt);
395 		if (Q_vsnprintf (msg, sizeof(msg)-1, fmt, argptr) < 0)
396 			Com_Printf ("WARNING: Com_DPrintf: message overflow.\n", LOG_WARNING);
397 		va_end (argptr);
398 
399 		msg[sizeof(msg)-1] = 0;
400 
401 		Com_Printf ("%s", LOG_DEBUG, msg);
402 	}
403 }
404 
405 
406 /*
407 =============
408 Com_Error
409 
410 Both client and server can use this, and it will
411 do the apropriate things.
412 =============
413 */
Com_Error(int code,const char * fmt,...)414 void Com_Error (int code, const char *fmt, ...)
415 {
416 	va_list		argptr;
417 	static char		msg[MAXPRINTMSG];
418 	static	qboolean	recursive;
419 
420 	if (recursive && code != ERR_DIE)
421 		Sys_Error ("recursive error after: %s", msg);
422 	recursive = true;
423 
424 	va_start (argptr,fmt);
425 	vsnprintf (msg, sizeof(msg)-1, fmt,argptr);
426 	va_end (argptr);
427 
428 	Com_EndRedirect (false);
429 
430 	if (err_fatal->intvalue)
431 		code = ERR_FATAL;
432 
433 	if (code == ERR_DISCONNECT)
434 	{
435 		Com_Printf ("Disconnected by server!\n", LOG_CLIENT);
436 #ifndef DEDICATED_ONLY
437 		CL_Drop (false, true);
438 #endif
439 		recursive = false;
440 
441 		longjmp (abortframe, -1);
442 	}
443 	else if (code == ERR_DROP || code == ERR_GAME || code == ERR_NET || code == ERR_HARD)
444 	{
445 		int	state = Com_ServerState() == ss_dead ? 0 : 1;
446 		Com_Printf ("********************\nERROR: %s\n********************\n", LOG_GENERAL, msg);
447 #ifndef NO_SERVER
448 		SV_Shutdown (va("Server exited: %s\n", msg), false, false);
449 #endif
450 #ifndef DEDICATED_ONLY
451 		CL_Drop (code == ERR_NET, false);
452 #endif
453 		recursive = false;
454 
455 		//r1: auto-restart server code on game crash
456 		if (state && (code == ERR_GAME || code == ERR_DROP))
457 		{
458 			const char *resmap;
459 
460 			resmap = Cvar_VariableString ("sv_restartmap");
461 
462 			if (resmap[0])
463 				Cmd_ExecuteString (va ("map %s", resmap));
464 		}
465 
466 		longjmp (abortframe, -1);
467 	}
468 	else
469 	{
470 		printf ("%s\n", msg);
471 		if (dbg_crash_on_fatal_error->intvalue)
472 			Sys_DebugBreak ();
473 
474 		//an err_die means the whole game is about to explode, avoid running any extra code if possible
475 		if (code != ERR_DIE)
476 		{
477 #ifndef NO_SERVER
478 			SV_Shutdown (va("Server fatal crashed: %s\n", msg), false, true);
479 #endif
480 #ifndef DEDICATED_ONLY
481 			if (dbg_unload->intvalue)
482 				CL_Shutdown ();
483 #endif
484 		}
485 	}
486 
487 	if (logfile)
488 	{
489 		fprintf (logfile, "Fatal Error\n*****************************\n"
490 						  "Server fatal crashed: %s\n"
491 						  "*****************************\n", msg);
492 		fclose (logfile);
493 		logfile = NULL;
494 	}
495 
496 	Sys_Error ("%s", msg);
497 	recursive = false;
498 }
499 
500 
501 /*
502 =============
503 Com_Quit
504 
505 Both client and server can use this, and it will
506 do the apropriate things.
507 =============
508 */
Com_Quit(void)509 void Com_Quit (void)
510 {
511 	//r1: optional quit message, reworded "Server quit"
512 #ifndef NO_SERVER
513 	if (Cmd_Argc() > 1)
514 		SV_Shutdown (va("Server has shut down: %s\n", Cmd_Args()), false, false);
515 	else
516 		SV_Shutdown ("Server has shut down\n", false, false);
517 #endif
518 #ifndef DEDICATED_ONLY
519 	CL_Shutdown ();
520 #endif
521 
522 	if (logfile)
523 	{
524 		fclose (logfile);
525 		logfile = NULL;
526 	}
527 
528 	Sys_Quit ();
529 }
530 
531 
532 /*
533 ==================
534 Com_ServerState
535 ==================
536 */
537 /*int Com_ServerState (void)
538 {
539 	return server_state;
540 }*/
541 
542 /*
543 ==================
544 Com_SetServerState
545 ==================
546 */
547 /*void Com_SetServerState (int state)
548 {
549 	server_state = state;
550 }*/
551 
552 
553 /*
554 ==============================================================================
555 
556 			MESSAGE IO FUNCTIONS
557 
558 Handles byte ordering and avoids alignment errors
559 ==============================================================================
560 */
561 
562 vec3_t	bytedirs[NUMVERTEXNORMALS] =
563 {
564 #include "../client/anorms.h"
565 };
566 
567 //
568 // writing functions
569 //
570 
571 byte		message_buff[0x10000];
572 sizebuf_t	msgbuff;
573 
MSG_WriteChar(int c)574 void MSG_WriteChar (int c)
575 {
576 	byte	*buf;
577 
578 /*#ifdef PARANOID
579 	if (c < -128 || c > 127)
580 		Com_Error (ERR_FATAL, "MSG_WriteChar: range error");
581 #endif*/
582 	Q_assert (!(c < -128 || c > 127));
583 
584 	buf = SZ_GetSpace (&msgbuff, 1);
585 	buf[0] = c;
586 }
587 
MSG_BeginWriting(int c)588 void MSG_BeginWriting (int c)
589 {
590 	byte	*buf;
591 
592 /*#ifdef PARANOID
593 	if (c < 0 || c > 255)
594 		Com_Error (ERR_FATAL, "MSG_WriteByte: range error");
595 #endif*/
596 	Q_assert (!(c < 0 || c > 255));
597 	Q_assert (!msgbuff.cursize);
598 
599 #ifdef _DEBUG
600 	memset (message_buff, 0xcc, sizeof(message_buff));
601 #endif
602 
603 	buf = SZ_GetSpace (&msgbuff, 1);
604 	buf[0] = c;
605 }
606 
MSG_WriteByte(int c)607 void MSG_WriteByte (int c)
608 {
609 	byte	*buf;
610 
611 /*#ifdef PARANOID
612 	if (c < 0 || c > 255)
613 		Com_Error (ERR_FATAL, "MSG_WriteByte: range error");
614 #endif*/
615 	Q_assert (!(c < 0 || c > 255));
616 
617 	buf = SZ_GetSpace (&msgbuff, 1);
618 	buf[0] = c;
619 }
620 
MSG_WriteShort(int c)621 void MSG_WriteShort (int c)
622 {
623 	byte	*buf;
624 
625 /*#ifdef PARANOID
626 	if (c < ((int16)0x8000) || c > (int16)0x7fff)
627 		Com_Error (ERR_FATAL, "MSG_WriteShort: range error");
628 #endif*/
629 	//XXX: unsigned shorts are written here too...
630 	//Q_assert (!(c < ((int16)0x8000) || c > (int16)0x7fff));
631 
632 	buf = SZ_GetSpace (&msgbuff, 2);
633 	buf[0] = c&0xff;
634 	buf[1] = (c>>8) &0xff;
635 }
636 
SZ_WriteShort(sizebuf_t * sbuf,int c)637 void SZ_WriteShort (sizebuf_t *sbuf, int c)
638 {
639 	byte	*buf;
640 
641 	buf = SZ_GetSpace (sbuf, 2);
642 	buf[0] = c&0xff;
643 	buf[1] = (c>>8) &0xff;
644 }
645 
SZ_WriteLong(sizebuf_t * sbuf,int c)646 void SZ_WriteLong (sizebuf_t *sbuf, int c)
647 {
648 	byte	*buf;
649 
650 	buf = SZ_GetSpace (sbuf, 4);
651 	buf[0] = c&0xff;
652 	buf[1] = (c>>8)&0xff;
653 	buf[2] = (c>>16)&0xff;
654 	buf[3] = c>>24;
655 }
656 
SZ_WriteByte(sizebuf_t * sbuf,int c)657 void SZ_WriteByte (sizebuf_t *sbuf, int c)
658 {
659 	byte	*buf;
660 
661 	Q_assert (!(c < 0 || c > 255));
662 
663 	buf = SZ_GetSpace (sbuf, 1);
664 	buf[0] = c;
665 }
666 
MSG_WriteLong(int c)667 void MSG_WriteLong (int c)
668 {
669 	byte	*buf;
670 
671 	buf = SZ_GetSpace (&msgbuff, 4);
672 	buf[0] = c&0xff;
673 	buf[1] = (c>>8)&0xff;
674 	buf[2] = (c>>16)&0xff;
675 	buf[3] = c>>24;
676 }
677 
MSG_WriteFloat(float f)678 void MSG_WriteFloat (float f)
679 {
680 	union
681 	{
682 		float	f;
683 		int	l;
684 	} dat;
685 
686 
687 	dat.f = f;
688 	dat.l = LittleLong (dat.l);
689 
690 	SZ_Write (&msgbuff, &dat.l, 4);
691 }
692 
MSG_WriteString(const char * s)693 void MSG_WriteString (const char *s)
694 {
695 	if (!s)
696 		SZ_Write (&msgbuff, "", 1);
697 	else
698 		SZ_Write (&msgbuff, s, (int)strlen(s)+1);
699 }
700 
MSG_Write(const void * data,int length)701 void MSG_Write (const void *data, int length)
702 {
703 	memcpy (SZ_GetSpace(&msgbuff,length),data,length);
704 }
705 
MSG_Print(const char * data)706 void MSG_Print (const char *data)
707 {
708 	int		len;
709 
710 	len = (int)strlen(data)+1;
711 
712 	Q_assert (len > 1);
713 
714 	if (msgbuff.cursize)
715 	{
716 		if (message_buff[msgbuff.cursize-1])
717 			memcpy ((byte *)SZ_GetSpace(&msgbuff, len),data,len); // no trailing 0
718 		else
719 			memcpy ((byte *)SZ_GetSpace(&msgbuff, len-1)-1,data,len); // write over trailing 0
720 	}
721 	else
722 		memcpy ((byte *)SZ_GetSpace(&msgbuff, len),data,len);
723 }
724 
MSG_GetLength(void)725 int	MSG_GetLength (void)
726 {
727 	return msgbuff.cursize;
728 }
729 
MSG_GetRawMsg(void)730 sizebuf_t *MSG_GetRawMsg (void)
731 {
732 	return &msgbuff;
733 }
734 
MSG_GetData(void)735 byte *MSG_GetData (void)
736 {
737 	return message_buff;
738 }
739 
MSG_GetType(void)740 byte MSG_GetType (void)
741 {
742 	Q_assert (msgbuff.cursize > 0);
743 
744 	return message_buff[0];
745 }
746 
MSG_FreeData(void)747 void MSG_FreeData (void)
748 {
749 	Q_assert (msgbuff.cursize > 0);
750 	SZ_Clear (&msgbuff);
751 #ifdef _DEBUG
752 	memset (message_buff, 0xcc, sizeof(message_buff));
753 #endif
754 }
755 
MSG_Clear(void)756 void MSG_Clear (void)
757 {
758 	SZ_Clear (&msgbuff);
759 #ifdef _DEBUG
760 	memset (message_buff, 0xcc, sizeof(message_buff));
761 #endif
762 }
763 
MSG_EndWriting(sizebuf_t * out)764 void MSG_EndWriting (sizebuf_t *out)
765 {
766 	Q_assert (msgbuff.cursize > 0);
767 
768 	//Q_assert (msgbuff.cursize < MAX_USABLEMSG);
769 
770 	if (out->cursize + msgbuff.cursize > out->maxsize)
771 	{
772 		Com_DPrintf ("MSG_EndWriting: overflow\n");
773 		SZ_Clear (out);
774 		out->overflowed = true;
775 	}
776 	else
777 	{
778 		SZ_Write (out, message_buff, msgbuff.cursize);
779 	}
780 
781 	SZ_Clear (&msgbuff);
782 #ifdef _DEBUG
783 	memset (message_buff, 0xcc, sizeof(message_buff));
784 #endif
785 }
786 
MSG_EndWrite(messagelist_t * out)787 void MSG_EndWrite (messagelist_t *out)
788 {
789 	Q_assert (msgbuff.cursize > 0);
790 
791 	//r1: use small local buffer if possible to avoid thousands of mallocs with tiny amounts
792 	if (msgbuff.cursize > MSG_MAX_SIZE_BEFORE_MALLOC)
793 	{
794 #ifndef NPROFILE
795 		msg_malloc_hits++;
796 #endif
797 		out->data = malloc (msgbuff.cursize);
798 	}
799 	else
800 	{
801 #ifndef NPROFILE
802 		msg_local_hits++;
803 #endif
804 		out->data = out->localbuff;
805 	}
806 
807 #ifndef NPROFILE
808 	if (msgbuff.cursize < sizeof(messageSizes) / sizeof(messageSizes[0]))
809 		messageSizes[msgbuff.cursize]++;
810 #endif
811 
812 	memcpy (out->data, message_buff, msgbuff.cursize);
813 	out->cursize = msgbuff.cursize;
814 }
815 
MSG_WriteCoord(float f)816 void MSG_WriteCoord (float f)
817 {
818 	MSG_WriteShort ((int)(f*8));
819 }
820 
MSG_WritePos(vec3_t pos)821 void MSG_WritePos (vec3_t pos)
822 {
823 	MSG_WriteShort ((int)(pos[0]*8));
824 	MSG_WriteShort ((int)(pos[1]*8));
825 	MSG_WriteShort ((int)(pos[2]*8));
826 }
827 
MSG_WriteAngle(float f)828 void MSG_WriteAngle (float f)
829 {
830 	MSG_WriteByte ((int)(f*256/360) & 255);
831 }
832 
MSG_WriteAngle16(float f)833 void MSG_WriteAngle16 (float f)
834 {
835 	MSG_WriteShort (ANGLE2SHORT(f));
836 }
837 
838 
MSG_WriteDeltaUsercmd(const usercmd_t * from,const usercmd_t * cmd,int protocol)839 void MSG_WriteDeltaUsercmd (const usercmd_t *from, const usercmd_t *cmd, int protocol)
840 {
841 	int		bits;
842 	int		buttons;
843 
844 //
845 // send the movement message
846 //
847 	bits = 0;
848 	buttons = 0;
849 
850 	if (cmd->angles[0] != from->angles[0])
851 		bits |= CM_ANGLE1;
852 	if (cmd->angles[1] != from->angles[1])
853 		bits |= CM_ANGLE2;
854 
855 	//FIXME: it's impossible for cl.viewangles roll to change,
856 	//is this ever legitimately set?
857 	if (cmd->angles[2] != from->angles[2])
858 		bits |= CM_ANGLE3;
859 
860 	if (cmd->forwardmove != from->forwardmove)
861 		bits |= CM_FORWARD;
862 	if (cmd->sidemove != from->sidemove)
863 		bits |= CM_SIDE;
864 	if (cmd->upmove != from->upmove)
865 		bits |= CM_UP;
866 
867 	if (cmd->buttons != from->buttons)
868 	{
869 		buttons = cmd->buttons;
870 		bits |= CM_BUTTONS;
871 	}
872 
873 	if (cmd->impulse != from->impulse)
874 		bits |= CM_IMPULSE;
875 
876     MSG_WriteByte (bits);
877 
878 	//waste not what precious bytes we have...
879 	if (protocol >= MINOR_VERSION_R1Q2_UCMD_UPDATES)
880 	{
881 		if (bits & CM_BUTTONS)
882 		{
883 			if ((bits & CM_FORWARD) && (cmd->forwardmove % 5) == 0)
884 				buttons |= BUTTON_UCMD_DBLFORWARD;
885 			if ((bits & CM_SIDE) && (cmd->sidemove % 5) == 0)
886 				buttons |= BUTTON_UCMD_DBLSIDE;
887 			if ((bits & CM_UP) && (cmd->upmove % 5) == 0)
888 				buttons |= BUTTON_UCMD_DBLUP;
889 
890 			if ((bits & CM_ANGLE1) && (cmd->angles[0] % 64) == 0 && (abs(cmd->angles[0] / 64)) < 128)
891 				buttons |= BUTTON_UCMD_DBL_ANGLE1;
892 			if ((bits & CM_ANGLE2) && (cmd->angles[1] % 256) == 0)
893 				buttons |= BUTTON_UCMD_DBL_ANGLE2;
894 
895 			MSG_WriteByte (buttons);
896 		}
897 	}
898 
899 	if (bits & CM_ANGLE1)
900 	{
901 		if (buttons & BUTTON_UCMD_DBL_ANGLE1)
902 			MSG_WriteChar (cmd->angles[0] / 64);
903 		else
904 			MSG_WriteShort (cmd->angles[0]);
905 	}
906 
907 	if (bits & CM_ANGLE2)
908 	{
909 		if (buttons & BUTTON_UCMD_DBL_ANGLE2)
910 			MSG_WriteChar (cmd->angles[1] / 256);
911 		else
912 			MSG_WriteShort (cmd->angles[1]);
913 	}
914 
915 	if (bits & CM_ANGLE3)
916 		MSG_WriteShort (cmd->angles[2]);
917 
918 	if (bits & CM_FORWARD)
919 	{
920 		if (buttons & BUTTON_UCMD_DBLFORWARD)
921 			MSG_WriteChar (cmd->forwardmove / 5);
922 		else
923 			MSG_WriteShort (cmd->forwardmove);
924 	}
925 
926 	if (bits & CM_SIDE)
927 	{
928 		if (buttons & BUTTON_UCMD_DBLSIDE)
929 			MSG_WriteChar (cmd->sidemove / 5);
930 		else
931 			MSG_WriteShort (cmd->sidemove);
932 	}
933 
934 	if (bits & CM_UP)
935 	{
936 		if (buttons & BUTTON_UCMD_DBLUP)
937 			MSG_WriteChar (cmd->upmove / 5);
938 		else
939 			MSG_WriteShort (cmd->upmove);
940 	}
941 
942 	if (protocol < MINOR_VERSION_R1Q2_UCMD_UPDATES)
943 	{
944  		if (bits & CM_BUTTONS)
945 	  		MSG_WriteByte (buttons);
946 	}
947 
948  	if (bits & CM_IMPULSE)
949 	    MSG_WriteByte (cmd->impulse);
950 
951     MSG_WriteByte (cmd->msec);
952 	MSG_WriteByte (cmd->lightlevel);
953 }
954 
955 
MSG_WriteDir(vec3_t dir)956 void MSG_WriteDir (vec3_t dir)
957 {
958 	int		i, best;
959 	float	d, bestd;
960 
961 	if (!dir)
962 	{
963 		MSG_WriteByte (0);
964 		return;
965 	}
966 
967 	bestd = 0;
968 	best = 0;
969 	for (i=0 ; i<NUMVERTEXNORMALS ; i++)
970 	{
971 		d = DotProduct (dir, bytedirs[i]);
972 		if (d > bestd)
973 		{
974 			bestd = d;
975 			best = i;
976 		}
977 	}
978 	MSG_WriteByte (best);
979 }
980 
981 
MSG_ReadDir(sizebuf_t * sb,vec3_t dir)982 void MSG_ReadDir (sizebuf_t *sb, vec3_t dir)
983 {
984 	int		b;
985 
986 	b = MSG_ReadByte (sb);
987 	if (b == -1 || b >= NUMVERTEXNORMALS)
988 		Com_Error (ERR_DROP, "MSG_ReadDir: out of range (%d)", b);
989 	VectorCopy (bytedirs[b], dir);
990 }
991 
992 
993 //============================================================
994 
995 //
996 // reading functions
997 //
998 
MSG_BeginReading(sizebuf_t * msg)999 void MSG_BeginReading (sizebuf_t *msg)
1000 {
1001 	msg->readcount = 0;
1002 }
1003 
1004 // returns -1 if no more characters are available
MSG_ReadChar(sizebuf_t * msg_read)1005 int MSG_ReadChar (sizebuf_t *msg_read)
1006 {
1007 	int	c;
1008 
1009 	if (msg_read->readcount+1 > msg_read->cursize)
1010 		c = -1;
1011 	else
1012 		c = (signed char)msg_read->data[msg_read->readcount];
1013 	msg_read->readcount++;
1014 
1015 	return c;
1016 }
1017 
MSG_ReadByte(sizebuf_t * msg_read)1018 int MSG_ReadByte (sizebuf_t *msg_read)
1019 {
1020 	int	c;
1021 
1022 	if (msg_read->readcount+1 > msg_read->cursize)
1023 		c = -1;
1024 	else
1025 		c = (unsigned char)msg_read->data[msg_read->readcount];
1026 	msg_read->readcount++;
1027 
1028 	return c;
1029 }
1030 
MSG_ReadShort(sizebuf_t * msg_read)1031 int MSG_ReadShort (sizebuf_t *msg_read)
1032 {
1033 	int	c;
1034 
1035 	if (msg_read->readcount+2 > msg_read->cursize)
1036 		c = -1;
1037 	else
1038 		c = (int16)(msg_read->data[msg_read->readcount]
1039 		+ (msg_read->data[msg_read->readcount+1]<<8));
1040 
1041 	msg_read->readcount += 2;
1042 
1043 	return c;
1044 }
1045 
MSG_ReadLong(sizebuf_t * msg_read)1046 int MSG_ReadLong (sizebuf_t *msg_read)
1047 {
1048 	int	c;
1049 
1050 	if (msg_read->readcount+4 > msg_read->cursize)
1051 		c = -1;
1052 	else
1053 		c = msg_read->data[msg_read->readcount]
1054 		+ (msg_read->data[msg_read->readcount+1]<<8)
1055 		+ (msg_read->data[msg_read->readcount+2]<<16)
1056 		+ (msg_read->data[msg_read->readcount+3]<<24);
1057 
1058 	msg_read->readcount += 4;
1059 
1060 	return c;
1061 }
1062 
MSG_ReadFloat(sizebuf_t * msg_read)1063 float MSG_ReadFloat (sizebuf_t *msg_read)
1064 {
1065 	union
1066 	{
1067 		byte	b[4];
1068 		float	f;
1069 		int	l;
1070 	} dat;
1071 
1072 	if (msg_read->readcount+4 > msg_read->cursize)
1073 		dat.f = -1;
1074 	else
1075 	{
1076 		dat.b[0] =	msg_read->data[msg_read->readcount];
1077 		dat.b[1] =	msg_read->data[msg_read->readcount+1];
1078 		dat.b[2] =	msg_read->data[msg_read->readcount+2];
1079 		dat.b[3] =	msg_read->data[msg_read->readcount+3];
1080 	}
1081 	msg_read->readcount += 4;
1082 
1083 	dat.l = LittleLong (dat.l);
1084 
1085 	return dat.f;
1086 }
1087 
MSG_ReadString(sizebuf_t * msg_read)1088 char *MSG_ReadString (sizebuf_t *msg_read)
1089 {
1090 	static char	string[2048];
1091 	int		l,c;
1092 
1093 	l = 0;
1094 	do
1095 	{
1096 		c = MSG_ReadByte (msg_read);
1097 		if (c == -1 || c == 0)
1098 			break;
1099 		string[l] = c;
1100 		l++;
1101 	} while (l < sizeof(string)-1);
1102 
1103 	string[l] = 0;
1104 
1105 	return string;
1106 }
1107 
MSG_ReadStringLine(sizebuf_t * msg_read)1108 char *MSG_ReadStringLine (sizebuf_t *msg_read)
1109 {
1110 	static char	string[2048];
1111 	int		l,c;
1112 
1113 	l = 0;
1114 	do
1115 	{
1116 		c = MSG_ReadByte (msg_read);
1117 		if (c == -1 || c == 0 || c == '\n')
1118 			break;
1119 		string[l] = c;
1120 		l++;
1121 	} while (l < sizeof(string)-1);
1122 
1123 	string[l] = 0;
1124 	return string;
1125 }
1126 
MSG_ReadCoord(sizebuf_t * msg_read)1127 float MSG_ReadCoord (sizebuf_t *msg_read)
1128 {
1129 	return MSG_ReadShort(msg_read) * 0.125f;
1130 }
1131 
MSG_ReadPos(sizebuf_t * msg_read,vec3_t pos)1132 void MSG_ReadPos (sizebuf_t *msg_read, vec3_t pos)
1133 {
1134 	pos[0] = MSG_ReadShort(msg_read) * 0.125f;
1135 	pos[1] = MSG_ReadShort(msg_read) * 0.125f;
1136 	pos[2] = MSG_ReadShort(msg_read) * 0.125f;
1137 }
1138 
MSG_ReadAngle(sizebuf_t * msg_read)1139 float MSG_ReadAngle (sizebuf_t *msg_read)
1140 {
1141 	return MSG_ReadChar(msg_read) * 1.40625f;
1142 }
1143 
MSG_ReadAngle16(sizebuf_t * msg_read)1144 float MSG_ReadAngle16 (sizebuf_t *msg_read)
1145 {
1146 	return SHORT2ANGLE(MSG_ReadShort(msg_read));
1147 }
1148 
1149 #ifndef NPROFILE
1150 unsigned long r1q2UserCmdOptimizedBytes = 0;
1151 #endif
1152 
MSG_ReadDeltaUsercmd(sizebuf_t * msg_read,usercmd_t * from,usercmd_t * move,int protocol)1153 void MSG_ReadDeltaUsercmd (sizebuf_t *msg_read, usercmd_t *from, usercmd_t /*@out@*/*move, int protocol)
1154 {
1155 	int			buttons;
1156 	int			bits;
1157 	unsigned	msec;
1158 
1159 	memcpy (move, from, sizeof(*move));
1160 
1161 	bits = MSG_ReadByte (msg_read);
1162 	buttons = 0;
1163 
1164 	if (protocol >= MINOR_VERSION_R1Q2_UCMD_UPDATES)
1165 	{
1166 		if (bits & CM_BUTTONS)
1167 		{
1168 			buttons = MSG_ReadByte (msg_read);
1169 
1170 			//only save real buttons, strip off the extra stolen bits
1171 			move->buttons = buttons & (BUTTON_ATTACK|BUTTON_USE|BUTTON_ANY);
1172 		}
1173 	}
1174 
1175 // read current angles
1176 	if (bits & CM_ANGLE1)
1177 	{
1178 		if (buttons & BUTTON_UCMD_DBL_ANGLE1)
1179 		{
1180 			#ifndef NPROFILE
1181 			r1q2UserCmdOptimizedBytes++;
1182 			#endif
1183 			move->angles[0] = MSG_ReadChar (msg_read) * 64;
1184 		}
1185 		else
1186 			move->angles[0] = MSG_ReadShort (msg_read);
1187 	}
1188 
1189 	if (bits & CM_ANGLE2)
1190 	{
1191 		if (buttons & BUTTON_UCMD_DBL_ANGLE2)
1192 		{
1193 			#ifndef NPROFILE
1194 			r1q2UserCmdOptimizedBytes++;
1195 			#endif
1196 			move->angles[1] = MSG_ReadChar (msg_read) * 256;
1197 		}
1198 		else
1199 			move->angles[1] = MSG_ReadShort (msg_read);
1200 	}
1201 
1202 	if (bits & CM_ANGLE3)
1203 		move->angles[2] = MSG_ReadShort (msg_read);
1204 
1205 // read movement
1206 	if (bits & CM_FORWARD)
1207 	{
1208 		if (buttons & BUTTON_UCMD_DBLFORWARD)
1209 		{
1210 			#ifndef NPROFILE
1211 			r1q2UserCmdOptimizedBytes++;
1212 			#endif
1213 			move->forwardmove = MSG_ReadChar (msg_read) * 5;
1214 		}
1215 		else
1216 			move->forwardmove = MSG_ReadShort (msg_read);
1217 	}
1218 
1219 	if (bits & CM_SIDE)
1220 	{
1221 		if (buttons & BUTTON_UCMD_DBLSIDE)
1222 		{
1223 			#ifndef NPROFILE
1224 			r1q2UserCmdOptimizedBytes++;
1225 			#endif
1226 			move->sidemove = MSG_ReadChar (msg_read) * 5;
1227 		}
1228 		else
1229 			move->sidemove = MSG_ReadShort (msg_read);
1230 	}
1231 
1232 	if (bits & CM_UP)
1233 	{
1234 		if (buttons & BUTTON_UCMD_DBLUP)
1235 		{
1236 			#ifndef NPROFILE
1237 			r1q2UserCmdOptimizedBytes++;
1238 			#endif
1239 			move->upmove = MSG_ReadChar (msg_read) * 5;
1240 		}
1241 		else
1242 			move->upmove = MSG_ReadShort (msg_read);
1243 	}
1244 
1245 // read buttons
1246 	if (protocol < MINOR_VERSION_R1Q2_UCMD_UPDATES)
1247 	{
1248 		if (bits & CM_BUTTONS)
1249 			move->buttons = MSG_ReadByte (msg_read);
1250 	}
1251 
1252 	if (bits & CM_IMPULSE)
1253 		move->impulse = MSG_ReadByte (msg_read);
1254 
1255 // read time to run command
1256 	msec = MSG_ReadByte (msg_read);
1257 
1258 	if (msec > 250)
1259 		Com_Printf ("MSG_ReadDeltaUsercmd: funky msec (%d)!\n", LOG_GENERAL, msec);
1260 
1261 	move->msec = msec;
1262 
1263 // read the light level
1264 	move->lightlevel = MSG_ReadByte (msg_read);
1265 }
1266 
1267 
MSG_ReadData(sizebuf_t * msg_read,void * data,int len)1268 void MSG_ReadData (sizebuf_t *msg_read, void *data, int len)
1269 {
1270 	int		i;
1271 
1272 	for (i=0 ; i<len ; i++)
1273 		((byte *)data)[i] = MSG_ReadByte (msg_read);
1274 }
1275 
1276 
1277 //===========================================================================
1278 
SZ_Init(sizebuf_t * buf,byte * data,int length)1279 void SZ_Init (sizebuf_t /*@out@*/*buf, byte /*@out@*/*data, int length)
1280 {
1281 	Q_assert (length > 0);
1282 
1283 	memset (buf, 0, sizeof(*buf));
1284 	buf->data = data;
1285 	buf->maxsize = length;
1286 	buf->buffsize = length;	//should never change this
1287 }
1288 
SZ_Clear(sizebuf_t * buf)1289 void SZ_Clear (sizebuf_t /*@out@*/*buf)
1290 {
1291 	buf->cursize = 0;
1292 	buf->overflowed = false;
1293 }
1294 
SZ_GetSpace(sizebuf_t * buf,int length)1295 void *SZ_GetSpace (sizebuf_t /*@out@*/*buf, int length)
1296 {
1297 	void	*data;
1298 
1299 	Q_assert (length > 0);
1300 
1301 	if (buf->cursize + length > buf->maxsize)
1302 	{
1303 		if (!buf->data)
1304 			Com_Error (ERR_FATAL, "SZ_GetSpace: attempted to write %d bytes to an uninitialized buffer!", length);
1305 
1306 		if (!buf->allowoverflow)
1307 		{
1308 			if (length > buf->maxsize)
1309 				Com_Error (ERR_FATAL, "SZ_GetSpace: %i is > full buffer size %d (%d)", length, buf->maxsize, buf->buffsize);
1310 
1311 			Com_Error (ERR_FATAL, "SZ_GetSpace: overflow without allowoverflow set (%d+%d > %d)", buf->cursize, length, buf->maxsize);
1312 		}
1313 
1314 		//r1: clear the buffer BEFORE the error!! (for console buffer)
1315 		if (buf->cursize + length >= buf->buffsize)
1316 		{
1317 			SZ_Clear (buf);
1318 			Com_DPrintf ("SZ_GetSpace: overflow\n");
1319 		}
1320 		else
1321 		{
1322 			Com_DPrintf ("SZ_GetSpace: overflowed maxsize\n");
1323 		}
1324 
1325 		buf->overflowed = true;
1326 	}
1327 
1328 	data = buf->data + buf->cursize;
1329 	buf->cursize += length;
1330 
1331 	return data;
1332 }
1333 
SZ_Write(sizebuf_t * buf,const void * data,int length)1334 void SZ_Write (sizebuf_t /*@out@*/*buf, const void *data, int length)
1335 {
1336 	memcpy (SZ_GetSpace(buf,length),data,length);
1337 }
1338 
SZ_Print(sizebuf_t * buf,const char * data)1339 void SZ_Print (sizebuf_t /*@out@*/*buf, const char *data)
1340 {
1341 	int		len;
1342 
1343 	len = (int)strlen(data)+1;
1344 
1345 	Q_assert (len > 1);
1346 
1347 	if (buf->cursize)
1348 	{
1349 		if (buf->data[buf->cursize-1])
1350 			memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
1351 		else
1352 			memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
1353 	}
1354 	else
1355 		memcpy ((byte *)SZ_GetSpace(buf, len),data,len);
1356 }
1357 
1358 
1359 //============================================================================
1360 
1361 
1362 /*
1363 ================
1364 COM_CheckParm
1365 
1366 Returns the position (1 to argc-1) in the program's argument list
1367 where the given parameter apears, or 0 if not present
1368 ================
1369 */
1370 /*int COM_CheckParm (const char *parm)
1371 {
1372 	int		i;
1373 
1374 	for (i=1 ; i<com_argc ; i++)
1375 	{
1376 		if (!strcmp (parm,com_argv[i]))
1377 			return i;
1378 	}
1379 
1380 	return 0;
1381 }*/
1382 
COM_Argc(void)1383 int COM_Argc (void)
1384 {
1385 	return com_argc;
1386 }
1387 
COM_Argv(int arg)1388 char *COM_Argv (int arg)
1389 {
1390 	if (arg < 0 || arg >= com_argc || !com_argv[arg])
1391 		return "";
1392 	return com_argv[arg];
1393 }
1394 
COM_ClearArgv(int arg)1395 void COM_ClearArgv (int arg)
1396 {
1397 	if (arg < 0 || arg >= com_argc || !com_argv[arg])
1398 		return;
1399 	com_argv[arg] = "";
1400 }
1401 
1402 
1403 /*
1404 ================
1405 COM_InitArgv
1406 ================
1407 */
COM_InitArgv(int argc,char ** argv)1408 void COM_InitArgv (int argc, char **argv)
1409 {
1410 	int		i;
1411 
1412 	if (argc > MAX_NUM_ARGVS)
1413 		Com_Error (ERR_FATAL, "argc > MAX_NUM_ARGVS");
1414 	com_argc = argc;
1415 	for (i=0 ; i<argc ; i++)
1416 	{
1417 		if (!argv[i] || strlen(argv[i]) >= MAX_TOKEN_CHARS )
1418 			com_argv[i] = "";
1419 		else
1420 			com_argv[i] = argv[i];
1421 	}
1422 }
1423 
1424 /*
1425 ================
1426 COM_AddParm
1427 
1428 Adds the given string at the end of the current argument list
1429 ================
1430 */
COM_AddParm(char * parm)1431 void COM_AddParm (char *parm)
1432 {
1433 	if (com_argc == MAX_NUM_ARGVS)
1434 		Com_Error (ERR_FATAL, "COM_AddParm: MAX_NUM_ARGVS");
1435 	com_argv[com_argc++] = parm;
1436 }
1437 
1438 
1439 
1440 
1441 /// just for debugging
1442 /*int	memsearch (byte *start, int count, int search)
1443 {
1444 	int		i;
1445 
1446 	for (i=0 ; i<count ; i++)
1447 		if (start[i] == search)
1448 			return i;
1449 	return -1;
1450 }*/
1451 
1452 
CopyString(const char * in,int tag)1453 char *CopyString (const char *in, int tag)
1454 {
1455 	char	*out;
1456 
1457 	out = Z_TagMalloc ((int)strlen(in)+1, tag);
1458 	strcpy (out, in);
1459 	return out;
1460 }
1461 
Info_Print(const char * s)1462 void Info_Print (const char *s)
1463 {
1464 	char	key[512];
1465 	char	value[512];
1466 	char	*o;
1467 	int		l;
1468 
1469 	if (*s == '\\')
1470 		s++;
1471 	while (*s)
1472 	{
1473 		o = key;
1474 		while (*s && *s != '\\')
1475 			*o++ = *s++;
1476 
1477 		l = (int)(o - key);
1478 		if (l < 20)
1479 		{
1480 			memset (o, ' ', 20-l);
1481 			key[20] = 0;
1482 		}
1483 		else
1484 			*o = 0;
1485 		Com_Printf ("%s", LOG_GENERAL, key);
1486 
1487 		if (!*s)
1488 		{
1489 			Com_Printf ("Info_Print: MISSING VALUE\n", LOG_GENERAL);
1490 			return;
1491 		}
1492 
1493 		o = value;
1494 		s++;
1495 		while (*s && *s != '\\')
1496 			*o++ = *s++;
1497 		*o = 0;
1498 
1499 		if (*s)
1500 			s++;
1501 		Com_Printf ("%s\n", LOG_GENERAL, value);
1502 	}
1503 }
1504 
1505 /*
1506 ==============================================================================
1507 
1508 						ZONE MEMORY ALLOCATION
1509 
1510 just cleared malloc with counters now...
1511 
1512 ==============================================================================
1513 */
1514 
1515 #define	Z_MAGIC			0x1d1d
1516 #define	Z_MAGIC_DEBUG	0x2d2d
1517 
1518 typedef struct zhead_s
1519 {
1520 	struct zhead_s	*prev, *next;
1521 	int16	magic;
1522 	int16	tag;			// for group free
1523 	int		size;
1524 	void	*allocationLocation;
1525 } zhead_t;
1526 
1527 typedef struct z_memloc_s
1528 {
1529 	void				*address;
1530 	uint32				time;
1531 	uint32				size;
1532 	struct	z_memloc_s	*next;
1533 	void				*allocationLocation;
1534 } z_memloc_t;
1535 
1536 static z_memloc_t	z_game_locations;
1537 
1538 static zhead_t	z_chain = {0};
1539 
1540 static long		z_count = 0;
1541 static long		z_bytes = 0;
1542 
1543 static unsigned long	z_allocs = 0;
1544 static unsigned long	z_level_allocs = 0;
1545 static unsigned long	z_game_allocs = 0;
1546 
1547 qboolean	free_from_game = false;
1548 
1549 /*
1550 ========================
1551 Z_Free
1552 ========================
1553 */
Z_FreeRelease(const void * ptr)1554 void EXPORT Z_FreeRelease (const void *ptr)
1555 {
1556 	zhead_t	*z;
1557 
1558 	z = ((zhead_t *)ptr) - 1;
1559 
1560 	if (z->magic != Z_MAGIC && z->magic != Z_MAGIC_DEBUG)
1561 		Com_Error (ERR_DIE, "Z_Free: bad magic");
1562 
1563 	z->prev->next = z->next;
1564 	z->next->prev = z->prev;
1565 
1566 	z_count--;
1567 	z_bytes -= z->size;
1568 	free (z);
1569 }
1570 
Z_FreeDebug(const void * ptr)1571 void EXPORT Z_FreeDebug (const void *ptr)
1572 {
1573 	zhead_t	*z;
1574 
1575 	if (!ptr)
1576 		Com_Error (ERR_DIE, "Z_Free: null pointer given from %s", free_from_game ? "GAME" : "EXECUTABLE");
1577 
1578 	z = ((zhead_t *)ptr) - 1;
1579 
1580 	Z_Verify ("Z_FreeDebug: START FREE FROM %s OF %p (%d bytes tagged %d (%s))", free_from_game ? "GAME" : "EXECUTABLE", ptr, z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG");
1581 
1582 	//magic test
1583 	if (z->magic != Z_MAGIC && z->magic != Z_MAGIC_DEBUG)
1584 		Com_Error (ERR_DIE, "Z_Free: bad magic freeing %p from %s", z, free_from_game ? "GAME" : "EXECUTABLE");
1585 
1586 	//size sanity test
1587 	if (z->size <= 0 || z->size > 0x40000000)
1588 	{
1589 		if (z_allowcorruption->intvalue)
1590 			Com_Printf ("Z_Free: crazy block size %d (maybe tag %d (%s)) from %s at %p, allocated at %p", LOG_ERROR, z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", free_from_game ? "GAME" : "EXECUTABLE", z, z->allocationLocation);
1591 		else
1592 			Com_Error (ERR_DIE, "Z_Free: crazy block size %d (maybe tag %d (%s)) from %s at %p allocated at %p", z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", free_from_game ? "GAME" : "EXECUTABLE", z, z->allocationLocation);
1593 	}
1594 
1595 	//we could segfault here if size is invalid :(
1596 	if (z->magic == Z_MAGIC_DEBUG && (*(byte **)&z)[z->size-1] != 0xCC)
1597 	{
1598 		if (z_allowcorruption->intvalue)
1599 			Com_Printf ("Z_Free: buffer overrun detected in block sized %d (tagged as %d (%s)) from %s at %p allocated at %p", LOG_ERROR, z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", free_from_game ? "GAME" : "EXECUTABLE", z, z->allocationLocation);
1600 		else
1601 			Com_Error (ERR_DIE, "Z_Free: buffer overrun detected in block sized %d (tagged as %d (%s)) from %s at %p allocated at %p", z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", free_from_game ? "GAME" : "EXECUTABLE", z, z->allocationLocation);
1602 	}
1603 
1604 	z->prev->next = z->next;
1605 	z->next->prev = z->prev;
1606 
1607 	if (z->next->magic != Z_MAGIC && z->next->magic != Z_MAGIC_DEBUG)
1608 		Com_Error (ERR_DIE, "Z_Free: memory corruption detected after free of block at %p from %s", z, free_from_game ? "GAME" : "EXECUTABLE");
1609 
1610 	z_count--;
1611 	z_bytes -= z->size;
1612 
1613 	if (z_count < 0 || z_bytes < 0)
1614 		Com_Error (ERR_DIE, "Z_Free: counters are screwed after free of %d bytes at %p tagged %d (%s) from %s", z->size, z, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", free_from_game ? "GAME" : "EXECUTABLE");
1615 
1616 	free (z);
1617 
1618 	Z_Verify ("Z_FreeDebug: END FREE OF %p FROM %s", ptr, free_from_game ? "GAME" : "EXECUTABLE");
1619 }
1620 
1621 /*
1622 ========================
1623 Z_Stats_f
1624 ========================
1625 */
1626 
1627 #define	TAG_GAME	765		// clear when unloading the dll
1628 #define	TAG_LEVEL	766		// clear when loading a new level
1629 
Z_Stats_f(void)1630 void Z_Stats_f (void)
1631 {
1632 	int i, total, num, bigtotal, bignum, level_count, level_size, game_count, game_size;
1633 	zhead_t	*z, *next;
1634 
1635 	bigtotal = bignum = level_size = level_count = game_size = game_count = 0;
1636 
1637 	for (i = 0; i < TAGMALLOC_MAX_TAGS; i++) {
1638 		total = num = 0;
1639 		for (z=z_chain.next ; z != &z_chain ; z=next)
1640 		{
1641 			next = z->next;
1642 			if (z->tag == i) {
1643 				total += z->size;
1644 				num++;
1645 			}
1646 
1647 			if (i == (TAGMALLOC_MAX_TAGS - 1)) {
1648 				if (z->tag == TAG_LEVEL) {
1649 					level_size += z->size;
1650 					level_count ++;
1651 				} else if (z->tag == TAG_GAME) {
1652 					game_size += z->size;
1653 					game_count++;
1654 				}
1655 			}
1656 		}
1657 		bigtotal += total;
1658 		bignum += num;
1659 		Com_Printf ("%14.14s: %8i bytes %5i blocks %8i allocs\n", LOG_GENERAL, tagmalloc_tags[i].name, total, num, tagmalloc_tags[i].allocs);
1660 	}
1661 
1662 	bigtotal += game_size;
1663 	bigtotal += level_size;
1664 
1665 	bignum += game_count;
1666 	bignum += level_count;
1667 
1668 	Com_Printf ("%14.14s: %8i bytes %5i blocks %8lu allocs\n", LOG_GENERAL, "DLL_LEVEL", level_size, level_count, z_level_allocs);
1669 	Com_Printf ("%14.14s: %8i bytes %5i blocks %8lu allocs\n\n", LOG_GENERAL, "DLL_GAME", game_size, game_count, z_game_allocs);
1670 
1671 	Com_Printf ("%lu unaccounted allocations\n", LOG_GENERAL, z_allocs);
1672 
1673 	Com_Printf ("  CALCED_TOTAL: %i bytes in %i blocks\n", LOG_GENERAL, bigtotal, bignum);
1674 	Com_Printf (" RUNNING_TOTAL: %li bytes in %li blocks\n", LOG_GENERAL, z_bytes, z_count);
1675 }
1676 
1677 /*
1678 ========================
1679 Z_FreeTags
1680 ========================
1681 */
Z_FreeTags(int tag)1682 void Z_FreeTags (int tag)
1683 {
1684 	zhead_t	*z, *next;
1685 
1686 	Z_Verify ("Z_FreeTags: START");
1687 
1688 	for (z=z_chain.next ; z != &z_chain ; z=next)
1689 	{
1690 		next = z->next;
1691 		if (z->tag == tag)
1692 			Z_Free ((void *)(z+1));
1693 	}
1694 
1695 	Z_Verify ("Z_FreeTags: END");
1696 }
1697 
1698 /*
1699 ========================
1700 Z_FreeTags
1701 ========================
1702 */
Z_Verify(const char * format,...)1703 void Z_Verify (const char *format, ...)
1704 {
1705 	va_list		argptr;
1706 	int			i;
1707 	zhead_t		*z, *next;
1708 	char		string[1024];
1709 
1710 	va_start (argptr, format);
1711 	vsnprintf (string, sizeof(string)-1, format, argptr);
1712 	va_end (argptr);
1713 
1714 	string[sizeof(string)-1] = 0;
1715 
1716 	i = 0;
1717 
1718 	for (z=z_chain.next ; z != &z_chain ; z=next)
1719 	{
1720 		next = z->next;
1721 		if (z->magic != Z_MAGIC)
1722 		{
1723 			if (z->magic == Z_MAGIC_DEBUG)
1724 			{
1725 				//size sanity test
1726 				if (z->size <= 0 || z->size > 0x40000000)
1727 				{
1728 					if (z_allowcorruption->intvalue)
1729 						Com_Printf ("Z_Verify: crazy block size %d (maybe tag %d (%s)) during '%s' at %p, allocated from %p", LOG_ERROR, z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", string, z, z->allocationLocation);
1730 					else
1731 						Com_Error (ERR_DIE, "Z_Verify: crazy block size %d (maybe tag %d (%s)) during '%s' at %p, allocated from %p", z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", string, z, z->allocationLocation);
1732 				}
1733 
1734 				//we could segfault here if size is invalid :(
1735 				if ((*(byte **)&z)[z->size-1] != 0xCC)
1736 				{
1737 					if (z_allowcorruption->intvalue)
1738 						Com_Printf ("Z_Verify: buffer overrun detected in block sized %d (tagged as %d (%s)) during '%s' at %p, allocated from %p", LOG_ERROR, z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", string, z, z->allocationLocation);
1739 					else
1740 						Com_Error (ERR_DIE, "Z_Verify: buffer overrun detected in block sized %d (tagged as %d (%s)) during '%s' at %p, allocated from %p", z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", string, z, z->allocationLocation);
1741 				}
1742 			}
1743 			else
1744 			{
1745 				if (z_allowcorruption->intvalue)
1746 					Com_Printf ("Z_Verify: memory corruption detected during '%s' in block %p allocated from %p", LOG_ERROR, string, (void *)(z+1), z->allocationLocation);
1747 				else
1748 					Com_Error (ERR_DIE, "Z_Verify: memory corruption detected during '%s' in block %p allocated from %p", string, (void *)(z+1), z->allocationLocation);
1749 			}
1750 		}
1751 
1752 		if (i++ > z_count * 2)
1753 			Com_Error (ERR_DIE, "Z_Verify: memory chain state corrupted during '%s'", string);
1754 	}
1755 }
1756 
Z_TagMallocDebug(int size,int tag)1757 RESTRICT void * EXPORT Z_TagMallocDebug (int size, int tag)
1758 {
1759 	zhead_t	*z;
1760 
1761 	Z_Verify ("Z_TagMallocDebug: START ALLOCATION OF %d BYTES FOR TAG %d (%s)", size, tag, tag < TAGMALLOC_MAX_TAGS ?  tagmalloc_tags[tag].name : "UNKNOWN TAG");
1762 
1763 	if (size <= 0 && tag < TAGMALLOC_MAX_TAGS)
1764 		Com_Error (ERR_DIE, "Z_TagMalloc: trying to allocate %d bytes!", size);
1765 
1766 	size = size + sizeof(zhead_t);
1767 
1768 	if (size > 0x40000000)
1769 		Com_Error (ERR_DIE, "Z_TagMalloc: trying to allocate %d bytes!", size);
1770 
1771 	size++;
1772 
1773 	z = malloc(size);
1774 
1775 	if (!z)
1776 		Com_Error (ERR_DIE, "Z_TagMalloc: Out of memory. Couldn't allocate %i bytes for %s (already %li bytes in %li blocks)", size, tagmalloc_tags[tag].name, z_bytes, z_count);
1777 
1778 	//memset (z, 0xCC, size);
1779 
1780 	(*(byte **)&z)[size-1] = 0xCC;
1781 
1782 	z_count++;
1783 
1784 	if (tag < TAGMALLOC_MAX_TAGS)
1785 		tagmalloc_tags[tag].allocs++;
1786 
1787 	z_bytes += size;
1788 
1789 	z->magic = Z_MAGIC_DEBUG;
1790 	z->tag = tag;
1791 	z->size = size;
1792 
1793 #if defined _WIN32
1794 	z->allocationLocation = _ReturnAddress ();
1795 #elif defined LINUX
1796 	z->allocationLocation = __builtin_return_address (0);
1797 #else
1798 	//FIXME: other OSes/CCs
1799 	z->allocationLocation = 0;
1800 #endif
1801 
1802 	z->next = z_chain.next;
1803 	z->prev = &z_chain;
1804 	z_chain.next->prev = z;
1805 	z_chain.next = z;
1806 
1807 	Z_Verify ("Z_TagMallocDebug: END ALLOCATION OF %d BYTES FOR TAG %d (%s)", size, tag, tag < TAGMALLOC_MAX_TAGS ?  tagmalloc_tags[tag].name : "UNKNOWN TAG");
1808 
1809 	return (void *)(z+1);
1810 }
1811 
1812 /*
1813 ========================
1814 Z_TagMalloc
1815 ========================
1816 */
Z_TagMallocRelease(int size,int tag)1817 RESTRICT void * EXPORT Z_TagMallocRelease (int size, int tag)
1818 {
1819 	zhead_t	*z;
1820 
1821 	//malloc can crash if negative size is passed, woops.
1822 	if (size < 0)
1823 		Com_Error (ERR_DIE, "Z_TagMalloc: Illegal allocation size of %d bytes from %p for tag %d", size,
1824 #if defined _WIN32
1825 		_ReturnAddress (),
1826 #elif defined LINUX
1827 		__builtin_return_address (0),
1828 #else
1829 		NULL,
1830 #endif
1831 		tag);
1832 
1833 	size = size + sizeof(zhead_t);
1834 	z = malloc(size);
1835 
1836 	if (!z)
1837 		Com_Error (ERR_DIE, "Z_TagMalloc: Out of memory. Couldn't allocate %i bytes for tag %d from %p (already %li bytes in %li blocks)", size, tag,
1838 #if defined _WIN32
1839 		_ReturnAddress (),
1840 #elif defined LINUX
1841 		__builtin_return_address (0),
1842 #else
1843 		NULL,
1844 #endif
1845 		z_bytes, z_count);
1846 
1847 	z_count++;
1848 
1849 	if ((uint32)tag < TAGMALLOC_MAX_TAGS)
1850 		tagmalloc_tags[tag].allocs++;
1851 
1852 	z_bytes += size;
1853 
1854 #if defined _WIN32
1855 	z->allocationLocation = _ReturnAddress ();
1856 #elif defined LINUX
1857 	z->allocationLocation = __builtin_return_address (0);
1858 #else
1859 	//FIXME: other OSes/CCs
1860 	z->allocationLocation = 0;
1861 #endif
1862 
1863 	z->magic = Z_MAGIC;
1864 	z->tag = tag;
1865 	z->size = size;
1866 
1867 	z->next = z_chain.next;
1868 	z->prev = &z_chain;
1869 	z_chain.next->prev = z;
1870 	z_chain.next = z;
1871 
1872 	return (void *)(z+1);
1873 }
1874 
Z_TagMallocGame(int size,int tag)1875 RESTRICT void * EXPORT Z_TagMallocGame (int size, int tag)
1876 {
1877 	z_memloc_t	*loc, *last, *newentry;
1878 	byte		*b;
1879 
1880 	void		*retAddr;
1881 
1882 #if defined _WIN32
1883 	retAddr = _ReturnAddress ();
1884 #elif defined LINUX
1885 	retAddr = __builtin_return_address (0);
1886 #else
1887 	//FIXME: other OSes/CCs
1888 	retAddr = 0;
1889 #endif
1890 
1891 	//aieeeee.
1892 	if (z_buggygame->intvalue)
1893 		size *= z_buggygame->intvalue;
1894 
1895 	if (!size)
1896 	{
1897 		if (z_buggygame->intvalue)
1898 		{
1899 			Com_Printf ("ERROR: Game DLL tried to allocate 0 bytes at %p. Giving it 1 byte of 0x00\n", LOG_ERROR|LOG_SERVER|LOG_GAME, retAddr);
1900 			size = 1;
1901 		}
1902 		else
1903 		{
1904 			Com_Error (ERR_DIE, "Game DLL tried to allocate 0 bytes from code at %p!", retAddr);
1905 		}
1906 	}
1907 
1908 	b = Z_TagMalloc (size+4, tag);
1909 
1910 	memset (b, 0, size);
1911 	*(int *)(b + size) = 0xFDFEFDFE;
1912 
1913 	if (tag == TAG_LEVEL)
1914 		z_level_allocs++;
1915 	else if (tag == TAG_GAME)
1916 		z_game_allocs++;
1917 
1918 	loc = &z_game_locations;
1919 	last = loc->next;
1920 	newentry = malloc (sizeof(*loc));
1921 	if (!newentry)
1922 		Com_Error (ERR_DIE, "Z_TagMallocGame: Out of memory.");
1923 
1924 	newentry->address = b;
1925 	newentry->size = size;
1926 	newentry->next = last;
1927 	newentry->time = curtime;
1928 	newentry->allocationLocation = retAddr;
1929 	loc->next = newentry;
1930 
1931 	return (void *)b;
1932 }
1933 
Z_FreeGame(void * buf)1934 void EXPORT Z_FreeGame (void *buf)
1935 {
1936 	z_memloc_t	*loc, *last;
1937 
1938 	void		*retAddr;
1939 
1940 #if defined _WIN32
1941 	retAddr = _ReturnAddress ();
1942 #elif defined LINUX
1943 	retAddr = __builtin_return_address (0);
1944 #else
1945 	//FIXME: other OSes/CCs
1946 	retAddr = 0;
1947 #endif
1948 
1949 	loc = last = &z_game_locations;
1950 
1951 	while (loc->next)
1952 	{
1953 		loc = loc->next;
1954 		if (buf == loc->address)
1955 		{
1956 			if (*(int *)((byte *)buf + loc->size) != 0xFDFEFDFE)
1957 			{
1958 				Com_Printf ("Memory corruption detected within the Game DLL. Please contact the mod author and inform them that they are not managing dynamically allocated memory correctly.\n", LOG_GENERAL);
1959 				Com_Error (ERR_DIE, "Z_FreeGame: Game DLL corrupted a memory block of size %d at %p (allocated %u ms ago from code at %p), detected during free at %p", loc->size, loc->address, curtime - loc->time, loc->allocationLocation, retAddr);
1960 			}
1961 			free_from_game = true;
1962 			Z_Free (buf);
1963 			free_from_game = false;
1964 
1965 			last->next = loc->next;
1966 			free (loc);
1967 			return;
1968 		}
1969 		last = loc;
1970 	}
1971 
1972 	if (z_buggygame->intvalue)
1973 	{
1974 		Com_Printf ("ERROR: Game DLL tried to free non-existent/freed memory at %p from code at %p, ignored.", LOG_ERROR|LOG_SERVER|LOG_GAME, buf, retAddr);
1975 	}
1976 	else
1977 	{
1978 		Com_Printf ("Memory management problem detected within the Game DLL. Please contact the mod author and inform them that they are not managing dynamically allocated memory correctly.\n", LOG_GENERAL);
1979 		Com_Error (ERR_DIE, "Z_FreeGame: Game DLL tried to free non-existent/freed memory at %p from code at %p", buf, retAddr);
1980 	}
1981 }
1982 
Z_FreeTagsGame(int tag)1983 void EXPORT Z_FreeTagsGame (int tag)
1984 {
1985 	zhead_t	*z, *next;
1986 
1987 	z_memloc_t	*loc, *last;
1988 
1989 	loc = last = &z_game_locations;
1990 
1991 	while (loc->next)
1992 	{
1993 		loc = loc->next;
1994 
1995 		if (*(int *)((byte *)loc->address + loc->size) != 0xFDFEFDFE)
1996 		{
1997 			Com_Printf ("Memory corruption detected within the Game DLL. Please contact the mod author and inform them that they are not managing dynamically allocated memory correctly.\n", LOG_GENERAL);
1998 			Com_Error (ERR_DIE, "Z_FreeTagsGame: Game DLL corrupted a memory block of size %d at %p (allocated %u ms ago from code at %p)", loc->size, loc->address, curtime - loc->time, loc->allocationLocation);
1999 		}
2000 	}
2001 
2002 	for (z=z_chain.next ; z != &z_chain ; z=next)
2003 	{
2004 		next = z->next;
2005 		if (z->tag == tag)
2006 			Z_FreeGame ((void *)(z+1));
2007 	}
2008 
2009 	Z_Verify (va("Z_FreeTags %d (GAME): END", tag));
2010 }
2011 
2012 
2013 /*
2014 ========================
2015 Z_Malloc
2016 ========================
2017 */
2018 
2019 /*void *Z_Malloc (int size)
2020 {
2021 	return Z_TagMalloc (size, 0);
2022 }*/
2023 
2024 
2025 //============================================================================
2026 
2027 static byte chktbl[1024] = {
2028 0x84, 0x47, 0x51, 0xc1, 0x93, 0x22, 0x21, 0x24, 0x2f, 0x66, 0x60, 0x4d, 0xb0, 0x7c, 0xda,
2029 0x88, 0x54, 0x15, 0x2b, 0xc6, 0x6c, 0x89, 0xc5, 0x9d, 0x48, 0xee, 0xe6, 0x8a, 0xb5, 0xf4,
2030 0xcb, 0xfb, 0xf1, 0x0c, 0x2e, 0xa0, 0xd7, 0xc9, 0x1f, 0xd6, 0x06, 0x9a, 0x09, 0x41, 0x54,
2031 0x67, 0x46, 0xc7, 0x74, 0xe3, 0xc8, 0xb6, 0x5d, 0xa6, 0x36, 0xc4, 0xab, 0x2c, 0x7e, 0x85,
2032 0xa8, 0xa4, 0xa6, 0x4d, 0x96, 0x19, 0x19, 0x9a, 0xcc, 0xd8, 0xac, 0x39, 0x5e, 0x3c, 0xf2,
2033 0xf5, 0x5a, 0x72, 0xe5, 0xa9, 0xd1, 0xb3, 0x23, 0x82, 0x6f, 0x29, 0xcb, 0xd1, 0xcc, 0x71,
2034 0xfb, 0xea, 0x92, 0xeb, 0x1c, 0xca, 0x4c, 0x70, 0xfe, 0x4d, 0xc9, 0x67, 0x43, 0x47, 0x94,
2035 0xb9, 0x47, 0xbc, 0x3f, 0x01, 0xab, 0x7b, 0xa6, 0xe2, 0x76, 0xef, 0x5a, 0x7a, 0x29, 0x0b,
2036 0x51, 0x54, 0x67, 0xd8, 0x1c, 0x14, 0x3e, 0x29, 0xec, 0xe9, 0x2d, 0x48, 0x67, 0xff, 0xed,
2037 0x54, 0x4f, 0x48, 0xc0, 0xaa, 0x61, 0xf7, 0x78, 0x12, 0x03, 0x7a, 0x9e, 0x8b, 0xcf, 0x83,
2038 0x7b, 0xae, 0xca, 0x7b, 0xd9, 0xe9, 0x53, 0x2a, 0xeb, 0xd2, 0xd8, 0xcd, 0xa3, 0x10, 0x25,
2039 0x78, 0x5a, 0xb5, 0x23, 0x06, 0x93, 0xb7, 0x84, 0xd2, 0xbd, 0x96, 0x75, 0xa5, 0x5e, 0xcf,
2040 0x4e, 0xe9, 0x50, 0xa1, 0xe6, 0x9d, 0xb1, 0xe3, 0x85, 0x66, 0x28, 0x4e, 0x43, 0xdc, 0x6e,
2041 0xbb, 0x33, 0x9e, 0xf3, 0x0d, 0x00, 0xc1, 0xcf, 0x67, 0x34, 0x06, 0x7c, 0x71, 0xe3, 0x63,
2042 0xb7, 0xb7, 0xdf, 0x92, 0xc4, 0xc2, 0x25, 0x5c, 0xff, 0xc3, 0x6e, 0xfc, 0xaa, 0x1e, 0x2a,
2043 0x48, 0x11, 0x1c, 0x36, 0x68, 0x78, 0x86, 0x79, 0x30, 0xc3, 0xd6, 0xde, 0xbc, 0x3a, 0x2a,
2044 0x6d, 0x1e, 0x46, 0xdd, 0xe0, 0x80, 0x1e, 0x44, 0x3b, 0x6f, 0xaf, 0x31, 0xda, 0xa2, 0xbd,
2045 0x77, 0x06, 0x56, 0xc0, 0xb7, 0x92, 0x4b, 0x37, 0xc0, 0xfc, 0xc2, 0xd5, 0xfb, 0xa8, 0xda,
2046 0xf5, 0x57, 0xa8, 0x18, 0xc0, 0xdf, 0xe7, 0xaa, 0x2a, 0xe0, 0x7c, 0x6f, 0x77, 0xb1, 0x26,
2047 0xba, 0xf9, 0x2e, 0x1d, 0x16, 0xcb, 0xb8, 0xa2, 0x44, 0xd5, 0x2f, 0x1a, 0x79, 0x74, 0x87,
2048 0x4b, 0x00, 0xc9, 0x4a, 0x3a, 0x65, 0x8f, 0xe6, 0x5d, 0xe5, 0x0a, 0x77, 0xd8, 0x1a, 0x14,
2049 0x41, 0x75, 0xb1, 0xe2, 0x50, 0x2c, 0x93, 0x38, 0x2b, 0x6d, 0xf3, 0xf6, 0xdb, 0x1f, 0xcd,
2050 0xff, 0x14, 0x70, 0xe7, 0x16, 0xe8, 0x3d, 0xf0, 0xe3, 0xbc, 0x5e, 0xb6, 0x3f, 0xcc, 0x81,
2051 0x24, 0x67, 0xf3, 0x97, 0x3b, 0xfe, 0x3a, 0x96, 0x85, 0xdf, 0xe4, 0x6e, 0x3c, 0x85, 0x05,
2052 0x0e, 0xa3, 0x2b, 0x07, 0xc8, 0xbf, 0xe5, 0x13, 0x82, 0x62, 0x08, 0x61, 0x69, 0x4b, 0x47,
2053 0x62, 0x73, 0x44, 0x64, 0x8e, 0xe2, 0x91, 0xa6, 0x9a, 0xb7, 0xe9, 0x04, 0xb6, 0x54, 0x0c,
2054 0xc5, 0xa9, 0x47, 0xa6, 0xc9, 0x08, 0xfe, 0x4e, 0xa6, 0xcc, 0x8a, 0x5b, 0x90, 0x6f, 0x2b,
2055 0x3f, 0xb6, 0x0a, 0x96, 0xc0, 0x78, 0x58, 0x3c, 0x76, 0x6d, 0x94, 0x1a, 0xe4, 0x4e, 0xb8,
2056 0x38, 0xbb, 0xf5, 0xeb, 0x29, 0xd8, 0xb0, 0xf3, 0x15, 0x1e, 0x99, 0x96, 0x3c, 0x5d, 0x63,
2057 0xd5, 0xb1, 0xad, 0x52, 0xb8, 0x55, 0x70, 0x75, 0x3e, 0x1a, 0xd5, 0xda, 0xf6, 0x7a, 0x48,
2058 0x7d, 0x44, 0x41, 0xf9, 0x11, 0xce, 0xd7, 0xca, 0xa5, 0x3d, 0x7a, 0x79, 0x7e, 0x7d, 0x25,
2059 0x1b, 0x77, 0xbc, 0xf7, 0xc7, 0x0f, 0x84, 0x95, 0x10, 0x92, 0x67, 0x15, 0x11, 0x5a, 0x5e,
2060 0x41, 0x66, 0x0f, 0x38, 0x03, 0xb2, 0xf1, 0x5d, 0xf8, 0xab, 0xc0, 0x02, 0x76, 0x84, 0x28,
2061 0xf4, 0x9d, 0x56, 0x46, 0x60, 0x20, 0xdb, 0x68, 0xa7, 0xbb, 0xee, 0xac, 0x15, 0x01, 0x2f,
2062 0x20, 0x09, 0xdb, 0xc0, 0x16, 0xa1, 0x89, 0xf9, 0x94, 0x59, 0x00, 0xc1, 0x76, 0xbf, 0xc1,
2063 0x4d, 0x5d, 0x2d, 0xa9, 0x85, 0x2c, 0xd6, 0xd3, 0x14, 0xcc, 0x02, 0xc3, 0xc2, 0xfa, 0x6b,
2064 0xb7, 0xa6, 0xef, 0xdd, 0x12, 0x26, 0xa4, 0x63, 0xe3, 0x62, 0xbd, 0x56, 0x8a, 0x52, 0x2b,
2065 0xb9, 0xdf, 0x09, 0xbc, 0x0e, 0x97, 0xa9, 0xb0, 0x82, 0x46, 0x08, 0xd5, 0x1a, 0x8e, 0x1b,
2066 0xa7, 0x90, 0x98, 0xb9, 0xbb, 0x3c, 0x17, 0x9a, 0xf2, 0x82, 0xba, 0x64, 0x0a, 0x7f, 0xca,
2067 0x5a, 0x8c, 0x7c, 0xd3, 0x79, 0x09, 0x5b, 0x26, 0xbb, 0xbd, 0x25, 0xdf, 0x3d, 0x6f, 0x9a,
2068 0x8f, 0xee, 0x21, 0x66, 0xb0, 0x8d, 0x84, 0x4c, 0x91, 0x45, 0xd4, 0x77, 0x4f, 0xb3, 0x8c,
2069 0xbc, 0xa8, 0x99, 0xaa, 0x19, 0x53, 0x7c, 0x02, 0x87, 0xbb, 0x0b, 0x7c, 0x1a, 0x2d, 0xdf,
2070 0x48, 0x44, 0x06, 0xd6, 0x7d, 0x0c, 0x2d, 0x35, 0x76, 0xae, 0xc4, 0x5f, 0x71, 0x85, 0x97,
2071 0xc4, 0x3d, 0xef, 0x52, 0xbe, 0x00, 0xe4, 0xcd, 0x49, 0xd1, 0xd1, 0x1c, 0x3c, 0xd0, 0x1c,
2072 0x42, 0xaf, 0xd4, 0xbd, 0x58, 0x34, 0x07, 0x32, 0xee, 0xb9, 0xb5, 0xea, 0xff, 0xd7, 0x8c,
2073 0x0d, 0x2e, 0x2f, 0xaf, 0x87, 0xbb, 0xe6, 0x52, 0x71, 0x22, 0xf5, 0x25, 0x17, 0xa1, 0x82,
2074 0x04, 0xc2, 0x4a, 0xbd, 0x57, 0xc6, 0xab, 0xc8, 0x35, 0x0c, 0x3c, 0xd9, 0xc2, 0x43, 0xdb,
2075 0x27, 0x92, 0xcf, 0xb8, 0x25, 0x60, 0xfa, 0x21, 0x3b, 0x04, 0x52, 0xc8, 0x96, 0xba, 0x74,
2076 0xe3, 0x67, 0x3e, 0x8e, 0x8d, 0x61, 0x90, 0x92, 0x59, 0xb6, 0x1a, 0x1c, 0x5e, 0x21, 0xc1,
2077 0x65, 0xe5, 0xa6, 0x34, 0x05, 0x6f, 0xc5, 0x60, 0xb1, 0x83, 0xc1, 0xd5, 0xd5, 0xed, 0xd9,
2078 0xc7, 0x11, 0x7b, 0x49, 0x7a, 0xf9, 0xf9, 0x84, 0x47, 0x9b, 0xe2, 0xa5, 0x82, 0xe0, 0xc2,
2079 0x88, 0xd0, 0xb2, 0x58, 0x88, 0x7f, 0x45, 0x09, 0x67, 0x74, 0x61, 0xbf, 0xe6, 0x40, 0xe2,
2080 0x9d, 0xc2, 0x47, 0x05, 0x89, 0xed, 0xcb, 0xbb, 0xb7, 0x27, 0xe7, 0xdc, 0x7a, 0xfd, 0xbf,
2081 0xa8, 0xd0, 0xaa, 0x10, 0x39, 0x3c, 0x20, 0xf0, 0xd3, 0x6e, 0xb1, 0x72, 0xf8, 0xe6, 0x0f,
2082 0xef, 0x37, 0xe5, 0x09, 0x33, 0x5a, 0x83, 0x43, 0x80, 0x4f, 0x65, 0x2f, 0x7c, 0x8c, 0x6a,
2083 0xa0, 0x82, 0x0c, 0xd4, 0xd4, 0xfa, 0x81, 0x60, 0x3d, 0xdf, 0x06, 0xf1, 0x5f, 0x08, 0x0d,
2084 0x6d, 0x43, 0xf2, 0xe3, 0x11, 0x7d, 0x80, 0x32, 0xc5, 0xfb, 0xc5, 0xd9, 0x27, 0xec, 0xc6,
2085 0x4e, 0x65, 0x27, 0x76, 0x87, 0xa6, 0xee, 0xee, 0xd7, 0x8b, 0xd1, 0xa0, 0x5c, 0xb0, 0x42,
2086 0x13, 0x0e, 0x95, 0x4a, 0xf2, 0x06, 0xc6, 0x43, 0x33, 0xf4, 0xc7, 0xf8, 0xe7, 0x1f, 0xdd,
2087 0xe4, 0x46, 0x4a, 0x70, 0x39, 0x6c, 0xd0, 0xed, 0xca, 0xbe, 0x60, 0x3b, 0xd1, 0x7b, 0x57,
2088 0x48, 0xe5, 0x3a, 0x79, 0xc1, 0x69, 0x33, 0x53, 0x1b, 0x80, 0xb8, 0x91, 0x7d, 0xb4, 0xf6,
2089 0x17, 0x1a, 0x1d, 0x5a, 0x32, 0xd6, 0xcc, 0x71, 0x29, 0x3f, 0x28, 0xbb, 0xf3, 0x5e, 0x71,
2090 0xb8, 0x43, 0xaf, 0xf8, 0xb9, 0x64, 0xef, 0xc4, 0xa5, 0x6c, 0x08, 0x53, 0xc7, 0x00, 0x10,
2091 0x39, 0x4f, 0xdd, 0xe4, 0xb6, 0x19, 0x27, 0xfb, 0xb8, 0xf5, 0x32, 0x73, 0xe5, 0xcb, 0x32,
2092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2094 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2096 0x00, 0x00, 0x00, 0x00
2097 };
2098 
2099 /*
2100 ====================
2101 COM_BlockSequenceCRCByte
2102 
2103 For proxy protecting
2104 ====================
2105 */
COM_BlockSequenceCRCByte(byte * base,int length,int sequence)2106 byte	COM_BlockSequenceCRCByte (byte *base, int length, int sequence)
2107 {
2108 	int				n;
2109 	int				x;
2110 	byte			*p;
2111 	byte			chkb[60 + 4];
2112 	uint16			crc;
2113 	byte			r;
2114 
2115 
2116 	if (sequence < 0)
2117 		Sys_Error("sequence < 0, this shouldn't happen\n");
2118 
2119 	p = chktbl + (sequence % (sizeof(chktbl) - 4));
2120 
2121 	if (length > 60)
2122 		length = 60;
2123 	memcpy (chkb, base, length);
2124 
2125 	chkb[length] = p[0];
2126 	chkb[length+1] = p[1];
2127 	chkb[length+2] = p[2];
2128 	chkb[length+3] = p[3];
2129 
2130 	length += 4;
2131 
2132 	crc = CRC_Block(chkb, length);
2133 
2134 	for (x=0, n=0; n<length; n++)
2135 		x += chkb[n];
2136 
2137 	r = (crc ^ x) & 0xff;
2138 
2139 	return r;
2140 }
2141 
2142 #ifdef USE_OPENSSL
Com_BlockChecksum(void * buffer,int length)2143 uint32 Com_BlockChecksum (void *buffer, int length)
2144 {
2145 	int			digest[4];
2146 	uint32		val;
2147 	MD4_CTX		ctx;
2148 
2149 	MD4_Init (&ctx);
2150 	MD4_Update (&ctx, (unsigned char *)buffer, length);
2151 	MD4_Final ( (unsigned char *)digest, &ctx);
2152 
2153 	val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
2154 
2155 	return val;
2156 }
2157 #endif
2158 
2159 //========================================================
2160 
2161 /*float	frand(void)
2162 {
2163 	return (randomMT()&32767)* (1.0/32767);
2164 }
2165 
2166 float	crand(void)
2167 {
2168 	return (randomMT()&32767)* (2.0/32767) - 1;
2169 }*/
2170 
2171 void Key_Init (void);
2172 void SCR_EndLoadingPlaque (void);
2173 
2174 /*
2175 =============
2176 Com_Error_f
2177 
2178 Just throw a fatal error to
2179 test error shutdown procedures
2180 =============
2181 */
Com_Error_f(void)2182 void Com_Error_f (void)
2183 {
2184 	Com_Error (ERR_FATAL, "%s", Cmd_Argv(1));
2185 }
2186 
2187 
2188 /*
2189 =================
2190 Qcommon_Init
2191 =================
2192 */
2193 
Q_NullFunc(void)2194 void Q_NullFunc(void)
2195 {
2196 }
2197 
Msg_Stats_f(void)2198 void Msg_Stats_f (void)
2199 {
2200 #ifndef NPROFILE
2201 	int		total;
2202 	int		i, j;
2203 	int		num;
2204 	int		sum;
2205 
2206 	total = msg_malloc_hits + msg_local_hits;
2207 
2208 	Com_Printf ("malloc: %d (%.2f%%), local: %d (%.2f%%)\n", LOG_GENERAL,
2209 		msg_malloc_hits, ((float)msg_malloc_hits / (float)total) * 100.0f,
2210 		msg_local_hits, ((float)msg_local_hits / (float)total) * 100.0f);
2211 
2212 	Com_Printf ("byte breakdown:\n", LOG_GENERAL);
2213 
2214 	total = 0;
2215 	num = 0;
2216 
2217 	for (i = 0; i < sizeof(messageSizes) / sizeof(messageSizes[0]); i += 10)
2218 	{
2219 		sum = 0;
2220 		for (j = i; j < i+ 10; j++)
2221 		{
2222 			sum += messageSizes[j];
2223 			total += j * messageSizes[j];
2224 			num += messageSizes[j];
2225 		}
2226 		Com_Printf ("%i-%d: %d\n", LOG_GENERAL, i, i + 10, sum);
2227 	}
2228 	Com_Printf ("mean: %.2f\n", LOG_GENERAL, (float)total / (float)num);
2229 #else
2230 	Com_Printf ("This binary was built with NPROFILE, no stats available.\n", LOG_GENERAL);
2231 #endif
2232 }
2233 
_z_debug_changed(cvar_t * cvar,char * o,char * n)2234 void _z_debug_changed (cvar_t *cvar, char *o, char *n)
2235 {
2236 	if (cvar->intvalue)
2237 	{
2238 		Z_TagMalloc = Z_TagMallocDebug;
2239 		Z_Free = Z_FreeDebug;
2240 	}
2241 	else
2242 	{
2243 		Z_TagMalloc = Z_TagMallocRelease;
2244 		Z_Free = Z_FreeRelease;
2245 	}
2246 
2247 	Com_Printf ("Z_Debug: Intensive memory checking %s.\n", LOG_GENERAL, cvar->intvalue ? "enabled" : "disabled");
2248 }
2249 
_logfile_changed(cvar_t * cvar,char * o,char * n)2250 void _logfile_changed (cvar_t *cvar, char *o, char *n)
2251 {
2252 	if (cvar->intvalue == 0)
2253 	{
2254 		if (logfile)
2255 		{
2256 			fclose (logfile);
2257 			logfile = NULL;
2258 		}
2259 	}
2260 }
2261 
Qcommon_Init(int argc,char ** argv)2262 void Qcommon_Init (int argc, char **argv)
2263 {
2264 	if (setjmp (abortframe) )
2265 		Sys_Error ("Error during initialization");
2266 
2267 	seedMT((uint32)time(0));
2268 
2269 	SZ_Init (&msgbuff, message_buff, sizeof(message_buff));
2270 
2271 	Z_Free = Z_FreeRelease;
2272 	Z_TagMalloc = Z_TagMallocRelease;
2273 
2274 	z_chain.next = z_chain.prev = &z_chain;
2275 
2276 	uninitialized_cvar.string = "";
2277 
2278 	// prepare enough of the subsystems to handle
2279 	// cvar and command buffer management
2280 	COM_InitArgv (argc, argv);
2281 
2282 	Swap_Init ();
2283 	Cbuf_Init ();
2284 
2285 	Cmd_Init ();
2286 	Cvar_Init ();
2287 
2288 	z_debug = Cvar_Get ("z_debug", "0", 0);
2289 	z_buggygame = Cvar_Get ("z_buggygame", "0", 0);
2290 	z_allowcorruption = Cvar_Get ("z_allowcorruption", "0", 0);
2291 
2292 	cl_quietstartup = Cvar_Get ("cl_quietstartup", "1", 0);
2293 
2294 	z_debug->changed = _z_debug_changed;
2295 	if (z_debug->intvalue)
2296 	{
2297 		Z_TagMalloc = Z_TagMallocDebug;
2298 		Z_Free = Z_FreeDebug;
2299 	}
2300 
2301 #ifndef DEDICATED_ONLY
2302 	Key_Init ();
2303 #else
2304 	//r1: stub out these so configs don't spam unknown cmd
2305 	Cmd_AddCommand ("bind",Q_NullFunc);
2306 	Cmd_AddCommand ("unbind",Q_NullFunc);
2307 	Cmd_AddCommand ("unbindall",Q_NullFunc);
2308 	Cmd_AddCommand ("bindlist",Q_NullFunc);
2309 #endif
2310 
2311 	Cmd_AddCommand ("msg_stats", Msg_Stats_f);
2312 	Cmd_AddCommand ("processtimes", Sys_ProcessTimes_f);
2313 	Cmd_AddCommand ("spinstats", Sys_Spinstats_f);
2314 
2315 	// we need to add the early commands twice, because
2316 	// a basedir or cddir needs to be set before execing
2317 	// config files, but we want other parms to override
2318 	// the settings of the config files
2319 	Cbuf_AddEarlyCommands (false);
2320 	Cbuf_Execute ();
2321 
2322 	FS_InitFilesystem ();
2323 
2324 	Cbuf_AddText ("exec default.cfg\n");
2325 	Cbuf_AddText ("exec config.cfg\n");
2326 
2327 	Cbuf_AddEarlyCommands (true);
2328 	Cbuf_Execute ();
2329 
2330 	//
2331 	// init commands and vars
2332 	//
2333     Cmd_AddCommand ("z_stats", Z_Stats_f);
2334     Cmd_AddCommand ("error", Com_Error_f);
2335 
2336 	host_speeds = Cvar_Get ("host_speeds", "0", 0);
2337 	log_stats = Cvar_Get ("log_stats", "0", 0);
2338 	timescale = Cvar_Get ("timescale", "1", 0);
2339 	fixedtime = Cvar_Get ("fixedtime", "0", 0);
2340 
2341 	logfile_active = Cvar_Get ("logfile", "0", 0);
2342 	logfile_timestamp = Cvar_Get ("logfile_timestamp", "1", 0);
2343 	logfile_timestamp_format = Cvar_Get ("logfile_timestamp_format", "[%Y-%m-%d %H:%M]", 0);
2344 	logfile_name = Cvar_Get ("logfile_name", "qconsole.log", 0);
2345 	logfile_filterlevel = Cvar_Get ("logfile_filterlevel", "0", 0);
2346 	logfile_active->changed = _logfile_changed;
2347 
2348 	con_filterlevel = Cvar_Get ("con_filterlevel", "0", 0);
2349 
2350 #ifndef DEDICATED_ONLY
2351 	showtrace = Cvar_Get ("showtrace", "0", 0);
2352 #endif
2353 #ifndef NO_SERVER
2354 #ifdef DEDICATED_ONLY
2355 	dedicated = Cvar_Get ("dedicated", "1", CVAR_NOSET);
2356 #else
2357 	dedicated = Cvar_Get ("dedicated", "0", CVAR_NOSET);
2358 #endif
2359 #endif
2360 
2361 	sys_loopstyle = Cvar_Get ("sys_loopstyle", "1", 0);
2362 
2363 	err_fatal = Cvar_Get ("err_fatal", "0", 0);
2364 
2365 	//s = va("R1Q2 %s %s %s %s", VERSION, CPUSTRING, __DATE__, BUILDSTRING);
2366 	Cvar_Get ("version", R1Q2_VERSION_STRING, CVAR_SERVERINFO|CVAR_NOSET);
2367 
2368 #ifndef NO_SERVER
2369 	if (dedicated->intvalue)
2370 		Cmd_AddCommand ("quit", Com_Quit);
2371 #endif
2372 
2373 	dbg_unload = Cvar_Get ("dbg_unload", "1", 0);
2374 	dbg_crash_on_fatal_error = Cvar_Get ("dbg_crash_on_fatal_error", "0", 0);
2375 
2376 	Sys_Init ();
2377 
2378 	NET_Init ();
2379 	Netchan_Init ();
2380 
2381 #ifndef NO_SERVER
2382 	SV_Init ();
2383 #endif
2384 
2385 	Com_Printf ("====== Quake2 Initialized ======\n", LOG_GENERAL);
2386 	Com_Printf ("R1Q2 build " BUILD ", compiled " __DATE__ ".\n"
2387 				"http://www.r1ch.net/stuff/r1q2/\n"
2388 				BUILDSTRING " " CPUSTRING " (%s)\n\n", LOG_GENERAL, binary_name);
2389 
2390 #ifndef DEDICATED_ONLY
2391 	CL_Init ();
2392 #endif
2393 
2394 	// add + commands from command line
2395 	if (!Cbuf_AddLateCommands ())
2396 	{
2397 		// if the user didn't give any commands, run default action
2398 #ifndef NO_SERVER
2399 		if (!dedicated->intvalue)
2400 		{
2401 #endif
2402 
2403 #ifndef DEDICATED_ONLY
2404 			Cbuf_AddText ("toggleconsole\n");
2405 
2406 			Com_Printf (
2407 				"Welcome to R1Q2.\n"
2408 				"\n"
2409 				"  Press <ESC> to open the menu.\n"
2410 				"  Type connect <host> to connect to a server.\n"
2411 				"  View the readme at http://www.r1ch.net/forum/index.php?board=8.0\n"
2412 				"\n", LOG_GENERAL);
2413 
2414 			Sys_UpdateURLMenu ("http://www.r1ch.net/forum/index.php?board=8.0");
2415 #endif
2416 
2417 #ifndef NO_SERVER
2418 		}
2419 		else
2420 			Cbuf_AddText ("dedicated_start\n");
2421 #endif
2422 		Cbuf_Execute ();
2423 	}
2424 #ifndef DEDICATED_ONLY
2425 	else
2426 	{
2427 		// the user asked for something explicit
2428 		// so drop the loading plaque
2429 		SCR_EndLoadingPlaque ();
2430 	}
2431 #endif
2432 
2433 	Cbuf_Execute ();
2434 
2435 	//MSG_NUinitHuffman ();
2436 
2437 	//ugly
2438 	q2_initialized = true;
2439 	logfile_timestamp_format->flags |= CVAR_NOSET;
2440 }
2441 
2442 /*
2443 =================
2444 Qcommon_Frame
2445 =================
2446 */
Qcommon_Frame(int msec)2447 void Qcommon_Frame (int msec)
2448 {
2449 #ifndef NO_SERVER
2450 	char *s;
2451 #endif
2452 
2453 #ifndef DEDICATED_ONLY
2454 	int		time_before = 0, time_between = 0, time_after;
2455 #endif
2456 
2457 	if (setjmp (abortframe) )
2458 		return;			// an ERR_DROP was thrown
2459 
2460 	//Com_Printf ("frame time: %d ms\n", LOG_GENERAL, msec);
2461 
2462 	/*if ( log_stats->modified )
2463 	{
2464 		log_stats->modified = false;
2465 		if ( log_stats->intvalue )
2466 		{
2467 			if ( log_stats_file )
2468 			{
2469 				fclose( log_stats_file );
2470 				log_stats_file = 0;
2471 			}
2472 			log_stats_file = fopen( "stats.log", "w" );
2473 			if ( log_stats_file )
2474 				fprintf( log_stats_file, "entities,dlights,parts,frame time\n" );
2475 		}
2476 		else
2477 		{
2478 			if ( log_stats_file )
2479 			{
2480 				fclose( log_stats_file );
2481 				log_stats_file = 0;
2482 			}
2483 		}
2484 	}*/
2485 
2486 	if (fixedtime->intvalue)
2487 	{
2488 		msec = fixedtime->intvalue;
2489 	}
2490 	else
2491 	{
2492 		msec = (int)(msec * timescale->value);
2493 
2494 		//r1: allow server to run zero msec frames to avoid spinloop
2495 		/*if (!dedicated->intvalue)
2496 		{
2497 			if (msec < 1)
2498 				msec = 1;
2499 		}*/
2500 	}
2501 
2502 #ifndef DEDICATED_ONLY
2503 	if (showtrace->intvalue)
2504 	{
2505 		extern	int c_traces, c_brush_traces;
2506 		extern	int	c_pointcontents;
2507 
2508 		Com_Printf ("%4i traces  %4i points\n", LOG_GENERAL, c_traces, c_pointcontents);
2509 		c_traces = 0;
2510 		c_brush_traces = 0;
2511 		c_pointcontents = 0;
2512 	}
2513 #endif
2514 
2515 #ifndef NO_SERVER
2516 #ifndef DEDICATED_ONLY
2517 	if (dedicated->intvalue)
2518 	{
2519 #endif
2520 		do
2521 		{
2522 			s = Sys_ConsoleInput ();
2523 			if (s)
2524 				Cbuf_AddText (va("%s\n",s));
2525 			Cbuf_Execute();
2526 		} while (s);
2527 #ifndef DEDICATED_ONLY
2528 	}
2529 #endif
2530 #endif
2531 
2532 	//Cbuf_Execute ();
2533 
2534 #ifndef DEDICATED_ONLY
2535 	if (host_speeds->intvalue)
2536 		time_before = Sys_Milliseconds ();
2537 #endif
2538 
2539 #ifndef NO_SERVER
2540 	SV_Frame (msec);
2541 #endif
2542 
2543 #ifndef DEDICATED_ONLY
2544 	if (host_speeds->intvalue)
2545 		time_between = Sys_Milliseconds ();
2546 
2547 	CL_Frame (msec);
2548 
2549 	if (host_speeds->intvalue) {
2550 		int			all, sv, gm, cl, rf;
2551 
2552 		time_after = Sys_Milliseconds ();
2553 
2554 		all = time_after - time_before;
2555 		sv = time_between - time_before;
2556 		cl = time_after - time_between;
2557 		gm = time_after_game - time_before_game;
2558 		rf = time_after_ref - time_before_ref;
2559 		sv -= gm;
2560 		cl -= rf;
2561 		Com_Printf ("all:%3i sv:%3i gm:%3i cl:%3i rf:%3i\n", LOG_GENERAL,
2562 			all, sv, gm, cl, rf);
2563 	}
2564 #endif
2565 
2566 }
2567 
2568 #ifndef NO_ZLIB
ZLibDecompress(byte * in,int inlen,byte * out,int outlen,int wbits)2569 int ZLibDecompress (byte *in, int inlen, byte *out, int outlen, int wbits)
2570 {
2571 	z_stream zs;
2572 	int result;
2573 
2574 	memset (&zs, 0, sizeof(zs));
2575 
2576 	zs.next_in = in;
2577 	zs.avail_in = 0;
2578 
2579 	zs.next_out = out;
2580 	zs.avail_out = outlen;
2581 
2582 	result = inflateInit2(&zs, wbits);
2583 	if (result != Z_OK)
2584 	{
2585 		Com_Error (ERR_DROP, "ZLib data error! Error %d on inflateInit.\nMessage: %s", result, zs.msg);
2586 		return 0;
2587 	}
2588 
2589 	zs.avail_in = inlen;
2590 
2591 	result = inflate(&zs, Z_FINISH);
2592 	if (result != Z_STREAM_END)
2593 	{
2594 		Com_Error (ERR_DROP, "ZLib data error! Error %d on inflate.\nMessage: %s", result, zs.msg);
2595 		zs.total_out = 0;
2596 	}
2597 
2598 	result = inflateEnd(&zs);
2599 	if (result != Z_OK)
2600 	{
2601 		Com_Error (ERR_DROP, "ZLib data error! Error %d on inflateEnd.\nMessage: %s", result, zs.msg);
2602 		return 0;
2603 	}
2604 
2605 	return zs.total_out;
2606 }
2607 
ZLibCompressChunk(byte * in,int len_in,byte * out,int len_out,int method,int wbits)2608 int ZLibCompressChunk(byte *in, int len_in, byte *out, int len_out, int method, int wbits)
2609 {
2610 	z_stream zs;
2611 	int result;
2612 
2613 	zs.next_in = in;
2614 	zs.avail_in = len_in;
2615 	zs.total_in = 0;
2616 
2617 	zs.next_out = out;
2618 	zs.avail_out = len_out;
2619 	zs.total_out = 0;
2620 
2621 	zs.msg = NULL;
2622 	zs.state = NULL;
2623 	zs.zalloc = Z_NULL;
2624 	zs.zfree = Z_NULL;
2625 	zs.opaque = NULL;
2626 
2627 	zs.data_type = Z_BINARY;
2628 	zs.adler = 0;
2629 	zs.reserved = 0;
2630 
2631 	result = deflateInit2 (&zs, method, Z_DEFLATED, wbits, 9, Z_DEFAULT_STRATEGY);
2632 	if (result != Z_OK)
2633 		return -1;
2634 
2635 	result = deflate(&zs, Z_FINISH);
2636 	if (result != Z_STREAM_END)
2637 		return -1;
2638 
2639 	result = deflateEnd(&zs);
2640 	if (result != Z_OK)
2641 		return -1;
2642 
2643 	return zs.total_out;
2644 }
2645 #endif
2646 
StripHighBits(char * string,int highbits)2647 void StripHighBits (char *string, int highbits)
2648 {
2649 	byte		high;
2650 	byte		c;
2651 	char		*p;
2652 
2653 	p = string;
2654 
2655 	if (highbits)
2656 		high = 127;
2657 	else
2658 		high = 255;
2659 
2660 	while (string[0])
2661 	{
2662 		c = *(string++);
2663 
2664 		if (c >= 32 && c <= high)
2665 			*p++ = c;
2666 	}
2667 
2668 	p[0] = '\0';
2669 }
2670 
isvalidchar(int c)2671 qboolean isvalidchar (int c)
2672 {
2673 	if (!isalnum(c) && c != '_' && c != '-')
2674 		return false;
2675 	return true;
2676 }
2677 
ExpandNewLines(char * string)2678 void ExpandNewLines (char *string)
2679 {
2680 	char *q = string;
2681 	char *s = q;
2682 
2683 	if (!string[0])
2684 		return;
2685 
2686 	while (*(q+1))
2687 	{
2688 		if (*q == '\\' && *(q+1) == 'n')
2689 		{
2690 			*s++ = '\n';
2691 			q++;
2692 		}
2693 		else
2694 		{
2695 			*s++ = *q;
2696 		}
2697 		q++;
2698 
2699 		//crashfix, check if we reached eol on an expansion.
2700 		if (!*q)
2701 			break;
2702 	}
2703 
2704 	if (*q)
2705 		*s++ = *q;
2706 	*s = '\0';
2707 }
2708 
StripQuotes(char * string)2709 char *StripQuotes (char *string)
2710 {
2711 	size_t	i;
2712 
2713 	if (!string[0])
2714 		return string;
2715 
2716 	i = strlen(string);
2717 
2718 	if (string[0] == '"' && string[i-1] == '"')
2719 	{
2720 		string[i-1] = 0;
2721 		return string + 1;
2722 	}
2723 
2724 	return string;
2725 }
2726 
MakePrintable(const void * subject,size_t numchars)2727 const char *MakePrintable (const void *subject, size_t numchars)
2728 {
2729 	int			len;
2730 	static char printable[4096];
2731 	char		tmp[8];
2732 	char		*p;
2733 	const byte	*s;
2734 
2735 	if (!subject)
2736 	{
2737 		strcpy (printable, "(null)");
2738 		return printable;
2739 	}
2740 
2741 	s = (const byte *)subject;
2742 	p = printable;
2743 	len = 0;
2744 
2745 	if (!numchars)
2746 		numchars = strlen((const char *) s);
2747 
2748 	while (numchars--)
2749 	{
2750 		if (isprint(s[0]))
2751 		{
2752 			*p++ = s[0];
2753 			len++;
2754 		}
2755 		else
2756 		{
2757 			sprintf (tmp, "%.3d", s[0]);
2758 			*p++ = '\\';
2759 			*p++ = tmp[0];
2760 			*p++ = tmp[1];
2761 			*p++ = tmp[2];
2762 			len += 4;
2763 		}
2764 
2765 		if (len >= sizeof(printable)-5)
2766 			break;
2767 
2768 		s++;
2769 	}
2770 
2771 	printable[len] = 0;
2772 	return printable;
2773 }
2774 
2775 /*
2776 =================
2777 Qcommon_Shutdown
2778 =================
2779 */
Qcommon_Shutdown(void)2780 void Qcommon_Shutdown (void)
2781 {
2782 }
2783 
Z_CheckGameLeaks(void)2784 void Z_CheckGameLeaks (void)
2785 {
2786 	z_memloc_t	*loc, *last;
2787 
2788 	loc = last = &z_game_locations;
2789 
2790 	if (loc->next)
2791 	{
2792 		Com_Printf ("Memory leak detected in Game DLL. Leaked blocks: ", LOG_GENERAL|LOG_WARNING);
2793 
2794 		while (loc->next)
2795 		{
2796 			loc = loc->next;
2797 			Com_Printf ("%p (%d bytes)%s", LOG_GENERAL|LOG_WARNING, loc->address, loc->size, loc->next ? ", " : "");
2798 		}
2799 		Com_Printf ("\n", LOG_GENERAL|LOG_WARNING);
2800 	}
2801 }
2802 
2803