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);
465 char *strupr (char *start)
477 char *strlower (char *start)
491 =============================================================================
495 =============================================================================
503 Checks for the given parameter in the program's command line arguments
504 Returns the argument number (1 to argc-1) or 0 if not present
507 int CheckParm (char *check)
511 for (i = 1;i<myargc;i++)
513 if ( !Q_strcasecmp(check, myargv[i]) )
527 int Q_filelength (FILE *f)
533 fseek (f, 0, SEEK_END);
535 fseek (f, pos, SEEK_SET);
541 FILE *SafeOpenWrite (char *filename)
545 f = fopen(filename, "wb");
548 Error ("Error opening %s: %s",filename,strerror(errno));
553 FILE *SafeOpenRead (char *filename)
557 f = fopen(filename, "rb");
560 Error ("Error opening %s: %s",filename,strerror(errno));
566 void SafeRead (FILE *f, void *buffer, int count)
568 if ( fread (buffer, 1, count, f) != (size_t)count)
569 Error ("File read failure");
573 void SafeWrite (FILE *f, void *buffer, int count)
575 if (fwrite (buffer, 1, count, f) != (size_t)count)
576 Error ("File write failure");
585 qboolean FileExists (char *filename)
589 f = fopen (filename, "r");
601 int LoadFile (char *filename, void **bufferptr)
607 f = SafeOpenRead (filename);
608 length = Q_filelength (f);
609 buffer = malloc (length+1);
610 ((char *)buffer)[length] = 0;
611 SafeRead (f, buffer, length);
626 int TryLoadFile (char *filename, void **bufferptr)
634 f = fopen (filename, "rb");
637 length = Q_filelength (f);
638 buffer = malloc (length+1);
639 ((char *)buffer)[length] = 0;
640 SafeRead (f, buffer, length);
653 void SaveFile (char *filename, void *buffer, int count)
657 f = SafeOpenWrite (filename);
658 SafeWrite (f, buffer, count);
664 void DefaultExtension (char *path, char *extension)
668 // if path doesnt have a .EXT, append extension
669 // (extension should include the .)
671 src = path + strlen(path) - 1;
673 while (*src != PATHSEPERATOR && src != path)
676 return; // it has an extension
680 strcat (path, extension);
684 void DefaultPath (char *path, char *basepath)
688 if (path[0] == PATHSEPERATOR)
689 return; // absolute path location
691 strcpy (path,basepath);
696 void StripFilename (char *path)
700 length = strlen(path)-1;
701 while (length > 0 && path[length] != PATHSEPERATOR)
706 void StripExtension (char *path)
710 length = strlen(path)-1;
711 while (length > 0 && path[length] != '.')
714 if (path[length] == '/')
715 return; // no extension
727 // FIXME: should include the slash, otherwise
728 // backing to an empty path will be wrong when appending a slash
729 void ExtractFilePath (char *path, char *dest)
733 src = path + strlen(path) - 1;
736 // back up until a \ or the start
738 while (src != path && *(src-1) != '\\' && *(src-1) != '/')
741 memcpy (dest, path, src-path);
745 void ExtractFileBase (char *path, char *dest)
749 src = path + strlen(path) - 1;
752 // back up until a \ or the start
754 while (src != path && *(src-1) != PATHSEPERATOR)
757 while (*src && *src != '.')
764 void ExtractFileExtension (char *path, char *dest)
768 src = path + strlen(path) - 1;
771 // back up until a . or the start
773 while (src != path && *(src-1) != '.')
777 *dest = 0; // no extension
790 int ParseHex (char *hex)
801 if (*str >= '0' && *str <= '9')
803 else if (*str >= 'a' && *str <= 'f')
804 num += 10 + *str-'a';
805 else if (*str >= 'A' && *str <= 'F')
806 num += 10 + *str-'A';
808 Error ("Bad hex number: %s",hex);
816 int ParseNum (char *str)
819 return ParseHex (str+1);
820 if (str[0] == '0' && str[1] == 'x')
821 return ParseHex (str+2);
828 ============================================================================
832 ============================================================================
835 #if GDEF_ARCH_ENDIAN_BIG
837 short LittleShort (short l)
847 short BigShort (short l)
853 int LittleLong (int l)
862 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
871 float LittleFloat (float l)
873 union {byte b[4]; float f;} in, out;
884 float BigFloat (float l)
893 short BigShort (short l)
903 short LittleShort (short l)
918 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
921 int LittleLong (int l)
926 float BigFloat (float l)
928 union {byte b[4]; float f;} in, out;
939 float LittleFloat (float l)
948 //=======================================================
953 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
954 // and the initial and final xor values shown below... in other words, the
955 // CCITT standard CRC used by XMODEM
957 #define CRC_INIT_VALUE 0xffff
958 #define CRC_XOR_VALUE 0x0000
960 static unsigned short crctable[256] =
962 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
963 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
964 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
965 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
966 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
967 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
968 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
969 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
970 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
971 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
972 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
973 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
974 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
975 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
976 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
977 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
978 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
979 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
980 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
981 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
982 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
983 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
984 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
985 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
986 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
987 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
988 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
989 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
990 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
991 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
992 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
993 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
996 void CRC_Init(unsigned short *crcvalue)
998 *crcvalue = CRC_INIT_VALUE;
1001 void CRC_ProcessByte(unsigned short *crcvalue, byte data)
1003 *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
1006 unsigned short CRC_Value(unsigned short crcvalue)
1008 return crcvalue ^ CRC_XOR_VALUE;
1010 //=============================================================================
1017 void CreatePath (char *path)
1024 for (ofs = path+1 ; *ofs ; ofs++)
1027 if (c == '/' || c == '\\')
1028 { // create the directory
1041 Used to archive source files
1044 void QCopyFile (char *from, char *to)
1049 length = LoadFile (from, &buffer);
1051 SaveFile (to, buffer, length);