]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/common/cmdlib.c
reduce more diff noise
[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 "globaldefs.h"
33 #include "mathlib.h"
34 #include "inout.h"
35 #include <sys/types.h>
36 #include <sys/stat.h>
37
38 #if GDEF_OS_WINDOWS
39 #include <direct.h>
40 #include <windows.h>
41 #endif
42
43 #if GDEF_OS_LINUX || GDEF_OS_MACOS
44 #include <unistd.h>
45 #endif
46
47 #ifdef NeXT
48 #include <libc.h>
49 #endif
50
51 #define BASEDIRNAME "quake"     // assumed to have a 2 or 3 following
52 #define PATHSEPERATOR   '/'
53
54 #ifdef SAFE_MALLOC
55 void *safe_malloc( size_t size ){
56         void *p;
57
58         p = malloc( size );
59         if ( !p ) {
60                 Error( "safe_malloc failed on allocation of %i bytes", size );
61         }
62
63         return p;
64 }
65
66 void *safe_malloc_info( size_t size, char* info ){
67         void *p;
68
69         p = malloc( size );
70         if ( !p ) {
71                 Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
72         }
73
74         return p;
75 }
76 #endif
77
78 // set these before calling CheckParm
79 int myargc;
80 char **myargv;
81
82 char com_token[1024];
83 qboolean com_eof;
84
85 qboolean archive;
86 char archivedir[1024];
87
88
89 /*
90    ===================
91    ExpandWildcards
92
93    Mimic unix command line expansion
94    ===================
95  */
96 #define MAX_EX_ARGC 1024
97 int ex_argc;
98 char    *ex_argv[MAX_EX_ARGC];
99 #if GDEF_OS_WINDOWS
100 #include "io.h"
101 void ExpandWildcards( int *argc, char ***argv ){
102         struct _finddata_t fileinfo;
103         int handle;
104         int i;
105         char filename[1024];
106         char filebase[1024];
107         char    *path;
108
109         ex_argc = 0;
110         for ( i = 0 ; i < *argc ; i++ )
111         {
112                 path = ( *argv )[i];
113                 if ( path[0] == '-'
114                          || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
115                         ex_argv[ex_argc++] = path;
116                         continue;
117                 }
118
119                 handle = _findfirst( path, &fileinfo );
120                 if ( handle == -1 ) {
121                         return;
122                 }
123
124                 ExtractFilePath( path, filebase );
125
126                 do
127                 {
128                         sprintf( filename, "%s%s", filebase, fileinfo.name );
129                         ex_argv[ex_argc++] = copystring( filename );
130                 } while ( _findnext( handle, &fileinfo ) != -1 );
131
132                 _findclose( handle );
133         }
134
135         *argc = ex_argc;
136         *argv = ex_argv;
137 }
138 #else
139 void ExpandWildcards( int *argc, char ***argv ){
140 }
141 #endif
142
143 /*
144
145    qdir will hold the path up to the quake directory, including the slash
146
147    f:\quake\
148    /raid/quake/
149
150    gamedir will hold qdir + the game directory (id1, id2, etc)
151
152  */
153
154 char qdir[1024];
155 char gamedir[1024];
156 char writedir[1024];
157
158 void SetQdirFromPath( const char *path ){
159         char temp[1024];
160         const char  *c;
161         const char *sep;
162         int len, count;
163
164         if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
165                 Q_getwd( temp );
166                 strcat( temp, path );
167                 path = temp;
168         }
169
170         // search for "quake2" in path
171
172         len = strlen( BASEDIRNAME );
173         for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
174         {
175                 int i;
176
177                 if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) {
178                         //
179                         //strncpy (qdir, path, c+len+2-path);
180                         // the +2 assumes a 2 or 3 following quake which is not the
181                         // case with a retail install
182                         // so we need to add up how much to the next separator
183                         sep = c + len;
184                         count = 1;
185                         while ( *sep && *sep != '/' && *sep != '\\' )
186                         {
187                                 sep++;
188                                 count++;
189                         }
190                         strncpy( qdir, path, c + len + count - path );
191                         Sys_Printf( "qdir: %s\n", qdir );
192                         for ( i = 0; i < (int) strlen( qdir ); i++ )
193                         {
194                                 if ( qdir[i] == '\\' ) {
195                                         qdir[i] = '/';
196                                 }
197                         }
198
199                         c += len + count;
200                         while ( *c )
201                         {
202                                 if ( *c == '/' || *c == '\\' ) {
203                                         strncpy( gamedir, path, c + 1 - path );
204
205                                         for ( i = 0; i < (int) strlen( gamedir ); i++ )
206                                         {
207                                                 if ( gamedir[i] == '\\' ) {
208                                                         gamedir[i] = '/';
209                                                 }
210                                         }
211
212                                         Sys_Printf( "gamedir: %s\n", gamedir );
213
214                                         if ( !writedir[0] ) {
215                                                 strcpy( writedir, gamedir );
216                                         }
217                                         else if ( writedir[strlen( writedir ) - 1] != '/' ) {
218                                                 writedir[strlen( writedir )] = '/';
219                                                 writedir[strlen( writedir ) + 1] = 0;
220                                         }
221
222                                         return;
223                                 }
224                                 c++;
225                         }
226                         Error( "No gamedir in %s", path );
227                         return;
228                 }
229         }
230         Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
231 }
232
233 char *ExpandArg( const char *path ){
234         static char full[1024];
235
236         if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
237                 Q_getwd( full );
238                 strcat( full, path );
239         }
240         else{
241                 strcpy( full, path );
242         }
243         return full;
244 }
245
246 char *ExpandPath( const char *path ){
247         static char full[1024];
248         if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
249                 strcpy( full, path );
250                 return full;
251         }
252         sprintf( full, "%s%s", qdir, path );
253         return full;
254 }
255
256 char *copystring( const char *s ){
257         char    *b;
258         b = safe_malloc( strlen( s ) + 1 );
259         strcpy( b, s );
260         return b;
261 }
262
263
264
265 /*
266    ================
267    I_FloatTime
268    ================
269  */
270 double I_FloatTime( void ){
271         time_t t;
272
273         time( &t );
274
275         return t;
276 #if 0
277 // more precise, less portable
278         struct timeval tp;
279         struct timezone tzp;
280         static int secbase;
281
282         gettimeofday( &tp, &tzp );
283
284         if ( !secbase ) {
285                 secbase = tp.tv_sec;
286                 return tp.tv_usec / 1000000.0;
287         }
288
289         return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
290 #endif
291 }
292
293 void Q_getwd( char *out ){
294         int i = 0;
295
296 #if GDEF_OS_WINDOWS
297         _getcwd( out, 256 );
298         strcat( out, "\\" );
299 #else
300         // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
301         if ( !getcwd( out, 256 ) ) {
302                 *out = 0;
303         }
304         strcat( out, "/" );
305 #endif
306         while ( out[i] != 0 )
307         {
308                 if ( out[i] == '\\' ) {
309                         out[i] = '/';
310                 }
311                 i++;
312         }
313 }
314
315
316 void Q_mkdir( const char *path ){
317         char parentbuf[256];
318         const char *p = NULL;
319         int retry = 2;
320         while ( retry-- )
321         {
322 #if GDEF_OS_WINDOWS
323                 const char *q = NULL;
324                 if ( _mkdir( path ) != -1 ) {
325                         return;
326                 }
327                 if ( errno == ENOENT ) {
328                         p = strrchr( path, '/' );
329                         q = strrchr( path, '\\' );
330                         if ( q && ( !p || q < p ) ) {
331                                 p = q;
332                         }
333                 }
334 #else
335                 if ( mkdir( path, 0777 ) != -1 ) {
336                         return;
337                 }
338                 if ( errno == ENOENT ) {
339                         p = strrchr( path, '/' );
340                 }
341 #endif
342                 if ( p ) {
343                         strncpy( parentbuf, path, sizeof( parentbuf ) );
344                         if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
345                                 parentbuf[p - path] = 0;
346                                 Sys_Printf( "mkdir: %s: creating parent %s first\n", path, parentbuf );
347                                 Q_mkdir( parentbuf );
348                                 continue;
349                         }
350                 }
351                 break;
352         }
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 #if GDEF_ARCH_ENDIAN_BIG
887
888 short   LittleShort( short l ){
889         byte b1,b2;
890
891         b1 = l & 255;
892         b2 = ( l >> 8 ) & 255;
893
894         return ( b1 << 8 ) + b2;
895 }
896
897 short   BigShort( short l ){
898         return l;
899 }
900
901
902 int    LittleLong( int l ){
903         byte b1,b2,b3,b4;
904
905         b1 = l & 255;
906         b2 = ( l >> 8 ) & 255;
907         b3 = ( l >> 16 ) & 255;
908         b4 = ( l >> 24 ) & 255;
909
910         return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
911 }
912
913 int    BigLong( int l ){
914         return l;
915 }
916
917
918 float   LittleFloat( float l ){
919         union {byte b[4]; float f; } in, out;
920
921         in.f = l;
922         out.b[0] = in.b[3];
923         out.b[1] = in.b[2];
924         out.b[2] = in.b[1];
925         out.b[3] = in.b[0];
926
927         return out.f;
928 }
929
930 float   BigFloat( float l ){
931         return l;
932 }
933
934
935 #else
936
937
938 short   BigShort( short l ){
939         byte b1,b2;
940
941         b1 = l & 255;
942         b2 = ( l >> 8 ) & 255;
943
944         return ( b1 << 8 ) + b2;
945 }
946
947 short   LittleShort( short l ){
948         return l;
949 }
950
951
952 int    BigLong( int l ){
953         byte b1,b2,b3,b4;
954
955         b1 = l & 255;
956         b2 = ( l >> 8 ) & 255;
957         b3 = ( l >> 16 ) & 255;
958         b4 = ( l >> 24 ) & 255;
959
960         return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
961 }
962
963 int    LittleLong( int l ){
964         return l;
965 }
966
967 float   BigFloat( float l ){
968         union {byte b[4]; float f; } in, out;
969
970         in.f = l;
971         out.b[0] = in.b[3];
972         out.b[1] = in.b[2];
973         out.b[2] = in.b[1];
974         out.b[3] = in.b[0];
975
976         return out.f;
977 }
978
979 float   LittleFloat( float l ){
980         return l;
981 }
982
983
984 #endif
985
986
987 //=======================================================
988
989
990 // FIXME: byte swap?
991
992 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
993 // and the initial and final xor values shown below...  in other words, the
994 // CCITT standard CRC used by XMODEM
995
996 #define CRC_INIT_VALUE  0xffff
997 #define CRC_XOR_VALUE   0x0000
998
999 static unsigned short crctable[256] =
1000 {
1001         0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1002         0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1003         0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1004         0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1005         0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1006         0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1007         0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1008         0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1009         0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1010         0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1011         0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1012         0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1013         0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1014         0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1015         0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1016         0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1017         0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1018         0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1019         0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1020         0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1021         0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1022         0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1023         0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1024         0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1025         0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1026         0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1027         0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1028         0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1029         0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1030         0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1031         0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1032         0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1033 };
1034
1035 void CRC_Init( unsigned short *crcvalue ){
1036         *crcvalue = CRC_INIT_VALUE;
1037 }
1038
1039 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1040         *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1041 }
1042
1043 unsigned short CRC_Value( unsigned short crcvalue ){
1044         return crcvalue ^ CRC_XOR_VALUE;
1045 }
1046 //=============================================================================
1047
1048 /*
1049    ============
1050    CreatePath
1051    ============
1052  */
1053 void    CreatePath( const char *path ){
1054         const char  *ofs;
1055         char c;
1056         char dir[1024];
1057
1058 #if GDEF_OS_WINDOWS
1059         int olddrive = -1;
1060
1061         if ( path[1] == ':' ) {
1062                 olddrive = _getdrive();
1063                 _chdrive( toupper( path[0] ) - 'A' + 1 );
1064         }
1065 #endif
1066
1067         if ( path[1] == ':' ) {
1068                 path += 2;
1069         }
1070
1071         for ( ofs = path + 1 ; *ofs ; ofs++ )
1072         {
1073                 c = *ofs;
1074                 if ( c == '/' || c == '\\' ) { // create the directory
1075                         memcpy( dir, path, ofs - path );
1076                         dir[ ofs - path ] = 0;
1077                         Q_mkdir( dir );
1078                 }
1079         }
1080
1081 #if GDEF_OS_WINDOWS
1082         if ( olddrive != -1 ) {
1083                 _chdrive( olddrive );
1084         }
1085 #endif
1086 }
1087
1088
1089 /*
1090    ============
1091    QCopyFile
1092
1093    Used to archive source files
1094    ============
1095  */
1096 void QCopyFile( const char *from, const char *to ){
1097         void    *buffer;
1098         int length;
1099
1100         length = LoadFile( from, &buffer );
1101         CreatePath( to );
1102         SaveFile( to, buffer, length );
1103         free( buffer );
1104 }
1105
1106 void Sys_Sleep( int n ){
1107 #if GDEF_OS_WINDOWS
1108         Sleep( n );
1109 #endif
1110 #if GDEF_OS_LINUX || GDEF_OS_MACOS
1111         usleep( n * 1000 );
1112 #endif
1113 }