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