]> git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/common/cmdlib.c
0b65ddaaeff9c6eb1db84dded47725ac49c09c74
[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 #if !GDEF_OS_WINDOWS
494 char *strupr (char *start)
495 {
496         char *in;
497         in = start;
498         while (*in)
499         {
500                 *in = toupper(*in);
501                 in++;
502         }
503         return start;
504 }
505 #endif
506
507 char *strlower( char *start ){
508         char    *in;
509         in = start;
510         while ( *in )
511         {
512                 *in = tolower( *in );
513                 in++;
514         }
515         return start;
516 }
517
518
519 /*
520    =============================================================================
521
522                         MISC FUNCTIONS
523
524    =============================================================================
525  */
526
527
528 /*
529    =================
530    CheckParm
531
532    Checks for the given parameter in the program's command line arguments
533    Returns the argument number (1 to argc-1) or 0 if not present
534    =================
535  */
536 int CheckParm( const char *check ){
537         int i;
538
539         for ( i = 1; i < myargc; i++ )
540         {
541                 if ( !Q_stricmp( check, myargv[i] ) ) {
542                         return i;
543                 }
544         }
545
546         return 0;
547 }
548
549
550
551 /*
552    ================
553    Q_filelength
554    ================
555  */
556 int Q_filelength( FILE *f ){
557         int pos;
558         int end;
559
560         pos = ftell( f );
561         fseek( f, 0, SEEK_END );
562         end = ftell( f );
563         fseek( f, pos, SEEK_SET );
564
565         return end;
566 }
567
568
569 FILE *SafeOpenWrite( const char *filename ){
570         FILE    *f;
571
572         f = fopen( filename, "wb" );
573
574         if ( !f ) {
575                 Error( "Error opening %s: %s",filename,strerror( errno ) );
576         }
577
578         return f;
579 }
580
581 FILE *SafeOpenRead( const char *filename ){
582         FILE    *f;
583
584         f = fopen( filename, "rb" );
585
586         if ( !f ) {
587                 Error( "Error opening %s: %s",filename,strerror( errno ) );
588         }
589
590         return f;
591 }
592
593
594 void SafeRead( FILE *f, void *buffer, int count ){
595         if ( fread( buffer, 1, count, f ) != (size_t)count ) {
596                 Error( "File read failure" );
597         }
598 }
599
600
601 void SafeWrite( FILE *f, const void *buffer, int count ){
602         if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
603                 Error( "File write failure" );
604         }
605 }
606
607
608 /*
609    ==============
610    FileExists
611    ==============
612  */
613 qboolean    FileExists( const char *filename ){
614         FILE    *f;
615
616         f = fopen( filename, "r" );
617         if ( !f ) {
618                 return false;
619         }
620         fclose( f );
621         return true;
622 }
623
624 /*
625    ==============
626    LoadFile
627    ==============
628  */
629 int    LoadFile( const char *filename, void **bufferptr ){
630         FILE    *f;
631         int length;
632         void    *buffer;
633
634         f = SafeOpenRead( filename );
635         length = Q_filelength( f );
636         buffer = safe_malloc( length + 1 );
637         ( (char *)buffer )[length] = 0;
638         SafeRead( f, buffer, length );
639         fclose( f );
640
641         *bufferptr = buffer;
642         return length;
643 }
644
645
646 /*
647    ==============
648    LoadFileBlock
649    -
650    rounds up memory allocation to 4K boundry
651    -
652    ==============
653  */
654 int    LoadFileBlock( const char *filename, void **bufferptr ){
655         FILE    *f;
656         int length, nBlock, nAllocSize;
657         void    *buffer;
658
659         f = SafeOpenRead( filename );
660         length = Q_filelength( f );
661         nAllocSize = length;
662         nBlock = nAllocSize % MEM_BLOCKSIZE;
663         if ( nBlock > 0 ) {
664                 nAllocSize += MEM_BLOCKSIZE - nBlock;
665         }
666         buffer = safe_malloc( nAllocSize + 1 );
667         memset( buffer, 0, nAllocSize + 1 );
668         SafeRead( f, buffer, length );
669         fclose( f );
670
671         *bufferptr = buffer;
672         return length;
673 }
674
675
676 /*
677    ==============
678    TryLoadFile
679
680    Allows failure
681    ==============
682  */
683 int    TryLoadFile( const char *filename, void **bufferptr ){
684         FILE    *f;
685         int length;
686         void    *buffer;
687
688         *bufferptr = NULL;
689
690         f = fopen( filename, "rb" );
691         if ( !f ) {
692                 return -1;
693         }
694         length = Q_filelength( f );
695         buffer = safe_malloc( length + 1 );
696         ( (char *)buffer )[length] = 0;
697         SafeRead( f, buffer, length );
698         fclose( f );
699
700         *bufferptr = buffer;
701         return length;
702 }
703
704
705 /*
706    ==============
707    SaveFile
708    ==============
709  */
710 void    SaveFile( const char *filename, const void *buffer, int count ){
711         FILE    *f;
712
713         f = SafeOpenWrite( filename );
714         SafeWrite( f, buffer, count );
715         fclose( f );
716 }
717
718
719
720 void DefaultExtension( char *path, const char *extension ){
721         char    *src;
722 //
723 // if path doesnt have a .EXT, append extension
724 // (extension should include the .)
725 //
726         src = path + strlen( path ) - 1;
727
728         while ( *src != '/' && *src != '\\' && src != path )
729         {
730                 if ( *src == '.' ) {
731                         return;                 // it has an extension
732                 }
733                 src--;
734         }
735
736         strcat( path, extension );
737 }
738
739
740 void DefaultPath( char *path, const char *basepath ){
741         char temp[128];
742
743         if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
744                 return;                   // absolute path location
745         }
746         strcpy( temp,path );
747         strcpy( path,basepath );
748         strcat( path,temp );
749 }
750
751
752 void    StripFilename( char *path ){
753         int length;
754
755         length = strlen( path ) - 1;
756         while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
757                 length--;
758         path[length] = 0;
759 }
760
761 void    StripExtension( char *path ){
762         int length;
763
764         length = strlen( path ) - 1;
765         while ( length > 0 && path[length] != '.' )
766         {
767                 length--;
768                 if ( path[length] == '/' || path[ length ] == '\\' ) {
769                         return;     // no extension
770                 }
771         }
772         if ( length ) {
773                 path[length] = 0;
774         }
775 }
776
777
778 /*
779    ====================
780    Extract file parts
781    ====================
782  */
783 // FIXME: should include the slash, otherwise
784 // backing to an empty path will be wrong when appending a slash
785 void ExtractFilePath( const char *path, char *dest ){
786         const char    *src;
787
788         src = path + strlen( path ) - 1;
789
790 //
791 // back up until a \ or the start
792 //
793         while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
794                 src--;
795
796         memcpy( dest, path, src - path );
797         dest[src - path] = 0;
798 }
799
800 void ExtractFileBase( const char *path, char *dest ){
801         const char    *src;
802
803         src = path + strlen( path ) - 1;
804
805 //
806 // back up until a \ or the start
807 //
808         while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
809                 src--;
810
811         while ( *src && *src != '.' )
812         {
813                 *dest++ = *src++;
814         }
815         *dest = 0;
816 }
817
818 void ExtractFileExtension( const char *path, char *dest ){
819         const char    *src;
820
821         src = path + strlen( path ) - 1;
822
823 //
824 // back up until a . or the start
825 //
826         while ( src != path && *( src - 1 ) != '.' )
827                 src--;
828         if ( src == path ) {
829                 *dest = 0;  // no extension
830                 return;
831         }
832
833         strcpy( dest,src );
834 }
835
836
837 /*
838    ==============
839    ParseNum / ParseHex
840    ==============
841  */
842 int ParseHex( const char *hex ){
843         const char    *str;
844         int num;
845
846         num = 0;
847         str = hex;
848
849         while ( *str )
850         {
851                 num <<= 4;
852                 if ( *str >= '0' && *str <= '9' ) {
853                         num += *str - '0';
854                 }
855                 else if ( *str >= 'a' && *str <= 'f' ) {
856                         num += 10 + *str - 'a';
857                 }
858                 else if ( *str >= 'A' && *str <= 'F' ) {
859                         num += 10 + *str - 'A';
860                 }
861                 else{
862                         Error( "Bad hex number: %s",hex );
863                 }
864                 str++;
865         }
866
867         return num;
868 }
869
870
871 int ParseNum( const char *str ){
872         if ( str[0] == '$' ) {
873                 return ParseHex( str + 1 );
874         }
875         if ( str[0] == '0' && str[1] == 'x' ) {
876                 return ParseHex( str + 2 );
877         }
878         return atol( str );
879 }
880 /*
881    // all output ends up through here
882    void FPrintf (int flag, char *buf)
883    {
884    printf(buf);
885
886    }
887
888    void Sys_FPrintf (int flag, const char *format, ...)
889    {
890    char out_buffer[4096];
891     va_list argptr;
892
893    if ((flag == SYS_VRB) && (verbose == false))
894     return;
895
896    va_start (argptr, format);
897     vsprintf (out_buffer, format, argptr);
898     va_end (argptr);
899
900    FPrintf (flag, out_buffer);
901    }
902
903    void Sys_Printf (const char *format, ...)
904    {
905    char out_buffer[4096];
906     va_list argptr;
907
908    va_start (argptr, format);
909     vsprintf (out_buffer, format, argptr);
910     va_end (argptr);
911
912    FPrintf (SYS_STD, out_buffer);
913    }
914
915
916    //=================
917    //Error
918    //
919    //For abnormal program terminations
920    //=================
921
922    void Error( const char *error, ...)
923    {
924    char out_buffer[4096];
925    char tmp[4096];
926     va_list argptr;
927
928     va_start (argptr,error);
929     vsprintf (tmp, error, argptr);
930     va_end (argptr);
931
932    sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
933
934    FPrintf( SYS_ERR, out_buffer );
935
936     exit (1);
937    }
938  */
939
940
941 /*
942    ============================================================================
943
944                     BYTE ORDER FUNCTIONS
945
946    ============================================================================
947  */
948
949 #if GDEF_ARCH_ENDIAN_BIG
950
951 short   LittleShort( short l ){
952         byte b1,b2;
953
954         b1 = l & 255;
955         b2 = ( l >> 8 ) & 255;
956
957         return ( b1 << 8 ) + b2;
958 }
959
960 short   BigShort( short l ){
961         return l;
962 }
963
964
965 int    LittleLong( int l ){
966         byte b1,b2,b3,b4;
967
968         b1 = l & 255;
969         b2 = ( l >> 8 ) & 255;
970         b3 = ( l >> 16 ) & 255;
971         b4 = ( l >> 24 ) & 255;
972
973         return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
974 }
975
976 int    BigLong( int l ){
977         return l;
978 }
979
980
981 float   LittleFloat( float l ){
982         union {byte b[4]; float f; } in, out;
983
984         in.f = l;
985         out.b[0] = in.b[3];
986         out.b[1] = in.b[2];
987         out.b[2] = in.b[1];
988         out.b[3] = in.b[0];
989
990         return out.f;
991 }
992
993 float   BigFloat( float l ){
994         return l;
995 }
996
997
998 #else
999
1000
1001 short   BigShort( short l ){
1002         byte b1,b2;
1003
1004         b1 = l & 255;
1005         b2 = ( l >> 8 ) & 255;
1006
1007         return ( b1 << 8 ) + b2;
1008 }
1009
1010 short   LittleShort( short l ){
1011         return l;
1012 }
1013
1014
1015 int    BigLong( int l ){
1016         byte b1,b2,b3,b4;
1017
1018         b1 = l & 255;
1019         b2 = ( l >> 8 ) & 255;
1020         b3 = ( l >> 16 ) & 255;
1021         b4 = ( l >> 24 ) & 255;
1022
1023         return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
1024 }
1025
1026 int    LittleLong( int l ){
1027         return l;
1028 }
1029
1030 float   BigFloat( float l ){
1031         union {byte b[4]; float f; } in, out;
1032
1033         in.f = l;
1034         out.b[0] = in.b[3];
1035         out.b[1] = in.b[2];
1036         out.b[2] = in.b[1];
1037         out.b[3] = in.b[0];
1038
1039         return out.f;
1040 }
1041
1042 float   LittleFloat( float l ){
1043         return l;
1044 }
1045
1046
1047 #endif
1048
1049
1050 //=======================================================
1051
1052
1053 // FIXME: byte swap?
1054
1055 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1056 // and the initial and final xor values shown below...  in other words, the
1057 // CCITT standard CRC used by XMODEM
1058
1059 #define CRC_INIT_VALUE  0xffff
1060 #define CRC_XOR_VALUE   0x0000
1061
1062 static unsigned short crctable[256] =
1063 {
1064         0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1065         0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1066         0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1067         0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1068         0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1069         0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1070         0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1071         0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1072         0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1073         0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1074         0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1075         0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1076         0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1077         0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1078         0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1079         0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1080         0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1081         0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1082         0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1083         0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1084         0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1085         0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1086         0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1087         0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1088         0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1089         0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1090         0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1091         0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1092         0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1093         0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1094         0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1095         0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1096 };
1097
1098 void CRC_Init( unsigned short *crcvalue ){
1099         *crcvalue = CRC_INIT_VALUE;
1100 }
1101
1102 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1103         *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1104 }
1105
1106 unsigned short CRC_Value( unsigned short crcvalue ){
1107         return crcvalue ^ CRC_XOR_VALUE;
1108 }
1109 //=============================================================================
1110
1111 /*
1112    ============
1113    CreatePath
1114    ============
1115  */
1116 void    CreatePath( const char *path ){
1117         const char  *ofs;
1118         char c;
1119         char dir[1024];
1120
1121 #if GDEF_OS_WINDOWS
1122         int olddrive = -1;
1123
1124         if ( path[1] == ':' ) {
1125                 olddrive = _getdrive();
1126                 _chdrive( toupper( path[0] ) - 'A' + 1 );
1127         }
1128 #endif
1129
1130         if ( path[1] == ':' ) {
1131                 path += 2;
1132         }
1133
1134         for ( ofs = path + 1 ; *ofs ; ofs++ )
1135         {
1136                 c = *ofs;
1137                 if ( c == '/' || c == '\\' ) { // create the directory
1138                         memcpy( dir, path, ofs - path );
1139                         dir[ ofs - path ] = 0;
1140                         Q_mkdir( dir );
1141                 }
1142         }
1143
1144 #if GDEF_OS_WINDOWS
1145         if ( olddrive != -1 ) {
1146                 _chdrive( olddrive );
1147         }
1148 #endif
1149 }
1150
1151
1152 /*
1153    ============
1154    QCopyFile
1155
1156    Used to archive source files
1157    ============
1158  */
1159 void QCopyFile( const char *from, const char *to ){
1160         void    *buffer;
1161         int length;
1162
1163         length = LoadFile( from, &buffer );
1164         CreatePath( to );
1165         SaveFile( to, buffer, length );
1166         free( buffer );
1167 }
1168
1169 void Sys_Sleep( int n ){
1170 #if GDEF_OS_WINDOWS
1171         Sleep( n );
1172 #else // !GDEF_OS_WINDOWS
1173         usleep( n * 1000 );
1174 #endif // !GDEF_OS_WINDOWS
1175 }