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