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