2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
5 This file is part of Quake 2 Tools source code.
7 Quake 2 Tools source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
12 Quake 2 Tools source code is distributed in the hope that it will be
13 useful, 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 Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
26 #include "globaldefs.h"
28 #include <sys/types.h>
39 #define BASEDIRNAME "quake2"
40 #define PATHSEPERATOR '/'
42 // set these before calling CheckParm
50 char archivedir[1024];
57 Mimic unix command line expansion
60 #define MAX_EX_ARGC 1024
62 char *ex_argv[MAX_EX_ARGC];
65 void ExpandWildcards (int *argc, char ***argv)
67 struct _finddata_t fileinfo;
75 for (i=0 ; i<*argc ; i++)
79 || ( !strstr(path, "*") && !strstr(path, "?") ) )
81 ex_argv[ex_argc++] = path;
85 handle = _findfirst (path, &fileinfo);
89 ExtractFilePath (path, filebase);
93 sprintf (filename, "%s%s", filebase, fileinfo.name);
94 ex_argv[ex_argc++] = copystring (filename);
95 } while (_findnext( handle, &fileinfo ) != -1);
104 void ExpandWildcards (int *argc, char ***argv)
115 For abnormal program terminations in windowed apps
118 void Error (char *error, ...)
125 err = GetLastError ();
127 va_start (argptr,error);
128 vsprintf (text, error,argptr);
131 sprintf (text2, "%s\nGetLastError() = %i", text, err);
132 MessageBox(NULL, text2, "Error", 0 /* MB_OK */ );
142 For abnormal program terminations in console apps
145 void Error (char *error, ...)
149 printf ("\n************ ERROR ************\n");
151 va_start (argptr,error);
152 vprintf (error,argptr);
160 // only printf if in verbose mode
161 qboolean verbose = false;
162 void qprintf (char *format, ...)
169 va_start (argptr,format);
170 vprintf (format,argptr);
177 qdir will hold the path up to the quake directory, including the slash
182 gamedir will hold qdir + the game directory (id1, id2, etc)
189 void SetQdirFromPath (char *path)
195 if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
202 // search for "quake2" in path
204 len = strlen(BASEDIRNAME);
205 for (c=path+strlen(path)-1 ; c != path ; c--)
206 if (!Q_strncasecmp (c, BASEDIRNAME, len))
208 strncpy (qdir, path, c+len+1-path);
209 qprintf ("qdir: %s\n", qdir);
213 if (*c == '/' || *c == '\\')
215 strncpy (gamedir, path, c+1-path);
216 qprintf ("gamedir: %s\n", gamedir);
221 Error ("No gamedir in %s", path);
224 Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
227 char *ExpandArg (char *path)
229 static char full[1024];
231 if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
241 char *ExpandPath (char *path)
243 static char full[1024];
245 Error ("ExpandPath called without qdir set");
246 if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
248 sprintf (full, "%s%s", qdir, path);
252 char *ExpandPathAndArchive (char *path)
255 char archivename[1024];
257 expanded = ExpandPath (path);
261 sprintf (archivename, "%s/%s", archivedir, path);
262 QCopyFile (expanded, archivename);
268 char *copystring(char *s)
271 b = malloc(strlen(s)+1);
283 double I_FloatTime (void)
291 // more precise, less portable
296 gettimeofday(&tp, &tzp);
301 return tp.tv_usec/1000000.0;
304 return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
308 void Q_getwd (char *out)
320 void Q_mkdir (char *path)
323 if (_mkdir (path) != -1)
326 if (mkdir (path, 0777) != -1)
330 Error ("mkdir %s: %s",path, strerror(errno));
337 returns -1 if not present
340 int FileTime (char *path)
344 if (stat (path,&buf) == -1)
356 Parse a token out of a string
359 char *COM_Parse (char *data)
372 while ( (c = *data) <= ' ')
377 return NULL; // end of file;
383 if (c=='/' && data[1] == '/')
385 while (*data && *data != '\n')
391 // handle quoted strings specially
408 // parse single characters
409 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
417 // parse a regular word
424 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
433 int Q_strncasecmp (char *s1, char *s2, int n)
443 return 0; // strings are equal until end point
447 if (c1 >= 'a' && c1 <= 'z')
449 if (c2 >= 'a' && c2 <= 'z')
452 return -1; // strings not equal
456 return 0; // strings are equal
459 int Q_strcasecmp (char *s1, char *s2)
461 return Q_strncasecmp (s1, s2, 99999);
464 // May be already defined with some compilers on Windows
466 char *strupr (char *start)
479 char *strlower (char *start)
493 =============================================================================
497 =============================================================================
505 Checks for the given parameter in the program's command line arguments
506 Returns the argument number (1 to argc-1) or 0 if not present
509 int CheckParm (char *check)
513 for (i = 1;i<myargc;i++)
515 if ( !Q_strcasecmp(check, myargv[i]) )
529 int Q_filelength (FILE *f)
535 fseek (f, 0, SEEK_END);
537 fseek (f, pos, SEEK_SET);
543 FILE *SafeOpenWrite (char *filename)
547 f = fopen(filename, "wb");
550 Error ("Error opening %s: %s",filename,strerror(errno));
555 FILE *SafeOpenRead (char *filename)
559 f = fopen(filename, "rb");
562 Error ("Error opening %s: %s",filename,strerror(errno));
568 void SafeRead (FILE *f, void *buffer, int count)
570 if ( fread (buffer, 1, count, f) != (size_t)count)
571 Error ("File read failure");
575 void SafeWrite (FILE *f, void *buffer, int count)
577 if (fwrite (buffer, 1, count, f) != (size_t)count)
578 Error ("File write failure");
587 qboolean FileExists (char *filename)
591 f = fopen (filename, "r");
603 int LoadFile (char *filename, void **bufferptr)
609 f = SafeOpenRead (filename);
610 length = Q_filelength (f);
611 buffer = malloc (length+1);
612 ((char *)buffer)[length] = 0;
613 SafeRead (f, buffer, length);
628 int TryLoadFile (char *filename, void **bufferptr)
636 f = fopen (filename, "rb");
639 length = Q_filelength (f);
640 buffer = malloc (length+1);
641 ((char *)buffer)[length] = 0;
642 SafeRead (f, buffer, length);
655 void SaveFile (char *filename, void *buffer, int count)
659 f = SafeOpenWrite (filename);
660 SafeWrite (f, buffer, count);
666 void DefaultExtension (char *path, char *extension)
670 // if path doesnt have a .EXT, append extension
671 // (extension should include the .)
673 src = path + strlen(path) - 1;
675 while (*src != PATHSEPERATOR && src != path)
678 return; // it has an extension
682 strcat (path, extension);
686 void DefaultPath (char *path, char *basepath)
690 if (path[0] == PATHSEPERATOR)
691 return; // absolute path location
693 strcpy (path,basepath);
698 void StripFilename (char *path)
702 length = strlen(path)-1;
703 while (length > 0 && path[length] != PATHSEPERATOR)
708 void StripExtension (char *path)
712 length = strlen(path)-1;
713 while (length > 0 && path[length] != '.')
716 if (path[length] == '/')
717 return; // no extension
729 // FIXME: should include the slash, otherwise
730 // backing to an empty path will be wrong when appending a slash
731 void ExtractFilePath (char *path, char *dest)
735 src = path + strlen(path) - 1;
738 // back up until a \ or the start
740 while (src != path && *(src-1) != '\\' && *(src-1) != '/')
743 memcpy (dest, path, src-path);
747 void ExtractFileBase (char *path, char *dest)
751 src = path + strlen(path) - 1;
754 // back up until a \ or the start
756 while (src != path && *(src-1) != PATHSEPERATOR)
759 while (*src && *src != '.')
766 void ExtractFileExtension (char *path, char *dest)
770 src = path + strlen(path) - 1;
773 // back up until a . or the start
775 while (src != path && *(src-1) != '.')
779 *dest = 0; // no extension
792 int ParseHex (char *hex)
803 if (*str >= '0' && *str <= '9')
805 else if (*str >= 'a' && *str <= 'f')
806 num += 10 + *str-'a';
807 else if (*str >= 'A' && *str <= 'F')
808 num += 10 + *str-'A';
810 Error ("Bad hex number: %s",hex);
818 int ParseNum (char *str)
821 return ParseHex (str+1);
822 if (str[0] == '0' && str[1] == 'x')
823 return ParseHex (str+2);
830 ============================================================================
834 ============================================================================
837 #if GDEF_ARCH_ENDIAN_BIG
839 short LittleShort (short l)
849 short BigShort (short l)
855 int LittleLong (int l)
864 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
873 float LittleFloat (float l)
875 union {byte b[4]; float f;} in, out;
886 float BigFloat (float l)
895 short BigShort (short l)
905 short LittleShort (short l)
920 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
923 int LittleLong (int l)
928 float BigFloat (float l)
930 union {byte b[4]; float f;} in, out;
941 float LittleFloat (float l)
950 //=======================================================
955 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
956 // and the initial and final xor values shown below... in other words, the
957 // CCITT standard CRC used by XMODEM
959 #define CRC_INIT_VALUE 0xffff
960 #define CRC_XOR_VALUE 0x0000
962 static unsigned short crctable[256] =
964 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
965 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
966 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
967 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
968 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
969 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
970 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
971 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
972 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
973 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
974 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
975 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
976 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
977 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
978 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
979 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
980 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
981 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
982 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
983 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
984 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
985 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
986 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
987 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
988 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
989 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
990 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
991 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
992 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
993 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
994 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
995 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
998 void CRC_Init(unsigned short *crcvalue)
1000 *crcvalue = CRC_INIT_VALUE;
1003 void CRC_ProcessByte(unsigned short *crcvalue, byte data)
1005 *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
1008 unsigned short CRC_Value(unsigned short crcvalue)
1010 return crcvalue ^ CRC_XOR_VALUE;
1012 //=============================================================================
1019 void CreatePath (char *path)
1026 for (ofs = path+1 ; *ofs ; ofs++)
1029 if (c == '/' || c == '\\')
1030 { // create the directory
1043 Used to archive source files
1046 void QCopyFile (char *from, char *to)
1051 length = LoadFile (from, &buffer);
1053 SaveFile (to, buffer, length);