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