• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) 1996-1997 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 
22 #include <ctype.h>
23 
24 #ifdef SERVERONLY
25 #include "qwsvdef.h"
26 #else
27 #include "quakedef.h"
28 #endif
29 
30 #define MAX_NUM_ARGVS	50
31 #define NUM_SAFE_ARGVS	6
32 
33 usercmd_t nullcmd; // guarenteed to be zero
34 
35 static char	*largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1];
36 static char	*argvdummy = " ";
37 
38 static char	*safeargvs[NUM_SAFE_ARGVS] =
39 	{"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse"};
40 
41 cvar_t	registered = CVAR2("registered","0");
42 
43 qboolean	com_modified;	// set true if using non-id files
44 
45 int		static_registered = 1;	// only for startup check, then set
46 
47 qboolean		msg_suppress_1 = 0;
48 
49 void COM_InitFilesystem (void);
50 void COM_Path_f (void);
51 
52 
53 // if a packfile directory differs from this, it is assumed to be hacked
54 #define	PAK0_COUNT		339
55 #define	PAK0_CRC		52883
56 
57 qboolean		standard_quake = true, rogue, hipnotic;
58 
59 char	gamedirfile[MAX_OSPATH];
60 
61 // this graphic needs to be in the pak file to use registered features
62 unsigned short pop[] =
63 {
64  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
65 ,0x0000,0x0000,0x6600,0x0000,0x0000,0x0000,0x6600,0x0000
66 ,0x0000,0x0066,0x0000,0x0000,0x0000,0x0000,0x0067,0x0000
67 ,0x0000,0x6665,0x0000,0x0000,0x0000,0x0000,0x0065,0x6600
68 ,0x0063,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6563
69 ,0x0064,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6564
70 ,0x0064,0x6564,0x0000,0x6469,0x6969,0x6400,0x0064,0x6564
71 ,0x0063,0x6568,0x6200,0x0064,0x6864,0x0000,0x6268,0x6563
72 ,0x0000,0x6567,0x6963,0x0064,0x6764,0x0063,0x6967,0x6500
73 ,0x0000,0x6266,0x6769,0x6a68,0x6768,0x6a69,0x6766,0x6200
74 ,0x0000,0x0062,0x6566,0x6666,0x6666,0x6666,0x6562,0x0000
75 ,0x0000,0x0000,0x0062,0x6364,0x6664,0x6362,0x0000,0x0000
76 ,0x0000,0x0000,0x0000,0x0062,0x6662,0x0000,0x0000,0x0000
77 ,0x0000,0x0000,0x0000,0x0061,0x6661,0x0000,0x0000,0x0000
78 ,0x0000,0x0000,0x0000,0x0000,0x6500,0x0000,0x0000,0x0000
79 ,0x0000,0x0000,0x0000,0x0000,0x6400,0x0000,0x0000,0x0000
80 };
81 
82 /*
83 
84 
85 All of Quake's data access is through a hierchal file system, but the contents of the file system can be transparently merged from several sources.
86 
87 The "base directory" is the path to the directory holding the quake.exe and all game directories.  The sys_* files pass this to host_init in quakeparms_t->basedir.  This can be overridden with the "-basedir" command line parm to allow code debugging in a different directory.  The base directory is
88 only used during filesystem initialization.
89 
90 The "game directory" is the first tree on the search path and directory that all generated files (savegames, screenshots, demos, config files) will be saved to.  This can be overridden with the "-game" command line parameter.  The game directory can never be changed while quake is executing.  This is a precacution against having a malicious server instruct clients to write files over areas they shouldn't.
91 
92 The "cache directory" is only used during development to save network bandwidth, especially over ISDN / T1 lines.  If there is a cache directory
93 specified, when a file is found by the normal search path, it will be mirrored
94 into the cache directory, then opened there.
95 
96 */
97 
98 //============================================================================
99 
100 
101 // ClearLink is used for new headnodes
ClearLink(link_t * l)102 void ClearLink (link_t *l)
103 {
104 	l->prev = l->next = l;
105 }
106 
RemoveLink(link_t * l)107 void RemoveLink (link_t *l)
108 {
109 	l->next->prev = l->prev;
110 	l->prev->next = l->next;
111 }
112 
InsertLinkBefore(link_t * l,link_t * before)113 void InsertLinkBefore (link_t *l, link_t *before)
114 {
115 	l->next = before;
116 	l->prev = before->prev;
117 	l->prev->next = l;
118 	l->next->prev = l;
119 }
InsertLinkAfter(link_t * l,link_t * after)120 void InsertLinkAfter (link_t *l, link_t *after)
121 {
122 	l->next = after->next;
123 	l->prev = after;
124 	l->prev->next = l;
125 	l->next->prev = l;
126 }
127 
128 /*
129 ============================================================================
130 
131 					LIBRARY REPLACEMENT FUNCTIONS
132 
133 ============================================================================
134 */
135 
136 #if 0
137 void Q_memset (void *dest, int fill, int count)
138 {
139 	int		i;
140 
141 	if ( (((long)dest | count) & 3) == 0)
142 	{
143 		count >>= 2;
144 		fill = fill | (fill<<8) | (fill<<16) | (fill<<24);
145 		for (i=0 ; i<count ; i++)
146 			((int *)dest)[i] = fill;
147 	}
148 	else
149 		for (i=0 ; i<count ; i++)
150 			((byte *)dest)[i] = fill;
151 }
152 
153 void Q_memcpy (void *dest, void *src, int count)
154 {
155 	int		i;
156 
157 	if (( ( (long)dest | (long)src | count) & 3) == 0 )
158 	{
159 		count>>=2;
160 		for (i=0 ; i<count ; i++)
161 			((int *)dest)[i] = ((int *)src)[i];
162 	}
163 	else
164 		for (i=0 ; i<count ; i++)
165 			((byte *)dest)[i] = ((byte *)src)[i];
166 }
167 
168 int Q_memcmp (void *m1, void *m2, int count)
169 {
170 	while(count)
171 	{
172 		count--;
173 		if (((byte *)m1)[count] != ((byte *)m2)[count])
174 			return -1;
175 	}
176 	return 0;
177 }
178 
179 void Q_strcpy (char *dest, char *src)
180 {
181 	while (*src)
182 	{
183 		*dest++ = *src++;
184 	}
185 	*dest++ = 0;
186 }
187 
188 void Q_strncpy (char *dest, char *src, int count)
189 {
190 	while (*src && count--)
191 	{
192 		*dest++ = *src++;
193 	}
194 	if (count)
195 		*dest++ = 0;
196 }
197 
198 int Q_strlen (char *str)
199 {
200 	int		count;
201 
202 	count = 0;
203 	while (str[count])
204 		count++;
205 
206 	return count;
207 }
208 
209 char *Q_strrchr(char *s, char c)
210 {
211     int len = Q_strlen(s);
212     s += len;
213     while (len--)
214         if (*--s == c) return s;
215     return 0;
216 }
217 
218 void Q_strcat (char *dest, char *src)
219 {
220 	dest += Q_strlen(dest);
221 	Q_strcpy (dest, src);
222 }
223 
224 int Q_strcmp (char *s1, char *s2)
225 {
226 	while (1)
227 	{
228 		if (*s1 != *s2)
229 			return -1;		// strings not equal
230 		if (!*s1)
231 			return 0;		// strings are equal
232 		s1++;
233 		s2++;
234 	}
235 
236 	return -1;
237 }
238 
239 int Q_strncmp (char *s1, char *s2, int count)
240 {
241 	while (1)
242 	{
243 		if (!count--)
244 			return 0;
245 		if (*s1 != *s2)
246 			return -1;		// strings not equal
247 		if (!*s1)
248 			return 0;		// strings are equal
249 		s1++;
250 		s2++;
251 	}
252 
253 	return -1;
254 }
255 
256 int Q_strncasecmp (char *s1, char *s2, int n)
257 {
258 	int		c1, c2;
259 
260 	while (1)
261 	{
262 		c1 = *s1++;
263 		c2 = *s2++;
264 
265 		if (!n--)
266 			return 0;		// strings are equal until end point
267 
268 		if (c1 != c2)
269 		{
270 			if (c1 >= 'a' && c1 <= 'z')
271 				c1 -= ('a' - 'A');
272 			if (c2 >= 'a' && c2 <= 'z')
273 				c2 -= ('a' - 'A');
274 			if (c1 != c2)
275 				return -1;		// strings not equal
276 		}
277 		if (!c1)
278 			return 0;		// strings are equal
279 //		s1++;
280 //		s2++;
281 	}
282 
283 	return -1;
284 }
285 
286 int Q_strcasecmp (char *s1, char *s2)
287 {
288 	return Q_strncasecmp (s1, s2, 99999);
289 }
290 
291 #endif
292 
Q_atoi(char * str)293 int Q_atoi (char *str)
294 {
295 	int		val;
296 	int		sign;
297 	int		c;
298 
299 	if (*str == '-')
300 	{
301 		sign = -1;
302 		str++;
303 	}
304 	else
305 		sign = 1;
306 
307 	val = 0;
308 
309 //
310 // check for hex
311 //
312 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
313 	{
314 		str += 2;
315 		while (1)
316 		{
317 			c = *str++;
318 			if (c >= '0' && c <= '9')
319 				val = (val<<4) + c - '0';
320 			else if (c >= 'a' && c <= 'f')
321 				val = (val<<4) + c - 'a' + 10;
322 			else if (c >= 'A' && c <= 'F')
323 				val = (val<<4) + c - 'A' + 10;
324 			else
325 				return val*sign;
326 		}
327 	}
328 
329 //
330 // check for character
331 //
332 	if (str[0] == '\'')
333 	{
334 		return sign * str[1];
335 	}
336 
337 //
338 // assume decimal
339 //
340 	while (1)
341 	{
342 		c = *str++;
343 		if (c <'0' || c > '9')
344 			return val*sign;
345 		val = val*10 + c - '0';
346 	}
347 
348 	return 0;
349 }
350 
351 
Q_atof(char * str)352 float Q_atof (char *str)
353 {
354 	double	val;
355 	int		sign;
356 	int		c;
357 	int		decimal, total;
358 
359 	if (*str == '-')
360 	{
361 		sign = -1;
362 		str++;
363 	}
364 	else
365 		sign = 1;
366 
367 	val = 0;
368 
369 //
370 // check for hex
371 //
372 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
373 	{
374 		str += 2;
375 		while (1)
376 		{
377 			c = *str++;
378 			if (c >= '0' && c <= '9')
379 				val = (val*16) + c - '0';
380 			else if (c >= 'a' && c <= 'f')
381 				val = (val*16) + c - 'a' + 10;
382 			else if (c >= 'A' && c <= 'F')
383 				val = (val*16) + c - 'A' + 10;
384 			else
385 				return val*sign;
386 		}
387 	}
388 
389 //
390 // check for character
391 //
392 	if (str[0] == '\'')
393 	{
394 		return sign * str[1];
395 	}
396 
397 //
398 // assume decimal
399 //
400 	decimal = -1;
401 	total = 0;
402 	while (1)
403 	{
404 		c = *str++;
405 		if (c == '.')
406 		{
407 			decimal = total;
408 			continue;
409 		}
410 		if (c <'0' || c > '9')
411 			break;
412 		val = val*10 + c - '0';
413 		total++;
414 	}
415 
416 	if (decimal == -1)
417 		return val*sign;
418 	while (total > decimal)
419 	{
420 		val /= 10;
421 		total--;
422 	}
423 
424 	return val*sign;
425 }
426 
427 /*
428 ============================================================================
429 
430 					BYTE ORDER FUNCTIONS
431 
432 ============================================================================
433 */
434 
435 qboolean	bigendien;
436 
437 short	(*BigShort) (short l);
438 short	(*LittleShort) (short l);
439 int	(*BigLong) (int l);
440 int	(*LittleLong) (int l);
441 float	(*BigFloat) (float l);
442 float	(*LittleFloat) (float l);
443 
ShortSwap(short l)444 short   ShortSwap (short l)
445 {
446 	byte    b1,b2;
447 
448 	b1 = l&255;
449 	b2 = (l>>8)&255;
450 
451 	return (b1<<8) + b2;
452 }
453 
ShortNoSwap(short l)454 short	ShortNoSwap (short l)
455 {
456 	return l;
457 }
458 
LongSwap(int l)459 int    LongSwap (int l)
460 {
461 	byte    b1,b2,b3,b4;
462 
463 	b1 = l&255;
464 	b2 = (l>>8)&255;
465 	b3 = (l>>16)&255;
466 	b4 = (l>>24)&255;
467 
468 	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
469 }
470 
LongNoSwap(int l)471 int	LongNoSwap (int l)
472 {
473 	return l;
474 }
475 
FloatSwap(float f)476 float FloatSwap (float f)
477 {
478 	union
479 	{
480 		float	f;
481 		byte	b[4];
482 	} dat1, dat2;
483 
484 
485 	dat1.f = f;
486 	dat2.b[0] = dat1.b[3];
487 	dat2.b[1] = dat1.b[2];
488 	dat2.b[2] = dat1.b[1];
489 	dat2.b[3] = dat1.b[0];
490 	return dat2.f;
491 }
492 
FloatNoSwap(float f)493 float FloatNoSwap (float f)
494 {
495 	return f;
496 }
497 
498 /*
499 ==============================================================================
500 
501 			MESSAGE IO FUNCTIONS
502 
503 Handles byte ordering and avoids alignment errors
504 ==============================================================================
505 */
506 
507 //
508 // writing functions
509 //
510 
MSG_WriteChar(sizebuf_t * sb,int c)511 void MSG_WriteChar (sizebuf_t *sb, int c)
512 {
513 	byte	*buf;
514 
515 #ifdef PARANOID
516 	if (c < -128 || c > 127)
517 		Sys_Error ("MSG_WriteChar: range error");
518 #endif
519 
520 	buf = SZ_GetSpace (sb, 1);
521 	buf[0] = c;
522 }
523 
MSG_WriteByte(sizebuf_t * sb,int c)524 void MSG_WriteByte (sizebuf_t *sb, int c)
525 {
526 	byte	*buf;
527 
528 #ifdef PARANOID
529 	if (c < 0 || c > 255)
530 		Sys_Error ("MSG_WriteByte: range error");
531 #endif
532 
533 	buf = SZ_GetSpace (sb, 1);
534 	buf[0] = c;
535 }
536 
MSG_WriteShort(sizebuf_t * sb,int c)537 void MSG_WriteShort (sizebuf_t *sb, int c)
538 {
539 	byte	*buf;
540 
541 #ifdef PARANOID
542 	if (c < ((short)0x8000) || c > (short)0x7fff)
543 		Sys_Error ("MSG_WriteShort: range error");
544 #endif
545 
546 	buf = SZ_GetSpace (sb, 2);
547 	buf[0] = c&0xff;
548 	buf[1] = c>>8;
549 }
550 
MSG_WriteLong(sizebuf_t * sb,int c)551 void MSG_WriteLong (sizebuf_t *sb, int c)
552 {
553 	byte	*buf;
554 
555 	buf = SZ_GetSpace (sb, 4);
556 	buf[0] = c&0xff;
557 	buf[1] = (c>>8)&0xff;
558 	buf[2] = (c>>16)&0xff;
559 	buf[3] = c>>24;
560 }
561 
MSG_WriteFloat(sizebuf_t * sb,float f)562 void MSG_WriteFloat (sizebuf_t *sb, float f)
563 {
564 	union
565 	{
566 		float	f;
567 		int	l;
568 	} dat;
569 
570 
571 	dat.f = f;
572 	dat.l = LittleLong (dat.l);
573 
574 	SZ_Write (sb, &dat.l, 4);
575 }
576 
MSG_WriteString(sizebuf_t * sb,char * s)577 void MSG_WriteString (sizebuf_t *sb, char *s)
578 {
579 	if (!s)
580 		SZ_Write (sb, "", 1);
581 	else
582 		SZ_Write (sb, s, Q_strlen(s)+1);
583 }
584 
MSG_WriteCoord(sizebuf_t * sb,float f)585 void MSG_WriteCoord (sizebuf_t *sb, float f)
586 {
587 	MSG_WriteShort (sb, (int)(f*8));
588 }
589 
MSG_WriteAngle(sizebuf_t * sb,float f)590 void MSG_WriteAngle (sizebuf_t *sb, float f)
591 {
592 	MSG_WriteByte (sb, (int)(f*256/360) & 255);
593 }
594 
MSG_WriteAngle16(sizebuf_t * sb,float f)595 void MSG_WriteAngle16 (sizebuf_t *sb, float f)
596 {
597 	MSG_WriteShort (sb, (int)(f*65536/360) & 65535);
598 }
599 
MSG_WriteDeltaUsercmd(sizebuf_t * buf,usercmd_t * from,usercmd_t * cmd)600 void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd)
601 {
602 	int		bits;
603 
604 //
605 // send the movement message
606 //
607 	bits = 0;
608 	if (cmd->angles[0] != from->angles[0])
609 		bits |= CM_ANGLE1;
610 	if (cmd->angles[1] != from->angles[1])
611 		bits |= CM_ANGLE2;
612 	if (cmd->angles[2] != from->angles[2])
613 		bits |= CM_ANGLE3;
614 	if (cmd->forwardmove != from->forwardmove)
615 		bits |= CM_FORWARD;
616 	if (cmd->sidemove != from->sidemove)
617 		bits |= CM_SIDE;
618 	if (cmd->upmove != from->upmove)
619 		bits |= CM_UP;
620 	if (cmd->buttons != from->buttons)
621 		bits |= CM_BUTTONS;
622 	if (cmd->impulse != from->impulse)
623 		bits |= CM_IMPULSE;
624 
625     MSG_WriteByte (buf, bits);
626 
627 	if (bits & CM_ANGLE1)
628 		MSG_WriteAngle16 (buf, cmd->angles[0]);
629 	if (bits & CM_ANGLE2)
630 		MSG_WriteAngle16 (buf, cmd->angles[1]);
631 	if (bits & CM_ANGLE3)
632 		MSG_WriteAngle16 (buf, cmd->angles[2]);
633 
634 	if (bits & CM_FORWARD)
635 		MSG_WriteShort (buf, cmd->forwardmove);
636 	if (bits & CM_SIDE)
637 	  	MSG_WriteShort (buf, cmd->sidemove);
638 	if (bits & CM_UP)
639 		MSG_WriteShort (buf, cmd->upmove);
640 
641  	if (bits & CM_BUTTONS)
642 	  	MSG_WriteByte (buf, cmd->buttons);
643  	if (bits & CM_IMPULSE)
644 	    MSG_WriteByte (buf, cmd->impulse);
645 	MSG_WriteByte (buf, cmd->msec);
646 }
647 
648 
649 //
650 // reading functions
651 //
652 int			msg_readcount;
653 qboolean	msg_badread;
654 
MSG_BeginReading(void)655 void MSG_BeginReading (void)
656 {
657 	msg_readcount = 0;
658 	msg_badread = false;
659 }
660 
MSG_GetReadCount(void)661 int MSG_GetReadCount(void)
662 {
663 	return msg_readcount;
664 }
665 
666 // returns -1 and sets msg_badread if no more characters are available
MSG_ReadChar(void)667 int MSG_ReadChar (void)
668 {
669 	int	c;
670 
671 	if (msg_readcount+1 > net_message.cursize)
672 	{
673 		msg_badread = true;
674 		return -1;
675 	}
676 
677 	c = (signed char)net_message.data[msg_readcount];
678 	msg_readcount++;
679 
680 	return c;
681 }
682 
MSG_ReadByte(void)683 int MSG_ReadByte (void)
684 {
685 	int	c;
686 
687 	if (msg_readcount+1 > net_message.cursize)
688 	{
689 		msg_badread = true;
690 		return -1;
691 	}
692 
693 	c = (unsigned char)net_message.data[msg_readcount];
694 	msg_readcount++;
695 
696 	return c;
697 }
698 
MSG_ReadShort(void)699 int MSG_ReadShort (void)
700 {
701 	int	c;
702 
703 	if (msg_readcount+2 > net_message.cursize)
704 	{
705 		msg_badread = true;
706 		return -1;
707 	}
708 
709 	c = (short)(net_message.data[msg_readcount]
710 	+ (net_message.data[msg_readcount+1]<<8));
711 
712 	msg_readcount += 2;
713 
714 	return c;
715 }
716 
MSG_ReadLong(void)717 int MSG_ReadLong (void)
718 {
719 	int	c;
720 
721 	if (msg_readcount+4 > net_message.cursize)
722 	{
723 		msg_badread = true;
724 		return -1;
725 	}
726 
727 	c = net_message.data[msg_readcount]
728 	+ (net_message.data[msg_readcount+1]<<8)
729 	+ (net_message.data[msg_readcount+2]<<16)
730 	+ (net_message.data[msg_readcount+3]<<24);
731 
732 	msg_readcount += 4;
733 
734 	return c;
735 }
736 
MSG_ReadFloat(void)737 float MSG_ReadFloat (void)
738 {
739 	union
740 	{
741 		byte	b[4];
742 		float	f;
743 		int	l;
744 	} dat;
745 
746 	dat.b[0] =	net_message.data[msg_readcount];
747 	dat.b[1] =	net_message.data[msg_readcount+1];
748 	dat.b[2] =	net_message.data[msg_readcount+2];
749 	dat.b[3] =	net_message.data[msg_readcount+3];
750 	msg_readcount += 4;
751 
752 	dat.l = LittleLong (dat.l);
753 
754 	return dat.f;
755 }
756 
MSG_ReadString(void)757 char *MSG_ReadString (void)
758 {
759 	static char	string[2048];
760 	int		l,c;
761 
762 	l = 0;
763 	do
764 	{
765 		c = MSG_ReadChar ();
766 		if (c == -1 || c == 0)
767 			break;
768 		string[l] = c;
769 		l++;
770 	} while (l < (int) sizeof(string)-1);
771 
772 	string[l] = 0;
773 
774 	return string;
775 }
776 
MSG_ReadStringLine(void)777 char *MSG_ReadStringLine (void)
778 {
779 	static char	string[2048];
780 	int		l,c;
781 
782 	l = 0;
783 	do
784 	{
785 		c = MSG_ReadChar ();
786 		if (c == -1 || c == 0 || c == '\n')
787 			break;
788 		string[l] = c;
789 		l++;
790 	} while (l < (int) sizeof(string)-1);
791 
792 	string[l] = 0;
793 
794 	return string;
795 }
796 
MSG_ReadCoord(void)797 float MSG_ReadCoord (void)
798 {
799 	return MSG_ReadShort() * (1.0/8);
800 }
801 
MSG_ReadAngle(void)802 float MSG_ReadAngle (void)
803 {
804 	return MSG_ReadChar() * (360.0/256);
805 }
806 
MSG_ReadAngle16(void)807 float MSG_ReadAngle16 (void)
808 {
809 	return MSG_ReadShort() * (360.0/65536);
810 }
811 
MSG_ReadDeltaUsercmd(usercmd_t * from,usercmd_t * move)812 void MSG_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move)
813 {
814 	int bits;
815 
816 	memcpy (move, from, sizeof(*move));
817 
818 	bits = MSG_ReadByte ();
819 
820 // read current angles
821 	if (bits & CM_ANGLE1)
822 		move->angles[0] = MSG_ReadAngle16 ();
823 	if (bits & CM_ANGLE2)
824 		move->angles[1] = MSG_ReadAngle16 ();
825 	if (bits & CM_ANGLE3)
826 		move->angles[2] = MSG_ReadAngle16 ();
827 
828 // read movement
829 	if (bits & CM_FORWARD)
830 		move->forwardmove = MSG_ReadShort ();
831 	if (bits & CM_SIDE)
832 		move->sidemove = MSG_ReadShort ();
833 	if (bits & CM_UP)
834 		move->upmove = MSG_ReadShort ();
835 
836 // read buttons
837 	if (bits & CM_BUTTONS)
838 		move->buttons = MSG_ReadByte ();
839 
840 	if (bits & CM_IMPULSE)
841 		move->impulse = MSG_ReadByte ();
842 
843 // read time to run command
844 	move->msec = MSG_ReadByte ();
845 }
846 
847 
848 //===========================================================================
849 
SZ_Clear(sizebuf_t * buf)850 void SZ_Clear (sizebuf_t *buf)
851 {
852 	buf->cursize = 0;
853 	buf->overflowed = false;
854 }
855 
SZ_GetSpace(sizebuf_t * buf,int length)856 void *SZ_GetSpace (sizebuf_t *buf, int length)
857 {
858 	void	*data;
859 
860 	if (buf->cursize + length > buf->maxsize)
861 	{
862 		if (!buf->allowoverflow)
863 			Sys_Error ("SZ_GetSpace: overflow without allowoverflow set (%d)", buf->maxsize);
864 
865 		if (length > buf->maxsize)
866 			Sys_Error ("SZ_GetSpace: %i is > full buffer size", length);
867 
868 		Sys_Printf ("SZ_GetSpace: overflow\n");	// because Con_Printf may be redirected
869 		SZ_Clear (buf);
870 		buf->overflowed = true;
871 	}
872 
873 	data = buf->data + buf->cursize;
874 	buf->cursize += length;
875 
876 	return data;
877 }
878 
SZ_Write(sizebuf_t * buf,void * data,int length)879 void SZ_Write (sizebuf_t *buf, void *data, int length)
880 {
881 	Q_memcpy (SZ_GetSpace(buf,length),data,length);
882 }
883 
SZ_Print(sizebuf_t * buf,char * data)884 void SZ_Print (sizebuf_t *buf, char *data)
885 {
886 	int		len;
887 
888 	len = Q_strlen(data)+1;
889 
890 	if (!buf->cursize || buf->data[buf->cursize-1])
891 		Q_memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
892 	else
893 		Q_memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
894 }
895 
896 
897 //============================================================================
898 
899 
900 /*
901 ============
902 COM_SkipPath
903 ============
904 */
COM_SkipPath(char * pathname)905 char *COM_SkipPath (char *pathname)
906 {
907 	char	*last;
908 
909 	last = pathname;
910 	while (*pathname)
911 	{
912 		if (*pathname=='/')
913 			last = pathname+1;
914 		pathname++;
915 	}
916 	return last;
917 }
918 
919 /*
920 ============
921 COM_StripExtension
922 ============
923 */
COM_StripExtension(char * in,char * out)924 void COM_StripExtension (char *in, char *out)
925 {
926 	while (*in && *in != '.')
927 		*out++ = *in++;
928 	*out = 0;
929 }
930 
931 /*
932 ============
933 COM_FileExtension
934 ============
935 */
COM_FileExtension(char * in)936 char *COM_FileExtension (char *in)
937 {
938 	static char exten[8];
939 	int		i;
940 
941 	while (*in && *in != '.')
942 		in++;
943 	if (!*in)
944 		return "";
945 	in++;
946 	for (i=0 ; i<7 && *in ; i++,in++)
947 		exten[i] = *in;
948 	exten[i] = 0;
949 	return exten;
950 }
951 
952 /*
953 ============
954 COM_FileBase
955 ============
956 */
COM_FileBase(char * in,char * out)957 void COM_FileBase (char *in, char *out)
958 {
959 	char *s, *s2;
960 
961 	s = in + strlen(in) - 1;
962 
963 	while (s != in && *s != '.')
964 		s--;
965 
966 	for (s2 = s ; *s2 && *s2 != '/' ; s2--)
967 	;
968 
969 	if (s-s2 < 2)
970 		strcpy (out,"?model?");
971 	else
972 	{
973 		s--;
974 		strncpy (out,s2+1, s-s2);
975 		out[s-s2] = 0;
976 	}
977 }
978 
979 
980 /*
981 ==================
982 COM_DefaultExtension
983 ==================
984 */
COM_DefaultExtension(char * path,char * extension)985 void COM_DefaultExtension (char *path, char *extension)
986 {
987 	char    *src;
988 //
989 // if path doesn't have a .EXT, append extension
990 // (extension should include the .)
991 //
992 	src = path + strlen(path) - 1;
993 
994 	while (*src != '/' && src != path)
995 	{
996 		if (*src == '.')
997 			return;                 // it has an extension
998 		src--;
999 	}
1000 
1001 	strcat (path, extension);
1002 }
1003 
1004 //============================================================================
1005 
1006 char		com_token[1024];
1007 int		com_argc;
1008 char	**com_argv;
1009 
1010 
1011 /*
1012 ==============
1013 COM_Parse
1014 
1015 Parse a token out of a string
1016 ==============
1017 */
COM_Parse(char * data)1018 char *COM_Parse (char *data)
1019 {
1020 	int		c;
1021 	int		len;
1022 
1023 	len = 0;
1024 	com_token[0] = 0;
1025 
1026 	if (!data)
1027 		return NULL;
1028 
1029 // skip whitespace
1030 skipwhite:
1031 	while ( (c = *data) <= ' ')
1032 	{
1033 		if (c == 0)
1034 			return NULL;			// end of file;
1035 		data++;
1036 	}
1037 
1038 // skip // comments
1039 	if (c=='/' && data[1] == '/')
1040 	{
1041 		while (*data && *data != '\n')
1042 			data++;
1043 		goto skipwhite;
1044 	}
1045 
1046 
1047 // handle quoted strings specially
1048 	if (c == '\"')
1049 	{
1050 		data++;
1051 		while (1)
1052 		{
1053 			c = *data++;
1054 			if (c=='\"' || !c)
1055 			{
1056 				com_token[len] = 0;
1057 				return data;
1058 			}
1059 			com_token[len] = c;
1060 			len++;
1061 		}
1062 	}
1063 
1064 // parse a regular word
1065 	do
1066 	{
1067 		com_token[len] = c;
1068 		data++;
1069 		len++;
1070 		c = *data;
1071 	} while (c>32);
1072 
1073 	com_token[len] = 0;
1074 	return data;
1075 }
1076 
1077 
1078 /*
1079 ================
1080 COM_CheckParm
1081 
1082 Returns the position (1 to argc-1) in the program's argument list
1083 where the given parameter apears, or 0 if not present
1084 ================
1085 */
COM_CheckParm(char * parm)1086 int COM_CheckParm (char *parm)
1087 {
1088 	int		i;
1089 
1090 	for (i=1 ; i<com_argc ; i++)
1091 	{
1092 		if (!com_argv[i])
1093 			continue;		// NEXTSTEP sometimes clears appkit vars.
1094 		if (!Q_strcmp (parm,com_argv[i]))
1095 			return i;
1096 	}
1097 
1098 	return 0;
1099 }
1100 
1101 /*
1102 ================
1103 COM_CheckRegistered
1104 
1105 Looks for the pop.txt file and verifies it.
1106 Sets the "registered" cvar.
1107 Immediately exits out if an alternate game was attempted to be started without
1108 being registered.
1109 ================
1110 */
COM_CheckRegistered(void)1111 void COM_CheckRegistered (void)
1112 {
1113 	FILE		*h;
1114 	unsigned short	check[128];
1115 	int			i;
1116 
1117 	COM_FOpenFile("gfx/pop.lmp", &h);
1118 	static_registered = 0;
1119 
1120 	if (!h)
1121 	{
1122 		Con_Printf ("Playing shareware version.\n");
1123 #if 0
1124 #ifndef SERVERONLY
1125 // FIXME DEBUG -- only temporary
1126 		if (com_modified)
1127 			Sys_Error ("You must have the registered version to play QuakeWorld");
1128 #endif
1129 #endif
1130 		return;
1131 	}
1132 
1133 	fread (check, 1, sizeof(check), h);
1134 	fclose (h);
1135 
1136 	for (i=0 ; i<128 ; i++)
1137 		if (pop[i] != (unsigned short)BigShort (check[i]))
1138 			Sys_Error ("Corrupted data file.");
1139 
1140 	Cvar_Set ("registered", "1");
1141 	static_registered = 1;
1142 	Con_Printf ("Playing registered version.\n");
1143 }
1144 
1145 
1146 
1147 /*
1148 ================
1149 COM_InitArgv
1150 ================
1151 */
COM_InitArgv(int argc,char ** argv)1152 void COM_InitArgv (int argc, char **argv)
1153 {
1154 	qboolean	safe;
1155 	int			i;
1156 
1157 	safe = false;
1158 
1159 	for (com_argc=0 ; (com_argc<MAX_NUM_ARGVS) && (com_argc < argc) ;
1160 		 com_argc++)
1161 	{
1162 		largv[com_argc] = argv[com_argc];
1163 		if (!Q_strcmp ("-safe", argv[com_argc]))
1164 			safe = true;
1165 	}
1166 
1167 	if (safe)
1168 	{
1169 	// force all the safe-mode switches. Note that we reserved extra space in
1170 	// case we need to add these, so we don't need an overflow check
1171 		for (i=0 ; i<NUM_SAFE_ARGVS ; i++)
1172 		{
1173 			largv[com_argc] = safeargvs[i];
1174 			com_argc++;
1175 		}
1176 	}
1177 
1178 	largv[com_argc] = argvdummy;
1179 	com_argv = largv;
1180 }
1181 
1182 /*
1183 ================
1184 COM_AddParm
1185 
1186 Adds the given string at the end of the current argument list
1187 ================
1188 */
COM_AddParm(char * parm)1189 void COM_AddParm (char *parm)
1190 {
1191 	largv[com_argc++] = parm;
1192 }
1193 
1194 
1195 /*
1196 ================
1197 COM_Init
1198 ================
1199 */
COM_Init(void)1200 void COM_Init (void)
1201 {
1202 	byte	swaptest[2] = {1,0};
1203 
1204 // set the byte swapping variables in a portable manner
1205 	if ( *(short *)swaptest == 1)
1206 	{
1207 		bigendien = false;
1208 		BigShort = ShortSwap;
1209 		LittleShort = ShortNoSwap;
1210 		BigLong = LongSwap;
1211 		LittleLong = LongNoSwap;
1212 		BigFloat = FloatSwap;
1213 		LittleFloat = FloatNoSwap;
1214 	}
1215 	else
1216 	{
1217 		bigendien = true;
1218 		BigShort = ShortNoSwap;
1219 		LittleShort = ShortSwap;
1220 		BigLong = LongNoSwap;
1221 		LittleLong = LongSwap;
1222 		BigFloat = FloatNoSwap;
1223 		LittleFloat = FloatSwap;
1224 	}
1225 
1226 	Cvar_RegisterVariable (&registered);
1227 	Cmd_AddCommand ("path", COM_Path_f);
1228 
1229 	COM_InitFilesystem ();
1230 	COM_CheckRegistered ();
1231 }
1232 
1233 
1234 /*
1235 ============
1236 va
1237 
1238 does a varargs printf into a temp buffer, so I don't need to have
1239 varargs versions of all text functions.
1240 FIXME: make this buffer size safe someday
1241 ============
1242 */
va(char * format,...)1243 char	*va(char *format, ...)
1244 {
1245 	va_list		argptr;
1246 	static char		string[1024];
1247 
1248 	va_start (argptr, format);
1249 	vsprintf (string, format,argptr);
1250 	va_end (argptr);
1251 
1252 	return string;
1253 }
1254 
1255 
1256 /// just for debugging
memsearch(byte * start,int count,int search)1257 int	memsearch (byte *start, int count, int search)
1258 {
1259 	int		i;
1260 
1261 	for (i=0 ; i<count ; i++)
1262 		if (start[i] == search)
1263 			return i;
1264 	return -1;
1265 }
1266 
1267 /*
1268 =============================================================================
1269 
1270 QUAKE FILESYSTEM
1271 
1272 =============================================================================
1273 */
1274 
1275 int	com_filesize;
1276 
1277 
1278 //
1279 // in memory
1280 //
1281 
1282 typedef struct
1283 {
1284 	char	name[MAX_QPATH];
1285 	int		filepos, filelen;
1286 } packfile_t;
1287 
1288 typedef struct pack_s
1289 {
1290 	char	filename[MAX_OSPATH];
1291 	FILE	*handle;
1292 	int		numfiles;
1293 	packfile_t	*files;
1294 } pack_t;
1295 
1296 //
1297 // on disk
1298 //
1299 typedef struct
1300 {
1301 	char	name[56];
1302 	int		filepos, filelen;
1303 } dpackfile_t;
1304 
1305 typedef struct
1306 {
1307 	char	id[4];
1308 	int		dirofs;
1309 	int		dirlen;
1310 } dpackheader_t;
1311 
1312 #define	MAX_FILES_IN_PACK	2048
1313 
1314 char	com_gamedir[MAX_OSPATH];
1315 char	com_basedir[MAX_OSPATH];
1316 
1317 typedef struct searchpath_s
1318 {
1319 	char	filename[MAX_OSPATH];
1320 	pack_t	*pack;		// only one of filename / pack will be used
1321 	struct searchpath_s *next;
1322 } searchpath_t;
1323 
1324 searchpath_t	*com_searchpaths;
1325 searchpath_t	*com_base_searchpaths;	// without gamedirs
1326 
1327 /*
1328 ================
1329 COM_filelength
1330 ================
1331 */
COM_filelength(FILE * f)1332 int COM_filelength (FILE *f)
1333 {
1334 	int		pos;
1335 	int		end;
1336 
1337 	pos = ftell (f);
1338 	fseek (f, 0, SEEK_END);
1339 	end = ftell (f);
1340 	fseek (f, pos, SEEK_SET);
1341 
1342 	return end;
1343 }
1344 
COM_FileOpenRead(char * path,FILE ** hndl)1345 int COM_FileOpenRead (char *path, FILE **hndl)
1346 {
1347 	FILE	*f;
1348 
1349 	f = fopen(path, "rb");
1350 	if (!f)
1351 	{
1352 		*hndl = NULL;
1353 		return -1;
1354 	}
1355 	*hndl = f;
1356 
1357 	return COM_filelength(f);
1358 }
1359 
1360 /*
1361 ============
1362 COM_Path_f
1363 
1364 ============
1365 */
COM_Path_f(void)1366 void COM_Path_f (void)
1367 {
1368 	searchpath_t	*s;
1369 
1370 	Con_Printf ("Current search path:\n");
1371 	for (s=com_searchpaths ; s ; s=s->next)
1372 	{
1373 		if (s == com_base_searchpaths)
1374 			Con_Printf ("----------\n");
1375 		if (s->pack)
1376 			Con_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles);
1377 		else
1378 			Con_Printf ("%s\n", s->filename);
1379 	}
1380 }
1381 
1382 /*
1383 ============
1384 COM_WriteFile
1385 
1386 The filename will be prefixed by the current game directory
1387 ============
1388 */
COM_WriteFile(char * filename,void * data,int len)1389 void COM_WriteFile (char *filename, void *data, int len)
1390 {
1391 	FILE	*f;
1392 	char	name[MAX_OSPATH];
1393 
1394 	sprintf (name, "%s/%s", com_gamedir, filename);
1395 
1396 	f = fopen (name, "wb");
1397 	if (!f) {
1398 		Sys_mkdir(com_gamedir);
1399 		f = fopen (name, "wb");
1400 		if (!f)
1401 			Sys_Error ("Error opening %s", filename);
1402 	}
1403 
1404 	Sys_Printf ("COM_WriteFile: %s\n", name);
1405 	fwrite (data, 1, len, f);
1406 	fclose (f);
1407 }
1408 
1409 
1410 /*
1411 ============
1412 COM_CreatePath
1413 
1414 Only used for CopyFile and download
1415 ============
1416 */
COM_CreatePath(char * path)1417 void	COM_CreatePath (char *path)
1418 {
1419 	char	*ofs;
1420 
1421 	for (ofs = path+1 ; *ofs ; ofs++)
1422 	{
1423 		if (*ofs == '/')
1424 		{	// create the directory
1425 			*ofs = 0;
1426 			Sys_mkdir (path);
1427 			*ofs = '/';
1428 		}
1429 	}
1430 }
1431 
1432 
1433 /*
1434 ===========
1435 COM_CopyFile
1436 
1437 Copies a file over from the net to the local cache, creating any directories
1438 needed.  This is for the convenience of developers using ISDN from home.
1439 ===========
1440 */
COM_CopyFile(char * netpath,char * cachepath)1441 void COM_CopyFile (char *netpath, char *cachepath)
1442 {
1443 	FILE	*in, *out;
1444 	int		remaining, count;
1445 	char	buf[4096];
1446 
1447 	remaining = COM_FileOpenRead (netpath, &in);
1448 	COM_CreatePath (cachepath);	// create directories up to the cache file
1449 	out = fopen(cachepath, "wb");
1450 	if (!out)
1451 		Sys_Error ("Error opening %s", cachepath);
1452 
1453 	while (remaining)
1454 	{
1455 		if (remaining < (int) sizeof(buf))
1456 			count = remaining;
1457 		else
1458 			count = sizeof(buf);
1459 		fread (buf, 1, count, in);
1460 		fwrite (buf, 1, count, out);
1461 		remaining -= count;
1462 	}
1463 
1464 	fclose (in);
1465 	fclose (out);
1466 }
1467 
1468 /*
1469 ===========
1470 COM_FindFile
1471 
1472 Finds the file in the search path.
1473 Sets com_filesize and one of handle or file
1474 ===========
1475 */
1476 int file_from_pak; // global indicating file came from pack file ZOID
1477 
COM_FOpenFile(char * filename,FILE ** file)1478 int COM_FOpenFile (char *filename, FILE **file)
1479 {
1480 	searchpath_t	*search;
1481 	char		netpath[MAX_OSPATH];
1482 	pack_t		*pak;
1483 	int			i;
1484 	int			findtime;
1485 
1486 	file_from_pak = 0;
1487 
1488 //
1489 // search through the path, one element at a time
1490 //
1491 	for (search = com_searchpaths ; search ; search = search->next)
1492 	{
1493 	// is the element a pak file?
1494 		if (search->pack)
1495 		{
1496 		// look through all the pak file elements
1497 			pak = search->pack;
1498 			for (i=0 ; i<pak->numfiles ; i++)
1499 				if (!strcmp (pak->files[i].name, filename))
1500 				{	// found it!
1501 					Sys_Printf ("PackFile: %s : %s\n",pak->filename, filename);
1502 				// open a new file on the pakfile
1503 					*file = fopen (pak->filename, "rb");
1504 					if (!*file)
1505 						Sys_Error ("Couldn't reopen %s", pak->filename);
1506 					fseek (*file, pak->files[i].filepos, SEEK_SET);
1507 					com_filesize = pak->files[i].filelen;
1508 					file_from_pak = 1;
1509 					return com_filesize;
1510 				}
1511 		}
1512 		else
1513 		{
1514 	// check a file in the directory tree
1515 			if (!static_registered)
1516 			{	// if not a registered version, don't ever go beyond base
1517 				if ( strchr (filename, '/') || strchr (filename,'\\'))
1518 					continue;
1519 			}
1520 
1521 			sprintf (netpath, "%s/%s",search->filename, filename);
1522 
1523 			findtime = Sys_FileTime (netpath);
1524 			if (findtime == -1)
1525 				continue;
1526 
1527 			Sys_Printf ("FindFile: %s\n",netpath);
1528 
1529 			*file = fopen (netpath, "rb");
1530 			return COM_filelength (*file);
1531 		}
1532 
1533 	}
1534 
1535 	Sys_Printf ("FindFile: can't find %s\n", filename);
1536 
1537 	*file = NULL;
1538 	com_filesize = -1;
1539 	return -1;
1540 }
1541 
1542 /*
1543 ============
1544 COM_LoadFile
1545 
1546 Filename are reletive to the quake directory.
1547 Allways appends a 0 byte to the loaded data.
1548 ============
1549 */
1550 cache_user_t *loadcache;
1551 byte	*loadbuf;
1552 int		loadsize;
COM_LoadFile(char * path,int usehunk)1553 byte *COM_LoadFile (char *path, int usehunk)
1554 {
1555 	FILE	*h;
1556 	byte	*buf;
1557 	char	base[32];
1558 	int		len;
1559 
1560 	buf = NULL;	// quiet compiler warning
1561 
1562 // look for it in the filesystem or pack files
1563 	len = com_filesize = COM_FOpenFile (path, &h);
1564 	if (!h)
1565 		return NULL;
1566 
1567 // extract the filename base name for hunk tag
1568 	COM_FileBase (path, base);
1569 
1570 	if (usehunk == 1)
1571 		buf = Hunk_AllocName (len+1, base);
1572 	else if (usehunk == 2)
1573 		buf = Hunk_TempAlloc (len+1);
1574 	else if (usehunk == 0)
1575 		buf = Z_Malloc (len+1);
1576 	else if (usehunk == 3)
1577 		buf = Cache_Alloc (loadcache, len+1, base);
1578 	else if (usehunk == 4)
1579 	{
1580 		if (len+1 > loadsize)
1581 			buf = Hunk_TempAlloc (len+1);
1582 		else
1583 			buf = loadbuf;
1584 	}
1585 	else
1586 		Sys_Error ("COM_LoadFile: bad usehunk");
1587 
1588 	if (!buf)
1589 		Sys_Error ("COM_LoadFile: not enough space for %s", path);
1590 
1591 	((byte *)buf)[len] = 0;
1592 #ifndef SERVERONLY
1593 	Draw_BeginDisc ();
1594 #endif
1595 	fread (buf, 1, len, h);
1596 	fclose (h);
1597 #ifndef SERVERONLY
1598 	Draw_EndDisc ();
1599 #endif
1600 
1601 	return buf;
1602 }
1603 
COM_LoadHunkFile(char * path)1604 byte *COM_LoadHunkFile (char *path)
1605 {
1606 	return COM_LoadFile (path, 1);
1607 }
1608 
COM_LoadTempFile(char * path)1609 byte *COM_LoadTempFile (char *path)
1610 {
1611 	return COM_LoadFile (path, 2);
1612 }
1613 
COM_LoadCacheFile(char * path,struct cache_user_s * cu)1614 void COM_LoadCacheFile (char *path, struct cache_user_s *cu)
1615 {
1616 	loadcache = cu;
1617 	COM_LoadFile (path, 3);
1618 }
1619 
1620 // uses temp hunk if larger than bufsize
COM_LoadStackFile(char * path,void * buffer,int bufsize)1621 byte *COM_LoadStackFile (char *path, void *buffer, int bufsize)
1622 {
1623 	byte	*buf;
1624 
1625 	loadbuf = (byte *)buffer;
1626 	loadsize = bufsize;
1627 	buf = COM_LoadFile (path, 4);
1628 
1629 	return buf;
1630 }
1631 
1632 /*
1633 =================
1634 COM_LoadPackFile
1635 
1636 Takes an explicit (not game tree related) path to a pak file.
1637 
1638 Loads the header and directory, adding the files at the beginning
1639 of the list so they override previous pack files.
1640 =================
1641 */
COM_LoadPackFile(char * packfile)1642 pack_t *COM_LoadPackFile (char *packfile)
1643 {
1644 	dpackheader_t	header;
1645 	int				i;
1646 	packfile_t		*newfiles;
1647 	int				numpackfiles;
1648 	pack_t			*pack;
1649 	FILE			*packhandle;
1650 	dpackfile_t		info[MAX_FILES_IN_PACK];
1651 	unsigned short		crc;
1652 
1653 	if (COM_FileOpenRead (packfile, &packhandle) == -1)
1654 		return NULL;
1655 
1656 	fread (&header, 1, sizeof(header), packhandle);
1657 	if (header.id[0] != 'P' || header.id[1] != 'A'
1658 	|| header.id[2] != 'C' || header.id[3] != 'K')
1659 		Sys_Error ("%s is not a packfile", packfile);
1660 	header.dirofs = LittleLong (header.dirofs);
1661 	header.dirlen = LittleLong (header.dirlen);
1662 
1663 	numpackfiles = header.dirlen / sizeof(dpackfile_t);
1664 
1665 	if (numpackfiles > MAX_FILES_IN_PACK)
1666 		Sys_Error ("%s has %i files", packfile, numpackfiles);
1667 
1668 	if (numpackfiles != PAK0_COUNT)
1669 		com_modified = true;	// not the original file
1670 
1671 	newfiles = Z_Malloc (numpackfiles * sizeof(packfile_t));
1672 
1673 	fseek (packhandle, header.dirofs, SEEK_SET);
1674 	fread (&info, 1, header.dirlen, packhandle);
1675 
1676 // crc the directory to check for modifications
1677 	crc = CRC_Block((byte *)info, header.dirlen);
1678 
1679 //	CRC_Init (&crc);
1680 //	for (i=0 ; i<header.dirlen ; i++)
1681 //		CRC_ProcessByte (&crc, ((byte *)info)[i]);
1682 	if (crc != PAK0_CRC)
1683 		com_modified = true;
1684 
1685 // parse the directory
1686 	for (i=0 ; i<numpackfiles ; i++)
1687 	{
1688 		strcpy (newfiles[i].name, info[i].name);
1689 		newfiles[i].filepos = LittleLong(info[i].filepos);
1690 		newfiles[i].filelen = LittleLong(info[i].filelen);
1691 	}
1692 
1693 	pack = Z_Malloc (sizeof (pack_t));
1694 	strcpy (pack->filename, packfile);
1695 	pack->handle = packhandle;
1696 	pack->numfiles = numpackfiles;
1697 	pack->files = newfiles;
1698 
1699 	Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles);
1700 	return pack;
1701 }
1702 
1703 
1704 /*
1705 ================
1706 COM_AddGameDirectory
1707 
1708 Sets com_gamedir, adds the directory to the head of the path,
1709 then loads and adds pak1.pak pak2.pak ...
1710 ================
1711 */
COM_AddGameDirectory(char * dir)1712 void COM_AddGameDirectory (char *dir)
1713 {
1714 	int				i;
1715 	searchpath_t	*search;
1716 	pack_t			*pak;
1717 	char			pakfile[MAX_OSPATH];
1718 	char			*p;
1719 
1720 	if ((p = strrchr(dir, '/')) != NULL)
1721 		strcpy(gamedirfile, ++p);
1722 	else
1723 		strcpy(gamedirfile, p);
1724 	strcpy (com_gamedir, dir);
1725 
1726 //
1727 // add the directory to the search path
1728 //
1729 	search = Hunk_Alloc (sizeof(searchpath_t));
1730 	strcpy (search->filename, dir);
1731 	search->next = com_searchpaths;
1732 	com_searchpaths = search;
1733 
1734 //
1735 // add any pak files in the format pak0.pak pak1.pak, ...
1736 //
1737 	for (i=0 ; ; i++)
1738 	{
1739 		sprintf (pakfile, "%s/pak%i.pak", dir, i);
1740 		pak = COM_LoadPackFile (pakfile);
1741 		if (!pak)
1742 			break;
1743 		search = Hunk_Alloc (sizeof(searchpath_t));
1744 		search->pack = pak;
1745 		search->next = com_searchpaths;
1746 		com_searchpaths = search;
1747 	}
1748 
1749 }
1750 
1751 /*
1752 ================
1753 COM_Gamedir
1754 
1755 Sets the gamedir and path to a different directory.
1756 ================
1757 */
COM_Gamedir(char * dir)1758 void COM_Gamedir (char *dir)
1759 {
1760 	searchpath_t	*search, *next;
1761 	int				i;
1762 	pack_t			*pak;
1763 	char			pakfile[MAX_OSPATH];
1764 
1765 	if (strstr(dir, "..") || strstr(dir, "/")
1766 		|| strstr(dir, "\\") || strstr(dir, ":") )
1767 	{
1768 		Con_Printf ("Gamedir should be a single filename, not a path\n");
1769 		return;
1770 	}
1771 
1772 	if (!strcmp(gamedirfile, dir))
1773 		return;		// still the same
1774 	strcpy (gamedirfile, dir);
1775 
1776 	//
1777 	// free up any current game dir info
1778 	//
1779 	while (com_searchpaths != com_base_searchpaths)
1780 	{
1781 		if (com_searchpaths->pack)
1782 		{
1783 			fclose (com_searchpaths->pack->handle);
1784 			Z_Free (com_searchpaths->pack->files);
1785 			Z_Free (com_searchpaths->pack);
1786 		}
1787 		next = com_searchpaths->next;
1788 		Z_Free (com_searchpaths);
1789 		com_searchpaths = next;
1790 	}
1791 
1792 	//
1793 	// flush all data, so it will be forced to reload
1794 	//
1795 	Cache_Flush ();
1796 
1797 	if (!strcmp(dir,"id1") || !strcmp(dir, "qw"))
1798 		return;
1799 
1800 	sprintf (com_gamedir, "%s/%s", com_basedir, dir);
1801 
1802 	//
1803 	// add the directory to the search path
1804 	//
1805 	search = Z_Malloc (sizeof(searchpath_t));
1806 	strcpy (search->filename, com_gamedir);
1807 	search->next = com_searchpaths;
1808 	com_searchpaths = search;
1809 
1810 	//
1811 	// add any pak files in the format pak0.pak pak1.pak, ...
1812 	//
1813 	for (i=0 ; ; i++)
1814 	{
1815 		sprintf (pakfile, "%s/pak%i.pak", com_gamedir, i);
1816 		pak = COM_LoadPackFile (pakfile);
1817 		if (!pak)
1818 			break;
1819 		search = Z_Malloc (sizeof(searchpath_t));
1820 		search->pack = pak;
1821 		search->next = com_searchpaths;
1822 		com_searchpaths = search;
1823 	}
1824 }
1825 
1826 /*
1827 ================
1828 COM_InitFilesystem
1829 ================
1830 */
COM_InitFilesystem(void)1831 void COM_InitFilesystem (void)
1832 {
1833 	int		i;
1834 
1835 //
1836 // -basedir <path>
1837 // Overrides the system supplied base directory (under id1)
1838 //
1839 	i = COM_CheckParm ("-basedir");
1840 	if (i && i < com_argc-1)
1841 		strcpy (com_basedir, com_argv[i+1]);
1842 	else
1843 		strcpy (com_basedir, host_parms.basedir);
1844 
1845 //
1846 // start up with id1 by default
1847 //
1848 	COM_AddGameDirectory (va("%s/id1", com_basedir) );
1849 	COM_AddGameDirectory (va("%s/qw", com_basedir) );
1850 
1851 	// any set gamedirs will be freed up to here
1852 	com_base_searchpaths = com_searchpaths;
1853 }
1854 
1855 
1856 
1857 /*
1858 =====================================================================
1859 
1860   INFO STRINGS
1861 
1862 =====================================================================
1863 */
1864 
1865 /*
1866 ===============
1867 Info_ValueForKey
1868 
1869 Searches the string for the given
1870 key and returns the associated value, or an empty string.
1871 ===============
1872 */
Info_ValueForKey(char * s,char * key)1873 char *Info_ValueForKey (char *s, char *key)
1874 {
1875 	char	pkey[512];
1876 	static	char value[4][512];	// use two buffers so compares
1877 								// work without stomping on each other
1878 	static	int	valueindex;
1879 	char	*o;
1880 
1881 	valueindex = (valueindex + 1) % 4;
1882 	if (*s == '\\')
1883 		s++;
1884 	while (1)
1885 	{
1886 		o = pkey;
1887 		while (*s != '\\')
1888 		{
1889 			if (!*s)
1890 				return "";
1891 			*o++ = *s++;
1892 		}
1893 		*o = 0;
1894 		s++;
1895 
1896 		o = value[valueindex];
1897 
1898 		while (*s != '\\' && *s)
1899 		{
1900 			if (!*s)
1901 				return "";
1902 			*o++ = *s++;
1903 		}
1904 		*o = 0;
1905 
1906 		if (!strcmp (key, pkey) )
1907 			return value[valueindex];
1908 
1909 		if (!*s)
1910 			return "";
1911 		s++;
1912 	}
1913 }
1914 
Info_RemoveKey(char * s,char * key)1915 void Info_RemoveKey (char *s, char *key)
1916 {
1917 	char	*start;
1918 	char	pkey[512];
1919 	char	value[512];
1920 	char	*o;
1921 
1922 	if (strstr (key, "\\"))
1923 	{
1924 		Con_Printf ("Can't use a key with a \\\n");
1925 		return;
1926 	}
1927 
1928 	while (1)
1929 	{
1930 		start = s;
1931 		if (*s == '\\')
1932 			s++;
1933 		o = pkey;
1934 		while (*s != '\\')
1935 		{
1936 			if (!*s)
1937 				return;
1938 			*o++ = *s++;
1939 		}
1940 		*o = 0;
1941 		s++;
1942 
1943 		o = value;
1944 		while (*s != '\\' && *s)
1945 		{
1946 			if (!*s)
1947 				return;
1948 			*o++ = *s++;
1949 		}
1950 		*o = 0;
1951 
1952 		if (!strcmp (key, pkey) )
1953 		{
1954 			strcpy (start, s);	// remove this part
1955 			return;
1956 		}
1957 
1958 		if (!*s)
1959 			return;
1960 	}
1961 
1962 }
1963 
Info_RemovePrefixedKeys(char * start,char prefix)1964 void Info_RemovePrefixedKeys (char *start, char prefix)
1965 {
1966 	char	*s;
1967 	char	pkey[512];
1968 	char	value[512];
1969 	char	*o;
1970 
1971 	s = start;
1972 
1973 	while (1)
1974 	{
1975 		if (*s == '\\')
1976 			s++;
1977 		o = pkey;
1978 		while (*s != '\\')
1979 		{
1980 			if (!*s)
1981 				return;
1982 			*o++ = *s++;
1983 		}
1984 		*o = 0;
1985 		s++;
1986 
1987 		o = value;
1988 		while (*s != '\\' && *s)
1989 		{
1990 			if (!*s)
1991 				return;
1992 			*o++ = *s++;
1993 		}
1994 		*o = 0;
1995 
1996 		if (pkey[0] == prefix)
1997 		{
1998 			Info_RemoveKey (start, pkey);
1999 			s = start;
2000 		}
2001 
2002 		if (!*s)
2003 			return;
2004 	}
2005 
2006 }
2007 
2008 
Info_SetValueForStarKey(char * s,char * key,char * value,int maxsize)2009 void Info_SetValueForStarKey (char *s, char *key, char *value, int maxsize)
2010 {
2011 	char	new[1024], *v;
2012 	int		c;
2013 #ifdef SERVERONLY
2014 	extern cvar_t sv_highchars;
2015 #endif
2016 
2017 	if (strstr (key, "\\") || strstr (value, "\\") )
2018 	{
2019 		Con_Printf ("Can't use keys or values with a \\\n");
2020 		return;
2021 	}
2022 
2023 	if (strstr (key, "\"") || strstr (value, "\"") )
2024 	{
2025 		Con_Printf ("Can't use keys or values with a \"\n");
2026 		return;
2027 	}
2028 
2029 	if (strlen(key) > 63 || strlen(value) > 63)
2030 	{
2031 		Con_Printf ("Keys and values must be < 64 characters.\n");
2032 		return;
2033 	}
2034 
2035 	// this next line is kinda trippy
2036 	if (*(v = Info_ValueForKey(s, key))) {
2037 		// key exists, make sure we have enough room for new value, if we don't,
2038 		// don't change it!
2039 		if ((int) (strlen(value) - strlen(v) + strlen(s)) > maxsize) {
2040 			Con_Printf ("Info string length exceeded\n");
2041 			return;
2042 		}
2043 	}
2044 	Info_RemoveKey (s, key);
2045 	if (!value || !strlen(value))
2046 		return;
2047 
2048 	sprintf (new, "\\%s\\%s", key, value);
2049 
2050 	if ((int)(strlen(new) + strlen(s)) > maxsize)
2051 	{
2052 		Con_Printf ("Info string length exceeded\n");
2053 		return;
2054 	}
2055 
2056 	// only copy ascii values
2057 	s += strlen(s);
2058 	v = new;
2059 	while (*v)
2060 	{
2061 		c = (unsigned char)*v++;
2062 #ifndef SERVERONLY
2063 		// client only allows highbits on name
2064 		if (stricmp(key, "name") != 0) {
2065 			c &= 127;
2066 			if (c < 32 || c > 127)
2067 				continue;
2068 			// auto lowercase team
2069 			if (stricmp(key, "team") == 0)
2070 				c = tolower(c);
2071 		}
2072 #else
2073 		if (!sv_highchars.value) {
2074 			c &= 127;
2075 			if (c < 32 || c > 127)
2076 				continue;
2077 		}
2078 #endif
2079 //		c &= 127;		// strip high bits
2080 		if (c > 13) // && c < 127)
2081 			*s++ = c;
2082 	}
2083 	*s = 0;
2084 }
2085 
Info_SetValueForKey(char * s,char * key,char * value,int maxsize)2086 void Info_SetValueForKey (char *s, char *key, char *value, int maxsize)
2087 {
2088 	if (key[0] == '*')
2089 	{
2090 		Con_Printf ("Can't set * keys\n");
2091 		return;
2092 	}
2093 
2094 	Info_SetValueForStarKey (s, key, value, maxsize);
2095 }
2096 
Info_Print(char * s)2097 void Info_Print (char *s)
2098 {
2099 	char	key[512];
2100 	char	value[512];
2101 	char	*o;
2102 	int		l;
2103 
2104 	if (*s == '\\')
2105 		s++;
2106 	while (*s)
2107 	{
2108 		o = key;
2109 		while (*s && *s != '\\')
2110 			*o++ = *s++;
2111 
2112 		l = o - key;
2113 		if (l < 20)
2114 		{
2115 			memset (o, ' ', 20-l);
2116 			key[20] = 0;
2117 		}
2118 		else
2119 			*o = 0;
2120 		Con_Printf ("%s", key);
2121 
2122 		if (!*s)
2123 		{
2124 			Con_Printf ("MISSING VALUE\n");
2125 			return;
2126 		}
2127 
2128 		o = value;
2129 		s++;
2130 		while (*s && *s != '\\')
2131 			*o++ = *s++;
2132 		*o = 0;
2133 
2134 		if (*s)
2135 			s++;
2136 		Con_Printf ("%s\n", value);
2137 	}
2138 }
2139 
2140 static byte chktbl[1024 + 4] = {
2141 0x78,0xd2,0x94,0xe3,0x41,0xec,0xd6,0xd5,0xcb,0xfc,0xdb,0x8a,0x4b,0xcc,0x85,0x01,
2142 0x23,0xd2,0xe5,0xf2,0x29,0xa7,0x45,0x94,0x4a,0x62,0xe3,0xa5,0x6f,0x3f,0xe1,0x7a,
2143 0x64,0xed,0x5c,0x99,0x29,0x87,0xa8,0x78,0x59,0x0d,0xaa,0x0f,0x25,0x0a,0x5c,0x58,
2144 0xfb,0x00,0xa7,0xa8,0x8a,0x1d,0x86,0x80,0xc5,0x1f,0xd2,0x28,0x69,0x71,0x58,0xc3,
2145 0x51,0x90,0xe1,0xf8,0x6a,0xf3,0x8f,0xb0,0x68,0xdf,0x95,0x40,0x5c,0xe4,0x24,0x6b,
2146 0x29,0x19,0x71,0x3f,0x42,0x63,0x6c,0x48,0xe7,0xad,0xa8,0x4b,0x91,0x8f,0x42,0x36,
2147 0x34,0xe7,0x32,0x55,0x59,0x2d,0x36,0x38,0x38,0x59,0x9b,0x08,0x16,0x4d,0x8d,0xf8,
2148 0x0a,0xa4,0x52,0x01,0xbb,0x52,0xa9,0xfd,0x40,0x18,0x97,0x37,0xff,0xc9,0x82,0x27,
2149 0xb2,0x64,0x60,0xce,0x00,0xd9,0x04,0xf0,0x9e,0x99,0xbd,0xce,0x8f,0x90,0x4a,0xdd,
2150 0xe1,0xec,0x19,0x14,0xb1,0xfb,0xca,0x1e,0x98,0x0f,0xd4,0xcb,0x80,0xd6,0x05,0x63,
2151 0xfd,0xa0,0x74,0xa6,0x86,0xf6,0x19,0x98,0x76,0x27,0x68,0xf7,0xe9,0x09,0x9a,0xf2,
2152 0x2e,0x42,0xe1,0xbe,0x64,0x48,0x2a,0x74,0x30,0xbb,0x07,0xcc,0x1f,0xd4,0x91,0x9d,
2153 0xac,0x55,0x53,0x25,0xb9,0x64,0xf7,0x58,0x4c,0x34,0x16,0xbc,0xf6,0x12,0x2b,0x65,
2154 0x68,0x25,0x2e,0x29,0x1f,0xbb,0xb9,0xee,0x6d,0x0c,0x8e,0xbb,0xd2,0x5f,0x1d,0x8f,
2155 0xc1,0x39,0xf9,0x8d,0xc0,0x39,0x75,0xcf,0x25,0x17,0xbe,0x96,0xaf,0x98,0x9f,0x5f,
2156 0x65,0x15,0xc4,0x62,0xf8,0x55,0xfc,0xab,0x54,0xcf,0xdc,0x14,0x06,0xc8,0xfc,0x42,
2157 0xd3,0xf0,0xad,0x10,0x08,0xcd,0xd4,0x11,0xbb,0xca,0x67,0xc6,0x48,0x5f,0x9d,0x59,
2158 0xe3,0xe8,0x53,0x67,0x27,0x2d,0x34,0x9e,0x9e,0x24,0x29,0xdb,0x69,0x99,0x86,0xf9,
2159 0x20,0xb5,0xbb,0x5b,0xb0,0xf9,0xc3,0x67,0xad,0x1c,0x9c,0xf7,0xcc,0xef,0xce,0x69,
2160 0xe0,0x26,0x8f,0x79,0xbd,0xca,0x10,0x17,0xda,0xa9,0x88,0x57,0x9b,0x15,0x24,0xba,
2161 0x84,0xd0,0xeb,0x4d,0x14,0xf5,0xfc,0xe6,0x51,0x6c,0x6f,0x64,0x6b,0x73,0xec,0x85,
2162 0xf1,0x6f,0xe1,0x67,0x25,0x10,0x77,0x32,0x9e,0x85,0x6e,0x69,0xb1,0x83,0x00,0xe4,
2163 0x13,0xa4,0x45,0x34,0x3b,0x40,0xff,0x41,0x82,0x89,0x79,0x57,0xfd,0xd2,0x8e,0xe8,
2164 0xfc,0x1d,0x19,0x21,0x12,0x00,0xd7,0x66,0xe5,0xc7,0x10,0x1d,0xcb,0x75,0xe8,0xfa,
2165 0xb6,0xee,0x7b,0x2f,0x1a,0x25,0x24,0xb9,0x9f,0x1d,0x78,0xfb,0x84,0xd0,0x17,0x05,
2166 0x71,0xb3,0xc8,0x18,0xff,0x62,0xee,0xed,0x53,0xab,0x78,0xd3,0x65,0x2d,0xbb,0xc7,
2167 0xc1,0xe7,0x70,0xa2,0x43,0x2c,0x7c,0xc7,0x16,0x04,0xd2,0x45,0xd5,0x6b,0x6c,0x7a,
2168 0x5e,0xa1,0x50,0x2e,0x31,0x5b,0xcc,0xe8,0x65,0x8b,0x16,0x85,0xbf,0x82,0x83,0xfb,
2169 0xde,0x9f,0x36,0x48,0x32,0x79,0xd6,0x9b,0xfb,0x52,0x45,0xbf,0x43,0xf7,0x0b,0x0b,
2170 0x19,0x19,0x31,0xc3,0x85,0xec,0x1d,0x8c,0x20,0xf0,0x3a,0xfa,0x80,0x4d,0x2c,0x7d,
2171 0xac,0x60,0x09,0xc0,0x40,0xee,0xb9,0xeb,0x13,0x5b,0xe8,0x2b,0xb1,0x20,0xf0,0xce,
2172 0x4c,0xbd,0xc6,0x04,0x86,0x70,0xc6,0x33,0xc3,0x15,0x0f,0x65,0x19,0xfd,0xc2,0xd3,
2173 
2174 // map checksum goes here
2175 0x00,0x00,0x00,0x00
2176 };
2177 
2178 static byte chkbuf[16 + 60 + 4];
2179 
2180 static unsigned last_mapchecksum = 0;
2181 
2182 #if 0
2183 /*
2184 ====================
2185 COM_BlockSequenceCheckByte
2186 
2187 For proxy protecting
2188 ====================
2189 */
2190 byte	COM_BlockSequenceCheckByte (byte *base, int length, int sequence, unsigned mapchecksum)
2191 {
2192 	int		checksum;
2193 	byte	*p;
2194 
2195 	if (last_mapchecksum != mapchecksum) {
2196 		last_mapchecksum = mapchecksum;
2197 		chktbl[1024] = (mapchecksum & 0xff000000) >> 24;
2198 		chktbl[1025] = (mapchecksum & 0x00ff0000) >> 16;
2199 		chktbl[1026] = (mapchecksum & 0x0000ff00) >> 8;
2200 		chktbl[1027] = (mapchecksum & 0x000000ff);
2201 
2202 		Com_BlockFullChecksum (chktbl, sizeof(chktbl), chkbuf);
2203 	}
2204 
2205 	p = chktbl + (sequence % (sizeof(chktbl) - 8));
2206 
2207 	if (length > 60)
2208 		length = 60;
2209 	memcpy (chkbuf + 16, base, length);
2210 
2211 	length += 16;
2212 
2213 	chkbuf[length] = (sequence & 0xff) ^ p[0];
2214 	chkbuf[length+1] = p[1];
2215 	chkbuf[length+2] = ((sequence>>8) & 0xff) ^ p[2];
2216 	chkbuf[length+3] = p[3];
2217 
2218 	length += 4;
2219 
2220 	checksum = LittleLong(Com_BlockChecksum (chkbuf, length));
2221 
2222 	checksum &= 0xff;
2223 
2224 	return checksum;
2225 }
2226 #endif
2227 
2228 /*
2229 ====================
2230 COM_BlockSequenceCRCByte
2231 
2232 For proxy protecting
2233 ====================
2234 */
COM_BlockSequenceCRCByte(byte * base,int length,int sequence)2235 byte	COM_BlockSequenceCRCByte (byte *base, int length, int sequence)
2236 {
2237 	unsigned short crc;
2238 	byte	*p;
2239 	byte chkb[60 + 4];
2240 
2241 	p = chktbl + (sequence % (sizeof(chktbl) - 8));
2242 
2243 	if (length > 60)
2244 		length = 60;
2245 	memcpy (chkb, base, length);
2246 
2247 	chkb[length] = (sequence & 0xff) ^ p[0];
2248 	chkb[length+1] = p[1];
2249 	chkb[length+2] = ((sequence>>8) & 0xff) ^ p[2];
2250 	chkb[length+3] = p[3];
2251 
2252 	length += 4;
2253 
2254 	crc = CRC_Block(chkb, length);
2255 
2256 	crc &= 0xff;
2257 
2258 	return crc;
2259 }
2260 
2261 // char *date = "Oct 24 1996";
2262 static char *date = __DATE__ ;
2263 static char *mon[12] =
2264 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
2265 static char mond[12] =
2266 { 31,    28,    31,    30,    31,    30,    31,    31,    30,    31,    30,    31 };
2267 
2268 // returns days since Oct 24 1996
build_number(void)2269 int build_number( void )
2270 {
2271 	int m = 0;
2272 	int d = 0;
2273 	int y = 0;
2274 	static int b = 0;
2275 
2276 	if (b != 0)
2277 		return b;
2278 
2279 	for (m = 0; m < 11; m++)
2280 	{
2281 		if (Q_strncasecmp( &date[0], mon[m], 3 ) == 0)
2282 			break;
2283 		d += mond[m];
2284 	}
2285 
2286 	d += atoi( &date[4] ) - 1;
2287 
2288 	y = atoi( &date[7] ) - 1900;
2289 
2290 	b = d + (int)((y - 1) * 365.25);
2291 
2292 	if (((y % 4) == 0) && m > 1)
2293 	{
2294 		b += 1;
2295 	}
2296 
2297 	b -= 35778; // Dec 16 1998
2298 
2299 	return b;
2300 }
2301 
2302