1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4
5 This file is part of Quake III Arena source code.
6
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22 // cmdlib.c
23
24 #include "cmdlib.h"
25 #include <sys/types.h>
26 #include <sys/stat.h>
27
28 #ifdef WIN32
29 #include <direct.h>
30 #include <windows.h>
31 #elif defined(NeXT)
32 #include <libc.h>
33 #else
34 #include <unistd.h>
35 #endif
36
37 #define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
38 #define PATHSEPERATOR '/'
39
40 // set these before calling CheckParm
41 int myargc;
42 char **myargv;
43
44 char com_token[1024];
45 qboolean com_eof;
46
47 qboolean archive;
48 char archivedir[1024];
49
50
51 /*
52 ===================
53 ExpandWildcards
54
55 Mimic unix command line expansion
56 ===================
57 */
58 #define MAX_EX_ARGC 1024
59 int ex_argc;
60 char *ex_argv[MAX_EX_ARGC];
61 #ifdef _WIN32
62 #include "io.h"
ExpandWildcards(int * argc,char *** argv)63 void ExpandWildcards( int *argc, char ***argv )
64 {
65 struct _finddata_t fileinfo;
66 int handle;
67 int i;
68 char filename[1024];
69 char filebase[1024];
70 char *path;
71
72 ex_argc = 0;
73 for (i=0 ; i<*argc ; i++)
74 {
75 path = (*argv)[i];
76 if ( path[0] == '-'
77 || ( !strstr(path, "*") && !strstr(path, "?") ) )
78 {
79 ex_argv[ex_argc++] = path;
80 continue;
81 }
82
83 handle = _findfirst (path, &fileinfo);
84 if (handle == -1)
85 return;
86
87 ExtractFilePath (path, filebase);
88
89 do
90 {
91 sprintf (filename, "%s%s", filebase, fileinfo.name);
92 ex_argv[ex_argc++] = copystring (filename);
93 } while (_findnext( handle, &fileinfo ) != -1);
94
95 _findclose (handle);
96 }
97
98 *argc = ex_argc;
99 *argv = ex_argv;
100 }
101 #else
ExpandWildcards(int * argc,char *** argv)102 void ExpandWildcards (int *argc, char ***argv)
103 {
104 }
105 #endif
106
107 #ifdef WIN_ERROR
108 #include <windows.h>
109 /*
110 =================
111 Error
112
113 For abnormal program terminations in windowed apps
114 =================
115 */
Error(const char * error,...)116 void Error( const char *error, ... )
117 {
118 va_list argptr;
119 char text[1024];
120 char text2[1024];
121 int err;
122
123 err = GetLastError ();
124
125 va_start (argptr,error);
126 vsprintf (text, error,argptr);
127 va_end (argptr);
128
129 sprintf (text2, "%s\nGetLastError() = %i", text, err);
130 MessageBox(NULL, text2, "Error", 0 /* MB_OK */ );
131
132 exit (1);
133 }
134
135 #else
136 /*
137 =================
138 Error
139
140 For abnormal program terminations in console apps
141 =================
142 */
Error(const char * error,...)143 void Error( const char *error, ...)
144 {
145 va_list argptr;
146
147 _printf ("\n************ ERROR ************\n");
148
149 va_start (argptr,error);
150 vprintf (error,argptr);
151 va_end (argptr);
152 _printf ("\r\n");
153
154 exit (1);
155 }
156 #endif
157
158 // only printf if in verbose mode
159 qboolean verbose = qfalse;
qprintf(const char * format,...)160 void qprintf( const char *format, ... ) {
161 va_list argptr;
162
163 if (!verbose)
164 return;
165
166 va_start (argptr,format);
167 vprintf (format,argptr);
168 va_end (argptr);
169
170 }
171
172 #ifdef WIN32
173 HWND hwndOut = NULL;
174 qboolean lookedForServer = qfalse;
175 UINT wm_BroadcastCommand = -1;
176 #endif
177
_printf(const char * format,...)178 void _printf( const char *format, ... ) {
179 va_list argptr;
180 char text[4096];
181 #ifdef WIN32
182 ATOM a;
183 #endif
184 va_start (argptr,format);
185 vsprintf (text, format, argptr);
186 va_end (argptr);
187
188 printf(text);
189
190 #ifdef WIN32
191 if (!lookedForServer) {
192 lookedForServer = qtrue;
193 hwndOut = FindWindow(NULL, "Q3Map Process Server");
194 if (hwndOut) {
195 wm_BroadcastCommand = RegisterWindowMessage( "Q3MPS_BroadcastCommand" );
196 }
197 }
198 if (hwndOut) {
199 a = GlobalAddAtom(text);
200 PostMessage(hwndOut, wm_BroadcastCommand, 0, (LPARAM)a);
201 }
202 #endif
203 }
204
205
206 /*
207
208 qdir will hold the path up to the quake directory, including the slash
209
210 f:\quake\
211 /raid/quake/
212
213 gamedir will hold qdir + the game directory (id1, id2, etc)
214
215 */
216
217 char qdir[1024];
218 char gamedir[1024];
219 char writedir[1024];
220
SetQdirFromPath(const char * path)221 void SetQdirFromPath( const char *path )
222 {
223 char temp[1024];
224 const char *c;
225 const char *sep;
226 int len, count;
227
228 if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
229 { // path is partial
230 Q_getwd (temp);
231 strcat (temp, path);
232 path = temp;
233 }
234
235 // search for "quake2" in path
236
237 len = strlen(BASEDIRNAME);
238 for (c=path+strlen(path)-1 ; c != path ; c--)
239 {
240 int i;
241
242 if (!Q_strncasecmp (c, BASEDIRNAME, len))
243 {
244 //
245 //strncpy (qdir, path, c+len+2-path);
246 // the +2 assumes a 2 or 3 following quake which is not the
247 // case with a retail install
248 // so we need to add up how much to the next separator
249 sep = c + len;
250 count = 1;
251 while (*sep && *sep != '/' && *sep != '\\')
252 {
253 sep++;
254 count++;
255 }
256 strncpy (qdir, path, c+len+count-path);
257 qprintf ("qdir: %s\n", qdir);
258 for ( i = 0; i < strlen( qdir ); i++ )
259 {
260 if ( qdir[i] == '\\' )
261 qdir[i] = '/';
262 }
263
264 c += len+count;
265 while (*c)
266 {
267 if (*c == '/' || *c == '\\')
268 {
269 strncpy (gamedir, path, c+1-path);
270
271 for ( i = 0; i < strlen( gamedir ); i++ )
272 {
273 if ( gamedir[i] == '\\' )
274 gamedir[i] = '/';
275 }
276
277 qprintf ("gamedir: %s\n", gamedir);
278
279 if ( !writedir[0] )
280 strcpy( writedir, gamedir );
281 else if ( writedir[strlen( writedir )-1] != '/' )
282 {
283 writedir[strlen( writedir )] = '/';
284 writedir[strlen( writedir )+1] = 0;
285 }
286
287 return;
288 }
289 c++;
290 }
291 Error ("No gamedir in %s", path);
292 return;
293 }
294 }
295 Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
296 }
297
ExpandArg(const char * path)298 char *ExpandArg (const char *path)
299 {
300 static char full[1024];
301
302 if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
303 {
304 Q_getwd (full);
305 strcat (full, path);
306 }
307 else
308 strcpy (full, path);
309 return full;
310 }
311
ExpandPath(const char * path)312 char *ExpandPath (const char *path)
313 {
314 static char full[1024];
315 if (!qdir[0])
316 Error ("ExpandPath called without qdir set");
317 if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
318 strcpy( full, path );
319 return full;
320 }
321 sprintf (full, "%s%s", qdir, path);
322 return full;
323 }
324
ExpandGamePath(const char * path)325 char *ExpandGamePath (const char *path)
326 {
327 static char full[1024];
328 if (!qdir[0])
329 Error ("ExpandGamePath called without qdir set");
330 if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
331 strcpy( full, path );
332 return full;
333 }
334 sprintf (full, "%s%s", gamedir, path);
335 return full;
336 }
337
ExpandPathAndArchive(const char * path)338 char *ExpandPathAndArchive (const char *path)
339 {
340 char *expanded;
341 char archivename[1024];
342
343 expanded = ExpandPath (path);
344
345 if (archive)
346 {
347 sprintf (archivename, "%s/%s", archivedir, path);
348 QCopyFile (expanded, archivename);
349 }
350 return expanded;
351 }
352
353
copystring(const char * s)354 char *copystring(const char *s)
355 {
356 char *b;
357 b = malloc(strlen(s)+1);
358 strcpy (b, s);
359 return b;
360 }
361
362
363
364 /*
365 ================
366 I_FloatTime
367 ================
368 */
I_FloatTime(void)369 double I_FloatTime (void)
370 {
371 time_t t;
372
373 time (&t);
374
375 return t;
376 #if 0
377 // more precise, less portable
378 struct timeval tp;
379 struct timezone tzp;
380 static int secbase;
381
382 gettimeofday(&tp, &tzp);
383
384 if (!secbase)
385 {
386 secbase = tp.tv_sec;
387 return tp.tv_usec/1000000.0;
388 }
389
390 return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
391 #endif
392 }
393
Q_getwd(char * out)394 void Q_getwd (char *out)
395 {
396 int i = 0;
397
398 #ifdef WIN32
399 _getcwd (out, 256);
400 strcat (out, "\\");
401 #else
402 getcwd (out, 256);
403 strcat (out, "/");
404 #endif
405
406 while ( out[i] != 0 )
407 {
408 if ( out[i] == '\\' )
409 out[i] = '/';
410 i++;
411 }
412 }
413
414
Q_mkdir(const char * path)415 void Q_mkdir (const char *path)
416 {
417 #ifdef WIN32
418 if (_mkdir (path) != -1)
419 return;
420 #else
421 if (mkdir (path, 0777) != -1)
422 return;
423 #endif
424 if (errno != EEXIST)
425 Error ("mkdir %s: %s",path, strerror(errno));
426 }
427
428 /*
429 ============
430 FileTime
431
432 returns -1 if not present
433 ============
434 */
FileTime(const char * path)435 int FileTime (const char *path)
436 {
437 struct stat buf;
438
439 if (stat (path,&buf) == -1)
440 return -1;
441
442 return buf.st_mtime;
443 }
444
445
446
447 /*
448 ==============
449 COM_Parse
450
451 Parse a token out of a string
452 ==============
453 */
COM_Parse(char * data)454 char *COM_Parse (char *data)
455 {
456 int c;
457 int len;
458
459 len = 0;
460 com_token[0] = 0;
461
462 if (!data)
463 return NULL;
464
465 // skip whitespace
466 skipwhite:
467 while ( (c = *data) <= ' ')
468 {
469 if (c == 0)
470 {
471 com_eof = qtrue;
472 return NULL; // end of file;
473 }
474 data++;
475 }
476
477 // skip // comments
478 if (c=='/' && data[1] == '/')
479 {
480 while (*data && *data != '\n')
481 data++;
482 goto skipwhite;
483 }
484
485
486 // handle quoted strings specially
487 if (c == '\"')
488 {
489 data++;
490 do
491 {
492 c = *data++;
493 if (c=='\"')
494 {
495 com_token[len] = 0;
496 return data;
497 }
498 com_token[len] = c;
499 len++;
500 } while (1);
501 }
502
503 // parse single characters
504 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
505 {
506 com_token[len] = c;
507 len++;
508 com_token[len] = 0;
509 return data+1;
510 }
511
512 // parse a regular word
513 do
514 {
515 com_token[len] = c;
516 data++;
517 len++;
518 c = *data;
519 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
520 break;
521 } while (c>32);
522
523 com_token[len] = 0;
524 return data;
525 }
526
527
Q_strncasecmp(const char * s1,const char * s2,int n)528 int Q_strncasecmp (const char *s1, const char *s2, int n)
529 {
530 int c1, c2;
531
532 do
533 {
534 c1 = *s1++;
535 c2 = *s2++;
536
537 if (!n--)
538 return 0; // strings are equal until end point
539
540 if (c1 != c2)
541 {
542 if (c1 >= 'a' && c1 <= 'z')
543 c1 -= ('a' - 'A');
544 if (c2 >= 'a' && c2 <= 'z')
545 c2 -= ('a' - 'A');
546 if (c1 != c2)
547 return -1; // strings not equal
548 }
549 } while (c1);
550
551 return 0; // strings are equal
552 }
553
Q_stricmp(const char * s1,const char * s2)554 int Q_stricmp (const char *s1, const char *s2)
555 {
556 return Q_strncasecmp (s1, s2, 99999);
557 }
558
559
strupr(char * start)560 char *strupr (char *start)
561 {
562 char *in;
563 in = start;
564 while (*in)
565 {
566 *in = toupper(*in);
567 in++;
568 }
569 return start;
570 }
571
strlower(char * start)572 char *strlower (char *start)
573 {
574 char *in;
575 in = start;
576 while (*in)
577 {
578 *in = tolower(*in);
579 in++;
580 }
581 return start;
582 }
583
584
585 /*
586 =============================================================================
587
588 MISC FUNCTIONS
589
590 =============================================================================
591 */
592
593
594 /*
595 =================
596 CheckParm
597
598 Checks for the given parameter in the program's command line arguments
599 Returns the argument number (1 to argc-1) or 0 if not present
600 =================
601 */
CheckParm(const char * check)602 int CheckParm (const char *check)
603 {
604 int i;
605
606 for (i = 1;i<myargc;i++)
607 {
608 if ( !Q_stricmp(check, myargv[i]) )
609 return i;
610 }
611
612 return 0;
613 }
614
615
616
617 /*
618 ================
619 Q_filelength
620 ================
621 */
Q_filelength(FILE * f)622 int Q_filelength (FILE *f)
623 {
624 int pos;
625 int end;
626
627 pos = ftell (f);
628 fseek (f, 0, SEEK_END);
629 end = ftell (f);
630 fseek (f, pos, SEEK_SET);
631
632 return end;
633 }
634
635 #ifdef MAX_PATH
636 #undef MAX_PATH
637 #endif
638 #define MAX_PATH 4096
myfopen(const char * filename,const char * mode)639 static FILE* myfopen(const char* filename, const char* mode)
640 {
641 char* p;
642 char fn[MAX_PATH];
643
644 fn[0] = '\0';
645 strncat(fn, filename, sizeof(fn)-1);
646
647 for(p=fn;*p;++p) if(*p == '\\') *p = '/';
648
649 return fopen(fn, mode);
650 }
651
652
SafeOpenWrite(const char * filename)653 FILE *SafeOpenWrite (const char *filename)
654 {
655 FILE *f;
656
657 f = myfopen(filename, "wb");
658
659 if (!f)
660 Error ("Error opening %s: %s",filename,strerror(errno));
661
662 return f;
663 }
664
SafeOpenRead(const char * filename)665 FILE *SafeOpenRead (const char *filename)
666 {
667 FILE *f;
668
669 f = myfopen(filename, "rb");
670
671 if (!f)
672 Error ("Error opening %s: %s",filename,strerror(errno));
673
674 return f;
675 }
676
677
SafeRead(FILE * f,void * buffer,int count)678 void SafeRead (FILE *f, void *buffer, int count)
679 {
680 if ( fread (buffer, 1, count, f) != (size_t)count)
681 Error ("File read failure");
682 }
683
684
SafeWrite(FILE * f,const void * buffer,int count)685 void SafeWrite (FILE *f, const void *buffer, int count)
686 {
687 if (fwrite (buffer, 1, count, f) != (size_t)count)
688 Error ("File write failure");
689 }
690
691
692 /*
693 ==============
694 FileExists
695 ==============
696 */
FileExists(const char * filename)697 qboolean FileExists (const char *filename)
698 {
699 FILE *f;
700
701 f = myfopen (filename, "r");
702 if (!f)
703 return qfalse;
704 fclose (f);
705 return qtrue;
706 }
707
708 /*
709 ==============
710 LoadFile
711 ==============
712 */
LoadFile(const char * filename,void ** bufferptr)713 int LoadFile( const char *filename, void **bufferptr )
714 {
715 FILE *f;
716 int length;
717 void *buffer;
718
719 f = SafeOpenRead (filename);
720 length = Q_filelength (f);
721 buffer = malloc (length+1);
722 ((char *)buffer)[length] = 0;
723 SafeRead (f, buffer, length);
724 fclose (f);
725
726 *bufferptr = buffer;
727 return length;
728 }
729
730
731 /*
732 ==============
733 LoadFileBlock
734 -
735 rounds up memory allocation to 4K boundry
736 -
737 ==============
738 */
LoadFileBlock(const char * filename,void ** bufferptr)739 int LoadFileBlock( const char *filename, void **bufferptr )
740 {
741 FILE *f;
742 int length, nBlock, nAllocSize;
743 void *buffer;
744
745 f = SafeOpenRead (filename);
746 length = Q_filelength (f);
747 nAllocSize = length;
748 nBlock = nAllocSize % MEM_BLOCKSIZE;
749 if ( nBlock > 0) {
750 nAllocSize += MEM_BLOCKSIZE - nBlock;
751 }
752 buffer = malloc (nAllocSize+1);
753 memset(buffer, 0, nAllocSize+1);
754 SafeRead (f, buffer, length);
755 fclose (f);
756
757 *bufferptr = buffer;
758 return length;
759 }
760
761
762 /*
763 ==============
764 TryLoadFile
765
766 Allows failure
767 ==============
768 */
TryLoadFile(const char * filename,void ** bufferptr)769 int TryLoadFile (const char *filename, void **bufferptr)
770 {
771 FILE *f;
772 int length;
773 void *buffer;
774
775 *bufferptr = NULL;
776
777 f = myfopen (filename, "rb");
778 if (!f)
779 return -1;
780 length = Q_filelength (f);
781 buffer = malloc (length+1);
782 ((char *)buffer)[length] = 0;
783 SafeRead (f, buffer, length);
784 fclose (f);
785
786 *bufferptr = buffer;
787 return length;
788 }
789
790
791 /*
792 ==============
793 SaveFile
794 ==============
795 */
SaveFile(const char * filename,const void * buffer,int count)796 void SaveFile (const char *filename, const void *buffer, int count)
797 {
798 FILE *f;
799
800 f = SafeOpenWrite (filename);
801 SafeWrite (f, buffer, count);
802 fclose (f);
803 }
804
805
806
DefaultExtension(char * path,const char * extension)807 void DefaultExtension (char *path, const char *extension)
808 {
809 char *src;
810 //
811 // if path doesnt have a .EXT, append extension
812 // (extension should include the .)
813 //
814 src = path + strlen(path) - 1;
815
816 while (*src != '/' && *src != '\\' && src != path)
817 {
818 if (*src == '.')
819 return; // it has an extension
820 src--;
821 }
822
823 strcat (path, extension);
824 }
825
826
DefaultPath(char * path,const char * basepath)827 void DefaultPath (char *path, const char *basepath)
828 {
829 char temp[128];
830
831 if (path[0] == PATHSEPERATOR)
832 return; // absolute path location
833 strcpy (temp,path);
834 strcpy (path,basepath);
835 strcat (path,temp);
836 }
837
838
StripFilename(char * path)839 void StripFilename (char *path)
840 {
841 int length;
842
843 length = strlen(path)-1;
844 while (length > 0 && path[length] != PATHSEPERATOR)
845 length--;
846 path[length] = 0;
847 }
848
StripExtension(char * path)849 void StripExtension (char *path)
850 {
851 int length;
852
853 length = strlen(path)-1;
854 while (length > 0 && path[length] != '.')
855 {
856 length--;
857 if (path[length] == '/')
858 return; // no extension
859 }
860 if (length)
861 path[length] = 0;
862 }
863
864
865 /*
866 ====================
867 Extract file parts
868 ====================
869 */
870 // FIXME: should include the slash, otherwise
871 // backing to an empty path will be wrong when appending a slash
ExtractFilePath(const char * path,char * dest)872 void ExtractFilePath (const char *path, char *dest)
873 {
874 const char *src;
875
876 src = path + strlen(path) - 1;
877
878 //
879 // back up until a \ or the start
880 //
881 while (src != path && *(src-1) != '\\' && *(src-1) != '/')
882 src--;
883
884 memcpy (dest, path, src-path);
885 dest[src-path] = 0;
886 }
887
ExtractFileBase(const char * path,char * dest)888 void ExtractFileBase (const char *path, char *dest)
889 {
890 const char *src;
891
892 src = path + strlen(path) - 1;
893
894 //
895 // back up until a \ or the start
896 //
897 while (src != path && *(src-1) != PATHSEPERATOR)
898 src--;
899
900 while (*src && *src != '.')
901 {
902 *dest++ = *src++;
903 }
904 *dest = 0;
905 }
906
ExtractFileExtension(const char * path,char * dest)907 void ExtractFileExtension (const char *path, char *dest)
908 {
909 const char *src;
910
911 src = path + strlen(path) - 1;
912
913 //
914 // back up until a . or the start
915 //
916 while (src != path && *(src-1) != '.')
917 src--;
918 if (src == path)
919 {
920 *dest = 0; // no extension
921 return;
922 }
923
924 strcpy (dest,src);
925 }
926
927
928 /*
929 ==============
930 ParseNum / ParseHex
931 ==============
932 */
ParseHex(const char * hex)933 int ParseHex (const char *hex)
934 {
935 const char *str;
936 int num;
937
938 num = 0;
939 str = hex;
940
941 while (*str)
942 {
943 num <<= 4;
944 if (*str >= '0' && *str <= '9')
945 num += *str-'0';
946 else if (*str >= 'a' && *str <= 'f')
947 num += 10 + *str-'a';
948 else if (*str >= 'A' && *str <= 'F')
949 num += 10 + *str-'A';
950 else
951 Error ("Bad hex number: %s",hex);
952 str++;
953 }
954
955 return num;
956 }
957
958
ParseNum(const char * str)959 int ParseNum (const char *str)
960 {
961 if (str[0] == '$')
962 return ParseHex (str+1);
963 if (str[0] == '0' && str[1] == 'x')
964 return ParseHex (str+2);
965 return atol (str);
966 }
967
968
969
970 /*
971 ============================================================================
972
973 BYTE ORDER FUNCTIONS
974
975 ============================================================================
976 */
977
ShortSwap(short l)978 short ShortSwap (short l)
979 {
980 byte b1,b2;
981
982 b1 = l&255;
983 b2 = (l>>8)&255;
984
985 return (b1<<8) + b2;
986 }
987
LongSwap(int l)988 int LongSwap (int l)
989 {
990 byte b1,b2,b3,b4;
991
992 b1 = l&255;
993 b2 = (l>>8)&255;
994 b3 = (l>>16)&255;
995 b4 = (l>>24)&255;
996
997 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
998 }
999
1000 typedef union {
1001 float f;
1002 unsigned int i;
1003 } _FloatByteUnion;
1004
FloatSwap(const float * f)1005 float FloatSwap (const float *f) {
1006 _FloatByteUnion out;
1007
1008 out.f = *f;
1009 out.i = LongSwap(out.i);
1010
1011 return out.f;
1012 }
1013
1014 //=======================================================
1015
1016
1017 // FIXME: byte swap?
1018
1019 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1020 // and the initial and final xor values shown below... in other words, the
1021 // CCITT standard CRC used by XMODEM
1022
1023 #define CRC_INIT_VALUE 0xffff
1024 #define CRC_XOR_VALUE 0x0000
1025
1026 static unsigned short crctable[256] =
1027 {
1028 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1029 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1030 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1031 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1032 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1033 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1034 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1035 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1036 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1037 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1038 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1039 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1040 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1041 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1042 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1043 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1044 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1045 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1046 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1047 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1048 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1049 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1050 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1051 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1052 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1053 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1054 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1055 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1056 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1057 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1058 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1059 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1060 };
1061
CRC_Init(unsigned short * crcvalue)1062 void CRC_Init(unsigned short *crcvalue)
1063 {
1064 *crcvalue = CRC_INIT_VALUE;
1065 }
1066
CRC_ProcessByte(unsigned short * crcvalue,byte data)1067 void CRC_ProcessByte(unsigned short *crcvalue, byte data)
1068 {
1069 *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
1070 }
1071
CRC_Value(unsigned short crcvalue)1072 unsigned short CRC_Value(unsigned short crcvalue)
1073 {
1074 return crcvalue ^ CRC_XOR_VALUE;
1075 }
1076 //=============================================================================
1077
1078 /*
1079 ============
1080 CreatePath
1081 ============
1082 */
CreatePath(const char * path)1083 void CreatePath (const char *path)
1084 {
1085 const char *ofs;
1086 char c;
1087 char dir[1024];
1088
1089 #ifdef _WIN32
1090 int olddrive = -1;
1091
1092 if ( path[1] == ':' )
1093 {
1094 olddrive = _getdrive();
1095 _chdrive( toupper( path[0] ) - 'A' + 1 );
1096 }
1097 #endif
1098
1099 if (path[1] == ':')
1100 path += 2;
1101
1102 for (ofs = path+1 ; *ofs ; ofs++)
1103 {
1104 c = *ofs;
1105 if (c == '/' || c == '\\')
1106 { // create the directory
1107 memcpy( dir, path, ofs - path );
1108 dir[ ofs - path ] = 0;
1109 Q_mkdir( dir );
1110 }
1111 }
1112
1113 #ifdef _WIN32
1114 if ( olddrive != -1 )
1115 {
1116 _chdrive( olddrive );
1117 }
1118 #endif
1119 }
1120
1121
1122 /*
1123 ============
1124 QCopyFile
1125
1126 Used to archive source files
1127 ============
1128 */
QCopyFile(const char * from,const char * to)1129 void QCopyFile (const char *from, const char *to)
1130 {
1131 void *buffer;
1132 int length;
1133
1134 length = LoadFile (from, &buffer);
1135 CreatePath (to);
1136 SaveFile (to, buffer, length);
1137 free (buffer);
1138 }
1139