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