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