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