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