2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
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.
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.
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
22 // Nurail: Swiped from quake3/common
25 #include "globaldefs.h"
29 #include <sys/types.h>
35 #else // !GDEF_OS_WINDOWS
37 #endif // !GDEF_OS_WINDOWS
43 #define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
44 #define HERETIC2_BASEDIRNAME "h"
45 #define PATHSEPERATOR '/'
47 // qboolean verbose = false;
49 void *safe_malloc( size_t size ){
54 Error( "safe_malloc failed on allocation of %i bytes", size );
61 void *safe_malloc_info( size_t size, char* info ){
66 Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
73 // set these before calling CheckParm
81 char archivedir[1024];
88 Mimic unix command line expansion
91 #define MAX_EX_ARGC 1024
93 char *ex_argv[MAX_EX_ARGC];
96 void ExpandWildcards( int *argc, char ***argv ){
97 struct _finddata_t fileinfo;
105 for ( i = 0 ; i < *argc ; i++ )
109 || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
110 ex_argv[ex_argc++] = path;
114 handle = _findfirst( path, &fileinfo );
115 if ( handle == -1 ) {
119 ExtractFilePath( path, filebase );
123 sprintf( filename, "%s%s", filebase, fileinfo.name );
124 ex_argv[ex_argc++] = copystring( filename );
125 } while ( _findnext( handle, &fileinfo ) != -1 );
127 _findclose( handle );
134 void ExpandWildcards( int *argc, char ***argv ){
140 qdir will hold the path up to the quake directory, including the slash
145 gamedir will hold qdir + the game directory (id1, id2, etc)
153 void SetQdirFromPath( const char *path ){
158 char basedirname[256];
160 if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
162 strcat( temp, path );
166 // search for "quake2" in path
168 if ( !strcmp( game, "heretic2" ) ) {
169 strncpy( basedirname, HERETIC2_BASEDIRNAME, 256 );
172 strncpy( basedirname, BASEDIRNAME, 256 );
175 len = strlen( basedirname );
176 for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
180 if ( !Q_strncasecmp( c, basedirname, len ) ) {
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
188 while ( *sep && *sep != '/' && *sep != '\\' )
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++ )
197 if ( qdir[i] == '\\' ) {
205 if ( *c == '/' || *c == '\\' ) {
206 strncpy( gamedir, path, c + 1 - path );
208 for ( i = 0; i < strlen( gamedir ); i++ )
210 if ( gamedir[i] == '\\' ) {
215 Sys_FPrintf( SYS_VRB, "gamedir: %s\n", gamedir );
217 if ( !writedir[0] ) {
218 strcpy( writedir, gamedir );
220 else if ( writedir[strlen( writedir ) - 1] != '/' ) {
221 writedir[strlen( writedir )] = '/';
222 writedir[strlen( writedir ) + 1] = 0;
229 Error( "No gamedir in %s", path );
233 Error( "SetQdirFromPath: no '%s' in %s", basedirname, path );
236 char *ExpandArg( const char *path ){
237 static char full[1024];
239 if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
241 strcat( full, path );
244 strcpy( full, path );
249 char *ExpandPath( const char *path ){
250 static char full[1024];
252 Error( "ExpandPath called without qdir set" );
254 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
255 strcpy( full, path );
258 sprintf( full, "%s%s", qdir, path );
262 char *ExpandGamePath( const char *path ){
263 static char full[1024];
265 Error( "ExpandGamePath called without qdir set" );
267 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
268 strcpy( full, path );
271 sprintf( full, "%s%s", gamedir, path );
275 char *ExpandPathAndArchive( const char *path ){
277 char archivename[1024];
279 expanded = ExpandPath( path );
282 sprintf( archivename, "%s/%s", archivedir, path );
283 QCopyFile( expanded, archivename );
289 char *copystring( const char *s ){
291 b = safe_malloc( strlen( s ) + 1 );
303 double I_FloatTime( void ){
310 // more precise, less portable
315 gettimeofday( &tp, &tzp );
319 return tp.tv_usec / 1000000.0;
322 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
326 void Q_getwd( char *out ){
333 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
337 while ( out[i] != 0 )
339 if ( out[i] == '\\' ) {
347 void Q_mkdir( const char *path ){
349 if ( _mkdir( path ) != -1 ) {
353 if ( mkdir( path, 0777 ) != -1 ) {
357 if ( errno != EEXIST ) {
358 Error( "mkdir %s: %s",path, strerror( errno ) );
366 returns -1 if not present
369 int FileTime( const char *path ){
372 if ( stat( path,&buf ) == -1 ) {
385 Parse a token out of a string
388 char *COM_Parse( char *data ){
401 while ( ( c = *data ) <= ' ' )
405 return NULL; // end of file;
411 if ( c == '/' && data[1] == '/' ) {
412 while ( *data && *data != '\n' )
418 // handle quoted strings specially
433 // parse single characters
434 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
441 // parse a regular word
448 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
457 int Q_strncasecmp( const char *s1, const char *s2, int n ){
466 return 0; // strings are equal until end point
470 if ( c1 >= 'a' && c1 <= 'z' ) {
473 if ( c2 >= 'a' && c2 <= 'z' ) {
477 return -1; // strings not equal
482 return 0; // strings are equal
485 int Q_stricmp( const char *s1, const char *s2 ){
486 return Q_strncasecmp( s1, s2, 99999 );
489 int Q_strcasecmp( const char *s1, const char *s2 ){
490 return Q_strncasecmp( s1, s2, 99999 );
494 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
495 // started getting warnings about that function, prolly a duplicate with the runtime function
496 // maybe we still need to have it in linux builds
498 char *strupr (char *start)
511 char *strlower( char *start ){
516 *in = tolower( *in );
524 =============================================================================
528 =============================================================================
536 Checks for the given parameter in the program's command line arguments
537 Returns the argument number (1 to argc-1) or 0 if not present
540 int CheckParm( const char *check ){
543 for ( i = 1; i < myargc; i++ )
545 if ( !Q_stricmp( check, myargv[i] ) ) {
560 int Q_filelength( FILE *f ){
565 fseek( f, 0, SEEK_END );
567 fseek( f, pos, SEEK_SET );
573 FILE *SafeOpenWrite( const char *filename ){
576 f = fopen( filename, "wb" );
579 Error( "Error opening %s: %s",filename,strerror( errno ) );
585 FILE *SafeOpenRead( const char *filename ){
588 f = fopen( filename, "rb" );
591 Error( "Error opening %s: %s",filename,strerror( errno ) );
598 void SafeRead( FILE *f, void *buffer, int count ){
599 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
600 Error( "File read failure" );
605 void SafeWrite( FILE *f, const void *buffer, int count ){
606 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
607 Error( "File write failure" );
617 qboolean FileExists( const char *filename ){
620 f = fopen( filename, "r" );
633 int LoadFile( const char *filename, void **bufferptr ){
638 f = SafeOpenRead( filename );
639 length = Q_filelength( f );
640 buffer = safe_malloc( length + 1 );
641 ( (char *)buffer )[length] = 0;
642 SafeRead( f, buffer, length );
654 rounds up memory allocation to 4K boundry
658 int LoadFileBlock( const char *filename, void **bufferptr ){
660 int length, nBlock, nAllocSize;
663 f = SafeOpenRead( filename );
664 length = Q_filelength( f );
666 nBlock = nAllocSize % MEM_BLOCKSIZE;
668 nAllocSize += MEM_BLOCKSIZE - nBlock;
670 buffer = safe_malloc( nAllocSize + 1 );
671 memset( buffer, 0, nAllocSize + 1 );
672 SafeRead( f, buffer, length );
687 int TryLoadFile( const char *filename, void **bufferptr ){
694 f = fopen( filename, "rb" );
698 length = Q_filelength( f );
699 buffer = safe_malloc( length + 1 );
700 ( (char *)buffer )[length] = 0;
701 SafeRead( f, buffer, length );
714 void SaveFile( const char *filename, const void *buffer, int count ){
717 f = SafeOpenWrite( filename );
718 SafeWrite( f, buffer, count );
724 void DefaultExtension( char *path, const char *extension ){
727 // if path doesnt have a .EXT, append extension
728 // (extension should include the .)
730 src = path + strlen( path ) - 1;
732 while ( *src != '/' && *src != '\\' && src != path )
735 return; // it has an extension
740 strcat( path, extension );
744 void DefaultPath( char *path, const char *basepath ){
747 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
748 return; // absolute path location
751 strcpy( path,basepath );
756 void StripFilename( char *path ){
759 length = strlen( path ) - 1;
760 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
765 void StripExtension( char *path ){
768 length = strlen( path ) - 1;
769 while ( length > 0 && path[length] != '.' )
772 if ( path[length] == '/' || path[ length ] == '\\' ) {
773 return; // no extension
787 // FIXME: should include the slash, otherwise
788 // backing to an empty path will be wrong when appending a slash
789 void ExtractFilePath( const char *path, char *dest ){
792 src = path + strlen( path ) - 1;
795 // back up until a \ or the start
797 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
800 memcpy( dest, path, src - path );
801 dest[src - path] = 0;
804 void ExtractFileBase( const char *path, char *dest ){
807 src = path + strlen( path ) - 1;
810 // back up until a \ or the start
812 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
815 while ( *src && *src != '.' )
822 void ExtractFileExtension( const char *path, char *dest ){
825 src = path + strlen( path ) - 1;
828 // back up until a . or the start
830 while ( src != path && *( src - 1 ) != '.' )
833 *dest = 0; // no extension
846 int ParseHex( const char *hex ){
856 if ( *str >= '0' && *str <= '9' ) {
859 else if ( *str >= 'a' && *str <= 'f' ) {
860 num += 10 + *str - 'a';
862 else if ( *str >= 'A' && *str <= 'F' ) {
863 num += 10 + *str - 'A';
866 Error( "Bad hex number: %s",hex );
875 int ParseNum( const char *str ){
876 if ( str[0] == '$' ) {
877 return ParseHex( str + 1 );
879 if ( str[0] == '0' && str[1] == 'x' ) {
880 return ParseHex( str + 2 );
885 // all output ends up through here
886 void FPrintf (int flag, char *buf)
892 void Sys_FPrintf (int flag, const char *format, ...)
894 char out_buffer[4096];
897 if ((flag == SYS_VRB) && (verbose == false))
900 va_start (argptr, format);
901 vsprintf (out_buffer, format, argptr);
904 FPrintf (flag, out_buffer);
907 void Sys_Printf (const char *format, ...)
909 char out_buffer[4096];
912 va_start (argptr, format);
913 vsprintf (out_buffer, format, argptr);
916 FPrintf (SYS_STD, out_buffer);
923 //For abnormal program terminations
926 void Error( const char *error, ...)
928 char out_buffer[4096];
932 va_start (argptr,error);
933 vsprintf (tmp, error, argptr);
936 sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
938 FPrintf( SYS_ERR, out_buffer );
946 ============================================================================
950 ============================================================================
953 #if GDEF_ARCH_ENDIAN_BIG
955 short LittleShort( short l ){
959 b2 = ( l >> 8 ) & 255;
961 return ( b1 << 8 ) + b2;
964 short BigShort( short l ){
969 int LittleLong( int l ){
973 b2 = ( l >> 8 ) & 255;
974 b3 = ( l >> 16 ) & 255;
975 b4 = ( l >> 24 ) & 255;
977 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
980 int BigLong( int l ){
985 float LittleFloat( float l ){
986 union {byte b[4]; float f; } in, out;
997 float BigFloat( float l ){
1005 short BigShort( short l ){
1009 b2 = ( l >> 8 ) & 255;
1011 return ( b1 << 8 ) + b2;
1014 short LittleShort( short l ){
1019 int BigLong( int l ){
1023 b2 = ( l >> 8 ) & 255;
1024 b3 = ( l >> 16 ) & 255;
1025 b4 = ( l >> 24 ) & 255;
1027 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
1030 int LittleLong( int l ){
1034 float BigFloat( float l ){
1035 union {byte b[4]; float f; } in, out;
1046 float LittleFloat( float l ){
1054 //=======================================================
1057 // FIXME: byte swap?
1059 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1060 // and the initial and final xor values shown below... in other words, the
1061 // CCITT standard CRC used by XMODEM
1063 #define CRC_INIT_VALUE 0xffff
1064 #define CRC_XOR_VALUE 0x0000
1066 static unsigned short crctable[256] =
1068 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1069 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1070 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1071 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1072 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1073 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1074 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1075 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1076 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1077 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1078 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1079 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1080 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1081 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1082 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1083 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1084 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1085 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1086 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1087 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1088 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1089 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1090 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1091 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1092 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1093 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1094 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1095 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1096 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1097 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1098 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1099 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1102 void CRC_Init( unsigned short *crcvalue ){
1103 *crcvalue = CRC_INIT_VALUE;
1106 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1107 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1110 unsigned short CRC_Value( unsigned short crcvalue ){
1111 return crcvalue ^ CRC_XOR_VALUE;
1113 //=============================================================================
1120 void CreatePath( const char *path ){
1128 if ( path[1] == ':' ) {
1129 olddrive = _getdrive();
1130 _chdrive( toupper( path[0] ) - 'A' + 1 );
1134 if ( path[1] == ':' ) {
1138 for ( ofs = path + 1 ; *ofs ; ofs++ )
1141 if ( c == '/' || c == '\\' ) { // create the directory
1142 memcpy( dir, path, ofs - path );
1143 dir[ ofs - path ] = 0;
1149 if ( olddrive != -1 ) {
1150 _chdrive( olddrive );
1160 Used to archive source files
1163 void QCopyFile( const char *from, const char *to ){
1167 length = LoadFile( from, &buffer );
1169 SaveFile( to, buffer, length );
1173 void Sys_Sleep( int n ){
1176 #else // !GDEF_OS_WINDOWS
1178 #endif // !GDEF_OS_WINDOWS