|
|
1.1 root 1: // common.c -- misc functions used in client and server
2:
3: #include "quakedef.h"
4:
1.1.1.3 ! root 5: #define NUM_SAFE_ARGVS 7
1.1 root 6:
1.1.1.3 ! root 7: static char *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1];
! 8: static char *argvdummy = " ";
1.1 root 9:
1.1.1.3 ! root 10: static char *safeargvs[NUM_SAFE_ARGVS] =
! 11: {"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse", "-dibonly"};
1.1 root 12:
1.1.1.3 ! root 13: cvar_t registered = {"registered","0"};
! 14: cvar_t cmdline = {"cmdline","0", false, true};
1.1 root 15:
1.1.1.3 ! root 16: qboolean com_modified; // set true if using non-id files
1.1 root 17:
1.1.1.3 ! root 18: qboolean proghack;
! 19:
! 20: int static_registered = 1; // only for startup check, then set
! 21:
! 22: qboolean msg_suppress_1 = 0;
1.1 root 23:
24: void COM_InitFilesystem (void);
25:
26: // if a packfile directory differs from this, it is assumed to be hacked
1.1.1.3 ! root 27: #define PAK0_COUNT 339
! 28: #define PAK0_CRC 32981
! 29:
! 30: char com_token[1024];
! 31: int com_argc;
! 32: char **com_argv;
! 33:
! 34: #define CMDLINE_LENGTH 256
! 35: char com_cmdline[CMDLINE_LENGTH];
! 36:
! 37: qboolean standard_quake = true, rogue, hipnotic;
1.1 root 38:
39: // this graphic needs to be in the pak file to use registered features
40: unsigned short pop[] =
41: {
42: 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
43: ,0x0000,0x0000,0x6600,0x0000,0x0000,0x0000,0x6600,0x0000
44: ,0x0000,0x0066,0x0000,0x0000,0x0000,0x0000,0x0067,0x0000
45: ,0x0000,0x6665,0x0000,0x0000,0x0000,0x0000,0x0065,0x6600
46: ,0x0063,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6563
47: ,0x0064,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6564
48: ,0x0064,0x6564,0x0000,0x6469,0x6969,0x6400,0x0064,0x6564
49: ,0x0063,0x6568,0x6200,0x0064,0x6864,0x0000,0x6268,0x6563
50: ,0x0000,0x6567,0x6963,0x0064,0x6764,0x0063,0x6967,0x6500
51: ,0x0000,0x6266,0x6769,0x6a68,0x6768,0x6a69,0x6766,0x6200
52: ,0x0000,0x0062,0x6566,0x6666,0x6666,0x6666,0x6562,0x0000
53: ,0x0000,0x0000,0x0062,0x6364,0x6664,0x6362,0x0000,0x0000
54: ,0x0000,0x0000,0x0000,0x0062,0x6662,0x0000,0x0000,0x0000
55: ,0x0000,0x0000,0x0000,0x0061,0x6661,0x0000,0x0000,0x0000
56: ,0x0000,0x0000,0x0000,0x0000,0x6500,0x0000,0x0000,0x0000
57: ,0x0000,0x0000,0x0000,0x0000,0x6400,0x0000,0x0000,0x0000
58: };
59:
60: /*
61:
62:
63: 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.
64:
65: 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
66: only used during filesystem initialization.
67:
68: 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.
69:
70: The "cache directory" is only used during development to save network bandwidth, especially over ISDN / T1 lines. If there is a cache directory
71: specified, when a file is found by the normal search path, it will be mirrored
72: into the cache directory, then opened there.
73:
74:
75:
76: FIXME:
77: The file "parms.txt" will be read out of the game directory and appended to the current command line arguments to allow different games to initialize startup parms differently. This could be used to add a "-sspeed 22050" for the high quality sound edition. Because they are added at the end, they will not override an explicit setting on the original command line.
78:
79: */
80:
81: //============================================================================
82:
83:
84: // ClearLink is used for new headnodes
85: void ClearLink (link_t *l)
86: {
87: l->prev = l->next = l;
88: }
89:
90: void RemoveLink (link_t *l)
91: {
92: l->next->prev = l->prev;
93: l->prev->next = l->next;
94: }
95:
96: void InsertLinkBefore (link_t *l, link_t *before)
97: {
98: l->next = before;
99: l->prev = before->prev;
100: l->prev->next = l;
101: l->next->prev = l;
102: }
103: void InsertLinkAfter (link_t *l, link_t *after)
104: {
105: l->next = after->next;
106: l->prev = after;
107: l->prev->next = l;
108: l->next->prev = l;
109: }
110:
111: /*
112: ============================================================================
113:
114: LIBRARY REPLACEMENT FUNCTIONS
115:
116: ============================================================================
117: */
118:
119: void Q_memset (void *dest, int fill, int count)
120: {
1.1.1.3 ! root 121: int i;
1.1 root 122:
123: if ( (((long)dest | count) & 3) == 0)
124: {
125: count >>= 2;
126: fill = fill | (fill<<8) | (fill<<16) | (fill<<24);
127: for (i=0 ; i<count ; i++)
128: ((int *)dest)[i] = fill;
129: }
130: else
131: for (i=0 ; i<count ; i++)
132: ((byte *)dest)[i] = fill;
133: }
134:
135: void Q_memcpy (void *dest, void *src, int count)
136: {
1.1.1.3 ! root 137: int i;
1.1 root 138:
139: if (( ( (long)dest | (long)src | count) & 3) == 0 )
140: {
141: count>>=2;
142: for (i=0 ; i<count ; i++)
143: ((int *)dest)[i] = ((int *)src)[i];
144: }
145: else
146: for (i=0 ; i<count ; i++)
147: ((byte *)dest)[i] = ((byte *)src)[i];
148: }
149:
150: int Q_memcmp (void *m1, void *m2, int count)
151: {
152: while(count)
153: {
154: count--;
155: if (((byte *)m1)[count] != ((byte *)m2)[count])
156: return -1;
157: }
158: return 0;
159: }
160:
161: void Q_strcpy (char *dest, char *src)
162: {
163: while (*src)
164: {
165: *dest++ = *src++;
166: }
167: *dest++ = 0;
168: }
169:
170: void Q_strncpy (char *dest, char *src, int count)
171: {
172: while (*src && count--)
173: {
174: *dest++ = *src++;
175: }
176: if (count)
177: *dest++ = 0;
178: }
179:
180: int Q_strlen (char *str)
181: {
1.1.1.3 ! root 182: int count;
1.1 root 183:
184: count = 0;
185: while (str[count])
186: count++;
187:
188: return count;
189: }
190:
191: char *Q_strrchr(char *s, char c)
192: {
193: int len = Q_strlen(s);
194: s += len;
195: while (len--)
1.1.1.3 ! root 196: if (*--s == c) return s;
1.1 root 197: return 0;
198: }
199:
200: void Q_strcat (char *dest, char *src)
201: {
202: dest += Q_strlen(dest);
203: Q_strcpy (dest, src);
204: }
205:
206: int Q_strcmp (char *s1, char *s2)
207: {
208: while (1)
209: {
210: if (*s1 != *s2)
1.1.1.3 ! root 211: return -1; // strings not equal
1.1 root 212: if (!*s1)
1.1.1.3 ! root 213: return 0; // strings are equal
1.1 root 214: s1++;
215: s2++;
216: }
217:
218: return -1;
219: }
220:
221: int Q_strncmp (char *s1, char *s2, int count)
222: {
223: while (1)
224: {
225: if (!count--)
226: return 0;
227: if (*s1 != *s2)
1.1.1.3 ! root 228: return -1; // strings not equal
1.1 root 229: if (!*s1)
1.1.1.3 ! root 230: return 0; // strings are equal
1.1 root 231: s1++;
232: s2++;
233: }
234:
235: return -1;
236: }
237:
238: int Q_strncasecmp (char *s1, char *s2, int n)
239: {
1.1.1.3 ! root 240: int c1, c2;
1.1 root 241:
242: while (1)
243: {
244: c1 = *s1++;
245: c2 = *s2++;
246:
247: if (!n--)
1.1.1.3 ! root 248: return 0; // strings are equal until end point
1.1 root 249:
250: if (c1 != c2)
251: {
252: if (c1 >= 'a' && c1 <= 'z')
253: c1 -= ('a' - 'A');
254: if (c2 >= 'a' && c2 <= 'z')
255: c2 -= ('a' - 'A');
256: if (c1 != c2)
1.1.1.3 ! root 257: return -1; // strings not equal
1.1 root 258: }
259: if (!c1)
1.1.1.3 ! root 260: return 0; // strings are equal
! 261: // s1++;
! 262: // s2++;
1.1 root 263: }
264:
265: return -1;
266: }
267:
268: int Q_strcasecmp (char *s1, char *s2)
269: {
270: return Q_strncasecmp (s1, s2, 99999);
271: }
272:
273: int Q_atoi (char *str)
274: {
1.1.1.3 ! root 275: int val;
! 276: int sign;
! 277: int c;
1.1 root 278:
279: if (*str == '-')
280: {
281: sign = -1;
282: str++;
283: }
284: else
285: sign = 1;
286:
287: val = 0;
288:
289: //
290: // check for hex
291: //
292: if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
293: {
294: str += 2;
295: while (1)
296: {
297: c = *str++;
298: if (c >= '0' && c <= '9')
299: val = (val<<4) + c - '0';
300: else if (c >= 'a' && c <= 'f')
301: val = (val<<4) + c - 'a' + 10;
302: else if (c >= 'A' && c <= 'F')
303: val = (val<<4) + c - 'A' + 10;
304: else
305: return val*sign;
306: }
307: }
308:
309: //
310: // check for character
311: //
312: if (str[0] == '\'')
313: {
314: return sign * str[1];
315: }
316:
317: //
318: // assume decimal
319: //
320: while (1)
321: {
322: c = *str++;
323: if (c <'0' || c > '9')
324: return val*sign;
325: val = val*10 + c - '0';
326: }
327:
328: return 0;
329: }
330:
331:
332: float Q_atof (char *str)
333: {
1.1.1.3 ! root 334: double val;
! 335: int sign;
! 336: int c;
! 337: int decimal, total;
1.1 root 338:
339: if (*str == '-')
340: {
341: sign = -1;
342: str++;
343: }
344: else
345: sign = 1;
346:
347: val = 0;
348:
349: //
350: // check for hex
351: //
352: if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
353: {
354: str += 2;
355: while (1)
356: {
357: c = *str++;
358: if (c >= '0' && c <= '9')
359: val = (val*16) + c - '0';
360: else if (c >= 'a' && c <= 'f')
361: val = (val*16) + c - 'a' + 10;
362: else if (c >= 'A' && c <= 'F')
363: val = (val*16) + c - 'A' + 10;
364: else
365: return val*sign;
366: }
367: }
368:
369: //
370: // check for character
371: //
372: if (str[0] == '\'')
373: {
374: return sign * str[1];
375: }
376:
377: //
378: // assume decimal
379: //
380: decimal = -1;
381: total = 0;
382: while (1)
383: {
384: c = *str++;
385: if (c == '.')
386: {
387: decimal = total;
388: continue;
389: }
390: if (c <'0' || c > '9')
391: break;
392: val = val*10 + c - '0';
393: total++;
394: }
395:
396: if (decimal == -1)
397: return val*sign;
398: while (total > decimal)
399: {
400: val /= 10;
401: total--;
402: }
403:
404: return val*sign;
405: }
406:
407: /*
408: ============================================================================
409:
410: BYTE ORDER FUNCTIONS
411:
412: ============================================================================
413: */
414:
1.1.1.3 ! root 415: qboolean bigendien;
1.1 root 416:
1.1.1.3 ! root 417: short (*BigShort) (short l);
! 418: short (*LittleShort) (short l);
! 419: int (*BigLong) (int l);
! 420: int (*LittleLong) (int l);
! 421: float (*BigFloat) (float l);
! 422: float (*LittleFloat) (float l);
1.1 root 423:
424: short ShortSwap (short l)
425: {
426: byte b1,b2;
427:
428: b1 = l&255;
429: b2 = (l>>8)&255;
430:
431: return (b1<<8) + b2;
432: }
433:
1.1.1.3 ! root 434: short ShortNoSwap (short l)
1.1 root 435: {
436: return l;
437: }
438:
439: int LongSwap (int l)
440: {
441: byte b1,b2,b3,b4;
442:
443: b1 = l&255;
444: b2 = (l>>8)&255;
445: b3 = (l>>16)&255;
446: b4 = (l>>24)&255;
447:
448: return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
449: }
450:
1.1.1.3 ! root 451: int LongNoSwap (int l)
1.1 root 452: {
453: return l;
454: }
455:
456: float FloatSwap (float f)
457: {
458: union
459: {
1.1.1.3 ! root 460: float f;
! 461: byte b[4];
1.1 root 462: } dat1, dat2;
463:
464:
465: dat1.f = f;
466: dat2.b[0] = dat1.b[3];
467: dat2.b[1] = dat1.b[2];
468: dat2.b[2] = dat1.b[1];
469: dat2.b[3] = dat1.b[0];
470: return dat2.f;
471: }
472:
473: float FloatNoSwap (float f)
474: {
475: return f;
476: }
477:
478: /*
479: ==============================================================================
480:
481: MESSAGE IO FUNCTIONS
482:
483: Handles byte ordering and avoids alignment errors
484: ==============================================================================
485: */
486:
487: //
488: // writing functions
489: //
490:
491: void MSG_WriteChar (sizebuf_t *sb, int c)
492: {
1.1.1.3 ! root 493: byte *buf;
1.1 root 494:
495: #ifdef PARANOID
496: if (c < -128 || c > 127)
497: Sys_Error ("MSG_WriteChar: range error");
498: #endif
499:
500: buf = SZ_GetSpace (sb, 1);
501: buf[0] = c;
502: }
503:
504: void MSG_WriteByte (sizebuf_t *sb, int c)
505: {
1.1.1.3 ! root 506: byte *buf;
1.1 root 507:
508: #ifdef PARANOID
509: if (c < 0 || c > 255)
510: Sys_Error ("MSG_WriteByte: range error");
511: #endif
512:
513: buf = SZ_GetSpace (sb, 1);
514: buf[0] = c;
515: }
516:
517: void MSG_WriteShort (sizebuf_t *sb, int c)
518: {
1.1.1.3 ! root 519: byte *buf;
1.1 root 520:
521: #ifdef PARANOID
522: if (c < ((short)0x8000) || c > (short)0x7fff)
523: Sys_Error ("MSG_WriteShort: range error");
524: #endif
525:
526: buf = SZ_GetSpace (sb, 2);
527: buf[0] = c&0xff;
528: buf[1] = c>>8;
529: }
530:
531: void MSG_WriteLong (sizebuf_t *sb, int c)
532: {
1.1.1.3 ! root 533: byte *buf;
1.1 root 534:
535: buf = SZ_GetSpace (sb, 4);
536: buf[0] = c&0xff;
537: buf[1] = (c>>8)&0xff;
538: buf[2] = (c>>16)&0xff;
539: buf[3] = c>>24;
540: }
541:
542: void MSG_WriteFloat (sizebuf_t *sb, float f)
543: {
544: union
545: {
1.1.1.3 ! root 546: float f;
! 547: int l;
1.1 root 548: } dat;
549:
550:
551: dat.f = f;
552: dat.l = LittleLong (dat.l);
553:
554: SZ_Write (sb, &dat.l, 4);
555: }
556:
557: void MSG_WriteString (sizebuf_t *sb, char *s)
558: {
559: if (!s)
560: SZ_Write (sb, "", 1);
561: else
562: SZ_Write (sb, s, Q_strlen(s)+1);
563: }
564:
565: void MSG_WriteCoord (sizebuf_t *sb, float f)
566: {
567: MSG_WriteShort (sb, (int)(f*8));
568: }
569:
570: void MSG_WriteAngle (sizebuf_t *sb, float f)
571: {
572: MSG_WriteByte (sb, ((int)f*256/360) & 255);
573: }
574:
575: //
576: // reading functions
577: //
1.1.1.3 ! root 578: int msg_readcount;
! 579: qboolean msg_badread;
1.1 root 580:
581: void MSG_BeginReading (void)
582: {
583: msg_readcount = 0;
584: msg_badread = false;
585: }
586:
587: // returns -1 and sets msg_badread if no more characters are available
588: int MSG_ReadChar (void)
589: {
1.1.1.3 ! root 590: int c;
1.1 root 591:
592: if (msg_readcount+1 > net_message.cursize)
593: {
594: msg_badread = true;
595: return -1;
596: }
597:
598: c = (signed char)net_message.data[msg_readcount];
599: msg_readcount++;
600:
601: return c;
602: }
603:
604: int MSG_ReadByte (void)
605: {
1.1.1.3 ! root 606: int c;
1.1 root 607:
608: if (msg_readcount+1 > net_message.cursize)
609: {
610: msg_badread = true;
611: return -1;
612: }
613:
614: c = (unsigned char)net_message.data[msg_readcount];
615: msg_readcount++;
616:
617: return c;
618: }
619:
620: int MSG_ReadShort (void)
621: {
1.1.1.3 ! root 622: int c;
1.1 root 623:
624: if (msg_readcount+2 > net_message.cursize)
625: {
626: msg_badread = true;
627: return -1;
628: }
629:
630: c = (short)(net_message.data[msg_readcount]
631: + (net_message.data[msg_readcount+1]<<8));
632:
633: msg_readcount += 2;
634:
635: return c;
636: }
637:
638: int MSG_ReadLong (void)
639: {
1.1.1.3 ! root 640: int c;
1.1 root 641:
642: if (msg_readcount+4 > net_message.cursize)
643: {
644: msg_badread = true;
645: return -1;
646: }
647:
648: c = net_message.data[msg_readcount]
649: + (net_message.data[msg_readcount+1]<<8)
650: + (net_message.data[msg_readcount+2]<<16)
651: + (net_message.data[msg_readcount+3]<<24);
652:
653: msg_readcount += 4;
654:
655: return c;
656: }
657:
658: float MSG_ReadFloat (void)
659: {
660: union
661: {
1.1.1.3 ! root 662: byte b[4];
! 663: float f;
! 664: int l;
1.1 root 665: } dat;
666:
1.1.1.3 ! root 667: dat.b[0] = net_message.data[msg_readcount];
! 668: dat.b[1] = net_message.data[msg_readcount+1];
! 669: dat.b[2] = net_message.data[msg_readcount+2];
! 670: dat.b[3] = net_message.data[msg_readcount+3];
1.1 root 671: msg_readcount += 4;
672:
673: dat.l = LittleLong (dat.l);
674:
1.1.1.3 ! root 675: return dat.f;
1.1 root 676: }
677:
678: char *MSG_ReadString (void)
679: {
1.1.1.3 ! root 680: static char string[2048];
! 681: int l,c;
1.1 root 682:
683: l = 0;
684: do
685: {
686: c = MSG_ReadChar ();
687: if (c == -1 || c == 0)
688: break;
689: string[l] = c;
690: l++;
691: } while (l < sizeof(string)-1);
692:
693: string[l] = 0;
694:
695: return string;
696: }
697:
698: float MSG_ReadCoord (void)
699: {
700: return MSG_ReadShort() * (1.0/8);
701: }
702:
703: float MSG_ReadAngle (void)
704: {
705: return MSG_ReadChar() * (360.0/256);
706: }
707:
708:
709:
710: //===========================================================================
711:
712: void SZ_Alloc (sizebuf_t *buf, int startsize)
713: {
714: if (startsize < 256)
715: startsize = 256;
716: buf->data = Hunk_AllocName (startsize, "sizebuf");
717: buf->maxsize = startsize;
718: buf->cursize = 0;
719: }
720:
721:
722: void SZ_Free (sizebuf_t *buf)
723: {
1.1.1.3 ! root 724: // Z_Free (buf->data);
! 725: // buf->data = NULL;
! 726: // buf->maxsize = 0;
1.1 root 727: buf->cursize = 0;
728: }
729:
730: void SZ_Clear (sizebuf_t *buf)
731: {
732: buf->cursize = 0;
733: }
734:
735: void *SZ_GetSpace (sizebuf_t *buf, int length)
736: {
1.1.1.3 ! root 737: void *data;
1.1 root 738:
739: if (buf->cursize + length > buf->maxsize)
740: {
741: if (!buf->allowoverflow)
742: Sys_Error ("SZ_GetSpace: overflow without allowoverflow set");
743:
744: if (length > buf->maxsize)
745: Sys_Error ("SZ_GetSpace: %i is > full buffer size", length);
746:
747: buf->overflowed = true;
748: Con_Printf ("SZ_GetSpace: overflow");
749: SZ_Clear (buf);
750: }
751:
752: data = buf->data + buf->cursize;
753: buf->cursize += length;
754:
755: return data;
756: }
757:
758: void SZ_Write (sizebuf_t *buf, void *data, int length)
759: {
1.1.1.3 ! root 760: Q_memcpy (SZ_GetSpace(buf,length),data,length);
1.1 root 761: }
762:
763: void SZ_Print (sizebuf_t *buf, char *data)
764: {
1.1.1.3 ! root 765: int len;
1.1 root 766:
767: len = Q_strlen(data)+1;
768:
769: // byte * cast to keep VC++ happy
770: if (buf->data[buf->cursize-1])
771: Q_memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
772: else
773: Q_memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
774: }
775:
776:
777: //============================================================================
778:
779:
780: /*
781: ============
782: COM_SkipPath
783: ============
784: */
785: char *COM_SkipPath (char *pathname)
786: {
1.1.1.3 ! root 787: char *last;
1.1 root 788:
789: last = pathname;
790: while (*pathname)
791: {
792: if (*pathname=='/')
793: last = pathname+1;
794: pathname++;
795: }
796: return last;
797: }
798:
799: /*
800: ============
801: COM_StripExtension
802: ============
803: */
804: void COM_StripExtension (char *in, char *out)
805: {
806: while (*in && *in != '.')
807: *out++ = *in++;
808: *out = 0;
809: }
810:
811: /*
812: ============
813: COM_FileExtension
814: ============
815: */
816: char *COM_FileExtension (char *in)
817: {
818: static char exten[8];
1.1.1.3 ! root 819: int i;
1.1 root 820:
821: while (*in && *in != '.')
822: in++;
823: if (!*in)
824: return "";
825: in++;
826: for (i=0 ; i<7 && *in ; i++,in++)
827: exten[i] = *in;
828: exten[i] = 0;
829: return exten;
830: }
831:
832: /*
833: ============
834: COM_FileBase
835: ============
836: */
837: void COM_FileBase (char *in, char *out)
838: {
839: char *s, *s2;
840:
841: s = in + strlen(in) - 1;
842:
843: while (s != in && *s != '.')
844: s--;
845:
846: for (s2 = s ; *s2 && *s2 != '/' ; s2--)
847: ;
848:
849: if (s-s2 < 2)
850: strcpy (out,"?model?");
851: else
852: {
853: s--;
854: strncpy (out,s2+1, s-s2);
855: out[s-s2] = 0;
856: }
857: }
858:
859:
860: /*
861: ==================
862: COM_DefaultExtension
863: ==================
864: */
865: void COM_DefaultExtension (char *path, char *extension)
866: {
867: char *src;
868: //
869: // if path doesn't have a .EXT, append extension
870: // (extension should include the .)
871: //
872: src = path + strlen(path) - 1;
873:
874: while (*src != '/' && src != path)
875: {
876: if (*src == '.')
877: return; // it has an extension
878: src--;
879: }
880:
881: strcat (path, extension);
882: }
883:
884:
885: /*
886: ==============
887: COM_Parse
888:
889: Parse a token out of a string
890: ==============
891: */
892: char *COM_Parse (char *data)
893: {
1.1.1.3 ! root 894: int c;
! 895: int len;
1.1 root 896:
897: len = 0;
898: com_token[0] = 0;
899:
900: if (!data)
901: return NULL;
902:
903: // skip whitespace
904: skipwhite:
905: while ( (c = *data) <= ' ')
906: {
907: if (c == 0)
1.1.1.3 ! root 908: return NULL; // end of file;
1.1 root 909: data++;
910: }
911:
912: // skip // comments
913: if (c=='/' && data[1] == '/')
914: {
915: while (*data && *data != '\n')
916: data++;
917: goto skipwhite;
918: }
919:
920:
921: // handle quoted strings specially
922: if (c == '\"')
923: {
924: data++;
925: while (1)
926: {
927: c = *data++;
928: if (c=='\"' || !c)
929: {
930: com_token[len] = 0;
931: return data;
932: }
933: com_token[len] = c;
934: len++;
935: }
936: }
937:
938: // parse single characters
939: if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
940: {
941: com_token[len] = c;
942: len++;
943: com_token[len] = 0;
944: return data+1;
945: }
946:
947: // parse a regular word
948: do
949: {
950: com_token[len] = c;
951: data++;
952: len++;
953: c = *data;
954: if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
955: break;
956: } while (c>32);
957:
958: com_token[len] = 0;
959: return data;
960: }
961:
962:
963: /*
964: ================
965: COM_CheckParm
966:
967: Returns the position (1 to argc-1) in the program's argument list
968: where the given parameter apears, or 0 if not present
969: ================
970: */
971: int COM_CheckParm (char *parm)
972: {
1.1.1.3 ! root 973: int i;
1.1 root 974:
975: for (i=1 ; i<com_argc ; i++)
976: {
977: if (!com_argv[i])
1.1.1.3 ! root 978: continue; // NEXTSTEP sometimes clears appkit vars.
1.1 root 979: if (!Q_strcmp (parm,com_argv[i]))
980: return i;
981: }
982:
983: return 0;
984: }
985:
986: /*
987: ================
988: COM_CheckRegistered
989:
990: Looks for the pop.txt file and verifies it.
991: Sets the "registered" cvar.
992: Immediately exits out if an alternate game was attempted to be started without
993: being registered.
994: ================
995: */
996: void COM_CheckRegistered (void)
997: {
1.1.1.3 ! root 998: int h;
! 999: unsigned short check[128];
! 1000: int i;
1.1 root 1001:
1002: COM_OpenFile("gfx/pop.lmp", &h);
1003: static_registered = 0;
1004:
1005: if (h == -1)
1006: {
1.1.1.3 ! root 1007: #if WINDED
! 1008: Sys_Error ("This dedicated server requires a full registered copy of Quake");
! 1009: #endif
1.1 root 1010: Con_Printf ("Playing shareware version.\n");
1.1.1.3 ! root 1011: if (com_modified)
! 1012: Sys_Error ("You must have the registered version to use modified games");
! 1013: return;
1.1 root 1014: }
1015:
1016: Sys_FileRead (h, check, sizeof(check));
1017: COM_CloseFile (h);
1018:
1019: for (i=0 ; i<128 ; i++)
1.1.1.3 ! root 1020: if (pop[i] != (unsigned short)BigShort (check[i]))
! 1021: Sys_Error ("Corrupted data file.");
1.1 root 1022:
1.1.1.3 ! root 1023: Cvar_Set ("cmdline", com_cmdline);
1.1 root 1024: Cvar_Set ("registered", "1");
1025: static_registered = 1;
1026: Con_Printf ("Playing registered version.\n");
1027: }
1028:
1029:
1030: void COM_Path_f (void);
1031:
1032:
1033: /*
1034: ================
1035: COM_InitArgv
1036: ================
1037: */
1038: void COM_InitArgv (int argc, char **argv)
1039: {
1.1.1.3 ! root 1040: qboolean safe;
! 1041: int i, j, n;
! 1042:
! 1043: // reconstitute the command line for the cmdline externally visible cvar
! 1044: n = 0;
! 1045:
! 1046: for (j=0 ; (j<MAX_NUM_ARGVS) && (j< argc) ; j++)
! 1047: {
! 1048: i = 0;
! 1049:
! 1050: while ((n < (CMDLINE_LENGTH - 1)) && argv[j][i])
! 1051: {
! 1052: com_cmdline[n++] = argv[j][i++];
! 1053: }
! 1054:
! 1055: if (n < (CMDLINE_LENGTH - 1))
! 1056: com_cmdline[n++] = ' ';
! 1057: else
! 1058: break;
! 1059: }
! 1060:
! 1061: com_cmdline[n] = 0;
1.1 root 1062:
1063: safe = false;
1064:
1065: for (com_argc=0 ; (com_argc<MAX_NUM_ARGVS) && (com_argc < argc) ;
1066: com_argc++)
1067: {
1068: largv[com_argc] = argv[com_argc];
1069: if (!Q_strcmp ("-safe", argv[com_argc]))
1070: safe = true;
1071: }
1072:
1073: if (safe)
1074: {
1075: // force all the safe-mode switches. Note that we reserved extra space in
1076: // case we need to add these, so we don't need an overflow check
1077: for (i=0 ; i<NUM_SAFE_ARGVS ; i++)
1078: {
1079: largv[com_argc] = safeargvs[i];
1080: com_argc++;
1081: }
1082: }
1083:
1084: largv[com_argc] = argvdummy;
1085: com_argv = largv;
1.1.1.3 ! root 1086:
! 1087: if (COM_CheckParm ("-rogue"))
! 1088: {
! 1089: rogue = true;
! 1090: standard_quake = false;
! 1091: }
! 1092:
! 1093: if (COM_CheckParm ("-hipnotic"))
! 1094: {
! 1095: hipnotic = true;
! 1096: standard_quake = false;
! 1097: }
1.1 root 1098: }
1099:
1100:
1101: /*
1102: ================
1103: COM_Init
1104: ================
1105: */
1106: void COM_Init (char *basedir)
1107: {
1.1.1.3 ! root 1108: byte swaptest[2] = {1,0};
1.1 root 1109:
1.1.1.3 ! root 1110: // set the byte swapping variables in a portable manner
1.1 root 1111: if ( *(short *)swaptest == 1)
1112: {
1113: bigendien = false;
1114: BigShort = ShortSwap;
1115: LittleShort = ShortNoSwap;
1116: BigLong = LongSwap;
1117: LittleLong = LongNoSwap;
1118: BigFloat = FloatSwap;
1119: LittleFloat = FloatNoSwap;
1120: }
1121: else
1122: {
1123: bigendien = true;
1124: BigShort = ShortNoSwap;
1125: LittleShort = ShortSwap;
1126: BigLong = LongNoSwap;
1127: LittleLong = LongSwap;
1128: BigFloat = FloatNoSwap;
1129: LittleFloat = FloatSwap;
1130: }
1131:
1132: Cvar_RegisterVariable (®istered);
1.1.1.3 ! root 1133: Cvar_RegisterVariable (&cmdline);
1.1 root 1134: Cmd_AddCommand ("path", COM_Path_f);
1135:
1136: COM_InitFilesystem ();
1137: COM_CheckRegistered ();
1138: }
1139:
1140:
1141: /*
1142: ============
1143: va
1144:
1145: does a varargs printf into a temp buffer, so I don't need to have
1146: varargs versions of all text functions.
1147: FIXME: make this buffer size safe someday
1148: ============
1149: */
1.1.1.3 ! root 1150: char *va(char *format, ...)
1.1 root 1151: {
1.1.1.3 ! root 1152: va_list argptr;
! 1153: static char string[1024];
1.1 root 1154:
1155: va_start (argptr, format);
1156: vsprintf (string, format,argptr);
1157: va_end (argptr);
1158:
1.1.1.3 ! root 1159: return string;
1.1 root 1160: }
1161:
1162:
1163: /// just for debugging
1.1.1.3 ! root 1164: int memsearch (byte *start, int count, int search)
1.1 root 1165: {
1.1.1.3 ! root 1166: int i;
1.1 root 1167:
1168: for (i=0 ; i<count ; i++)
1169: if (start[i] == search)
1170: return i;
1171: return -1;
1172: }
1173:
1174: /*
1175: =============================================================================
1176:
1177: QUAKE FILESYSTEM
1178:
1179: =============================================================================
1180: */
1181:
1.1.1.3 ! root 1182: int com_filesize;
1.1 root 1183:
1184:
1185: //
1186: // in memory
1187: //
1188:
1189: typedef struct
1190: {
1.1.1.3 ! root 1191: char name[MAX_QPATH];
! 1192: int filepos, filelen;
1.1 root 1193: } packfile_t;
1194:
1195: typedef struct pack_s
1196: {
1.1.1.3 ! root 1197: char filename[MAX_OSPATH];
! 1198: int handle;
! 1199: int numfiles;
! 1200: packfile_t *files;
1.1 root 1201: } pack_t;
1202:
1203: //
1204: // on disk
1205: //
1206: typedef struct
1207: {
1.1.1.3 ! root 1208: char name[56];
! 1209: int filepos, filelen;
1.1 root 1210: } dpackfile_t;
1211:
1212: typedef struct
1213: {
1.1.1.3 ! root 1214: char id[4];
! 1215: int dirofs;
! 1216: int dirlen;
1.1 root 1217: } dpackheader_t;
1218:
1.1.1.3 ! root 1219: #define MAX_FILES_IN_PACK 2048
1.1 root 1220:
1.1.1.3 ! root 1221: char com_cachedir[MAX_OSPATH];
! 1222: char com_gamedir[MAX_OSPATH];
1.1 root 1223:
1224: typedef struct searchpath_s
1225: {
1.1.1.3 ! root 1226: char filename[MAX_OSPATH];
! 1227: pack_t *pack; // only one of filename / pack will be used
1.1 root 1228: struct searchpath_s *next;
1229: } searchpath_t;
1230:
1.1.1.3 ! root 1231: searchpath_t *com_searchpaths;
1.1 root 1232:
1233: /*
1234: ============
1235: COM_Path_f
1236:
1237: ============
1238: */
1239: void COM_Path_f (void)
1240: {
1.1.1.3 ! root 1241: searchpath_t *s;
1.1 root 1242:
1243: Con_Printf ("Current search path:\n");
1244: for (s=com_searchpaths ; s ; s=s->next)
1245: {
1246: if (s->pack)
1247: {
1248: Con_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles);
1249: }
1250: else
1251: Con_Printf ("%s\n", s->filename);
1252: }
1253: }
1254:
1255: /*
1256: ============
1257: COM_WriteFile
1258:
1259: The filename will be prefixed by the current game directory
1260: ============
1261: */
1262: void COM_WriteFile (char *filename, void *data, int len)
1263: {
1.1.1.3 ! root 1264: int handle;
! 1265: char name[MAX_OSPATH];
1.1 root 1266:
1267: sprintf (name, "%s/%s", com_gamedir, filename);
1268:
1269: handle = Sys_FileOpenWrite (name);
1270: if (handle == -1)
1271: {
1272: Sys_Printf ("COM_WriteFile: failed on %s\n", name);
1273: return;
1274: }
1275:
1276: Sys_Printf ("COM_WriteFile: %s\n", name);
1277: Sys_FileWrite (handle, data, len);
1278: Sys_FileClose (handle);
1279: }
1280:
1281:
1282: /*
1283: ============
1284: COM_CreatePath
1285:
1286: Only used for CopyFile
1287: ============
1288: */
1.1.1.3 ! root 1289: void COM_CreatePath (char *path)
1.1 root 1290: {
1.1.1.3 ! root 1291: char *ofs;
1.1 root 1292:
1293: for (ofs = path+1 ; *ofs ; ofs++)
1294: {
1295: if (*ofs == '/')
1.1.1.3 ! root 1296: { // create the directory
1.1 root 1297: *ofs = 0;
1298: Sys_mkdir (path);
1299: *ofs = '/';
1300: }
1301: }
1302: }
1303:
1304:
1305: /*
1306: ===========
1307: COM_CopyFile
1308:
1309: Copies a file over from the net to the local cache, creating any directories
1310: needed. This is for the convenience of developers using ISDN from home.
1311: ===========
1312: */
1313: void COM_CopyFile (char *netpath, char *cachepath)
1314: {
1.1.1.3 ! root 1315: int in, out;
! 1316: int remaining, count;
! 1317: char buf[4096];
1.1 root 1318:
1.1.1.3 ! root 1319: remaining = Sys_FileOpenRead (netpath, &in);
! 1320: COM_CreatePath (cachepath); // create directories up to the cache file
1.1 root 1321: out = Sys_FileOpenWrite (cachepath);
1322:
1323: while (remaining)
1324: {
1325: if (remaining < sizeof(buf))
1326: count = remaining;
1327: else
1328: count = sizeof(buf);
1329: Sys_FileRead (in, buf, count);
1330: Sys_FileWrite (out, buf, count);
1331: remaining -= count;
1332: }
1333:
1334: Sys_FileClose (in);
1.1.1.3 ! root 1335: Sys_FileClose (out);
1.1 root 1336: }
1337:
1338: /*
1339: ===========
1340: COM_FindFile
1341:
1342: Finds the file in the search path.
1343: Sets com_filesize and one of handle or file
1344: ===========
1345: */
1346: int COM_FindFile (char *filename, int *handle, FILE **file)
1347: {
1.1.1.3 ! root 1348: searchpath_t *search;
! 1349: char netpath[MAX_OSPATH];
! 1350: char cachepath[MAX_OSPATH];
! 1351: pack_t *pak;
! 1352: int i;
! 1353: int findtime, cachetime;
1.1 root 1354:
1355: if (file && handle)
1356: Sys_Error ("COM_FindFile: both handle and file set");
1357: if (!file && !handle)
1358: Sys_Error ("COM_FindFile: neither handle or file set");
1359:
1360: //
1361: // search through the path, one element at a time
1362: //
1.1.1.3 ! root 1363: search = com_searchpaths;
! 1364: if (proghack)
! 1365: { // gross hack to use quake 1 progs with quake 2 maps
! 1366: if (!strcmp(filename, "progs.dat"))
! 1367: search = search->next;
! 1368: }
! 1369:
! 1370: for ( ; search ; search = search->next)
1.1 root 1371: {
1372: // is the element a pak file?
1373: if (search->pack)
1374: {
1375: // look through all the pak file elements
1376: pak = search->pack;
1377: for (i=0 ; i<pak->numfiles ; i++)
1378: if (!strcmp (pak->files[i].name, filename))
1.1.1.3 ! root 1379: { // found it!
1.1 root 1380: Sys_Printf ("PackFile: %s : %s\n",pak->filename, filename);
1381: if (handle)
1382: {
1383: *handle = pak->handle;
1384: Sys_FileSeek (pak->handle, pak->files[i].filepos);
1385: }
1386: else
1.1.1.3 ! root 1387: { // open a new file on the pakfile
1.1 root 1388: *file = fopen (pak->filename, "rb");
1389: if (*file)
1390: fseek (*file, pak->files[i].filepos, SEEK_SET);
1391: }
1392: com_filesize = pak->files[i].filelen;
1393: return com_filesize;
1394: }
1395: }
1396: else
1.1.1.3 ! root 1397: {
1.1 root 1398: // check a file in the directory tree
1399: if (!static_registered)
1.1.1.3 ! root 1400: { // if not a registered version, don't ever go beyond base
1.1 root 1401: if ( strchr (filename, '/') || strchr (filename,'\\'))
1402: continue;
1403: }
1404:
1405: sprintf (netpath, "%s/%s",search->filename, filename);
1406:
1407: findtime = Sys_FileTime (netpath);
1408: if (findtime == -1)
1409: continue;
1410:
1411: // see if the file needs to be updated in the cache
1412: if (!com_cachedir[0])
1413: strcpy (cachepath, netpath);
1414: else
1415: {
1.1.1.3 ! root 1416: #if defined(_WIN32)
! 1417: if ((strlen(netpath) < 2) || (netpath[1] != ':'))
! 1418: sprintf (cachepath,"%s%s", com_cachedir, netpath);
! 1419: else
! 1420: sprintf (cachepath,"%s%s", com_cachedir, netpath+2);
! 1421: #else
! 1422: sprintf (cachepath,"%s%s", com_cachedir, netpath);
! 1423: #endif
! 1424:
1.1 root 1425: cachetime = Sys_FileTime (cachepath);
1426:
1427: if (cachetime < findtime)
1428: COM_CopyFile (netpath, cachepath);
1429: strcpy (netpath, cachepath);
1430: }
1431:
1432: Sys_Printf ("FindFile: %s\n",netpath);
1433: com_filesize = Sys_FileOpenRead (netpath, &i);
1434: if (handle)
1435: *handle = i;
1436: else
1437: {
1438: Sys_FileClose (i);
1439: *file = fopen (netpath, "rb");
1440: }
1441: return com_filesize;
1442: }
1443:
1444: }
1445:
1446: Sys_Printf ("FindFile: can't find %s\n", filename);
1447:
1448: if (handle)
1449: *handle = -1;
1450: else
1451: *file = NULL;
1452: com_filesize = -1;
1453: return -1;
1454: }
1455:
1456:
1457: /*
1458: ===========
1459: COM_OpenFile
1460:
1461: filename never has a leading slash, but may contain directory walks
1462: returns a handle and a length
1463: it may actually be inside a pak file
1464: ===========
1465: */
1466: int COM_OpenFile (char *filename, int *handle)
1467: {
1468: return COM_FindFile (filename, handle, NULL);
1469: }
1470:
1471: /*
1472: ===========
1473: COM_FOpenFile
1474:
1475: If the requested file is inside a packfile, a new FILE * will be opened
1476: into the file.
1477: ===========
1478: */
1479: int COM_FOpenFile (char *filename, FILE **file)
1480: {
1481: return COM_FindFile (filename, NULL, file);
1482: }
1483:
1484: /*
1485: ============
1486: COM_CloseFile
1487:
1488: If it is a pak file handle, don't really close it
1489: ============
1490: */
1491: void COM_CloseFile (int h)
1492: {
1.1.1.3 ! root 1493: searchpath_t *s;
1.1 root 1494:
1495: for (s = com_searchpaths ; s ; s=s->next)
1496: if (s->pack && s->pack->handle == h)
1497: return;
1498:
1499: Sys_FileClose (h);
1500: }
1501:
1502:
1503: /*
1504: ============
1505: COM_LoadFile
1506:
1507: Filename are reletive to the quake directory.
1508: Allways appends a 0 byte.
1509: ============
1510: */
1511: cache_user_t *loadcache;
1.1.1.3 ! root 1512: byte *loadbuf;
! 1513: int loadsize;
1.1 root 1514: byte *COM_LoadFile (char *path, int usehunk)
1515: {
1.1.1.3 ! root 1516: int h;
! 1517: byte *buf;
! 1518: char base[32];
! 1519: int len;
1.1 root 1520:
1.1.1.3 ! root 1521: buf = NULL; // quiet compiler warning
1.1 root 1522:
1523: // look for it in the filesystem or pack files
1524: len = COM_OpenFile (path, &h);
1525: if (h == -1)
1526: return NULL;
1527:
1528: // extract the filename base name for hunk tag
1529: COM_FileBase (path, base);
1530:
1531: if (usehunk == 1)
1532: buf = Hunk_AllocName (len+1, base);
1533: else if (usehunk == 2)
1534: buf = Hunk_TempAlloc (len+1);
1535: else if (usehunk == 0)
1536: buf = Z_Malloc (len+1);
1537: else if (usehunk == 3)
1538: buf = Cache_Alloc (loadcache, len+1, base);
1539: else if (usehunk == 4)
1540: {
1541: if (len+1 > loadsize)
1542: buf = Hunk_TempAlloc (len+1);
1543: else
1544: buf = loadbuf;
1545: }
1546: else
1547: Sys_Error ("COM_LoadFile: bad usehunk");
1548:
1549: if (!buf)
1550: Sys_Error ("COM_LoadFile: not enough space for %s", path);
1551:
1552: ((byte *)buf)[len] = 0;
1553:
1554: Draw_BeginDisc ();
1.1.1.3 ! root 1555: Sys_FileRead (h, buf, len);
1.1 root 1556: COM_CloseFile (h);
1557: Draw_EndDisc ();
1558:
1559: return buf;
1560: }
1561:
1562: byte *COM_LoadHunkFile (char *path)
1563: {
1564: return COM_LoadFile (path, 1);
1565: }
1566:
1567: byte *COM_LoadTempFile (char *path)
1568: {
1569: return COM_LoadFile (path, 2);
1570: }
1571:
1572: void COM_LoadCacheFile (char *path, struct cache_user_s *cu)
1573: {
1574: loadcache = cu;
1575: COM_LoadFile (path, 3);
1576: }
1577:
1578: // uses temp hunk if larger than bufsize
1579: byte *COM_LoadStackFile (char *path, void *buffer, int bufsize)
1580: {
1.1.1.3 ! root 1581: byte *buf;
1.1 root 1582:
1583: loadbuf = (byte *)buffer;
1584: loadsize = bufsize;
1585: buf = COM_LoadFile (path, 4);
1586:
1587: return buf;
1588: }
1589:
1590: /*
1591: =================
1592: COM_LoadPackFile
1593:
1594: Takes an explicit (not game tree related) path to a pak file.
1595:
1596: Loads the header and directory, adding the files at the beginning
1597: of the list so they override previous pack files.
1598: =================
1599: */
1600: pack_t *COM_LoadPackFile (char *packfile)
1601: {
1.1.1.3 ! root 1602: dpackheader_t header;
! 1603: int i;
! 1604: packfile_t *newfiles;
! 1605: int numpackfiles;
! 1606: pack_t *pack;
! 1607: int packhandle;
! 1608: dpackfile_t info[MAX_FILES_IN_PACK];
! 1609: unsigned short crc;
1.1 root 1610:
1611: if (Sys_FileOpenRead (packfile, &packhandle) == -1)
1612: {
1.1.1.3 ! root 1613: // Con_Printf ("Couldn't open %s\n", packfile);
1.1 root 1614: return NULL;
1615: }
1616: Sys_FileRead (packhandle, (void *)&header, sizeof(header));
1617: if (header.id[0] != 'P' || header.id[1] != 'A'
1618: || header.id[2] != 'C' || header.id[3] != 'K')
1619: Sys_Error ("%s is not a packfile", packfile);
1620: header.dirofs = LittleLong (header.dirofs);
1621: header.dirlen = LittleLong (header.dirlen);
1622:
1623: numpackfiles = header.dirlen / sizeof(dpackfile_t);
1624:
1625: if (numpackfiles > MAX_FILES_IN_PACK)
1626: Sys_Error ("%s has %i files", packfile, numpackfiles);
1627:
1628: if (numpackfiles != PAK0_COUNT)
1.1.1.3 ! root 1629: com_modified = true; // not the original file
1.1 root 1630:
1631: newfiles = Hunk_AllocName (numpackfiles * sizeof(packfile_t), "packfile");
1632:
1633: Sys_FileSeek (packhandle, header.dirofs);
1634: Sys_FileRead (packhandle, (void *)info, header.dirlen);
1635:
1636: // crc the directory to check for modifications
1637: CRC_Init (&crc);
1638: for (i=0 ; i<header.dirlen ; i++)
1639: CRC_ProcessByte (&crc, ((byte *)info)[i]);
1640: if (crc != PAK0_CRC)
1641: com_modified = true;
1642:
1643: // parse the directory
1644: for (i=0 ; i<numpackfiles ; i++)
1645: {
1646: strcpy (newfiles[i].name, info[i].name);
1647: newfiles[i].filepos = LittleLong(info[i].filepos);
1648: newfiles[i].filelen = LittleLong(info[i].filelen);
1649: }
1650:
1651: pack = Hunk_Alloc (sizeof (pack_t));
1652: strcpy (pack->filename, packfile);
1653: pack->handle = packhandle;
1654: pack->numfiles = numpackfiles;
1655: pack->files = newfiles;
1656:
1657: Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles);
1658: return pack;
1659: }
1660:
1661:
1662: /*
1663: ================
1664: COM_AddGameDirectory
1665:
1666: Sets com_gamedir, adds the directory to the head of the path,
1667: then loads and adds pak1.pak pak2.pak ...
1668: ================
1669: */
1670: void COM_AddGameDirectory (char *dir)
1671: {
1.1.1.3 ! root 1672: int i;
! 1673: searchpath_t *search;
! 1674: pack_t *pak;
! 1675: char pakfile[MAX_OSPATH];
1.1 root 1676:
1677: strcpy (com_gamedir, dir);
1678:
1679: //
1680: // add the directory to the search path
1681: //
1682: search = Hunk_Alloc (sizeof(searchpath_t));
1683: strcpy (search->filename, dir);
1684: search->next = com_searchpaths;
1685: com_searchpaths = search;
1686:
1687: //
1688: // add any pak files in the format pak0.pak pak1.pak, ...
1689: //
1690: for (i=0 ; ; i++)
1691: {
1692: sprintf (pakfile, "%s/pak%i.pak", dir, i);
1693: pak = COM_LoadPackFile (pakfile);
1694: if (!pak)
1695: break;
1696: search = Hunk_Alloc (sizeof(searchpath_t));
1697: search->pack = pak;
1698: search->next = com_searchpaths;
1.1.1.3 ! root 1699: com_searchpaths = search;
1.1 root 1700: }
1701:
1702: //
1703: // add the contents of the parms.txt file to the end of the command line
1704: //
1705:
1706: }
1707:
1708: /*
1709: ================
1710: COM_InitFilesystem
1711: ================
1712: */
1713: void COM_InitFilesystem (void)
1714: {
1.1.1.3 ! root 1715: int i, j;
! 1716: char basedir[MAX_OSPATH];
! 1717: searchpath_t *search;
1.1 root 1718:
1719: //
1720: // -basedir <path>
1.1.1.3 ! root 1721: // Overrides the system supplied base directory (under GAMENAME)
1.1 root 1722: //
1723: i = COM_CheckParm ("-basedir");
1724: if (i && i < com_argc-1)
1725: strcpy (basedir, com_argv[i+1]);
1726: else
1727: strcpy (basedir, host_parms.basedir);
1728:
1.1.1.3 ! root 1729: j = strlen (basedir);
! 1730:
! 1731: if (j > 0)
! 1732: {
! 1733: if ((basedir[j-1] == '\\') || (basedir[j-1] == '/'))
! 1734: basedir[j-1] = 0;
! 1735: }
! 1736:
1.1 root 1737: //
1738: // -cachedir <path>
1739: // Overrides the system supplied cache directory (NULL or /qcache)
1740: // -cachedir - will disable caching.
1741: //
1742: i = COM_CheckParm ("-cachedir");
1743: if (i && i < com_argc-1)
1744: {
1745: if (com_argv[i+1][0] == '-')
1746: com_cachedir[0] = 0;
1747: else
1748: strcpy (com_cachedir, com_argv[i+1]);
1749: }
1750: else if (host_parms.cachedir)
1751: strcpy (com_cachedir, host_parms.cachedir);
1752: else
1753: com_cachedir[0] = 0;
1754:
1755: //
1.1.1.3 ! root 1756: // start up with GAMENAME by default (id1)
1.1 root 1757: //
1.1.1.3 ! root 1758: COM_AddGameDirectory (va("%s/"GAMENAME, basedir) );
! 1759:
! 1760: if (COM_CheckParm ("-rogue"))
! 1761: COM_AddGameDirectory (va("%s/rogue", basedir) );
! 1762: if (COM_CheckParm ("-hipnotic"))
! 1763: COM_AddGameDirectory (va("%s/hipnotic", basedir) );
1.1 root 1764:
1765: //
1766: // -game <gamedir>
1767: // Adds basedir/gamedir as an override game
1768: //
1769: i = COM_CheckParm ("-game");
1770: if (i && i < com_argc-1)
1771: {
1772: com_modified = true;
1773: COM_AddGameDirectory (va("%s/%s", basedir, com_argv[i+1]));
1774: }
1775:
1776: //
1777: // -path <dir or packfile> [<dir or packfile>] ...
1778: // Fully specifies the exact serach path, overriding the generated one
1779: //
1780: i = COM_CheckParm ("-path");
1781: if (i)
1782: {
1783: com_modified = true;
1784: com_searchpaths = NULL;
1785: while (++i < com_argc)
1786: {
1787: if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-')
1788: break;
1789:
1790: search = Hunk_Alloc (sizeof(searchpath_t));
1791: if ( !strcmp(COM_FileExtension(com_argv[i]), "pak") )
1792: {
1793: search->pack = COM_LoadPackFile (com_argv[i]);
1794: if (!search->pack)
1795: Sys_Error ("Couldn't load packfile: %s", com_argv[i]);
1796: }
1797: else
1798: strcpy (search->filename, com_argv[i]);
1799: search->next = com_searchpaths;
1800: com_searchpaths = search;
1801: }
1802: }
1.1.1.3 ! root 1803:
! 1804: if (COM_CheckParm ("-proghack"))
! 1805: proghack = true;
1.1 root 1806: }
1807:
1808:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.