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