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