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