]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/common/cmdlib.c
60f615a0be05692795716c7c7153798eb68b1c39
[xonotic/netradiant.git] / tools / quake2 / extra / common / cmdlib.c
1 /*
2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
4
5 This file is part of Quake 2 Tools source code.
6
7 Quake 2 Tools 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 2 Tools 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 2 Tools 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
23 // cmdlib.c
24
25 #include "cmdlib.h"
26 #include <sys/types.h>
27 #include <sys/stat.h>
28
29 #ifdef WIN32
30 #include <direct.h>
31 #endif
32
33 #ifdef NeXT
34 #include <libc.h>
35 #endif
36
37 #define BASEDIRNAME     "quake2"
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"
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
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 */
116 void Error (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 */
143 void Error (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 ("\n");
153
154         exit (1);
155 }
156 #endif
157
158 // only printf if in verbose mode
159 qboolean verbose = false;
160 void qprintf (char *format, ...)
161 {
162         va_list argptr;
163
164         if (!verbose)
165                 return;
166
167         va_start (argptr,format);
168         vprintf (format,argptr);
169         va_end (argptr);
170 }
171
172
173 /*
174
175 qdir will hold the path up to the quake directory, including the slash
176
177   f:\quake\
178   /raid/quake/
179
180 gamedir will hold qdir + the game directory (id1, id2, etc)
181
182   */
183
184 char            qdir[1024];
185 char            gamedir[1024];
186
187 void SetQdirFromPath (char *path)
188 {
189         char    temp[1024];
190         char    *c;
191         int             len;
192
193         if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
194         {       // path is partial
195                 Q_getwd (temp);
196                 strcat (temp, path);
197                 path = temp;
198         }
199
200         // search for "quake2" in path
201
202         len = strlen(BASEDIRNAME);
203         for (c=path+strlen(path)-1 ; c != path ; c--)
204                 if (!Q_strncasecmp (c, BASEDIRNAME, len))
205                 {
206                         strncpy (qdir, path, c+len+1-path);
207                         qprintf ("qdir: %s\n", qdir);
208                         c += len+1;
209                         while (*c)
210                         {
211                                 if (*c == '/' || *c == '\\')
212                                 {
213                                         strncpy (gamedir, path, c+1-path);
214                                         qprintf ("gamedir: %s\n", gamedir);
215                                         return;
216                                 }
217                                 c++;
218                         }
219                         Error ("No gamedir in %s", path);
220                         return;
221                 }
222         Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
223 }
224
225 char *ExpandArg (char *path)
226 {
227         static char full[1024];
228
229         if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
230         {
231                 Q_getwd (full);
232                 strcat (full, path);
233         }
234         else
235                 strcpy (full, path);
236         return full;
237 }
238
239 char *ExpandPath (char *path)
240 {
241         static char full[1024];
242         if (!qdir)
243                 Error ("ExpandPath called without qdir set");
244         if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
245                 return path;
246         sprintf (full, "%s%s", qdir, path);
247         return full;
248 }
249
250 char *ExpandPathAndArchive (char *path)
251 {
252         char    *expanded;
253         char    archivename[1024];
254
255         expanded = ExpandPath (path);
256
257         if (archive)
258         {
259                 sprintf (archivename, "%s/%s", archivedir, path);
260                 QCopyFile (expanded, archivename);
261         }
262         return expanded;
263 }
264
265
266 char *copystring(char *s)
267 {
268         char    *b;
269         b = malloc(strlen(s)+1);
270         strcpy (b, s);
271         return b;
272 }
273
274
275
276 /*
277 ================
278 I_FloatTime
279 ================
280 */
281 double I_FloatTime (void)
282 {
283         time_t  t;
284
285         time (&t);
286
287         return t;
288 #if 0
289 // more precise, less portable
290         struct timeval tp;
291         struct timezone tzp;
292         static int              secbase;
293
294         gettimeofday(&tp, &tzp);
295
296         if (!secbase)
297         {
298                 secbase = tp.tv_sec;
299                 return tp.tv_usec/1000000.0;
300         }
301
302         return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
303 #endif
304 }
305
306 void Q_getwd (char *out)
307 {
308 #ifdef WIN32
309    _getcwd (out, 256);
310    strcat (out, "\\");
311 #else
312    getwd (out);
313    strcat (out, "/");
314 #endif
315 }
316
317
318 void Q_mkdir (char *path)
319 {
320 #ifdef WIN32
321         if (_mkdir (path) != -1)
322                 return;
323 #else
324         if (mkdir (path, 0777) != -1)
325                 return;
326 #endif
327         if (errno != EEXIST)
328                 Error ("mkdir %s: %s",path, strerror(errno));
329 }
330
331 /*
332 ============
333 FileTime
334
335 returns -1 if not present
336 ============
337 */
338 int     FileTime (char *path)
339 {
340         struct  stat    buf;
341
342         if (stat (path,&buf) == -1)
343                 return -1;
344
345         return buf.st_mtime;
346 }
347
348
349
350 /*
351 ==============
352 COM_Parse
353
354 Parse a token out of a string
355 ==============
356 */
357 char *COM_Parse (char *data)
358 {
359         int             c;
360         int             len;
361
362         len = 0;
363         com_token[0] = 0;
364
365         if (!data)
366                 return NULL;
367
368 // skip whitespace
369 skipwhite:
370         while ( (c = *data) <= ' ')
371         {
372                 if (c == 0)
373                 {
374                         com_eof = true;
375                         return NULL;                    // end of file;
376                 }
377                 data++;
378         }
379
380 // skip // comments
381         if (c=='/' && data[1] == '/')
382         {
383                 while (*data && *data != '\n')
384                         data++;
385                 goto skipwhite;
386         }
387
388
389 // handle quoted strings specially
390         if (c == '\"')
391         {
392                 data++;
393                 do
394                 {
395                         c = *data++;
396                         if (c=='\"')
397                         {
398                                 com_token[len] = 0;
399                                 return data;
400                         }
401                         com_token[len] = c;
402                         len++;
403                 } while (1);
404         }
405
406 // parse single characters
407         if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
408         {
409                 com_token[len] = c;
410                 len++;
411                 com_token[len] = 0;
412                 return data+1;
413         }
414
415 // parse a regular word
416         do
417         {
418                 com_token[len] = c;
419                 data++;
420                 len++;
421                 c = *data;
422         if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
423                         break;
424         } while (c>32);
425
426         com_token[len] = 0;
427         return data;
428 }
429
430
431 int Q_strncasecmp (char *s1, char *s2, int n)
432 {
433         int             c1, c2;
434
435         do
436         {
437                 c1 = *s1++;
438                 c2 = *s2++;
439
440                 if (!n--)
441                         return 0;               // strings are equal until end point
442
443                 if (c1 != c2)
444                 {
445                         if (c1 >= 'a' && c1 <= 'z')
446                                 c1 -= ('a' - 'A');
447                         if (c2 >= 'a' && c2 <= 'z')
448                                 c2 -= ('a' - 'A');
449                         if (c1 != c2)
450                                 return -1;              // strings not equal
451                 }
452         } while (c1);
453
454         return 0;               // strings are equal
455 }
456
457 int Q_strcasecmp (char *s1, char *s2)
458 {
459         return Q_strncasecmp (s1, s2, 99999);
460 }
461
462
463 char *strupr (char *start)
464 {
465         char    *in;
466         in = start;
467         while (*in)
468         {
469                 *in = toupper(*in);
470                 in++;
471         }
472         return start;
473 }
474
475 char *strlower (char *start)
476 {
477         char    *in;
478         in = start;
479         while (*in)
480         {
481                 *in = tolower(*in);
482                 in++;
483         }
484         return start;
485 }
486
487
488 /*
489 =============================================================================
490
491                                                 MISC FUNCTIONS
492
493 =============================================================================
494 */
495
496
497 /*
498 =================
499 CheckParm
500
501 Checks for the given parameter in the program's command line arguments
502 Returns the argument number (1 to argc-1) or 0 if not present
503 =================
504 */
505 int CheckParm (char *check)
506 {
507         int             i;
508
509         for (i = 1;i<myargc;i++)
510         {
511                 if ( !Q_strcasecmp(check, myargv[i]) )
512                         return i;
513         }
514
515         return 0;
516 }
517
518
519
520 /*
521 ================
522 Q_filelength
523 ================
524 */
525 int Q_filelength (FILE *f)
526 {
527         int             pos;
528         int             end;
529
530         pos = ftell (f);
531         fseek (f, 0, SEEK_END);
532         end = ftell (f);
533         fseek (f, pos, SEEK_SET);
534
535         return end;
536 }
537
538
539 FILE *SafeOpenWrite (char *filename)
540 {
541         FILE    *f;
542
543         f = fopen(filename, "wb");
544
545         if (!f)
546                 Error ("Error opening %s: %s",filename,strerror(errno));
547
548         return f;
549 }
550
551 FILE *SafeOpenRead (char *filename)
552 {
553         FILE    *f;
554
555         f = fopen(filename, "rb");
556
557         if (!f)
558                 Error ("Error opening %s: %s",filename,strerror(errno));
559
560         return f;
561 }
562
563
564 void SafeRead (FILE *f, void *buffer, int count)
565 {
566         if ( fread (buffer, 1, count, f) != (size_t)count)
567                 Error ("File read failure");
568 }
569
570
571 void SafeWrite (FILE *f, void *buffer, int count)
572 {
573         if (fwrite (buffer, 1, count, f) != (size_t)count)
574                 Error ("File write failure");
575 }
576
577
578 /*
579 ==============
580 FileExists
581 ==============
582 */
583 qboolean        FileExists (char *filename)
584 {
585         FILE    *f;
586
587         f = fopen (filename, "r");
588         if (!f)
589                 return false;
590         fclose (f);
591         return true;
592 }
593
594 /*
595 ==============
596 LoadFile
597 ==============
598 */
599 int    LoadFile (char *filename, void **bufferptr)
600 {
601         FILE    *f;
602         int    length;
603         void    *buffer;
604
605         f = SafeOpenRead (filename);
606         length = Q_filelength (f);
607         buffer = malloc (length+1);
608         ((char *)buffer)[length] = 0;
609         SafeRead (f, buffer, length);
610         fclose (f);
611
612         *bufferptr = buffer;
613         return length;
614 }
615
616
617 /*
618 ==============
619 TryLoadFile
620
621 Allows failure
622 ==============
623 */
624 int    TryLoadFile (char *filename, void **bufferptr)
625 {
626         FILE    *f;
627         int    length;
628         void    *buffer;
629
630         *bufferptr = NULL;
631
632         f = fopen (filename, "rb");
633         if (!f)
634                 return -1;
635         length = Q_filelength (f);
636         buffer = malloc (length+1);
637         ((char *)buffer)[length] = 0;
638         SafeRead (f, buffer, length);
639         fclose (f);
640
641         *bufferptr = buffer;
642         return length;
643 }
644
645
646 /*
647 ==============
648 SaveFile
649 ==============
650 */
651 void    SaveFile (char *filename, void *buffer, int count)
652 {
653         FILE    *f;
654
655         f = SafeOpenWrite (filename);
656         SafeWrite (f, buffer, count);
657         fclose (f);
658 }
659
660
661
662 void DefaultExtension (char *path, char *extension)
663 {
664         char    *src;
665 //
666 // if path doesnt have a .EXT, append extension
667 // (extension should include the .)
668 //
669         src = path + strlen(path) - 1;
670
671         while (*src != PATHSEPERATOR && src != path)
672         {
673                 if (*src == '.')
674                         return;                 // it has an extension
675                 src--;
676         }
677
678         strcat (path, extension);
679 }
680
681
682 void DefaultPath (char *path, char *basepath)
683 {
684         char    temp[128];
685
686         if (path[0] == PATHSEPERATOR)
687                 return;                   // absolute path location
688         strcpy (temp,path);
689         strcpy (path,basepath);
690         strcat (path,temp);
691 }
692
693
694 void    StripFilename (char *path)
695 {
696         int             length;
697
698         length = strlen(path)-1;
699         while (length > 0 && path[length] != PATHSEPERATOR)
700                 length--;
701         path[length] = 0;
702 }
703
704 void    StripExtension (char *path)
705 {
706         int             length;
707
708         length = strlen(path)-1;
709         while (length > 0 && path[length] != '.')
710         {
711                 length--;
712                 if (path[length] == '/')
713                         return;         // no extension
714         }
715         if (length)
716                 path[length] = 0;
717 }
718
719
720 /*
721 ====================
722 Extract file parts
723 ====================
724 */
725 // FIXME: should include the slash, otherwise
726 // backing to an empty path will be wrong when appending a slash
727 void ExtractFilePath (char *path, char *dest)
728 {
729         char    *src;
730
731         src = path + strlen(path) - 1;
732
733 //
734 // back up until a \ or the start
735 //
736         while (src != path && *(src-1) != '\\' && *(src-1) != '/')
737                 src--;
738
739         memcpy (dest, path, src-path);
740         dest[src-path] = 0;
741 }
742
743 void ExtractFileBase (char *path, char *dest)
744 {
745         char    *src;
746
747         src = path + strlen(path) - 1;
748
749 //
750 // back up until a \ or the start
751 //
752         while (src != path && *(src-1) != PATHSEPERATOR)
753                 src--;
754
755         while (*src && *src != '.')
756         {
757                 *dest++ = *src++;
758         }
759         *dest = 0;
760 }
761
762 void ExtractFileExtension (char *path, char *dest)
763 {
764         char    *src;
765
766         src = path + strlen(path) - 1;
767
768 //
769 // back up until a . or the start
770 //
771         while (src != path && *(src-1) != '.')
772                 src--;
773         if (src == path)
774         {
775                 *dest = 0;      // no extension
776                 return;
777         }
778
779         strcpy (dest,src);
780 }
781
782
783 /*
784 ==============
785 ParseNum / ParseHex
786 ==============
787 */
788 int ParseHex (char *hex)
789 {
790         char    *str;
791         int    num;
792
793         num = 0;
794         str = hex;
795
796         while (*str)
797         {
798                 num <<= 4;
799                 if (*str >= '0' && *str <= '9')
800                         num += *str-'0';
801                 else if (*str >= 'a' && *str <= 'f')
802                         num += 10 + *str-'a';
803                 else if (*str >= 'A' && *str <= 'F')
804                         num += 10 + *str-'A';
805                 else
806                         Error ("Bad hex number: %s",hex);
807                 str++;
808         }
809
810         return num;
811 }
812
813
814 int ParseNum (char *str)
815 {
816         if (str[0] == '$')
817                 return ParseHex (str+1);
818         if (str[0] == '0' && str[1] == 'x')
819                 return ParseHex (str+2);
820         return atol (str);
821 }
822
823
824
825 /*
826 ============================================================================
827
828                                         BYTE ORDER FUNCTIONS
829
830 ============================================================================
831 */
832
833 #ifdef _SGI_SOURCE
834 #define __BIG_ENDIAN__
835 #endif
836
837 #ifdef __BIG_ENDIAN__
838
839 short   LittleShort (short l)
840 {
841         byte    b1,b2;
842
843         b1 = l&255;
844         b2 = (l>>8)&255;
845
846         return (b1<<8) + b2;
847 }
848
849 short   BigShort (short l)
850 {
851         return l;
852 }
853
854
855 int    LittleLong (int l)
856 {
857         byte    b1,b2,b3,b4;
858
859         b1 = l&255;
860         b2 = (l>>8)&255;
861         b3 = (l>>16)&255;
862         b4 = (l>>24)&255;
863
864         return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
865 }
866
867 int    BigLong (int l)
868 {
869         return l;
870 }
871
872
873 float   LittleFloat (float l)
874 {
875         union {byte b[4]; float f;} in, out;
876
877         in.f = l;
878         out.b[0] = in.b[3];
879         out.b[1] = in.b[2];
880         out.b[2] = in.b[1];
881         out.b[3] = in.b[0];
882
883         return out.f;
884 }
885
886 float   BigFloat (float l)
887 {
888         return l;
889 }
890
891
892 #else
893
894
895 short   BigShort (short l)
896 {
897         byte    b1,b2;
898
899         b1 = l&255;
900         b2 = (l>>8)&255;
901
902         return (b1<<8) + b2;
903 }
904
905 short   LittleShort (short l)
906 {
907         return l;
908 }
909
910
911 int    BigLong (int l)
912 {
913         byte    b1,b2,b3,b4;
914
915         b1 = l&255;
916         b2 = (l>>8)&255;
917         b3 = (l>>16)&255;
918         b4 = (l>>24)&255;
919
920         return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
921 }
922
923 int    LittleLong (int l)
924 {
925         return l;
926 }
927
928 float   BigFloat (float l)
929 {
930         union {byte b[4]; float f;} in, out;
931
932         in.f = l;
933         out.b[0] = in.b[3];
934         out.b[1] = in.b[2];
935         out.b[2] = in.b[1];
936         out.b[3] = in.b[0];
937
938         return out.f;
939 }
940
941 float   LittleFloat (float l)
942 {
943         return l;
944 }
945
946
947 #endif
948
949
950 //=======================================================
951
952
953 // FIXME: byte swap?
954
955 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
956 // and the initial and final xor values shown below...  in other words, the
957 // CCITT standard CRC used by XMODEM
958
959 #define CRC_INIT_VALUE  0xffff
960 #define CRC_XOR_VALUE   0x0000
961
962 static unsigned short crctable[256] =
963 {
964         0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
965         0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
966         0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
967         0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
968         0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
969         0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
970         0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
971         0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
972         0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
973         0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
974         0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
975         0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
976         0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
977         0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
978         0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
979         0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
980         0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
981         0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
982         0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
983         0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
984         0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
985         0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
986         0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
987         0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
988         0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
989         0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
990         0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
991         0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
992         0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
993         0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
994         0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
995         0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
996 };
997
998 void CRC_Init(unsigned short *crcvalue)
999 {
1000         *crcvalue = CRC_INIT_VALUE;
1001 }
1002
1003 void CRC_ProcessByte(unsigned short *crcvalue, byte data)
1004 {
1005         *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
1006 }
1007
1008 unsigned short CRC_Value(unsigned short crcvalue)
1009 {
1010         return crcvalue ^ CRC_XOR_VALUE;
1011 }
1012 //=============================================================================
1013
1014 /*
1015 ============
1016 CreatePath
1017 ============
1018 */
1019 void    CreatePath (char *path)
1020 {
1021         char    *ofs, c;
1022
1023         if (path[1] == ':')
1024                 path += 2;
1025
1026         for (ofs = path+1 ; *ofs ; ofs++)
1027         {
1028                 c = *ofs;
1029                 if (c == '/' || c == '\\')
1030                 {       // create the directory
1031                         *ofs = 0;
1032                         Q_mkdir (path);
1033                         *ofs = c;
1034                 }
1035         }
1036 }
1037
1038
1039 /*
1040 ============
1041 QCopyFile
1042
1043   Used to archive source files
1044 ============
1045 */
1046 void QCopyFile (char *from, char *to)
1047 {
1048         void    *buffer;
1049         int             length;
1050
1051         length = LoadFile (from, &buffer);
1052         CreatePath (to);
1053         SaveFile (to, buffer, length);
1054         free (buffer);
1055 }