home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 22 / PCPP #22.iso / Quake2 / q2source_12_11 / utils3 / common / cmdlib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-15  |  16.6 KB  |  1,034 lines

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