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