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