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