Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

cmdlib.c (20754B)


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