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 (®istered);
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