]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/common/cmdlib.c
quake2,heretic2: attempt to fix undeclared strupr, <3 Kai
[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 "globaldefs.h"
27
28 #include <sys/types.h>
29 #include <sys/stat.h>
30
31 #if GDEF_OS_WINDOWS
32 #include <direct.h>
33 #endif
34
35 #ifdef NeXT
36 #include <libc.h>
37 #endif
38
39 #define BASEDIRNAME     "quake2"
40 #define PATHSEPERATOR   '/'
41
42 // set these before calling CheckParm
43 int myargc;
44 char **myargv;
45
46 char            com_token[1024];
47 qboolean        com_eof;
48
49 qboolean                archive;
50 char                    archivedir[1024];
51
52
53 /*
54 ===================
55 ExpandWildcards
56
57 Mimic unix command line expansion
58 ===================
59 */
60 #define MAX_EX_ARGC     1024
61 int             ex_argc;
62 char    *ex_argv[MAX_EX_ARGC];
63 #if GDEF_OS_WINDOWS
64 #include "io.h"
65 void ExpandWildcards (int *argc, char ***argv)
66 {
67         struct _finddata_t fileinfo;
68         int             handle;
69         int             i;
70         char    filename[1024];
71         char    filebase[1024];
72         char    *path;
73
74         ex_argc = 0;
75         for (i=0 ; i<*argc ; i++)
76         {
77                 path = (*argv)[i];
78                 if ( path[0] == '-'
79                         || ( !strstr(path, "*") && !strstr(path, "?") ) )
80                 {
81                         ex_argv[ex_argc++] = path;
82                         continue;
83                 }
84
85                 handle = _findfirst (path, &fileinfo);
86                 if (handle == -1)
87                         return;
88
89                 ExtractFilePath (path, filebase);
90
91                 do
92                 {
93                         sprintf (filename, "%s%s", filebase, fileinfo.name);
94                         ex_argv[ex_argc++] = copystring (filename);
95                 } while (_findnext( handle, &fileinfo ) != -1);
96
97                 _findclose (handle);
98         }
99
100         *argc = ex_argc;
101         *argv = ex_argv;
102 }
103 #else
104 void ExpandWildcards (int *argc, char ***argv)
105 {
106 }
107 #endif
108
109 #ifdef WIN_ERROR
110 #include <windows.h>
111 /*
112 =================
113 Error
114
115 For abnormal program terminations in windowed apps
116 =================
117 */
118 void Error (char *error, ...)
119 {
120         va_list argptr;
121         char    text[1024];
122         char    text2[1024];
123         int             err;
124
125         err = GetLastError ();
126
127         va_start (argptr,error);
128         vsprintf (text, error,argptr);
129         va_end (argptr);
130
131         sprintf (text2, "%s\nGetLastError() = %i", text, err);
132     MessageBox(NULL, text2, "Error", 0 /* MB_OK */ );
133
134         exit (1);
135 }
136
137 #else
138 /*
139 =================
140 Error
141
142 For abnormal program terminations in console apps
143 =================
144 */
145 void Error (char *error, ...)
146 {
147         va_list argptr;
148
149         printf ("\n************ ERROR ************\n");
150
151         va_start (argptr,error);
152         vprintf (error,argptr);
153         va_end (argptr);
154         printf ("\n");
155
156         exit (1);
157 }
158 #endif
159
160 // only printf if in verbose mode
161 qboolean verbose = false;
162 void qprintf (char *format, ...)
163 {
164         va_list argptr;
165
166         if (!verbose)
167                 return;
168
169         va_start (argptr,format);
170         vprintf (format,argptr);
171         va_end (argptr);
172 }
173
174
175 /*
176
177 qdir will hold the path up to the quake directory, including the slash
178
179   f:\quake\
180   /raid/quake/
181
182 gamedir will hold qdir + the game directory (id1, id2, etc)
183
184   */
185
186 char            qdir[1024];
187 char            gamedir[1024];
188
189 void SetQdirFromPath (char *path)
190 {
191         char    temp[1024];
192         char    *c;
193         int             len;
194
195         if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
196         {       // path is partial
197                 Q_getwd (temp);
198                 strcat (temp, path);
199                 path = temp;
200         }
201
202         // search for "quake2" in path
203
204         len = strlen(BASEDIRNAME);
205         for (c=path+strlen(path)-1 ; c != path ; c--)
206                 if (!Q_strncasecmp (c, BASEDIRNAME, len))
207                 {
208                         strncpy (qdir, path, c+len+1-path);
209                         qprintf ("qdir: %s\n", qdir);
210                         c += len+1;
211                         while (*c)
212                         {
213                                 if (*c == '/' || *c == '\\')
214                                 {
215                                         strncpy (gamedir, path, c+1-path);
216                                         qprintf ("gamedir: %s\n", gamedir);
217                                         return;
218                                 }
219                                 c++;
220                         }
221                         Error ("No gamedir in %s", path);
222                         return;
223                 }
224         Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
225 }
226
227 char *ExpandArg (char *path)
228 {
229         static char full[1024];
230
231         if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
232         {
233                 Q_getwd (full);
234                 strcat (full, path);
235         }
236         else
237                 strcpy (full, path);
238         return full;
239 }
240
241 char *ExpandPath (char *path)
242 {
243         static char full[1024];
244         if (!qdir)
245                 Error ("ExpandPath called without qdir set");
246         if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
247                 return path;
248         sprintf (full, "%s%s", qdir, path);
249         return full;
250 }
251
252 char *ExpandPathAndArchive (char *path)
253 {
254         char    *expanded;
255         char    archivename[1024];
256
257         expanded = ExpandPath (path);
258
259         if (archive)
260         {
261                 sprintf (archivename, "%s/%s", archivedir, path);
262                 QCopyFile (expanded, archivename);
263         }
264         return expanded;
265 }
266
267
268 char *copystring(char *s)
269 {
270         char    *b;
271         b = malloc(strlen(s)+1);
272         strcpy (b, s);
273         return b;
274 }
275
276
277
278 /*
279 ================
280 I_FloatTime
281 ================
282 */
283 double I_FloatTime (void)
284 {
285         time_t  t;
286
287         time (&t);
288
289         return t;
290 #if 0
291 // more precise, less portable
292         struct timeval tp;
293         struct timezone tzp;
294         static int              secbase;
295
296         gettimeofday(&tp, &tzp);
297
298         if (!secbase)
299         {
300                 secbase = tp.tv_sec;
301                 return tp.tv_usec/1000000.0;
302         }
303
304         return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
305 #endif
306 }
307
308 void Q_getwd (char *out)
309 {
310 #if GDEF_OS_WINDOWS
311    _getcwd (out, 256);
312    strcat (out, "\\");
313 #else
314    getwd (out);
315    strcat (out, "/");
316 #endif
317 }
318
319
320 void Q_mkdir (char *path)
321 {
322 #if GDEF_OS_WINDOWS
323         if (_mkdir (path) != -1)
324                 return;
325 #else
326         if (mkdir (path, 0777) != -1)
327                 return;
328 #endif
329         if (errno != EEXIST)
330                 Error ("mkdir %s: %s",path, strerror(errno));
331 }
332
333 /*
334 ============
335 FileTime
336
337 returns -1 if not present
338 ============
339 */
340 int     FileTime (char *path)
341 {
342         struct  stat    buf;
343
344         if (stat (path,&buf) == -1)
345                 return -1;
346
347         return buf.st_mtime;
348 }
349
350
351
352 /*
353 ==============
354 COM_Parse
355
356 Parse a token out of a string
357 ==============
358 */
359 char *COM_Parse (char *data)
360 {
361         int             c;
362         int             len;
363
364         len = 0;
365         com_token[0] = 0;
366
367         if (!data)
368                 return NULL;
369
370 // skip whitespace
371 skipwhite:
372         while ( (c = *data) <= ' ')
373         {
374                 if (c == 0)
375                 {
376                         com_eof = true;
377                         return NULL;                    // end of file;
378                 }
379                 data++;
380         }
381
382 // skip // comments
383         if (c=='/' && data[1] == '/')
384         {
385                 while (*data && *data != '\n')
386                         data++;
387                 goto skipwhite;
388         }
389
390
391 // handle quoted strings specially
392         if (c == '\"')
393         {
394                 data++;
395                 do
396                 {
397                         c = *data++;
398                         if (c=='\"')
399                         {
400                                 com_token[len] = 0;
401                                 return data;
402                         }
403                         com_token[len] = c;
404                         len++;
405                 } while (1);
406         }
407
408 // parse single characters
409         if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
410         {
411                 com_token[len] = c;
412                 len++;
413                 com_token[len] = 0;
414                 return data+1;
415         }
416
417 // parse a regular word
418         do
419         {
420                 com_token[len] = c;
421                 data++;
422                 len++;
423                 c = *data;
424         if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
425                         break;
426         } while (c>32);
427
428         com_token[len] = 0;
429         return data;
430 }
431
432
433 int Q_strncasecmp (char *s1, char *s2, int n)
434 {
435         int             c1, c2;
436
437         do
438         {
439                 c1 = *s1++;
440                 c2 = *s2++;
441
442                 if (!n--)
443                         return 0;               // strings are equal until end point
444
445                 if (c1 != c2)
446                 {
447                         if (c1 >= 'a' && c1 <= 'z')
448                                 c1 -= ('a' - 'A');
449                         if (c2 >= 'a' && c2 <= 'z')
450                                 c2 -= ('a' - 'A');
451                         if (c1 != c2)
452                                 return -1;              // strings not equal
453                 }
454         } while (c1);
455
456         return 0;               // strings are equal
457 }
458
459 int Q_strcasecmp (char *s1, char *s2)
460 {
461         return Q_strncasecmp (s1, s2, 99999);
462 }
463
464 // May be already defined with some compilers on Windows
465 #ifndef strupr
466 char *strupr (char *start)
467 {
468         char    *in;
469         in = start;
470         while (*in)
471         {
472                 *in = toupper(*in);
473                 in++;
474         }
475         return start;
476 }
477 #endif
478
479 char *strlower (char *start)
480 {
481         char    *in;
482         in = start;
483         while (*in)
484         {
485                 *in = tolower(*in);
486                 in++;
487         }
488         return start;
489 }
490
491
492 /*
493 =============================================================================
494
495                                                 MISC FUNCTIONS
496
497 =============================================================================
498 */
499
500
501 /*
502 =================
503 CheckParm
504
505 Checks for the given parameter in the program's command line arguments
506 Returns the argument number (1 to argc-1) or 0 if not present
507 =================
508 */
509 int CheckParm (char *check)
510 {
511         int             i;
512
513         for (i = 1;i<myargc;i++)
514         {
515                 if ( !Q_strcasecmp(check, myargv[i]) )
516                         return i;
517         }
518
519         return 0;
520 }
521
522
523
524 /*
525 ================
526 Q_filelength
527 ================
528 */
529 int Q_filelength (FILE *f)
530 {
531         int             pos;
532         int             end;
533
534         pos = ftell (f);
535         fseek (f, 0, SEEK_END);
536         end = ftell (f);
537         fseek (f, pos, SEEK_SET);
538
539         return end;
540 }
541
542
543 FILE *SafeOpenWrite (char *filename)
544 {
545         FILE    *f;
546
547         f = fopen(filename, "wb");
548
549         if (!f)
550                 Error ("Error opening %s: %s",filename,strerror(errno));
551
552         return f;
553 }
554
555 FILE *SafeOpenRead (char *filename)
556 {
557         FILE    *f;
558
559         f = fopen(filename, "rb");
560
561         if (!f)
562                 Error ("Error opening %s: %s",filename,strerror(errno));
563
564         return f;
565 }
566
567
568 void SafeRead (FILE *f, void *buffer, int count)
569 {
570         if ( fread (buffer, 1, count, f) != (size_t)count)
571                 Error ("File read failure");
572 }
573
574
575 void SafeWrite (FILE *f, void *buffer, int count)
576 {
577         if (fwrite (buffer, 1, count, f) != (size_t)count)
578                 Error ("File write failure");
579 }
580
581
582 /*
583 ==============
584 FileExists
585 ==============
586 */
587 qboolean        FileExists (char *filename)
588 {
589         FILE    *f;
590
591         f = fopen (filename, "r");
592         if (!f)
593                 return false;
594         fclose (f);
595         return true;
596 }
597
598 /*
599 ==============
600 LoadFile
601 ==============
602 */
603 int    LoadFile (char *filename, void **bufferptr)
604 {
605         FILE    *f;
606         int    length;
607         void    *buffer;
608
609         f = SafeOpenRead (filename);
610         length = Q_filelength (f);
611         buffer = malloc (length+1);
612         ((char *)buffer)[length] = 0;
613         SafeRead (f, buffer, length);
614         fclose (f);
615
616         *bufferptr = buffer;
617         return length;
618 }
619
620
621 /*
622 ==============
623 TryLoadFile
624
625 Allows failure
626 ==============
627 */
628 int    TryLoadFile (char *filename, void **bufferptr)
629 {
630         FILE    *f;
631         int    length;
632         void    *buffer;
633
634         *bufferptr = NULL;
635
636         f = fopen (filename, "rb");
637         if (!f)
638                 return -1;
639         length = Q_filelength (f);
640         buffer = malloc (length+1);
641         ((char *)buffer)[length] = 0;
642         SafeRead (f, buffer, length);
643         fclose (f);
644
645         *bufferptr = buffer;
646         return length;
647 }
648
649
650 /*
651 ==============
652 SaveFile
653 ==============
654 */
655 void    SaveFile (char *filename, void *buffer, int count)
656 {
657         FILE    *f;
658
659         f = SafeOpenWrite (filename);
660         SafeWrite (f, buffer, count);
661         fclose (f);
662 }
663
664
665
666 void DefaultExtension (char *path, char *extension)
667 {
668         char    *src;
669 //
670 // if path doesnt have a .EXT, append extension
671 // (extension should include the .)
672 //
673         src = path + strlen(path) - 1;
674
675         while (*src != PATHSEPERATOR && src != path)
676         {
677                 if (*src == '.')
678                         return;                 // it has an extension
679                 src--;
680         }
681
682         strcat (path, extension);
683 }
684
685
686 void DefaultPath (char *path, char *basepath)
687 {
688         char    temp[128];
689
690         if (path[0] == PATHSEPERATOR)
691                 return;                   // absolute path location
692         strcpy (temp,path);
693         strcpy (path,basepath);
694         strcat (path,temp);
695 }
696
697
698 void    StripFilename (char *path)
699 {
700         int             length;
701
702         length = strlen(path)-1;
703         while (length > 0 && path[length] != PATHSEPERATOR)
704                 length--;
705         path[length] = 0;
706 }
707
708 void    StripExtension (char *path)
709 {
710         int             length;
711
712         length = strlen(path)-1;
713         while (length > 0 && path[length] != '.')
714         {
715                 length--;
716                 if (path[length] == '/')
717                         return;         // no extension
718         }
719         if (length)
720                 path[length] = 0;
721 }
722
723
724 /*
725 ====================
726 Extract file parts
727 ====================
728 */
729 // FIXME: should include the slash, otherwise
730 // backing to an empty path will be wrong when appending a slash
731 void ExtractFilePath (char *path, char *dest)
732 {
733         char    *src;
734
735         src = path + strlen(path) - 1;
736
737 //
738 // back up until a \ or the start
739 //
740         while (src != path && *(src-1) != '\\' && *(src-1) != '/')
741                 src--;
742
743         memcpy (dest, path, src-path);
744         dest[src-path] = 0;
745 }
746
747 void ExtractFileBase (char *path, char *dest)
748 {
749         char    *src;
750
751         src = path + strlen(path) - 1;
752
753 //
754 // back up until a \ or the start
755 //
756         while (src != path && *(src-1) != PATHSEPERATOR)
757                 src--;
758
759         while (*src && *src != '.')
760         {
761                 *dest++ = *src++;
762         }
763         *dest = 0;
764 }
765
766 void ExtractFileExtension (char *path, char *dest)
767 {
768         char    *src;
769
770         src = path + strlen(path) - 1;
771
772 //
773 // back up until a . or the start
774 //
775         while (src != path && *(src-1) != '.')
776                 src--;
777         if (src == path)
778         {
779                 *dest = 0;      // no extension
780                 return;
781         }
782
783         strcpy (dest,src);
784 }
785
786
787 /*
788 ==============
789 ParseNum / ParseHex
790 ==============
791 */
792 int ParseHex (char *hex)
793 {
794         char    *str;
795         int    num;
796
797         num = 0;
798         str = hex;
799
800         while (*str)
801         {
802                 num <<= 4;
803                 if (*str >= '0' && *str <= '9')
804                         num += *str-'0';
805                 else if (*str >= 'a' && *str <= 'f')
806                         num += 10 + *str-'a';
807                 else if (*str >= 'A' && *str <= 'F')
808                         num += 10 + *str-'A';
809                 else
810                         Error ("Bad hex number: %s",hex);
811                 str++;
812         }
813
814         return num;
815 }
816
817
818 int ParseNum (char *str)
819 {
820         if (str[0] == '$')
821                 return ParseHex (str+1);
822         if (str[0] == '0' && str[1] == 'x')
823                 return ParseHex (str+2);
824         return atol (str);
825 }
826
827
828
829 /*
830 ============================================================================
831
832                                         BYTE ORDER FUNCTIONS
833
834 ============================================================================
835 */
836
837 #if GDEF_ARCH_ENDIAN_BIG
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 }