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