Annotation of quakeworld/client/common.c, revision 1.1

1.1     ! root        1: /*
        !             2: Copyright (C) 1996-1997 Id Software, Inc.
        !             3: 
        !             4: This program is free software; you can redistribute it and/or
        !             5: modify it under the terms of the GNU General Public License
        !             6: as published by the Free Software Foundation; either version 2
        !             7: of the License, or (at your option) any later version.
        !             8: 
        !             9: This program is distributed in the hope that it will be useful,
        !            10: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
        !            12: 
        !            13: See the GNU General Public License for more details.
        !            14: 
        !            15: You should have received a copy of the GNU General Public License
        !            16: along with this program; if not, write to the Free Software
        !            17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
        !            18: 
        !            19: */
        !            20: // common.c -- misc functions used in client and server
        !            21: 
        !            22: #include <ctype.h>
        !            23: 
        !            24: #ifdef SERVERONLY 
        !            25: #include "qwsvdef.h"
        !            26: #else
        !            27: #include "quakedef.h"
        !            28: #endif
        !            29: 
        !            30: #define MAX_NUM_ARGVS  50
        !            31: #define NUM_SAFE_ARGVS 6
        !            32: 
        !            33: usercmd_t nullcmd; // guarenteed to be zero
        !            34: 
        !            35: static char    *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1];
        !            36: static char    *argvdummy = " ";
        !            37: 
        !            38: static char    *safeargvs[NUM_SAFE_ARGVS] =
        !            39:        {"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse"};
        !            40: 
        !            41: cvar_t registered = {"registered","0"};
        !            42: 
        !            43: qboolean       com_modified;   // set true if using non-id files
        !            44: 
        !            45: int            static_registered = 1;  // only for startup check, then set
        !            46: 
        !            47: qboolean               msg_suppress_1 = 0;
        !            48: 
        !            49: void COM_InitFilesystem (void);
        !            50: void COM_Path_f (void);
        !            51: 
        !            52: 
        !            53: // if a packfile directory differs from this, it is assumed to be hacked
        !            54: #define        PAK0_COUNT              339
        !            55: #define        PAK0_CRC                52883
        !            56: 
        !            57: qboolean               standard_quake = true, rogue, hipnotic;
        !            58: 
        !            59: char   gamedirfile[MAX_OSPATH];
        !            60: 
        !            61: // this graphic needs to be in the pak file to use registered features
        !            62: unsigned short pop[] =
        !            63: {
        !            64:  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
        !            65: ,0x0000,0x0000,0x6600,0x0000,0x0000,0x0000,0x6600,0x0000
        !            66: ,0x0000,0x0066,0x0000,0x0000,0x0000,0x0000,0x0067,0x0000
        !            67: ,0x0000,0x6665,0x0000,0x0000,0x0000,0x0000,0x0065,0x6600
        !            68: ,0x0063,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6563
        !            69: ,0x0064,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6564
        !            70: ,0x0064,0x6564,0x0000,0x6469,0x6969,0x6400,0x0064,0x6564
        !            71: ,0x0063,0x6568,0x6200,0x0064,0x6864,0x0000,0x6268,0x6563
        !            72: ,0x0000,0x6567,0x6963,0x0064,0x6764,0x0063,0x6967,0x6500
        !            73: ,0x0000,0x6266,0x6769,0x6a68,0x6768,0x6a69,0x6766,0x6200
        !            74: ,0x0000,0x0062,0x6566,0x6666,0x6666,0x6666,0x6562,0x0000
        !            75: ,0x0000,0x0000,0x0062,0x6364,0x6664,0x6362,0x0000,0x0000
        !            76: ,0x0000,0x0000,0x0000,0x0062,0x6662,0x0000,0x0000,0x0000
        !            77: ,0x0000,0x0000,0x0000,0x0061,0x6661,0x0000,0x0000,0x0000
        !            78: ,0x0000,0x0000,0x0000,0x0000,0x6500,0x0000,0x0000,0x0000
        !            79: ,0x0000,0x0000,0x0000,0x0000,0x6400,0x0000,0x0000,0x0000
        !            80: };
        !            81: 
        !            82: /*
        !            83: 
        !            84: 
        !            85: All of Quake's data access is through a hierchal file system, but the contents of the file system can be transparently merged from several sources.
        !            86: 
        !            87: The "base directory" is the path to the directory holding the quake.exe and all game directories.  The sys_* files pass this to host_init in quakeparms_t->basedir.  This can be overridden with the "-basedir" command line parm to allow code debugging in a different directory.  The base directory is
        !            88: only used during filesystem initialization.
        !            89: 
        !            90: The "game directory" is the first tree on the search path and directory that all generated files (savegames, screenshots, demos, config files) will be saved to.  This can be overridden with the "-game" command line parameter.  The game directory can never be changed while quake is executing.  This is a precacution against having a malicious server instruct clients to write files over areas they shouldn't.
        !            91: 
        !            92: The "cache directory" is only used during development to save network bandwidth, especially over ISDN / T1 lines.  If there is a cache directory
        !            93: specified, when a file is found by the normal search path, it will be mirrored
        !            94: into the cache directory, then opened there.
        !            95:        
        !            96: */
        !            97: 
        !            98: //============================================================================
        !            99: 
        !           100: 
        !           101: // ClearLink is used for new headnodes
        !           102: void ClearLink (link_t *l)
        !           103: {
        !           104:        l->prev = l->next = l;
        !           105: }
        !           106: 
        !           107: void RemoveLink (link_t *l)
        !           108: {
        !           109:        l->next->prev = l->prev;
        !           110:        l->prev->next = l->next;
        !           111: }
        !           112: 
        !           113: void InsertLinkBefore (link_t *l, link_t *before)
        !           114: {
        !           115:        l->next = before;
        !           116:        l->prev = before->prev;
        !           117:        l->prev->next = l;
        !           118:        l->next->prev = l;
        !           119: }
        !           120: void InsertLinkAfter (link_t *l, link_t *after)
        !           121: {
        !           122:        l->next = after->next;
        !           123:        l->prev = after;
        !           124:        l->prev->next = l;
        !           125:        l->next->prev = l;
        !           126: }
        !           127: 
        !           128: /*
        !           129: ============================================================================
        !           130: 
        !           131:                                        LIBRARY REPLACEMENT FUNCTIONS
        !           132: 
        !           133: ============================================================================
        !           134: */
        !           135: 
        !           136: #if 0
        !           137: void Q_memset (void *dest, int fill, int count)
        !           138: {
        !           139:        int             i;
        !           140:        
        !           141:        if ( (((long)dest | count) & 3) == 0)
        !           142:        {
        !           143:                count >>= 2;
        !           144:                fill = fill | (fill<<8) | (fill<<16) | (fill<<24);
        !           145:                for (i=0 ; i<count ; i++)
        !           146:                        ((int *)dest)[i] = fill;
        !           147:        }
        !           148:        else
        !           149:                for (i=0 ; i<count ; i++)
        !           150:                        ((byte *)dest)[i] = fill;
        !           151: }
        !           152: 
        !           153: void Q_memcpy (void *dest, void *src, int count)
        !           154: {
        !           155:        int             i;
        !           156:        
        !           157:        if (( ( (long)dest | (long)src | count) & 3) == 0 )
        !           158:        {
        !           159:                count>>=2;
        !           160:                for (i=0 ; i<count ; i++)
        !           161:                        ((int *)dest)[i] = ((int *)src)[i];
        !           162:        }
        !           163:        else
        !           164:                for (i=0 ; i<count ; i++)
        !           165:                        ((byte *)dest)[i] = ((byte *)src)[i];
        !           166: }
        !           167: 
        !           168: int Q_memcmp (void *m1, void *m2, int count)
        !           169: {
        !           170:        while(count)
        !           171:        {
        !           172:                count--;
        !           173:                if (((byte *)m1)[count] != ((byte *)m2)[count])
        !           174:                        return -1;
        !           175:        }
        !           176:        return 0;
        !           177: }
        !           178: 
        !           179: void Q_strcpy (char *dest, char *src)
        !           180: {
        !           181:        while (*src)
        !           182:        {
        !           183:                *dest++ = *src++;
        !           184:        }
        !           185:        *dest++ = 0;
        !           186: }
        !           187: 
        !           188: void Q_strncpy (char *dest, char *src, int count)
        !           189: {
        !           190:        while (*src && count--)
        !           191:        {
        !           192:                *dest++ = *src++;
        !           193:        }
        !           194:        if (count)
        !           195:                *dest++ = 0;
        !           196: }
        !           197: 
        !           198: int Q_strlen (char *str)
        !           199: {
        !           200:        int             count;
        !           201:        
        !           202:        count = 0;
        !           203:        while (str[count])
        !           204:                count++;
        !           205: 
        !           206:        return count;
        !           207: }
        !           208: 
        !           209: char *Q_strrchr(char *s, char c)
        !           210: {
        !           211:     int len = Q_strlen(s);
        !           212:     s += len;
        !           213:     while (len--)
        !           214:         if (*--s == c) return s;
        !           215:     return 0;
        !           216: }
        !           217: 
        !           218: void Q_strcat (char *dest, char *src)
        !           219: {
        !           220:        dest += Q_strlen(dest);
        !           221:        Q_strcpy (dest, src);
        !           222: }
        !           223: 
        !           224: int Q_strcmp (char *s1, char *s2)
        !           225: {
        !           226:        while (1)
        !           227:        {
        !           228:                if (*s1 != *s2)
        !           229:                        return -1;              // strings not equal    
        !           230:                if (!*s1)
        !           231:                        return 0;               // strings are equal
        !           232:                s1++;
        !           233:                s2++;
        !           234:        }
        !           235:        
        !           236:        return -1;
        !           237: }
        !           238: 
        !           239: int Q_strncmp (char *s1, char *s2, int count)
        !           240: {
        !           241:        while (1)
        !           242:        {
        !           243:                if (!count--)
        !           244:                        return 0;
        !           245:                if (*s1 != *s2)
        !           246:                        return -1;              // strings not equal    
        !           247:                if (!*s1)
        !           248:                        return 0;               // strings are equal
        !           249:                s1++;
        !           250:                s2++;
        !           251:        }
        !           252:        
        !           253:        return -1;
        !           254: }
        !           255: 
        !           256: int Q_strncasecmp (char *s1, char *s2, int n)
        !           257: {
        !           258:        int             c1, c2;
        !           259:        
        !           260:        while (1)
        !           261:        {
        !           262:                c1 = *s1++;
        !           263:                c2 = *s2++;
        !           264: 
        !           265:                if (!n--)
        !           266:                        return 0;               // strings are equal until end point
        !           267:                
        !           268:                if (c1 != c2)
        !           269:                {
        !           270:                        if (c1 >= 'a' && c1 <= 'z')
        !           271:                                c1 -= ('a' - 'A');
        !           272:                        if (c2 >= 'a' && c2 <= 'z')
        !           273:                                c2 -= ('a' - 'A');
        !           274:                        if (c1 != c2)
        !           275:                                return -1;              // strings not equal
        !           276:                }
        !           277:                if (!c1)
        !           278:                        return 0;               // strings are equal
        !           279: //             s1++;
        !           280: //             s2++;
        !           281:        }
        !           282:        
        !           283:        return -1;
        !           284: }
        !           285: 
        !           286: int Q_strcasecmp (char *s1, char *s2)
        !           287: {
        !           288:        return Q_strncasecmp (s1, s2, 99999);
        !           289: }
        !           290: 
        !           291: #endif
        !           292: 
        !           293: int Q_atoi (char *str)
        !           294: {
        !           295:        int             val;
        !           296:        int             sign;
        !           297:        int             c;
        !           298:        
        !           299:        if (*str == '-')
        !           300:        {
        !           301:                sign = -1;
        !           302:                str++;
        !           303:        }
        !           304:        else
        !           305:                sign = 1;
        !           306:                
        !           307:        val = 0;
        !           308: 
        !           309: //
        !           310: // check for hex
        !           311: //
        !           312:        if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
        !           313:        {
        !           314:                str += 2;
        !           315:                while (1)
        !           316:                {
        !           317:                        c = *str++;
        !           318:                        if (c >= '0' && c <= '9')
        !           319:                                val = (val<<4) + c - '0';
        !           320:                        else if (c >= 'a' && c <= 'f')
        !           321:                                val = (val<<4) + c - 'a' + 10;
        !           322:                        else if (c >= 'A' && c <= 'F')
        !           323:                                val = (val<<4) + c - 'A' + 10;
        !           324:                        else
        !           325:                                return val*sign;
        !           326:                }
        !           327:        }
        !           328:        
        !           329: //
        !           330: // check for character
        !           331: //
        !           332:        if (str[0] == '\'')
        !           333:        {
        !           334:                return sign * str[1];
        !           335:        }
        !           336:        
        !           337: //
        !           338: // assume decimal
        !           339: //
        !           340:        while (1)
        !           341:        {
        !           342:                c = *str++;
        !           343:                if (c <'0' || c > '9')
        !           344:                        return val*sign;
        !           345:                val = val*10 + c - '0';
        !           346:        }
        !           347:        
        !           348:        return 0;
        !           349: }
        !           350: 
        !           351: 
        !           352: float Q_atof (char *str)
        !           353: {
        !           354:        double  val;
        !           355:        int             sign;
        !           356:        int             c;
        !           357:        int             decimal, total;
        !           358:        
        !           359:        if (*str == '-')
        !           360:        {
        !           361:                sign = -1;
        !           362:                str++;
        !           363:        }
        !           364:        else
        !           365:                sign = 1;
        !           366:                
        !           367:        val = 0;
        !           368: 
        !           369: //
        !           370: // check for hex
        !           371: //
        !           372:        if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
        !           373:        {
        !           374:                str += 2;
        !           375:                while (1)
        !           376:                {
        !           377:                        c = *str++;
        !           378:                        if (c >= '0' && c <= '9')
        !           379:                                val = (val*16) + c - '0';
        !           380:                        else if (c >= 'a' && c <= 'f')
        !           381:                                val = (val*16) + c - 'a' + 10;
        !           382:                        else if (c >= 'A' && c <= 'F')
        !           383:                                val = (val*16) + c - 'A' + 10;
        !           384:                        else
        !           385:                                return val*sign;
        !           386:                }
        !           387:        }
        !           388:        
        !           389: //
        !           390: // check for character
        !           391: //
        !           392:        if (str[0] == '\'')
        !           393:        {
        !           394:                return sign * str[1];
        !           395:        }
        !           396:        
        !           397: //
        !           398: // assume decimal
        !           399: //
        !           400:        decimal = -1;
        !           401:        total = 0;
        !           402:        while (1)
        !           403:        {
        !           404:                c = *str++;
        !           405:                if (c == '.')
        !           406:                {
        !           407:                        decimal = total;
        !           408:                        continue;
        !           409:                }
        !           410:                if (c <'0' || c > '9')
        !           411:                        break;
        !           412:                val = val*10 + c - '0';
        !           413:                total++;
        !           414:        }
        !           415: 
        !           416:        if (decimal == -1)
        !           417:                return val*sign;
        !           418:        while (total > decimal)
        !           419:        {
        !           420:                val /= 10;
        !           421:                total--;
        !           422:        }
        !           423:        
        !           424:        return val*sign;
        !           425: }
        !           426: 
        !           427: /*
        !           428: ============================================================================
        !           429: 
        !           430:                                        BYTE ORDER FUNCTIONS
        !           431: 
        !           432: ============================================================================
        !           433: */
        !           434: 
        !           435: qboolean       bigendien;
        !           436: 
        !           437: short  (*BigShort) (short l);
        !           438: short  (*LittleShort) (short l);
        !           439: int    (*BigLong) (int l);
        !           440: int    (*LittleLong) (int l);
        !           441: float  (*BigFloat) (float l);
        !           442: float  (*LittleFloat) (float l);
        !           443: 
        !           444: short   ShortSwap (short l)
        !           445: {
        !           446:        byte    b1,b2;
        !           447: 
        !           448:        b1 = l&255;
        !           449:        b2 = (l>>8)&255;
        !           450: 
        !           451:        return (b1<<8) + b2;
        !           452: }
        !           453: 
        !           454: short  ShortNoSwap (short l)
        !           455: {
        !           456:        return l;
        !           457: }
        !           458: 
        !           459: int    LongSwap (int l)
        !           460: {
        !           461:        byte    b1,b2,b3,b4;
        !           462: 
        !           463:        b1 = l&255;
        !           464:        b2 = (l>>8)&255;
        !           465:        b3 = (l>>16)&255;
        !           466:        b4 = (l>>24)&255;
        !           467: 
        !           468:        return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
        !           469: }
        !           470: 
        !           471: int    LongNoSwap (int l)
        !           472: {
        !           473:        return l;
        !           474: }
        !           475: 
        !           476: float FloatSwap (float f)
        !           477: {
        !           478:        union
        !           479:        {
        !           480:                float   f;
        !           481:                byte    b[4];
        !           482:        } dat1, dat2;
        !           483:        
        !           484:        
        !           485:        dat1.f = f;
        !           486:        dat2.b[0] = dat1.b[3];
        !           487:        dat2.b[1] = dat1.b[2];
        !           488:        dat2.b[2] = dat1.b[1];
        !           489:        dat2.b[3] = dat1.b[0];
        !           490:        return dat2.f;
        !           491: }
        !           492: 
        !           493: float FloatNoSwap (float f)
        !           494: {
        !           495:        return f;
        !           496: }
        !           497: 
        !           498: /*
        !           499: ==============================================================================
        !           500: 
        !           501:                        MESSAGE IO FUNCTIONS
        !           502: 
        !           503: Handles byte ordering and avoids alignment errors
        !           504: ==============================================================================
        !           505: */
        !           506: 
        !           507: //
        !           508: // writing functions
        !           509: //
        !           510: 
        !           511: void MSG_WriteChar (sizebuf_t *sb, int c)
        !           512: {
        !           513:        byte    *buf;
        !           514:        
        !           515: #ifdef PARANOID
        !           516:        if (c < -128 || c > 127)
        !           517:                Sys_Error ("MSG_WriteChar: range error");
        !           518: #endif
        !           519: 
        !           520:        buf = SZ_GetSpace (sb, 1);
        !           521:        buf[0] = c;
        !           522: }
        !           523: 
        !           524: void MSG_WriteByte (sizebuf_t *sb, int c)
        !           525: {
        !           526:        byte    *buf;
        !           527:        
        !           528: #ifdef PARANOID
        !           529:        if (c < 0 || c > 255)
        !           530:                Sys_Error ("MSG_WriteByte: range error");
        !           531: #endif
        !           532: 
        !           533:        buf = SZ_GetSpace (sb, 1);
        !           534:        buf[0] = c;
        !           535: }
        !           536: 
        !           537: void MSG_WriteShort (sizebuf_t *sb, int c)
        !           538: {
        !           539:        byte    *buf;
        !           540:        
        !           541: #ifdef PARANOID
        !           542:        if (c < ((short)0x8000) || c > (short)0x7fff)
        !           543:                Sys_Error ("MSG_WriteShort: range error");
        !           544: #endif
        !           545: 
        !           546:        buf = SZ_GetSpace (sb, 2);
        !           547:        buf[0] = c&0xff;
        !           548:        buf[1] = c>>8;
        !           549: }
        !           550: 
        !           551: void MSG_WriteLong (sizebuf_t *sb, int c)
        !           552: {
        !           553:        byte    *buf;
        !           554:        
        !           555:        buf = SZ_GetSpace (sb, 4);
        !           556:        buf[0] = c&0xff;
        !           557:        buf[1] = (c>>8)&0xff;
        !           558:        buf[2] = (c>>16)&0xff;
        !           559:        buf[3] = c>>24;
        !           560: }
        !           561: 
        !           562: void MSG_WriteFloat (sizebuf_t *sb, float f)
        !           563: {
        !           564:        union
        !           565:        {
        !           566:                float   f;
        !           567:                int     l;
        !           568:        } dat;
        !           569:        
        !           570:        
        !           571:        dat.f = f;
        !           572:        dat.l = LittleLong (dat.l);
        !           573:        
        !           574:        SZ_Write (sb, &dat.l, 4);
        !           575: }
        !           576: 
        !           577: void MSG_WriteString (sizebuf_t *sb, char *s)
        !           578: {
        !           579:        if (!s)
        !           580:                SZ_Write (sb, "", 1);
        !           581:        else
        !           582:                SZ_Write (sb, s, Q_strlen(s)+1);
        !           583: }
        !           584: 
        !           585: void MSG_WriteCoord (sizebuf_t *sb, float f)
        !           586: {
        !           587:        MSG_WriteShort (sb, (int)(f*8));
        !           588: }
        !           589: 
        !           590: void MSG_WriteAngle (sizebuf_t *sb, float f)
        !           591: {
        !           592:        MSG_WriteByte (sb, (int)(f*256/360) & 255);
        !           593: }
        !           594: 
        !           595: void MSG_WriteAngle16 (sizebuf_t *sb, float f)
        !           596: {
        !           597:        MSG_WriteShort (sb, (int)(f*65536/360) & 65535);
        !           598: }
        !           599: 
        !           600: void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd)
        !           601: {
        !           602:        int             bits;
        !           603: 
        !           604: //
        !           605: // send the movement message
        !           606: //
        !           607:        bits = 0;
        !           608:        if (cmd->angles[0] != from->angles[0])
        !           609:                bits |= CM_ANGLE1;
        !           610:        if (cmd->angles[1] != from->angles[1])
        !           611:                bits |= CM_ANGLE2;
        !           612:        if (cmd->angles[2] != from->angles[2])
        !           613:                bits |= CM_ANGLE3;
        !           614:        if (cmd->forwardmove != from->forwardmove)
        !           615:                bits |= CM_FORWARD;
        !           616:        if (cmd->sidemove != from->sidemove)
        !           617:                bits |= CM_SIDE;
        !           618:        if (cmd->upmove != from->upmove)
        !           619:                bits |= CM_UP;
        !           620:        if (cmd->buttons != from->buttons)
        !           621:                bits |= CM_BUTTONS;
        !           622:        if (cmd->impulse != from->impulse)
        !           623:                bits |= CM_IMPULSE;
        !           624: 
        !           625:     MSG_WriteByte (buf, bits);
        !           626: 
        !           627:        if (bits & CM_ANGLE1)
        !           628:                MSG_WriteAngle16 (buf, cmd->angles[0]);
        !           629:        if (bits & CM_ANGLE2)
        !           630:                MSG_WriteAngle16 (buf, cmd->angles[1]);
        !           631:        if (bits & CM_ANGLE3)
        !           632:                MSG_WriteAngle16 (buf, cmd->angles[2]);
        !           633:        
        !           634:        if (bits & CM_FORWARD)
        !           635:                MSG_WriteShort (buf, cmd->forwardmove);
        !           636:        if (bits & CM_SIDE)
        !           637:                MSG_WriteShort (buf, cmd->sidemove);
        !           638:        if (bits & CM_UP)
        !           639:                MSG_WriteShort (buf, cmd->upmove);
        !           640: 
        !           641:        if (bits & CM_BUTTONS)
        !           642:                MSG_WriteByte (buf, cmd->buttons);
        !           643:        if (bits & CM_IMPULSE)
        !           644:            MSG_WriteByte (buf, cmd->impulse);
        !           645:        MSG_WriteByte (buf, cmd->msec);
        !           646: }
        !           647: 
        !           648: 
        !           649: //
        !           650: // reading functions
        !           651: //
        !           652: int                    msg_readcount;
        !           653: qboolean       msg_badread;
        !           654: 
        !           655: void MSG_BeginReading (void)
        !           656: {
        !           657:        msg_readcount = 0;
        !           658:        msg_badread = false;
        !           659: }
        !           660: 
        !           661: int MSG_GetReadCount(void)
        !           662: {
        !           663:        return msg_readcount;
        !           664: }
        !           665: 
        !           666: // returns -1 and sets msg_badread if no more characters are available
        !           667: int MSG_ReadChar (void)
        !           668: {
        !           669:        int     c;
        !           670:        
        !           671:        if (msg_readcount+1 > net_message.cursize)
        !           672:        {
        !           673:                msg_badread = true;
        !           674:                return -1;
        !           675:        }
        !           676:                
        !           677:        c = (signed char)net_message.data[msg_readcount];
        !           678:        msg_readcount++;
        !           679:        
        !           680:        return c;
        !           681: }
        !           682: 
        !           683: int MSG_ReadByte (void)
        !           684: {
        !           685:        int     c;
        !           686:        
        !           687:        if (msg_readcount+1 > net_message.cursize)
        !           688:        {
        !           689:                msg_badread = true;
        !           690:                return -1;
        !           691:        }
        !           692:                
        !           693:        c = (unsigned char)net_message.data[msg_readcount];
        !           694:        msg_readcount++;
        !           695:        
        !           696:        return c;
        !           697: }
        !           698: 
        !           699: int MSG_ReadShort (void)
        !           700: {
        !           701:        int     c;
        !           702:        
        !           703:        if (msg_readcount+2 > net_message.cursize)
        !           704:        {
        !           705:                msg_badread = true;
        !           706:                return -1;
        !           707:        }
        !           708:                
        !           709:        c = (short)(net_message.data[msg_readcount]
        !           710:        + (net_message.data[msg_readcount+1]<<8));
        !           711:        
        !           712:        msg_readcount += 2;
        !           713:        
        !           714:        return c;
        !           715: }
        !           716: 
        !           717: int MSG_ReadLong (void)
        !           718: {
        !           719:        int     c;
        !           720:        
        !           721:        if (msg_readcount+4 > net_message.cursize)
        !           722:        {
        !           723:                msg_badread = true;
        !           724:                return -1;
        !           725:        }
        !           726:                
        !           727:        c = net_message.data[msg_readcount]
        !           728:        + (net_message.data[msg_readcount+1]<<8)
        !           729:        + (net_message.data[msg_readcount+2]<<16)
        !           730:        + (net_message.data[msg_readcount+3]<<24);
        !           731:        
        !           732:        msg_readcount += 4;
        !           733:        
        !           734:        return c;
        !           735: }
        !           736: 
        !           737: float MSG_ReadFloat (void)
        !           738: {
        !           739:        union
        !           740:        {
        !           741:                byte    b[4];
        !           742:                float   f;
        !           743:                int     l;
        !           744:        } dat;
        !           745:        
        !           746:        dat.b[0] =      net_message.data[msg_readcount];
        !           747:        dat.b[1] =      net_message.data[msg_readcount+1];
        !           748:        dat.b[2] =      net_message.data[msg_readcount+2];
        !           749:        dat.b[3] =      net_message.data[msg_readcount+3];
        !           750:        msg_readcount += 4;
        !           751:        
        !           752:        dat.l = LittleLong (dat.l);
        !           753: 
        !           754:        return dat.f;   
        !           755: }
        !           756: 
        !           757: char *MSG_ReadString (void)
        !           758: {
        !           759:        static char     string[2048];
        !           760:        int             l,c;
        !           761:        
        !           762:        l = 0;
        !           763:        do
        !           764:        {
        !           765:                c = MSG_ReadChar ();
        !           766:                if (c == -1 || c == 0)
        !           767:                        break;
        !           768:                string[l] = c;
        !           769:                l++;
        !           770:        } while (l < sizeof(string)-1);
        !           771:        
        !           772:        string[l] = 0;
        !           773:        
        !           774:        return string;
        !           775: }
        !           776: 
        !           777: char *MSG_ReadStringLine (void)
        !           778: {
        !           779:        static char     string[2048];
        !           780:        int             l,c;
        !           781:        
        !           782:        l = 0;
        !           783:        do
        !           784:        {
        !           785:                c = MSG_ReadChar ();
        !           786:                if (c == -1 || c == 0 || c == '\n')
        !           787:                        break;
        !           788:                string[l] = c;
        !           789:                l++;
        !           790:        } while (l < sizeof(string)-1);
        !           791:        
        !           792:        string[l] = 0;
        !           793:        
        !           794:        return string;
        !           795: }
        !           796: 
        !           797: float MSG_ReadCoord (void)
        !           798: {
        !           799:        return MSG_ReadShort() * (1.0/8);
        !           800: }
        !           801: 
        !           802: float MSG_ReadAngle (void)
        !           803: {
        !           804:        return MSG_ReadChar() * (360.0/256);
        !           805: }
        !           806: 
        !           807: float MSG_ReadAngle16 (void)
        !           808: {
        !           809:        return MSG_ReadShort() * (360.0/65536);
        !           810: }
        !           811: 
        !           812: void MSG_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move)
        !           813: {
        !           814:        int bits;
        !           815: 
        !           816:        memcpy (move, from, sizeof(*move));
        !           817: 
        !           818:        bits = MSG_ReadByte ();
        !           819:                
        !           820: // read current angles
        !           821:        if (bits & CM_ANGLE1)
        !           822:                move->angles[0] = MSG_ReadAngle16 ();
        !           823:        if (bits & CM_ANGLE2)
        !           824:                move->angles[1] = MSG_ReadAngle16 ();
        !           825:        if (bits & CM_ANGLE3)
        !           826:                move->angles[2] = MSG_ReadAngle16 ();
        !           827:                
        !           828: // read movement
        !           829:        if (bits & CM_FORWARD)
        !           830:                move->forwardmove = MSG_ReadShort ();
        !           831:        if (bits & CM_SIDE)
        !           832:                move->sidemove = MSG_ReadShort ();
        !           833:        if (bits & CM_UP)
        !           834:                move->upmove = MSG_ReadShort ();
        !           835:        
        !           836: // read buttons
        !           837:        if (bits & CM_BUTTONS)
        !           838:                move->buttons = MSG_ReadByte ();
        !           839: 
        !           840:        if (bits & CM_IMPULSE)
        !           841:                move->impulse = MSG_ReadByte ();
        !           842: 
        !           843: // read time to run command
        !           844:        move->msec = MSG_ReadByte ();
        !           845: }
        !           846: 
        !           847: 
        !           848: //===========================================================================
        !           849: 
        !           850: void SZ_Clear (sizebuf_t *buf)
        !           851: {
        !           852:        buf->cursize = 0;
        !           853:        buf->overflowed = false;
        !           854: }
        !           855: 
        !           856: void *SZ_GetSpace (sizebuf_t *buf, int length)
        !           857: {
        !           858:        void    *data;
        !           859:        
        !           860:        if (buf->cursize + length > buf->maxsize)
        !           861:        {
        !           862:                if (!buf->allowoverflow)
        !           863:                        Sys_Error ("SZ_GetSpace: overflow without allowoverflow set (%d)", buf->maxsize);
        !           864:                
        !           865:                if (length > buf->maxsize)
        !           866:                        Sys_Error ("SZ_GetSpace: %i is > full buffer size", length);
        !           867:                        
        !           868:                Sys_Printf ("SZ_GetSpace: overflow\n"); // because Con_Printf may be redirected
        !           869:                SZ_Clear (buf); 
        !           870:                buf->overflowed = true;
        !           871:        }
        !           872: 
        !           873:        data = buf->data + buf->cursize;
        !           874:        buf->cursize += length;
        !           875:        
        !           876:        return data;
        !           877: }
        !           878: 
        !           879: void SZ_Write (sizebuf_t *buf, void *data, int length)
        !           880: {
        !           881:        Q_memcpy (SZ_GetSpace(buf,length),data,length);         
        !           882: }
        !           883: 
        !           884: void SZ_Print (sizebuf_t *buf, char *data)
        !           885: {
        !           886:        int             len;
        !           887:        
        !           888:        len = Q_strlen(data)+1;
        !           889: 
        !           890:        if (!buf->cursize || buf->data[buf->cursize-1])
        !           891:                Q_memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
        !           892:        else
        !           893:                Q_memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
        !           894: }
        !           895: 
        !           896: 
        !           897: //============================================================================
        !           898: 
        !           899: 
        !           900: /*
        !           901: ============
        !           902: COM_SkipPath
        !           903: ============
        !           904: */
        !           905: char *COM_SkipPath (char *pathname)
        !           906: {
        !           907:        char    *last;
        !           908:        
        !           909:        last = pathname;
        !           910:        while (*pathname)
        !           911:        {
        !           912:                if (*pathname=='/')
        !           913:                        last = pathname+1;
        !           914:                pathname++;
        !           915:        }
        !           916:        return last;
        !           917: }
        !           918: 
        !           919: /*
        !           920: ============
        !           921: COM_StripExtension
        !           922: ============
        !           923: */
        !           924: void COM_StripExtension (char *in, char *out)
        !           925: {
        !           926:        while (*in && *in != '.')
        !           927:                *out++ = *in++;
        !           928:        *out = 0;
        !           929: }
        !           930: 
        !           931: /*
        !           932: ============
        !           933: COM_FileExtension
        !           934: ============
        !           935: */
        !           936: char *COM_FileExtension (char *in)
        !           937: {
        !           938:        static char exten[8];
        !           939:        int             i;
        !           940: 
        !           941:        while (*in && *in != '.')
        !           942:                in++;
        !           943:        if (!*in)
        !           944:                return "";
        !           945:        in++;
        !           946:        for (i=0 ; i<7 && *in ; i++,in++)
        !           947:                exten[i] = *in;
        !           948:        exten[i] = 0;
        !           949:        return exten;
        !           950: }
        !           951: 
        !           952: /*
        !           953: ============
        !           954: COM_FileBase
        !           955: ============
        !           956: */
        !           957: void COM_FileBase (char *in, char *out)
        !           958: {
        !           959:        char *s, *s2;
        !           960:        
        !           961:        s = in + strlen(in) - 1;
        !           962:        
        !           963:        while (s != in && *s != '.')
        !           964:                s--;
        !           965:        
        !           966:        for (s2 = s ; *s2 && *s2 != '/' ; s2--)
        !           967:        ;
        !           968:        
        !           969:        if (s-s2 < 2)
        !           970:                strcpy (out,"?model?");
        !           971:        else
        !           972:        {
        !           973:                s--;
        !           974:                strncpy (out,s2+1, s-s2);
        !           975:                out[s-s2] = 0;
        !           976:        }
        !           977: }
        !           978: 
        !           979: 
        !           980: /*
        !           981: ==================
        !           982: COM_DefaultExtension
        !           983: ==================
        !           984: */
        !           985: void COM_DefaultExtension (char *path, char *extension)
        !           986: {
        !           987:        char    *src;
        !           988: //
        !           989: // if path doesn't have a .EXT, append extension
        !           990: // (extension should include the .)
        !           991: //
        !           992:        src = path + strlen(path) - 1;
        !           993: 
        !           994:        while (*src != '/' && src != path)
        !           995:        {
        !           996:                if (*src == '.')
        !           997:                        return;                 // it has an extension
        !           998:                src--;
        !           999:        }
        !          1000: 
        !          1001:        strcat (path, extension);
        !          1002: }
        !          1003: 
        !          1004: //============================================================================
        !          1005: 
        !          1006: char           com_token[1024];
        !          1007: int            com_argc;
        !          1008: char   **com_argv;
        !          1009: 
        !          1010: 
        !          1011: /*
        !          1012: ==============
        !          1013: COM_Parse
        !          1014: 
        !          1015: Parse a token out of a string
        !          1016: ==============
        !          1017: */
        !          1018: char *COM_Parse (char *data)
        !          1019: {
        !          1020:        int             c;
        !          1021:        int             len;
        !          1022:        
        !          1023:        len = 0;
        !          1024:        com_token[0] = 0;
        !          1025:        
        !          1026:        if (!data)
        !          1027:                return NULL;
        !          1028:                
        !          1029: // skip whitespace
        !          1030: skipwhite:
        !          1031:        while ( (c = *data) <= ' ')
        !          1032:        {
        !          1033:                if (c == 0)
        !          1034:                        return NULL;                    // end of file;
        !          1035:                data++;
        !          1036:        }
        !          1037:        
        !          1038: // skip // comments
        !          1039:        if (c=='/' && data[1] == '/')
        !          1040:        {
        !          1041:                while (*data && *data != '\n')
        !          1042:                        data++;
        !          1043:                goto skipwhite;
        !          1044:        }
        !          1045:        
        !          1046: 
        !          1047: // handle quoted strings specially
        !          1048:        if (c == '\"')
        !          1049:        {
        !          1050:                data++;
        !          1051:                while (1)
        !          1052:                {
        !          1053:                        c = *data++;
        !          1054:                        if (c=='\"' || !c)
        !          1055:                        {
        !          1056:                                com_token[len] = 0;
        !          1057:                                return data;
        !          1058:                        }
        !          1059:                        com_token[len] = c;
        !          1060:                        len++;
        !          1061:                }
        !          1062:        }
        !          1063: 
        !          1064: // parse a regular word
        !          1065:        do
        !          1066:        {
        !          1067:                com_token[len] = c;
        !          1068:                data++;
        !          1069:                len++;
        !          1070:                c = *data;
        !          1071:        } while (c>32);
        !          1072:        
        !          1073:        com_token[len] = 0;
        !          1074:        return data;
        !          1075: }
        !          1076: 
        !          1077: 
        !          1078: /*
        !          1079: ================
        !          1080: COM_CheckParm
        !          1081: 
        !          1082: Returns the position (1 to argc-1) in the program's argument list
        !          1083: where the given parameter apears, or 0 if not present
        !          1084: ================
        !          1085: */
        !          1086: int COM_CheckParm (char *parm)
        !          1087: {
        !          1088:        int             i;
        !          1089:        
        !          1090:        for (i=1 ; i<com_argc ; i++)
        !          1091:        {
        !          1092:                if (!com_argv[i])
        !          1093:                        continue;               // NEXTSTEP sometimes clears appkit vars.
        !          1094:                if (!Q_strcmp (parm,com_argv[i]))
        !          1095:                        return i;
        !          1096:        }
        !          1097:                
        !          1098:        return 0;
        !          1099: }
        !          1100: 
        !          1101: /*
        !          1102: ================
        !          1103: COM_CheckRegistered
        !          1104: 
        !          1105: Looks for the pop.txt file and verifies it.
        !          1106: Sets the "registered" cvar.
        !          1107: Immediately exits out if an alternate game was attempted to be started without
        !          1108: being registered.
        !          1109: ================
        !          1110: */
        !          1111: void COM_CheckRegistered (void)
        !          1112: {
        !          1113:        FILE            *h;
        !          1114:        unsigned short  check[128];
        !          1115:        int                     i;
        !          1116: 
        !          1117:        COM_FOpenFile("gfx/pop.lmp", &h);
        !          1118:        static_registered = 0;
        !          1119: 
        !          1120:        if (!h)
        !          1121:        {
        !          1122:                Con_Printf ("Playing shareware version.\n");
        !          1123: #ifndef SERVERONLY
        !          1124: // FIXME DEBUG -- only temporary
        !          1125:                if (com_modified)
        !          1126:                        Sys_Error ("You must have the registered version to play QuakeWorld");
        !          1127: #endif
        !          1128:                return;
        !          1129:        }
        !          1130: 
        !          1131:        fread (check, 1, sizeof(check), h);
        !          1132:        fclose (h);
        !          1133:        
        !          1134:        for (i=0 ; i<128 ; i++)
        !          1135:                if (pop[i] != (unsigned short)BigShort (check[i]))
        !          1136:                        Sys_Error ("Corrupted data file.");
        !          1137:        
        !          1138:        Cvar_Set ("registered", "1");
        !          1139:        static_registered = 1;
        !          1140:        Con_Printf ("Playing registered version.\n");
        !          1141: }
        !          1142: 
        !          1143: 
        !          1144: 
        !          1145: /*
        !          1146: ================
        !          1147: COM_InitArgv
        !          1148: ================
        !          1149: */
        !          1150: void COM_InitArgv (int argc, char **argv)
        !          1151: {
        !          1152:        qboolean        safe;
        !          1153:        int                     i;
        !          1154: 
        !          1155:        safe = false;
        !          1156: 
        !          1157:        for (com_argc=0 ; (com_argc<MAX_NUM_ARGVS) && (com_argc < argc) ;
        !          1158:                 com_argc++)
        !          1159:        {
        !          1160:                largv[com_argc] = argv[com_argc];
        !          1161:                if (!Q_strcmp ("-safe", argv[com_argc]))
        !          1162:                        safe = true;
        !          1163:        }
        !          1164: 
        !          1165:        if (safe)
        !          1166:        {
        !          1167:        // force all the safe-mode switches. Note that we reserved extra space in
        !          1168:        // case we need to add these, so we don't need an overflow check
        !          1169:                for (i=0 ; i<NUM_SAFE_ARGVS ; i++)
        !          1170:                {
        !          1171:                        largv[com_argc] = safeargvs[i];
        !          1172:                        com_argc++;
        !          1173:                }
        !          1174:        }
        !          1175: 
        !          1176:        largv[com_argc] = argvdummy;
        !          1177:        com_argv = largv;
        !          1178: }
        !          1179: 
        !          1180: /*
        !          1181: ================
        !          1182: COM_AddParm
        !          1183: 
        !          1184: Adds the given string at the end of the current argument list
        !          1185: ================
        !          1186: */
        !          1187: void COM_AddParm (char *parm)
        !          1188: {
        !          1189:        largv[com_argc++] = parm;
        !          1190: }
        !          1191: 
        !          1192: 
        !          1193: /*
        !          1194: ================
        !          1195: COM_Init
        !          1196: ================
        !          1197: */
        !          1198: void COM_Init (void)
        !          1199: {
        !          1200:        byte    swaptest[2] = {1,0};
        !          1201: 
        !          1202: // set the byte swapping variables in a portable manner        
        !          1203:        if ( *(short *)swaptest == 1)
        !          1204:        {
        !          1205:                bigendien = false;
        !          1206:                BigShort = ShortSwap;
        !          1207:                LittleShort = ShortNoSwap;
        !          1208:                BigLong = LongSwap;
        !          1209:                LittleLong = LongNoSwap;
        !          1210:                BigFloat = FloatSwap;
        !          1211:                LittleFloat = FloatNoSwap;
        !          1212:        }
        !          1213:        else
        !          1214:        {
        !          1215:                bigendien = true;
        !          1216:                BigShort = ShortNoSwap;
        !          1217:                LittleShort = ShortSwap;
        !          1218:                BigLong = LongNoSwap;
        !          1219:                LittleLong = LongSwap;
        !          1220:                BigFloat = FloatNoSwap;
        !          1221:                LittleFloat = FloatSwap;
        !          1222:        }
        !          1223: 
        !          1224:        Cvar_RegisterVariable (&registered);
        !          1225:        Cmd_AddCommand ("path", COM_Path_f);
        !          1226: 
        !          1227:        COM_InitFilesystem ();
        !          1228:        COM_CheckRegistered ();
        !          1229: }
        !          1230: 
        !          1231: 
        !          1232: /*
        !          1233: ============
        !          1234: va
        !          1235: 
        !          1236: does a varargs printf into a temp buffer, so I don't need to have
        !          1237: varargs versions of all text functions.
        !          1238: FIXME: make this buffer size safe someday
        !          1239: ============
        !          1240: */
        !          1241: char   *va(char *format, ...)
        !          1242: {
        !          1243:        va_list         argptr;
        !          1244:        static char             string[1024];
        !          1245:        
        !          1246:        va_start (argptr, format);
        !          1247:        vsprintf (string, format,argptr);
        !          1248:        va_end (argptr);
        !          1249: 
        !          1250:        return string;  
        !          1251: }
        !          1252: 
        !          1253: 
        !          1254: /// just for debugging
        !          1255: int    memsearch (byte *start, int count, int search)
        !          1256: {
        !          1257:        int             i;
        !          1258:        
        !          1259:        for (i=0 ; i<count ; i++)
        !          1260:                if (start[i] == search)
        !          1261:                        return i;
        !          1262:        return -1;
        !          1263: }
        !          1264: 
        !          1265: /*
        !          1266: =============================================================================
        !          1267: 
        !          1268: QUAKE FILESYSTEM
        !          1269: 
        !          1270: =============================================================================
        !          1271: */
        !          1272: 
        !          1273: int    com_filesize;
        !          1274: 
        !          1275: 
        !          1276: //
        !          1277: // in memory
        !          1278: //
        !          1279: 
        !          1280: typedef struct
        !          1281: {
        !          1282:        char    name[MAX_QPATH];
        !          1283:        int             filepos, filelen;
        !          1284: } packfile_t;
        !          1285: 
        !          1286: typedef struct pack_s
        !          1287: {
        !          1288:        char    filename[MAX_OSPATH];
        !          1289:        FILE    *handle;
        !          1290:        int             numfiles;
        !          1291:        packfile_t      *files;
        !          1292: } pack_t;
        !          1293: 
        !          1294: //
        !          1295: // on disk
        !          1296: //
        !          1297: typedef struct
        !          1298: {
        !          1299:        char    name[56];
        !          1300:        int             filepos, filelen;
        !          1301: } dpackfile_t;
        !          1302: 
        !          1303: typedef struct
        !          1304: {
        !          1305:        char    id[4];
        !          1306:        int             dirofs;
        !          1307:        int             dirlen;
        !          1308: } dpackheader_t;
        !          1309: 
        !          1310: #define        MAX_FILES_IN_PACK       2048
        !          1311: 
        !          1312: char   com_gamedir[MAX_OSPATH];
        !          1313: char   com_basedir[MAX_OSPATH];
        !          1314: 
        !          1315: typedef struct searchpath_s
        !          1316: {
        !          1317:        char    filename[MAX_OSPATH];
        !          1318:        pack_t  *pack;          // only one of filename / pack will be used
        !          1319:        struct searchpath_s *next;
        !          1320: } searchpath_t;
        !          1321: 
        !          1322: searchpath_t   *com_searchpaths;
        !          1323: searchpath_t   *com_base_searchpaths;  // without gamedirs
        !          1324: 
        !          1325: /*
        !          1326: ================
        !          1327: COM_filelength
        !          1328: ================
        !          1329: */
        !          1330: int COM_filelength (FILE *f)
        !          1331: {
        !          1332:        int             pos;
        !          1333:        int             end;
        !          1334: 
        !          1335:        pos = ftell (f);
        !          1336:        fseek (f, 0, SEEK_END);
        !          1337:        end = ftell (f);
        !          1338:        fseek (f, pos, SEEK_SET);
        !          1339: 
        !          1340:        return end;
        !          1341: }
        !          1342: 
        !          1343: int COM_FileOpenRead (char *path, FILE **hndl)
        !          1344: {
        !          1345:        FILE    *f;
        !          1346: 
        !          1347:        f = fopen(path, "rb");
        !          1348:        if (!f)
        !          1349:        {
        !          1350:                *hndl = NULL;
        !          1351:                return -1;
        !          1352:        }
        !          1353:        *hndl = f;
        !          1354:        
        !          1355:        return COM_filelength(f);
        !          1356: }
        !          1357: 
        !          1358: /*
        !          1359: ============
        !          1360: COM_Path_f
        !          1361: 
        !          1362: ============
        !          1363: */
        !          1364: void COM_Path_f (void)
        !          1365: {
        !          1366:        searchpath_t    *s;
        !          1367:        
        !          1368:        Con_Printf ("Current search path:\n");
        !          1369:        for (s=com_searchpaths ; s ; s=s->next)
        !          1370:        {
        !          1371:                if (s == com_base_searchpaths)
        !          1372:                        Con_Printf ("----------\n");
        !          1373:                if (s->pack)
        !          1374:                        Con_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles);
        !          1375:                else
        !          1376:                        Con_Printf ("%s\n", s->filename);
        !          1377:        }
        !          1378: }
        !          1379: 
        !          1380: /*
        !          1381: ============
        !          1382: COM_WriteFile
        !          1383: 
        !          1384: The filename will be prefixed by the current game directory
        !          1385: ============
        !          1386: */
        !          1387: void COM_WriteFile (char *filename, void *data, int len)
        !          1388: {
        !          1389:        FILE    *f;
        !          1390:        char    name[MAX_OSPATH];
        !          1391:        
        !          1392:        sprintf (name, "%s/%s", com_gamedir, filename);
        !          1393:        
        !          1394:        f = fopen (name, "wb");
        !          1395:        if (!f) {
        !          1396:                Sys_mkdir(com_gamedir);
        !          1397:                f = fopen (name, "wb");
        !          1398:                if (!f)
        !          1399:                        Sys_Error ("Error opening %s", filename);
        !          1400:        }
        !          1401:        
        !          1402:        Sys_Printf ("COM_WriteFile: %s\n", name);
        !          1403:        fwrite (data, 1, len, f);
        !          1404:        fclose (f);
        !          1405: }
        !          1406: 
        !          1407: 
        !          1408: /*
        !          1409: ============
        !          1410: COM_CreatePath
        !          1411: 
        !          1412: Only used for CopyFile and download
        !          1413: ============
        !          1414: */
        !          1415: void   COM_CreatePath (char *path)
        !          1416: {
        !          1417:        char    *ofs;
        !          1418:        
        !          1419:        for (ofs = path+1 ; *ofs ; ofs++)
        !          1420:        {
        !          1421:                if (*ofs == '/')
        !          1422:                {       // create the directory
        !          1423:                        *ofs = 0;
        !          1424:                        Sys_mkdir (path);
        !          1425:                        *ofs = '/';
        !          1426:                }
        !          1427:        }
        !          1428: }
        !          1429: 
        !          1430: 
        !          1431: /*
        !          1432: ===========
        !          1433: COM_CopyFile
        !          1434: 
        !          1435: Copies a file over from the net to the local cache, creating any directories
        !          1436: needed.  This is for the convenience of developers using ISDN from home.
        !          1437: ===========
        !          1438: */
        !          1439: void COM_CopyFile (char *netpath, char *cachepath)
        !          1440: {
        !          1441:        FILE    *in, *out;
        !          1442:        int             remaining, count;
        !          1443:        char    buf[4096];
        !          1444:        
        !          1445:        remaining = COM_FileOpenRead (netpath, &in);            
        !          1446:        COM_CreatePath (cachepath);     // create directories up to the cache file
        !          1447:        out = fopen(cachepath, "wb");
        !          1448:        if (!out)
        !          1449:                Sys_Error ("Error opening %s", cachepath);
        !          1450:        
        !          1451:        while (remaining)
        !          1452:        {
        !          1453:                if (remaining < sizeof(buf))
        !          1454:                        count = remaining;
        !          1455:                else
        !          1456:                        count = sizeof(buf);
        !          1457:                fread (buf, 1, count, in);
        !          1458:                fwrite (buf, 1, count, out);
        !          1459:                remaining -= count;
        !          1460:        }
        !          1461: 
        !          1462:        fclose (in);
        !          1463:        fclose (out);
        !          1464: }
        !          1465: 
        !          1466: /*
        !          1467: ===========
        !          1468: COM_FindFile
        !          1469: 
        !          1470: Finds the file in the search path.
        !          1471: Sets com_filesize and one of handle or file
        !          1472: ===========
        !          1473: */
        !          1474: int file_from_pak; // global indicating file came from pack file ZOID
        !          1475: 
        !          1476: int COM_FOpenFile (char *filename, FILE **file)
        !          1477: {
        !          1478:        searchpath_t    *search;
        !          1479:        char            netpath[MAX_OSPATH];
        !          1480:        pack_t          *pak;
        !          1481:        int                     i;
        !          1482:        int                     findtime;
        !          1483: 
        !          1484:        file_from_pak = 0;
        !          1485:                
        !          1486: //
        !          1487: // search through the path, one element at a time
        !          1488: //
        !          1489:        for (search = com_searchpaths ; search ; search = search->next)
        !          1490:        {
        !          1491:        // is the element a pak file?
        !          1492:                if (search->pack)
        !          1493:                {
        !          1494:                // look through all the pak file elements
        !          1495:                        pak = search->pack;
        !          1496:                        for (i=0 ; i<pak->numfiles ; i++)
        !          1497:                                if (!strcmp (pak->files[i].name, filename))
        !          1498:                                {       // found it!
        !          1499:                                        Sys_Printf ("PackFile: %s : %s\n",pak->filename, filename);
        !          1500:                                // open a new file on the pakfile
        !          1501:                                        *file = fopen (pak->filename, "rb");
        !          1502:                                        if (!*file)
        !          1503:                                                Sys_Error ("Couldn't reopen %s", pak->filename);        
        !          1504:                                        fseek (*file, pak->files[i].filepos, SEEK_SET);
        !          1505:                                        com_filesize = pak->files[i].filelen;
        !          1506:                                        file_from_pak = 1;
        !          1507:                                        return com_filesize;
        !          1508:                                }
        !          1509:                }
        !          1510:                else
        !          1511:                {               
        !          1512:        // check a file in the directory tree
        !          1513:                        if (!static_registered)
        !          1514:                        {       // if not a registered version, don't ever go beyond base
        !          1515:                                if ( strchr (filename, '/') || strchr (filename,'\\'))
        !          1516:                                        continue;
        !          1517:                        }
        !          1518:                        
        !          1519:                        sprintf (netpath, "%s/%s",search->filename, filename);
        !          1520:                        
        !          1521:                        findtime = Sys_FileTime (netpath);
        !          1522:                        if (findtime == -1)
        !          1523:                                continue;
        !          1524:                                
        !          1525:                        Sys_Printf ("FindFile: %s\n",netpath);
        !          1526: 
        !          1527:                        *file = fopen (netpath, "rb");
        !          1528:                        return COM_filelength (*file);
        !          1529:                }
        !          1530:                
        !          1531:        }
        !          1532:        
        !          1533:        Sys_Printf ("FindFile: can't find %s\n", filename);
        !          1534:        
        !          1535:        *file = NULL;
        !          1536:        com_filesize = -1;
        !          1537:        return -1;
        !          1538: }
        !          1539: 
        !          1540: /*
        !          1541: ============
        !          1542: COM_LoadFile
        !          1543: 
        !          1544: Filename are reletive to the quake directory.
        !          1545: Allways appends a 0 byte to the loaded data.
        !          1546: ============
        !          1547: */
        !          1548: cache_user_t *loadcache;
        !          1549: byte   *loadbuf;
        !          1550: int            loadsize;
        !          1551: byte *COM_LoadFile (char *path, int usehunk)
        !          1552: {
        !          1553:        FILE    *h;
        !          1554:        byte    *buf;
        !          1555:        char    base[32];
        !          1556:        int             len;
        !          1557: 
        !          1558:        buf = NULL;     // quiet compiler warning
        !          1559: 
        !          1560: // look for it in the filesystem or pack files
        !          1561:        len = com_filesize = COM_FOpenFile (path, &h);
        !          1562:        if (!h)
        !          1563:                return NULL;
        !          1564:        
        !          1565: // extract the filename base name for hunk tag
        !          1566:        COM_FileBase (path, base);
        !          1567:        
        !          1568:        if (usehunk == 1)
        !          1569:                buf = Hunk_AllocName (len+1, base);
        !          1570:        else if (usehunk == 2)
        !          1571:                buf = Hunk_TempAlloc (len+1);
        !          1572:        else if (usehunk == 0)
        !          1573:                buf = Z_Malloc (len+1);
        !          1574:        else if (usehunk == 3)
        !          1575:                buf = Cache_Alloc (loadcache, len+1, base);
        !          1576:        else if (usehunk == 4)
        !          1577:        {
        !          1578:                if (len+1 > loadsize)
        !          1579:                        buf = Hunk_TempAlloc (len+1);
        !          1580:                else
        !          1581:                        buf = loadbuf;
        !          1582:        }
        !          1583:        else
        !          1584:                Sys_Error ("COM_LoadFile: bad usehunk");
        !          1585: 
        !          1586:        if (!buf)
        !          1587:                Sys_Error ("COM_LoadFile: not enough space for %s", path);
        !          1588:                
        !          1589:        ((byte *)buf)[len] = 0;
        !          1590: #ifndef SERVERONLY
        !          1591:        Draw_BeginDisc ();
        !          1592: #endif
        !          1593:        fread (buf, 1, len, h);
        !          1594:        fclose (h);
        !          1595: #ifndef SERVERONLY
        !          1596:        Draw_EndDisc ();
        !          1597: #endif
        !          1598: 
        !          1599:        return buf;
        !          1600: }
        !          1601: 
        !          1602: byte *COM_LoadHunkFile (char *path)
        !          1603: {
        !          1604:        return COM_LoadFile (path, 1);
        !          1605: }
        !          1606: 
        !          1607: byte *COM_LoadTempFile (char *path)
        !          1608: {
        !          1609:        return COM_LoadFile (path, 2);
        !          1610: }
        !          1611: 
        !          1612: void COM_LoadCacheFile (char *path, struct cache_user_s *cu)
        !          1613: {
        !          1614:        loadcache = cu;
        !          1615:        COM_LoadFile (path, 3);
        !          1616: }
        !          1617: 
        !          1618: // uses temp hunk if larger than bufsize
        !          1619: byte *COM_LoadStackFile (char *path, void *buffer, int bufsize)
        !          1620: {
        !          1621:        byte    *buf;
        !          1622:        
        !          1623:        loadbuf = (byte *)buffer;
        !          1624:        loadsize = bufsize;
        !          1625:        buf = COM_LoadFile (path, 4);
        !          1626:        
        !          1627:        return buf;
        !          1628: }
        !          1629: 
        !          1630: /*
        !          1631: =================
        !          1632: COM_LoadPackFile
        !          1633: 
        !          1634: Takes an explicit (not game tree related) path to a pak file.
        !          1635: 
        !          1636: Loads the header and directory, adding the files at the beginning
        !          1637: of the list so they override previous pack files.
        !          1638: =================
        !          1639: */
        !          1640: pack_t *COM_LoadPackFile (char *packfile)
        !          1641: {
        !          1642:        dpackheader_t   header;
        !          1643:        int                             i;
        !          1644:        packfile_t              *newfiles;
        !          1645:        int                             numpackfiles;
        !          1646:        pack_t                  *pack;
        !          1647:        FILE                    *packhandle;
        !          1648:        dpackfile_t             info[MAX_FILES_IN_PACK];
        !          1649:        unsigned short          crc;
        !          1650: 
        !          1651:        if (COM_FileOpenRead (packfile, &packhandle) == -1)
        !          1652:                return NULL;
        !          1653: 
        !          1654:        fread (&header, 1, sizeof(header), packhandle);
        !          1655:        if (header.id[0] != 'P' || header.id[1] != 'A'
        !          1656:        || header.id[2] != 'C' || header.id[3] != 'K')
        !          1657:                Sys_Error ("%s is not a packfile", packfile);
        !          1658:        header.dirofs = LittleLong (header.dirofs);
        !          1659:        header.dirlen = LittleLong (header.dirlen);
        !          1660: 
        !          1661:        numpackfiles = header.dirlen / sizeof(dpackfile_t);
        !          1662: 
        !          1663:        if (numpackfiles > MAX_FILES_IN_PACK)
        !          1664:                Sys_Error ("%s has %i files", packfile, numpackfiles);
        !          1665: 
        !          1666:        if (numpackfiles != PAK0_COUNT)
        !          1667:                com_modified = true;    // not the original file
        !          1668: 
        !          1669:        newfiles = Z_Malloc (numpackfiles * sizeof(packfile_t));
        !          1670: 
        !          1671:        fseek (packhandle, header.dirofs, SEEK_SET);
        !          1672:        fread (&info, 1, header.dirlen, packhandle);
        !          1673: 
        !          1674: // crc the directory to check for modifications
        !          1675:        crc = CRC_Block((byte *)info, header.dirlen);
        !          1676: 
        !          1677: //     CRC_Init (&crc);
        !          1678: //     for (i=0 ; i<header.dirlen ; i++)
        !          1679: //             CRC_ProcessByte (&crc, ((byte *)info)[i]);
        !          1680:        if (crc != PAK0_CRC)
        !          1681:                com_modified = true;
        !          1682: 
        !          1683: // parse the directory
        !          1684:        for (i=0 ; i<numpackfiles ; i++)
        !          1685:        {
        !          1686:                strcpy (newfiles[i].name, info[i].name);
        !          1687:                newfiles[i].filepos = LittleLong(info[i].filepos);
        !          1688:                newfiles[i].filelen = LittleLong(info[i].filelen);
        !          1689:        }
        !          1690: 
        !          1691:        pack = Z_Malloc (sizeof (pack_t));
        !          1692:        strcpy (pack->filename, packfile);
        !          1693:        pack->handle = packhandle;
        !          1694:        pack->numfiles = numpackfiles;
        !          1695:        pack->files = newfiles;
        !          1696:        
        !          1697:        Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles);
        !          1698:        return pack;
        !          1699: }
        !          1700: 
        !          1701: 
        !          1702: /*
        !          1703: ================
        !          1704: COM_AddGameDirectory
        !          1705: 
        !          1706: Sets com_gamedir, adds the directory to the head of the path,
        !          1707: then loads and adds pak1.pak pak2.pak ... 
        !          1708: ================
        !          1709: */
        !          1710: void COM_AddGameDirectory (char *dir)
        !          1711: {
        !          1712:        int                             i;
        !          1713:        searchpath_t    *search;
        !          1714:        pack_t                  *pak;
        !          1715:        char                    pakfile[MAX_OSPATH];
        !          1716:        char                    *p;
        !          1717: 
        !          1718:        if ((p = strrchr(dir, '/')) != NULL)
        !          1719:                strcpy(gamedirfile, ++p);
        !          1720:        else
        !          1721:                strcpy(gamedirfile, p);
        !          1722:        strcpy (com_gamedir, dir);
        !          1723: 
        !          1724: //
        !          1725: // add the directory to the search path
        !          1726: //
        !          1727:        search = Hunk_Alloc (sizeof(searchpath_t));
        !          1728:        strcpy (search->filename, dir);
        !          1729:        search->next = com_searchpaths;
        !          1730:        com_searchpaths = search;
        !          1731: 
        !          1732: //
        !          1733: // add any pak files in the format pak0.pak pak1.pak, ...
        !          1734: //
        !          1735:        for (i=0 ; ; i++)
        !          1736:        {
        !          1737:                sprintf (pakfile, "%s/pak%i.pak", dir, i);
        !          1738:                pak = COM_LoadPackFile (pakfile);
        !          1739:                if (!pak)
        !          1740:                        break;
        !          1741:                search = Hunk_Alloc (sizeof(searchpath_t));
        !          1742:                search->pack = pak;
        !          1743:                search->next = com_searchpaths;
        !          1744:                com_searchpaths = search;               
        !          1745:        }
        !          1746: 
        !          1747: }
        !          1748: 
        !          1749: /*
        !          1750: ================
        !          1751: COM_Gamedir
        !          1752: 
        !          1753: Sets the gamedir and path to a different directory.
        !          1754: ================
        !          1755: */
        !          1756: void COM_Gamedir (char *dir)
        !          1757: {
        !          1758:        searchpath_t    *search, *next;
        !          1759:        int                             i;
        !          1760:        pack_t                  *pak;
        !          1761:        char                    pakfile[MAX_OSPATH];
        !          1762: 
        !          1763:        if (strstr(dir, "..") || strstr(dir, "/")
        !          1764:                || strstr(dir, "\\") || strstr(dir, ":") )
        !          1765:        {
        !          1766:                Con_Printf ("Gamedir should be a single filename, not a path\n");
        !          1767:                return;
        !          1768:        }
        !          1769: 
        !          1770:        if (!strcmp(gamedirfile, dir))
        !          1771:                return;         // still the same
        !          1772:        strcpy (gamedirfile, dir);
        !          1773: 
        !          1774:        //
        !          1775:        // free up any current game dir info
        !          1776:        //
        !          1777:        while (com_searchpaths != com_base_searchpaths)
        !          1778:        {
        !          1779:                if (com_searchpaths->pack)
        !          1780:                {
        !          1781:                        fclose (com_searchpaths->pack->handle);
        !          1782:                        Z_Free (com_searchpaths->pack->files);
        !          1783:                        Z_Free (com_searchpaths->pack);
        !          1784:                }
        !          1785:                next = com_searchpaths->next;
        !          1786:                Z_Free (com_searchpaths);
        !          1787:                com_searchpaths = next;
        !          1788:        }
        !          1789: 
        !          1790:        //
        !          1791:        // flush all data, so it will be forced to reload
        !          1792:        //
        !          1793:        Cache_Flush ();
        !          1794: 
        !          1795:        if (!strcmp(dir,"id1") || !strcmp(dir, "qw"))
        !          1796:                return;
        !          1797: 
        !          1798:        sprintf (com_gamedir, "%s/%s", com_basedir, dir);
        !          1799: 
        !          1800:        //
        !          1801:        // add the directory to the search path
        !          1802:        //
        !          1803:        search = Z_Malloc (sizeof(searchpath_t));
        !          1804:        strcpy (search->filename, com_gamedir);
        !          1805:        search->next = com_searchpaths;
        !          1806:        com_searchpaths = search;
        !          1807: 
        !          1808:        //
        !          1809:        // add any pak files in the format pak0.pak pak1.pak, ...
        !          1810:        //
        !          1811:        for (i=0 ; ; i++)
        !          1812:        {
        !          1813:                sprintf (pakfile, "%s/pak%i.pak", com_gamedir, i);
        !          1814:                pak = COM_LoadPackFile (pakfile);
        !          1815:                if (!pak)
        !          1816:                        break;
        !          1817:                search = Z_Malloc (sizeof(searchpath_t));
        !          1818:                search->pack = pak;
        !          1819:                search->next = com_searchpaths;
        !          1820:                com_searchpaths = search;               
        !          1821:        }
        !          1822: }
        !          1823: 
        !          1824: /*
        !          1825: ================
        !          1826: COM_InitFilesystem
        !          1827: ================
        !          1828: */
        !          1829: void COM_InitFilesystem (void)
        !          1830: {
        !          1831:        int             i;
        !          1832: 
        !          1833: //
        !          1834: // -basedir <path>
        !          1835: // Overrides the system supplied base directory (under id1)
        !          1836: //
        !          1837:        i = COM_CheckParm ("-basedir");
        !          1838:        if (i && i < com_argc-1)
        !          1839:                strcpy (com_basedir, com_argv[i+1]);
        !          1840:        else
        !          1841:                strcpy (com_basedir, host_parms.basedir);
        !          1842: 
        !          1843: //
        !          1844: // start up with id1 by default
        !          1845: //
        !          1846:        COM_AddGameDirectory (va("%s/id1", com_basedir) );
        !          1847:        COM_AddGameDirectory (va("%s/qw", com_basedir) );
        !          1848: 
        !          1849:        // any set gamedirs will be freed up to here
        !          1850:        com_base_searchpaths = com_searchpaths;
        !          1851: }
        !          1852: 
        !          1853: 
        !          1854: 
        !          1855: /*
        !          1856: =====================================================================
        !          1857: 
        !          1858:   INFO STRINGS
        !          1859: 
        !          1860: =====================================================================
        !          1861: */
        !          1862: 
        !          1863: /*
        !          1864: ===============
        !          1865: Info_ValueForKey
        !          1866: 
        !          1867: Searches the string for the given
        !          1868: key and returns the associated value, or an empty string.
        !          1869: ===============
        !          1870: */
        !          1871: char *Info_ValueForKey (char *s, char *key)
        !          1872: {
        !          1873:        char    pkey[512];
        !          1874:        static  char value[4][512];     // use two buffers so compares
        !          1875:                                                                // work without stomping on each other
        !          1876:        static  int     valueindex;
        !          1877:        char    *o;
        !          1878:        
        !          1879:        valueindex = (valueindex + 1) % 4;
        !          1880:        if (*s == '\\')
        !          1881:                s++;
        !          1882:        while (1)
        !          1883:        {
        !          1884:                o = pkey;
        !          1885:                while (*s != '\\')
        !          1886:                {
        !          1887:                        if (!*s)
        !          1888:                                return "";
        !          1889:                        *o++ = *s++;
        !          1890:                }
        !          1891:                *o = 0;
        !          1892:                s++;
        !          1893: 
        !          1894:                o = value[valueindex];
        !          1895: 
        !          1896:                while (*s != '\\' && *s)
        !          1897:                {
        !          1898:                        if (!*s)
        !          1899:                                return "";
        !          1900:                        *o++ = *s++;
        !          1901:                }
        !          1902:                *o = 0;
        !          1903: 
        !          1904:                if (!strcmp (key, pkey) )
        !          1905:                        return value[valueindex];
        !          1906: 
        !          1907:                if (!*s)
        !          1908:                        return "";
        !          1909:                s++;
        !          1910:        }
        !          1911: }
        !          1912: 
        !          1913: void Info_RemoveKey (char *s, char *key)
        !          1914: {
        !          1915:        char    *start;
        !          1916:        char    pkey[512];
        !          1917:        char    value[512];
        !          1918:        char    *o;
        !          1919: 
        !          1920:        if (strstr (key, "\\"))
        !          1921:        {
        !          1922:                Con_Printf ("Can't use a key with a \\\n");
        !          1923:                return;
        !          1924:        }
        !          1925: 
        !          1926:        while (1)
        !          1927:        {
        !          1928:                start = s;
        !          1929:                if (*s == '\\')
        !          1930:                        s++;
        !          1931:                o = pkey;
        !          1932:                while (*s != '\\')
        !          1933:                {
        !          1934:                        if (!*s)
        !          1935:                                return;
        !          1936:                        *o++ = *s++;
        !          1937:                }
        !          1938:                *o = 0;
        !          1939:                s++;
        !          1940: 
        !          1941:                o = value;
        !          1942:                while (*s != '\\' && *s)
        !          1943:                {
        !          1944:                        if (!*s)
        !          1945:                                return;
        !          1946:                        *o++ = *s++;
        !          1947:                }
        !          1948:                *o = 0;
        !          1949: 
        !          1950:                if (!strcmp (key, pkey) )
        !          1951:                {
        !          1952:                        strcpy (start, s);      // remove this part
        !          1953:                        return;
        !          1954:                }
        !          1955: 
        !          1956:                if (!*s)
        !          1957:                        return;
        !          1958:        }
        !          1959: 
        !          1960: }
        !          1961: 
        !          1962: void Info_RemovePrefixedKeys (char *start, char prefix)
        !          1963: {
        !          1964:        char    *s;
        !          1965:        char    pkey[512];
        !          1966:        char    value[512];
        !          1967:        char    *o;
        !          1968: 
        !          1969:        s = start;
        !          1970: 
        !          1971:        while (1)
        !          1972:        {
        !          1973:                if (*s == '\\')
        !          1974:                        s++;
        !          1975:                o = pkey;
        !          1976:                while (*s != '\\')
        !          1977:                {
        !          1978:                        if (!*s)
        !          1979:                                return;
        !          1980:                        *o++ = *s++;
        !          1981:                }
        !          1982:                *o = 0;
        !          1983:                s++;
        !          1984: 
        !          1985:                o = value;
        !          1986:                while (*s != '\\' && *s)
        !          1987:                {
        !          1988:                        if (!*s)
        !          1989:                                return;
        !          1990:                        *o++ = *s++;
        !          1991:                }
        !          1992:                *o = 0;
        !          1993: 
        !          1994:                if (pkey[0] == prefix)
        !          1995:                {
        !          1996:                        Info_RemoveKey (start, pkey);
        !          1997:                        s = start;
        !          1998:                }
        !          1999: 
        !          2000:                if (!*s)
        !          2001:                        return;
        !          2002:        }
        !          2003: 
        !          2004: }
        !          2005: 
        !          2006: 
        !          2007: void Info_SetValueForStarKey (char *s, char *key, char *value, int maxsize)
        !          2008: {
        !          2009:        char    new[1024], *v;
        !          2010:        int             c;
        !          2011: #ifdef SERVERONLY
        !          2012:        extern cvar_t sv_highchars;
        !          2013: #endif
        !          2014: 
        !          2015:        if (strstr (key, "\\") || strstr (value, "\\") )
        !          2016:        {
        !          2017:                Con_Printf ("Can't use keys or values with a \\\n");
        !          2018:                return;
        !          2019:        }
        !          2020: 
        !          2021:        if (strstr (key, "\"") || strstr (value, "\"") )
        !          2022:        {
        !          2023:                Con_Printf ("Can't use keys or values with a \"\n");
        !          2024:                return;
        !          2025:        }
        !          2026: 
        !          2027:        if (strlen(key) > 63 || strlen(value) > 63)
        !          2028:        {
        !          2029:                Con_Printf ("Keys and values must be < 64 characters.\n");
        !          2030:                return;
        !          2031:        }
        !          2032: 
        !          2033:        // this next line is kinda trippy
        !          2034:        if (*(v = Info_ValueForKey(s, key))) {
        !          2035:                // key exists, make sure we have enough room for new value, if we don't,
        !          2036:                // don't change it!
        !          2037:                if (strlen(value) - strlen(v) + strlen(s) > maxsize) {
        !          2038:                        Con_Printf ("Info string length exceeded\n");
        !          2039:                        return;
        !          2040:                }
        !          2041:        }
        !          2042:        Info_RemoveKey (s, key);
        !          2043:        if (!value || !strlen(value))
        !          2044:                return;
        !          2045: 
        !          2046:        sprintf (new, "\\%s\\%s", key, value);
        !          2047: 
        !          2048:        if ((int)(strlen(new) + strlen(s)) > maxsize)
        !          2049:        {
        !          2050:                Con_Printf ("Info string length exceeded\n");
        !          2051:                return;
        !          2052:        }
        !          2053: 
        !          2054:        // only copy ascii values
        !          2055:        s += strlen(s);
        !          2056:        v = new;
        !          2057:        while (*v)
        !          2058:        {
        !          2059:                c = (unsigned char)*v++;
        !          2060: #ifndef SERVERONLY
        !          2061:                // client only allows highbits on name
        !          2062:                if (stricmp(key, "name") != 0) {
        !          2063:                        c &= 127;
        !          2064:                        if (c < 32 || c > 127)
        !          2065:                                continue;
        !          2066:                        // auto lowercase team
        !          2067:                        if (stricmp(key, "team") == 0)
        !          2068:                                c = tolower(c);
        !          2069:                }
        !          2070: #else
        !          2071:                if (!sv_highchars.value) {
        !          2072:                        c &= 127;
        !          2073:                        if (c < 32 || c > 127)
        !          2074:                                continue;
        !          2075:                }
        !          2076: #endif
        !          2077: //             c &= 127;               // strip high bits
        !          2078:                if (c > 13) // && c < 127)
        !          2079:                        *s++ = c;
        !          2080:        }
        !          2081:        *s = 0;
        !          2082: }
        !          2083: 
        !          2084: void Info_SetValueForKey (char *s, char *key, char *value, int maxsize)
        !          2085: {
        !          2086:        if (key[0] == '*')
        !          2087:        {
        !          2088:                Con_Printf ("Can't set * keys\n");
        !          2089:                return;
        !          2090:        }
        !          2091: 
        !          2092:        Info_SetValueForStarKey (s, key, value, maxsize);
        !          2093: }
        !          2094: 
        !          2095: void Info_Print (char *s)
        !          2096: {
        !          2097:        char    key[512];
        !          2098:        char    value[512];
        !          2099:        char    *o;
        !          2100:        int             l;
        !          2101: 
        !          2102:        if (*s == '\\')
        !          2103:                s++;
        !          2104:        while (*s)
        !          2105:        {
        !          2106:                o = key;
        !          2107:                while (*s && *s != '\\')
        !          2108:                        *o++ = *s++;
        !          2109: 
        !          2110:                l = o - key;
        !          2111:                if (l < 20)
        !          2112:                {
        !          2113:                        memset (o, ' ', 20-l);
        !          2114:                        key[20] = 0;
        !          2115:                }
        !          2116:                else
        !          2117:                        *o = 0;
        !          2118:                Con_Printf ("%s", key);
        !          2119: 
        !          2120:                if (!*s)
        !          2121:                {
        !          2122:                        Con_Printf ("MISSING VALUE\n");
        !          2123:                        return;
        !          2124:                }
        !          2125: 
        !          2126:                o = value;
        !          2127:                s++;
        !          2128:                while (*s && *s != '\\')
        !          2129:                        *o++ = *s++;
        !          2130:                *o = 0;
        !          2131: 
        !          2132:                if (*s)
        !          2133:                        s++;
        !          2134:                Con_Printf ("%s\n", value);
        !          2135:        }
        !          2136: }
        !          2137: 
        !          2138: static byte chktbl[1024 + 4] = {
        !          2139: 0x78,0xd2,0x94,0xe3,0x41,0xec,0xd6,0xd5,0xcb,0xfc,0xdb,0x8a,0x4b,0xcc,0x85,0x01,
        !          2140: 0x23,0xd2,0xe5,0xf2,0x29,0xa7,0x45,0x94,0x4a,0x62,0xe3,0xa5,0x6f,0x3f,0xe1,0x7a,
        !          2141: 0x64,0xed,0x5c,0x99,0x29,0x87,0xa8,0x78,0x59,0x0d,0xaa,0x0f,0x25,0x0a,0x5c,0x58,
        !          2142: 0xfb,0x00,0xa7,0xa8,0x8a,0x1d,0x86,0x80,0xc5,0x1f,0xd2,0x28,0x69,0x71,0x58,0xc3,
        !          2143: 0x51,0x90,0xe1,0xf8,0x6a,0xf3,0x8f,0xb0,0x68,0xdf,0x95,0x40,0x5c,0xe4,0x24,0x6b,
        !          2144: 0x29,0x19,0x71,0x3f,0x42,0x63,0x6c,0x48,0xe7,0xad,0xa8,0x4b,0x91,0x8f,0x42,0x36,
        !          2145: 0x34,0xe7,0x32,0x55,0x59,0x2d,0x36,0x38,0x38,0x59,0x9b,0x08,0x16,0x4d,0x8d,0xf8,
        !          2146: 0x0a,0xa4,0x52,0x01,0xbb,0x52,0xa9,0xfd,0x40,0x18,0x97,0x37,0xff,0xc9,0x82,0x27,
        !          2147: 0xb2,0x64,0x60,0xce,0x00,0xd9,0x04,0xf0,0x9e,0x99,0xbd,0xce,0x8f,0x90,0x4a,0xdd,
        !          2148: 0xe1,0xec,0x19,0x14,0xb1,0xfb,0xca,0x1e,0x98,0x0f,0xd4,0xcb,0x80,0xd6,0x05,0x63,
        !          2149: 0xfd,0xa0,0x74,0xa6,0x86,0xf6,0x19,0x98,0x76,0x27,0x68,0xf7,0xe9,0x09,0x9a,0xf2,
        !          2150: 0x2e,0x42,0xe1,0xbe,0x64,0x48,0x2a,0x74,0x30,0xbb,0x07,0xcc,0x1f,0xd4,0x91,0x9d,
        !          2151: 0xac,0x55,0x53,0x25,0xb9,0x64,0xf7,0x58,0x4c,0x34,0x16,0xbc,0xf6,0x12,0x2b,0x65,
        !          2152: 0x68,0x25,0x2e,0x29,0x1f,0xbb,0xb9,0xee,0x6d,0x0c,0x8e,0xbb,0xd2,0x5f,0x1d,0x8f,
        !          2153: 0xc1,0x39,0xf9,0x8d,0xc0,0x39,0x75,0xcf,0x25,0x17,0xbe,0x96,0xaf,0x98,0x9f,0x5f,
        !          2154: 0x65,0x15,0xc4,0x62,0xf8,0x55,0xfc,0xab,0x54,0xcf,0xdc,0x14,0x06,0xc8,0xfc,0x42,
        !          2155: 0xd3,0xf0,0xad,0x10,0x08,0xcd,0xd4,0x11,0xbb,0xca,0x67,0xc6,0x48,0x5f,0x9d,0x59,
        !          2156: 0xe3,0xe8,0x53,0x67,0x27,0x2d,0x34,0x9e,0x9e,0x24,0x29,0xdb,0x69,0x99,0x86,0xf9,
        !          2157: 0x20,0xb5,0xbb,0x5b,0xb0,0xf9,0xc3,0x67,0xad,0x1c,0x9c,0xf7,0xcc,0xef,0xce,0x69,
        !          2158: 0xe0,0x26,0x8f,0x79,0xbd,0xca,0x10,0x17,0xda,0xa9,0x88,0x57,0x9b,0x15,0x24,0xba,
        !          2159: 0x84,0xd0,0xeb,0x4d,0x14,0xf5,0xfc,0xe6,0x51,0x6c,0x6f,0x64,0x6b,0x73,0xec,0x85,
        !          2160: 0xf1,0x6f,0xe1,0x67,0x25,0x10,0x77,0x32,0x9e,0x85,0x6e,0x69,0xb1,0x83,0x00,0xe4,
        !          2161: 0x13,0xa4,0x45,0x34,0x3b,0x40,0xff,0x41,0x82,0x89,0x79,0x57,0xfd,0xd2,0x8e,0xe8,
        !          2162: 0xfc,0x1d,0x19,0x21,0x12,0x00,0xd7,0x66,0xe5,0xc7,0x10,0x1d,0xcb,0x75,0xe8,0xfa,
        !          2163: 0xb6,0xee,0x7b,0x2f,0x1a,0x25,0x24,0xb9,0x9f,0x1d,0x78,0xfb,0x84,0xd0,0x17,0x05,
        !          2164: 0x71,0xb3,0xc8,0x18,0xff,0x62,0xee,0xed,0x53,0xab,0x78,0xd3,0x65,0x2d,0xbb,0xc7,
        !          2165: 0xc1,0xe7,0x70,0xa2,0x43,0x2c,0x7c,0xc7,0x16,0x04,0xd2,0x45,0xd5,0x6b,0x6c,0x7a,
        !          2166: 0x5e,0xa1,0x50,0x2e,0x31,0x5b,0xcc,0xe8,0x65,0x8b,0x16,0x85,0xbf,0x82,0x83,0xfb,
        !          2167: 0xde,0x9f,0x36,0x48,0x32,0x79,0xd6,0x9b,0xfb,0x52,0x45,0xbf,0x43,0xf7,0x0b,0x0b,
        !          2168: 0x19,0x19,0x31,0xc3,0x85,0xec,0x1d,0x8c,0x20,0xf0,0x3a,0xfa,0x80,0x4d,0x2c,0x7d,
        !          2169: 0xac,0x60,0x09,0xc0,0x40,0xee,0xb9,0xeb,0x13,0x5b,0xe8,0x2b,0xb1,0x20,0xf0,0xce,
        !          2170: 0x4c,0xbd,0xc6,0x04,0x86,0x70,0xc6,0x33,0xc3,0x15,0x0f,0x65,0x19,0xfd,0xc2,0xd3,
        !          2171: 
        !          2172: // map checksum goes here
        !          2173: 0x00,0x00,0x00,0x00
        !          2174: };
        !          2175: 
        !          2176: static byte chkbuf[16 + 60 + 4];
        !          2177: 
        !          2178: static unsigned last_mapchecksum = 0;
        !          2179: 
        !          2180: #if 0
        !          2181: /*
        !          2182: ====================
        !          2183: COM_BlockSequenceCheckByte
        !          2184: 
        !          2185: For proxy protecting
        !          2186: ====================
        !          2187: */
        !          2188: byte   COM_BlockSequenceCheckByte (byte *base, int length, int sequence, unsigned mapchecksum)
        !          2189: {
        !          2190:        int             checksum;
        !          2191:        byte    *p;
        !          2192: 
        !          2193:        if (last_mapchecksum != mapchecksum) {
        !          2194:                last_mapchecksum = mapchecksum;
        !          2195:                chktbl[1024] = (mapchecksum & 0xff000000) >> 24;
        !          2196:                chktbl[1025] = (mapchecksum & 0x00ff0000) >> 16;
        !          2197:                chktbl[1026] = (mapchecksum & 0x0000ff00) >> 8;
        !          2198:                chktbl[1027] = (mapchecksum & 0x000000ff);
        !          2199: 
        !          2200:                Com_BlockFullChecksum (chktbl, sizeof(chktbl), chkbuf);
        !          2201:        }
        !          2202: 
        !          2203:        p = chktbl + (sequence % (sizeof(chktbl) - 8));
        !          2204: 
        !          2205:        if (length > 60)
        !          2206:                length = 60;
        !          2207:        memcpy (chkbuf + 16, base, length);
        !          2208: 
        !          2209:        length += 16;
        !          2210: 
        !          2211:        chkbuf[length] = (sequence & 0xff) ^ p[0];
        !          2212:        chkbuf[length+1] = p[1];
        !          2213:        chkbuf[length+2] = ((sequence>>8) & 0xff) ^ p[2];
        !          2214:        chkbuf[length+3] = p[3];
        !          2215: 
        !          2216:        length += 4;
        !          2217: 
        !          2218:        checksum = LittleLong(Com_BlockChecksum (chkbuf, length));
        !          2219: 
        !          2220:        checksum &= 0xff;
        !          2221: 
        !          2222:        return checksum;
        !          2223: }
        !          2224: #endif
        !          2225: 
        !          2226: /*
        !          2227: ====================
        !          2228: COM_BlockSequenceCRCByte
        !          2229: 
        !          2230: For proxy protecting
        !          2231: ====================
        !          2232: */
        !          2233: byte   COM_BlockSequenceCRCByte (byte *base, int length, int sequence)
        !          2234: {
        !          2235:        unsigned short crc;
        !          2236:        byte    *p;
        !          2237:        byte chkb[60 + 4];
        !          2238: 
        !          2239:        p = chktbl + (sequence % (sizeof(chktbl) - 8));
        !          2240: 
        !          2241:        if (length > 60)
        !          2242:                length = 60;
        !          2243:        memcpy (chkb, base, length);
        !          2244: 
        !          2245:        chkb[length] = (sequence & 0xff) ^ p[0];
        !          2246:        chkb[length+1] = p[1];
        !          2247:        chkb[length+2] = ((sequence>>8) & 0xff) ^ p[2];
        !          2248:        chkb[length+3] = p[3];
        !          2249: 
        !          2250:        length += 4;
        !          2251: 
        !          2252:        crc = CRC_Block(chkb, length);
        !          2253: 
        !          2254:        crc &= 0xff;
        !          2255: 
        !          2256:        return crc;
        !          2257: }
        !          2258: 
        !          2259: // char *date = "Oct 24 1996";
        !          2260: static char *date = __DATE__ ;
        !          2261: static char *mon[12] = 
        !          2262: { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
        !          2263: static char mond[12] = 
        !          2264: { 31,    28,    31,    30,    31,    30,    31,    31,    30,    31,    30,    31 };
        !          2265: 
        !          2266: // returns days since Oct 24 1996
        !          2267: int build_number( void )
        !          2268: {
        !          2269:        int m = 0; 
        !          2270:        int d = 0;
        !          2271:        int y = 0;
        !          2272:        static int b = 0;
        !          2273: 
        !          2274:        if (b != 0)
        !          2275:                return b;
        !          2276: 
        !          2277:        for (m = 0; m < 11; m++)
        !          2278:        {
        !          2279:                if (Q_strncasecmp( &date[0], mon[m], 3 ) == 0)
        !          2280:                        break;
        !          2281:                d += mond[m];
        !          2282:        }
        !          2283: 
        !          2284:        d += atoi( &date[4] ) - 1;
        !          2285: 
        !          2286:        y = atoi( &date[7] ) - 1900;
        !          2287: 
        !          2288:        b = d + (int)((y - 1) * 365.25);
        !          2289: 
        !          2290:        if (((y % 4) == 0) && m > 1)
        !          2291:        {
        !          2292:                b += 1;
        !          2293:        }
        !          2294: 
        !          2295:        b -= 35778; // Dec 16 1998
        !          2296: 
        !          2297:        return b;
        !          2298: }
        !          2299: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.