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