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 <sys/types.h>
37 #define BASEDIRNAME "quake2"
38 #define PATHSEPERATOR '/'
40 // set these before calling CheckParm
48 char archivedir[1024];
55 Mimic unix command line expansion
58 #define MAX_EX_ARGC 1024
60 char *ex_argv[MAX_EX_ARGC];
63 void ExpandWildcards (int *argc, char ***argv)
65 struct _finddata_t fileinfo;
73 for (i=0 ; i<*argc ; i++)
77 || ( !strstr(path, "*") && !strstr(path, "?") ) )
79 ex_argv[ex_argc++] = path;
83 handle = _findfirst (path, &fileinfo);
87 ExtractFilePath (path, filebase);
91 sprintf (filename, "%s%s", filebase, fileinfo.name);
92 ex_argv[ex_argc++] = copystring (filename);
93 } while (_findnext( handle, &fileinfo ) != -1);
102 void ExpandWildcards (int *argc, char ***argv)
113 For abnormal program terminations in windowed apps
116 void Error (char *error, ...)
123 err = GetLastError ();
125 va_start (argptr,error);
126 vsprintf (text, error,argptr);
129 sprintf (text2, "%s\nGetLastError() = %i", text, err);
130 MessageBox(NULL, text2, "Error", 0 /* MB_OK */ );
140 For abnormal program terminations in console apps
143 void Error (char *error, ...)
147 printf ("\n************ ERROR ************\n");
149 va_start (argptr,error);
150 vprintf (error,argptr);
158 // only printf if in verbose mode
159 qboolean verbose = false;
160 void qprintf (char *format, ...)
167 va_start (argptr,format);
168 vprintf (format,argptr);
175 qdir will hold the path up to the quake directory, including the slash
180 gamedir will hold qdir + the game directory (id1, id2, etc)
187 void SetQdirFromPath (char *path)
193 if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
200 // search for "quake2" in path
202 len = strlen(BASEDIRNAME);
203 for (c=path+strlen(path)-1 ; c != path ; c--)
204 if (!Q_strncasecmp (c, BASEDIRNAME, len))
206 strncpy (qdir, path, c+len+1-path);
207 qprintf ("qdir: %s\n", qdir);
211 if (*c == '/' || *c == '\\')
213 strncpy (gamedir, path, c+1-path);
214 qprintf ("gamedir: %s\n", gamedir);
219 Error ("No gamedir in %s", path);
222 Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
225 char *ExpandArg (char *path)
227 static char full[1024];
229 if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
239 char *ExpandPath (char *path)
241 static char full[1024];
243 Error ("ExpandPath called without qdir set");
244 if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
246 sprintf (full, "%s%s", qdir, path);
250 char *ExpandPathAndArchive (char *path)
253 char archivename[1024];
255 expanded = ExpandPath (path);
259 sprintf (archivename, "%s/%s", archivedir, path);
260 QCopyFile (expanded, archivename);
266 char *copystring(char *s)
269 b = malloc(strlen(s)+1);
281 double I_FloatTime (void)
289 // more precise, less portable
294 gettimeofday(&tp, &tzp);
299 return tp.tv_usec/1000000.0;
302 return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
306 void Q_getwd (char *out)
318 void Q_mkdir (char *path)
321 if (_mkdir (path) != -1)
324 if (mkdir (path, 0777) != -1)
328 Error ("mkdir %s: %s",path, strerror(errno));
335 returns -1 if not present
338 int FileTime (char *path)
342 if (stat (path,&buf) == -1)
354 Parse a token out of a string
357 char *COM_Parse (char *data)
370 while ( (c = *data) <= ' ')
375 return NULL; // end of file;
381 if (c=='/' && data[1] == '/')
383 while (*data && *data != '\n')
389 // handle quoted strings specially
406 // parse single characters
407 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
415 // parse a regular word
422 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
431 int Q_strncasecmp (char *s1, char *s2, int n)
441 return 0; // strings are equal until end point
445 if (c1 >= 'a' && c1 <= 'z')
447 if (c2 >= 'a' && c2 <= 'z')
450 return -1; // strings not equal
454 return 0; // strings are equal
457 int Q_strcasecmp (char *s1, char *s2)
459 return Q_strncasecmp (s1, s2, 99999);
463 char *strupr (char *start)
475 char *strlower (char *start)
489 =============================================================================
493 =============================================================================
501 Checks for the given parameter in the program's command line arguments
502 Returns the argument number (1 to argc-1) or 0 if not present
505 int CheckParm (char *check)
509 for (i = 1;i<myargc;i++)
511 if ( !Q_strcasecmp(check, myargv[i]) )
525 int Q_filelength (FILE *f)
531 fseek (f, 0, SEEK_END);
533 fseek (f, pos, SEEK_SET);
539 FILE *SafeOpenWrite (char *filename)
543 f = fopen(filename, "wb");
546 Error ("Error opening %s: %s",filename,strerror(errno));
551 FILE *SafeOpenRead (char *filename)
555 f = fopen(filename, "rb");
558 Error ("Error opening %s: %s",filename,strerror(errno));
564 void SafeRead (FILE *f, void *buffer, int count)
566 if ( fread (buffer, 1, count, f) != (size_t)count)
567 Error ("File read failure");
571 void SafeWrite (FILE *f, void *buffer, int count)
573 if (fwrite (buffer, 1, count, f) != (size_t)count)
574 Error ("File write failure");
583 qboolean FileExists (char *filename)
587 f = fopen (filename, "r");
599 int LoadFile (char *filename, void **bufferptr)
605 f = SafeOpenRead (filename);
606 length = Q_filelength (f);
607 buffer = malloc (length+1);
608 ((char *)buffer)[length] = 0;
609 SafeRead (f, buffer, length);
624 int TryLoadFile (char *filename, void **bufferptr)
632 f = fopen (filename, "rb");
635 length = Q_filelength (f);
636 buffer = malloc (length+1);
637 ((char *)buffer)[length] = 0;
638 SafeRead (f, buffer, length);
651 void SaveFile (char *filename, void *buffer, int count)
655 f = SafeOpenWrite (filename);
656 SafeWrite (f, buffer, count);
662 void DefaultExtension (char *path, char *extension)
666 // if path doesnt have a .EXT, append extension
667 // (extension should include the .)
669 src = path + strlen(path) - 1;
671 while (*src != PATHSEPERATOR && src != path)
674 return; // it has an extension
678 strcat (path, extension);
682 void DefaultPath (char *path, char *basepath)
686 if (path[0] == PATHSEPERATOR)
687 return; // absolute path location
689 strcpy (path,basepath);
694 void StripFilename (char *path)
698 length = strlen(path)-1;
699 while (length > 0 && path[length] != PATHSEPERATOR)
704 void StripExtension (char *path)
708 length = strlen(path)-1;
709 while (length > 0 && path[length] != '.')
712 if (path[length] == '/')
713 return; // no extension
725 // FIXME: should include the slash, otherwise
726 // backing to an empty path will be wrong when appending a slash
727 void ExtractFilePath (char *path, char *dest)
731 src = path + strlen(path) - 1;
734 // back up until a \ or the start
736 while (src != path && *(src-1) != '\\' && *(src-1) != '/')
739 memcpy (dest, path, src-path);
743 void ExtractFileBase (char *path, char *dest)
747 src = path + strlen(path) - 1;
750 // back up until a \ or the start
752 while (src != path && *(src-1) != PATHSEPERATOR)
755 while (*src && *src != '.')
762 void ExtractFileExtension (char *path, char *dest)
766 src = path + strlen(path) - 1;
769 // back up until a . or the start
771 while (src != path && *(src-1) != '.')
775 *dest = 0; // no extension
788 int ParseHex (char *hex)
799 if (*str >= '0' && *str <= '9')
801 else if (*str >= 'a' && *str <= 'f')
802 num += 10 + *str-'a';
803 else if (*str >= 'A' && *str <= 'F')
804 num += 10 + *str-'A';
806 Error ("Bad hex number: %s",hex);
814 int ParseNum (char *str)
817 return ParseHex (str+1);
818 if (str[0] == '0' && str[1] == 'x')
819 return ParseHex (str+2);
826 ============================================================================
830 ============================================================================
834 #define __BIG_ENDIAN__
837 #ifdef __BIG_ENDIAN__
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);