Annotation of quakeworld/client/common.c, revision 1.1.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.