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 }