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