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