]> git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/common/cmdlib.c
Merge commit 'a255fbd84e64e4f8bb6e6786b6f65579071742b6' into garux-merge
[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
465 char *strupr (char *start)
466 {
467         char    *in;
468         in = start;
469         while (*in)
470         {
471                 *in = toupper(*in);
472                 in++;
473         }
474         return start;
475 }
476
477 char *strlower (char *start)
478 {
479         char    *in;
480         in = start;
481         while (*in)
482         {
483                 *in = tolower(*in);
484                 in++;
485         }
486         return start;
487 }
488
489
490 /*
491 =============================================================================
492
493                                                 MISC FUNCTIONS
494
495 =============================================================================
496 */
497
498
499 /*
500 =================
501 CheckParm
502
503 Checks for the given parameter in the program's command line arguments
504 Returns the argument number (1 to argc-1) or 0 if not present
505 =================
506 */
507 int CheckParm (char *check)
508 {
509         int             i;
510
511         for (i = 1;i<myargc;i++)
512         {
513                 if ( !Q_strcasecmp(check, myargv[i]) )
514                         return i;
515         }
516
517         return 0;
518 }
519
520
521
522 /*
523 ================
524 Q_filelength
525 ================
526 */
527 int Q_filelength (FILE *f)
528 {
529         int             pos;
530         int             end;
531
532         pos = ftell (f);
533         fseek (f, 0, SEEK_END);
534         end = ftell (f);
535         fseek (f, pos, SEEK_SET);
536
537         return end;
538 }
539
540
541 FILE *SafeOpenWrite (char *filename)
542 {
543         FILE    *f;
544
545         f = fopen(filename, "wb");
546
547         if (!f)
548                 Error ("Error opening %s: %s",filename,strerror(errno));
549
550         return f;
551 }
552
553 FILE *SafeOpenRead (char *filename)
554 {
555         FILE    *f;
556
557         f = fopen(filename, "rb");
558
559         if (!f)
560                 Error ("Error opening %s: %s",filename,strerror(errno));
561
562         return f;
563 }
564
565
566 void SafeRead (FILE *f, void *buffer, int count)
567 {
568         if ( fread (buffer, 1, count, f) != (size_t)count)
569                 Error ("File read failure");
570 }
571
572
573 void SafeWrite (FILE *f, void *buffer, int count)
574 {
575         if (fwrite (buffer, 1, count, f) != (size_t)count)
576                 Error ("File write failure");
577 }
578
579
580 /*
581 ==============
582 FileExists
583 ==============
584 */
585 qboolean        FileExists (char *filename)
586 {
587         FILE    *f;
588
589         f = fopen (filename, "r");
590         if (!f)
591                 return false;
592         fclose (f);
593         return true;
594 }
595
596 /*
597 ==============
598 LoadFile
599 ==============
600 */
601 int    LoadFile (char *filename, void **bufferptr)
602 {
603         FILE    *f;
604         int    length;
605         void    *buffer;
606
607         f = SafeOpenRead (filename);
608         length = Q_filelength (f);
609         buffer = malloc (length+1);
610         ((char *)buffer)[length] = 0;
611         SafeRead (f, buffer, length);
612         fclose (f);
613
614         *bufferptr = buffer;
615         return length;
616 }
617
618
619 /*
620 ==============
621 TryLoadFile
622
623 Allows failure
624 ==============
625 */
626 int    TryLoadFile (char *filename, void **bufferptr)
627 {
628         FILE    *f;
629         int    length;
630         void    *buffer;
631
632         *bufferptr = NULL;
633
634         f = fopen (filename, "rb");
635         if (!f)
636                 return -1;
637         length = Q_filelength (f);
638         buffer = malloc (length+1);
639         ((char *)buffer)[length] = 0;
640         SafeRead (f, buffer, length);
641         fclose (f);
642
643         *bufferptr = buffer;
644         return length;
645 }
646
647
648 /*
649 ==============
650 SaveFile
651 ==============
652 */
653 void    SaveFile (char *filename, void *buffer, int count)
654 {
655         FILE    *f;
656
657         f = SafeOpenWrite (filename);
658         SafeWrite (f, buffer, count);
659         fclose (f);
660 }
661
662
663
664 void DefaultExtension (char *path, char *extension)
665 {
666         char    *src;
667 //
668 // if path doesnt have a .EXT, append extension
669 // (extension should include the .)
670 //
671         src = path + strlen(path) - 1;
672
673         while (*src != PATHSEPERATOR && src != path)
674         {
675                 if (*src == '.')
676                         return;                 // it has an extension
677                 src--;
678         }
679
680         strcat (path, extension);
681 }
682
683
684 void DefaultPath (char *path, char *basepath)
685 {
686         char    temp[128];
687
688         if (path[0] == PATHSEPERATOR)
689                 return;                   // absolute path location
690         strcpy (temp,path);
691         strcpy (path,basepath);
692         strcat (path,temp);
693 }
694
695
696 void    StripFilename (char *path)
697 {
698         int             length;
699
700         length = strlen(path)-1;
701         while (length > 0 && path[length] != PATHSEPERATOR)
702                 length--;
703         path[length] = 0;
704 }
705
706 void    StripExtension (char *path)
707 {
708         int             length;
709
710         length = strlen(path)-1;
711         while (length > 0 && path[length] != '.')
712         {
713                 length--;
714                 if (path[length] == '/')
715                         return;         // no extension
716         }
717         if (length)
718                 path[length] = 0;
719 }
720
721
722 /*
723 ====================
724 Extract file parts
725 ====================
726 */
727 // FIXME: should include the slash, otherwise
728 // backing to an empty path will be wrong when appending a slash
729 void ExtractFilePath (char *path, char *dest)
730 {
731         char    *src;
732
733         src = path + strlen(path) - 1;
734
735 //
736 // back up until a \ or the start
737 //
738         while (src != path && *(src-1) != '\\' && *(src-1) != '/')
739                 src--;
740
741         memcpy (dest, path, src-path);
742         dest[src-path] = 0;
743 }
744
745 void ExtractFileBase (char *path, char *dest)
746 {
747         char    *src;
748
749         src = path + strlen(path) - 1;
750
751 //
752 // back up until a \ or the start
753 //
754         while (src != path && *(src-1) != PATHSEPERATOR)
755                 src--;
756
757         while (*src && *src != '.')
758         {
759                 *dest++ = *src++;
760         }
761         *dest = 0;
762 }
763
764 void ExtractFileExtension (char *path, char *dest)
765 {
766         char    *src;
767
768         src = path + strlen(path) - 1;
769
770 //
771 // back up until a . or the start
772 //
773         while (src != path && *(src-1) != '.')
774                 src--;
775         if (src == path)
776         {
777                 *dest = 0;      // no extension
778                 return;
779         }
780
781         strcpy (dest,src);
782 }
783
784
785 /*
786 ==============
787 ParseNum / ParseHex
788 ==============
789 */
790 int ParseHex (char *hex)
791 {
792         char    *str;
793         int    num;
794
795         num = 0;
796         str = hex;
797
798         while (*str)
799         {
800                 num <<= 4;
801                 if (*str >= '0' && *str <= '9')
802                         num += *str-'0';
803                 else if (*str >= 'a' && *str <= 'f')
804                         num += 10 + *str-'a';
805                 else if (*str >= 'A' && *str <= 'F')
806                         num += 10 + *str-'A';
807                 else
808                         Error ("Bad hex number: %s",hex);
809                 str++;
810         }
811
812         return num;
813 }
814
815
816 int ParseNum (char *str)
817 {
818         if (str[0] == '$')
819                 return ParseHex (str+1);
820         if (str[0] == '0' && str[1] == 'x')
821                 return ParseHex (str+2);
822         return atol (str);
823 }
824
825
826
827 /*
828 ============================================================================
829
830                                         BYTE ORDER FUNCTIONS
831
832 ============================================================================
833 */
834
835 #if GDEF_ARCH_ENDIAN_BIG
836
837 short   LittleShort (short l)
838 {
839         byte    b1,b2;
840
841         b1 = l&255;
842         b2 = (l>>8)&255;
843
844         return (b1<<8) + b2;
845 }
846
847 short   BigShort (short l)
848 {
849         return l;
850 }
851
852
853 int    LittleLong (int l)
854 {
855         byte    b1,b2,b3,b4;
856
857         b1 = l&255;
858         b2 = (l>>8)&255;
859         b3 = (l>>16)&255;
860         b4 = (l>>24)&255;
861
862         return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
863 }
864
865 int    BigLong (int l)
866 {
867         return l;
868 }
869
870
871 float   LittleFloat (float l)
872 {
873         union {byte b[4]; float f;} in, out;
874
875         in.f = l;
876         out.b[0] = in.b[3];
877         out.b[1] = in.b[2];
878         out.b[2] = in.b[1];
879         out.b[3] = in.b[0];
880
881         return out.f;
882 }
883
884 float   BigFloat (float l)
885 {
886         return l;
887 }
888
889
890 #else
891
892
893 short   BigShort (short l)
894 {
895         byte    b1,b2;
896
897         b1 = l&255;
898         b2 = (l>>8)&255;
899
900         return (b1<<8) + b2;
901 }
902
903 short   LittleShort (short l)
904 {
905         return l;
906 }
907
908
909 int    BigLong (int l)
910 {
911         byte    b1,b2,b3,b4;
912
913         b1 = l&255;
914         b2 = (l>>8)&255;
915         b3 = (l>>16)&255;
916         b4 = (l>>24)&255;
917
918         return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
919 }
920
921 int    LittleLong (int l)
922 {
923         return l;
924 }
925
926 float   BigFloat (float l)
927 {
928         union {byte b[4]; float f;} in, out;
929
930         in.f = l;
931         out.b[0] = in.b[3];
932         out.b[1] = in.b[2];
933         out.b[2] = in.b[1];
934         out.b[3] = in.b[0];
935
936         return out.f;
937 }
938
939 float   LittleFloat (float l)
940 {
941         return l;
942 }
943
944
945 #endif
946
947
948 //=======================================================
949
950
951 // FIXME: byte swap?
952
953 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
954 // and the initial and final xor values shown below...  in other words, the
955 // CCITT standard CRC used by XMODEM
956
957 #define CRC_INIT_VALUE  0xffff
958 #define CRC_XOR_VALUE   0x0000
959
960 static unsigned short crctable[256] =
961 {
962         0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
963         0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
964         0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
965         0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
966         0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
967         0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
968         0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
969         0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
970         0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
971         0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
972         0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
973         0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
974         0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
975         0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
976         0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
977         0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
978         0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
979         0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
980         0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
981         0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
982         0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
983         0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
984         0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
985         0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
986         0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
987         0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
988         0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
989         0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
990         0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
991         0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
992         0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
993         0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
994 };
995
996 void CRC_Init(unsigned short *crcvalue)
997 {
998         *crcvalue = CRC_INIT_VALUE;
999 }
1000
1001 void CRC_ProcessByte(unsigned short *crcvalue, byte data)
1002 {
1003         *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
1004 }
1005
1006 unsigned short CRC_Value(unsigned short crcvalue)
1007 {
1008         return crcvalue ^ CRC_XOR_VALUE;
1009 }
1010 //=============================================================================
1011
1012 /*
1013 ============
1014 CreatePath
1015 ============
1016 */
1017 void    CreatePath (char *path)
1018 {
1019         char    *ofs, c;
1020
1021         if (path[1] == ':')
1022                 path += 2;
1023
1024         for (ofs = path+1 ; *ofs ; ofs++)
1025         {
1026                 c = *ofs;
1027                 if (c == '/' || c == '\\')
1028                 {       // create the directory
1029                         *ofs = 0;
1030                         Q_mkdir (path);
1031                         *ofs = c;
1032                 }
1033         }
1034 }
1035
1036
1037 /*
1038 ============
1039 QCopyFile
1040
1041   Used to archive source files
1042 ============
1043 */
1044 void QCopyFile (char *from, char *to)
1045 {
1046         void    *buffer;
1047         int             length;
1048
1049         length = LoadFile (from, &buffer);
1050         CreatePath (to);
1051         SaveFile (to, buffer, length);
1052         free (buffer);
1053 }