Annotation of quake1/common.c, revision 1.1.1.3

1.1       root        1: // common.c -- misc functions used in client and server
                      2: 
                      3: #include "quakedef.h"
                      4: 
1.1.1.3 ! root        5: #define NUM_SAFE_ARGVS  7
1.1       root        6: 
1.1.1.3 ! root        7: static char     *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1];
        !             8: static char     *argvdummy = " ";
1.1       root        9: 
1.1.1.3 ! root       10: static char     *safeargvs[NUM_SAFE_ARGVS] =
        !            11:        {"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse", "-dibonly"};
1.1       root       12: 
1.1.1.3 ! root       13: cvar_t  registered = {"registered","0"};
        !            14: cvar_t  cmdline = {"cmdline","0", false, true};
1.1       root       15: 
1.1.1.3 ! root       16: qboolean        com_modified;   // set true if using non-id files
1.1       root       17: 
1.1.1.3 ! root       18: qboolean               proghack;
        !            19: 
        !            20: int             static_registered = 1;  // only for startup check, then set
        !            21: 
        !            22: qboolean               msg_suppress_1 = 0;
1.1       root       23: 
                     24: void COM_InitFilesystem (void);
                     25: 
                     26: // if a packfile directory differs from this, it is assumed to be hacked
1.1.1.3 ! root       27: #define PAK0_COUNT              339
        !            28: #define PAK0_CRC                32981
        !            29: 
        !            30: char   com_token[1024];
        !            31: int            com_argc;
        !            32: char   **com_argv;
        !            33: 
        !            34: #define CMDLINE_LENGTH 256
        !            35: char   com_cmdline[CMDLINE_LENGTH];
        !            36: 
        !            37: qboolean               standard_quake = true, rogue, hipnotic;
1.1       root       38: 
                     39: // this graphic needs to be in the pak file to use registered features
                     40: unsigned short pop[] =
                     41: {
                     42:  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
                     43: ,0x0000,0x0000,0x6600,0x0000,0x0000,0x0000,0x6600,0x0000
                     44: ,0x0000,0x0066,0x0000,0x0000,0x0000,0x0000,0x0067,0x0000
                     45: ,0x0000,0x6665,0x0000,0x0000,0x0000,0x0000,0x0065,0x6600
                     46: ,0x0063,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6563
                     47: ,0x0064,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6564
                     48: ,0x0064,0x6564,0x0000,0x6469,0x6969,0x6400,0x0064,0x6564
                     49: ,0x0063,0x6568,0x6200,0x0064,0x6864,0x0000,0x6268,0x6563
                     50: ,0x0000,0x6567,0x6963,0x0064,0x6764,0x0063,0x6967,0x6500
                     51: ,0x0000,0x6266,0x6769,0x6a68,0x6768,0x6a69,0x6766,0x6200
                     52: ,0x0000,0x0062,0x6566,0x6666,0x6666,0x6666,0x6562,0x0000
                     53: ,0x0000,0x0000,0x0062,0x6364,0x6664,0x6362,0x0000,0x0000
                     54: ,0x0000,0x0000,0x0000,0x0062,0x6662,0x0000,0x0000,0x0000
                     55: ,0x0000,0x0000,0x0000,0x0061,0x6661,0x0000,0x0000,0x0000
                     56: ,0x0000,0x0000,0x0000,0x0000,0x6500,0x0000,0x0000,0x0000
                     57: ,0x0000,0x0000,0x0000,0x0000,0x6400,0x0000,0x0000,0x0000
                     58: };
                     59: 
                     60: /*
                     61: 
                     62: 
                     63: 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.
                     64: 
                     65: 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
                     66: only used during filesystem initialization.
                     67: 
                     68: 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.
                     69: 
                     70: The "cache directory" is only used during development to save network bandwidth, especially over ISDN / T1 lines.  If there is a cache directory
                     71: specified, when a file is found by the normal search path, it will be mirrored
                     72: into the cache directory, then opened there.
                     73: 
                     74: 
                     75: 
                     76: FIXME:
                     77: The file "parms.txt" will be read out of the game directory and appended to the current command line arguments to allow different games to initialize startup parms differently.  This could be used to add a "-sspeed 22050" for the high quality sound edition.  Because they are added at the end, they will not override an explicit setting on the original command line.
                     78:        
                     79: */
                     80: 
                     81: //============================================================================
                     82: 
                     83: 
                     84: // ClearLink is used for new headnodes
                     85: void ClearLink (link_t *l)
                     86: {
                     87:        l->prev = l->next = l;
                     88: }
                     89: 
                     90: void RemoveLink (link_t *l)
                     91: {
                     92:        l->next->prev = l->prev;
                     93:        l->prev->next = l->next;
                     94: }
                     95: 
                     96: void InsertLinkBefore (link_t *l, link_t *before)
                     97: {
                     98:        l->next = before;
                     99:        l->prev = before->prev;
                    100:        l->prev->next = l;
                    101:        l->next->prev = l;
                    102: }
                    103: void InsertLinkAfter (link_t *l, link_t *after)
                    104: {
                    105:        l->next = after->next;
                    106:        l->prev = after;
                    107:        l->prev->next = l;
                    108:        l->next->prev = l;
                    109: }
                    110: 
                    111: /*
                    112: ============================================================================
                    113: 
                    114:                                        LIBRARY REPLACEMENT FUNCTIONS
                    115: 
                    116: ============================================================================
                    117: */
                    118: 
                    119: void Q_memset (void *dest, int fill, int count)
                    120: {
1.1.1.3 ! root      121:        int             i;
1.1       root      122:        
                    123:        if ( (((long)dest | count) & 3) == 0)
                    124:        {
                    125:                count >>= 2;
                    126:                fill = fill | (fill<<8) | (fill<<16) | (fill<<24);
                    127:                for (i=0 ; i<count ; i++)
                    128:                        ((int *)dest)[i] = fill;
                    129:        }
                    130:        else
                    131:                for (i=0 ; i<count ; i++)
                    132:                        ((byte *)dest)[i] = fill;
                    133: }
                    134: 
                    135: void Q_memcpy (void *dest, void *src, int count)
                    136: {
1.1.1.3 ! root      137:        int             i;
1.1       root      138:        
                    139:        if (( ( (long)dest | (long)src | count) & 3) == 0 )
                    140:        {
                    141:                count>>=2;
                    142:                for (i=0 ; i<count ; i++)
                    143:                        ((int *)dest)[i] = ((int *)src)[i];
                    144:        }
                    145:        else
                    146:                for (i=0 ; i<count ; i++)
                    147:                        ((byte *)dest)[i] = ((byte *)src)[i];
                    148: }
                    149: 
                    150: int Q_memcmp (void *m1, void *m2, int count)
                    151: {
                    152:        while(count)
                    153:        {
                    154:                count--;
                    155:                if (((byte *)m1)[count] != ((byte *)m2)[count])
                    156:                        return -1;
                    157:        }
                    158:        return 0;
                    159: }
                    160: 
                    161: void Q_strcpy (char *dest, char *src)
                    162: {
                    163:        while (*src)
                    164:        {
                    165:                *dest++ = *src++;
                    166:        }
                    167:        *dest++ = 0;
                    168: }
                    169: 
                    170: void Q_strncpy (char *dest, char *src, int count)
                    171: {
                    172:        while (*src && count--)
                    173:        {
                    174:                *dest++ = *src++;
                    175:        }
                    176:        if (count)
                    177:                *dest++ = 0;
                    178: }
                    179: 
                    180: int Q_strlen (char *str)
                    181: {
1.1.1.3 ! root      182:        int             count;
1.1       root      183:        
                    184:        count = 0;
                    185:        while (str[count])
                    186:                count++;
                    187: 
                    188:        return count;
                    189: }
                    190: 
                    191: char *Q_strrchr(char *s, char c)
                    192: {
                    193:     int len = Q_strlen(s);
                    194:     s += len;
                    195:     while (len--)
1.1.1.3 ! root      196:        if (*--s == c) return s;
1.1       root      197:     return 0;
                    198: }
                    199: 
                    200: void Q_strcat (char *dest, char *src)
                    201: {
                    202:        dest += Q_strlen(dest);
                    203:        Q_strcpy (dest, src);
                    204: }
                    205: 
                    206: int Q_strcmp (char *s1, char *s2)
                    207: {
                    208:        while (1)
                    209:        {
                    210:                if (*s1 != *s2)
1.1.1.3 ! root      211:                        return -1;              // strings not equal    
1.1       root      212:                if (!*s1)
1.1.1.3 ! root      213:                        return 0;               // strings are equal
1.1       root      214:                s1++;
                    215:                s2++;
                    216:        }
                    217:        
                    218:        return -1;
                    219: }
                    220: 
                    221: int Q_strncmp (char *s1, char *s2, int count)
                    222: {
                    223:        while (1)
                    224:        {
                    225:                if (!count--)
                    226:                        return 0;
                    227:                if (*s1 != *s2)
1.1.1.3 ! root      228:                        return -1;              // strings not equal    
1.1       root      229:                if (!*s1)
1.1.1.3 ! root      230:                        return 0;               // strings are equal
1.1       root      231:                s1++;
                    232:                s2++;
                    233:        }
                    234:        
                    235:        return -1;
                    236: }
                    237: 
                    238: int Q_strncasecmp (char *s1, char *s2, int n)
                    239: {
1.1.1.3 ! root      240:        int             c1, c2;
1.1       root      241:        
                    242:        while (1)
                    243:        {
                    244:                c1 = *s1++;
                    245:                c2 = *s2++;
                    246: 
                    247:                if (!n--)
1.1.1.3 ! root      248:                        return 0;               // strings are equal until end point
1.1       root      249:                
                    250:                if (c1 != c2)
                    251:                {
                    252:                        if (c1 >= 'a' && c1 <= 'z')
                    253:                                c1 -= ('a' - 'A');
                    254:                        if (c2 >= 'a' && c2 <= 'z')
                    255:                                c2 -= ('a' - 'A');
                    256:                        if (c1 != c2)
1.1.1.3 ! root      257:                                return -1;              // strings not equal
1.1       root      258:                }
                    259:                if (!c1)
1.1.1.3 ! root      260:                        return 0;               // strings are equal
        !           261: //              s1++;
        !           262: //              s2++;
1.1       root      263:        }
                    264:        
                    265:        return -1;
                    266: }
                    267: 
                    268: int Q_strcasecmp (char *s1, char *s2)
                    269: {
                    270:        return Q_strncasecmp (s1, s2, 99999);
                    271: }
                    272: 
                    273: int Q_atoi (char *str)
                    274: {
1.1.1.3 ! root      275:        int             val;
        !           276:        int             sign;
        !           277:        int             c;
1.1       root      278:        
                    279:        if (*str == '-')
                    280:        {
                    281:                sign = -1;
                    282:                str++;
                    283:        }
                    284:        else
                    285:                sign = 1;
                    286:                
                    287:        val = 0;
                    288: 
                    289: //
                    290: // check for hex
                    291: //
                    292:        if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
                    293:        {
                    294:                str += 2;
                    295:                while (1)
                    296:                {
                    297:                        c = *str++;
                    298:                        if (c >= '0' && c <= '9')
                    299:                                val = (val<<4) + c - '0';
                    300:                        else if (c >= 'a' && c <= 'f')
                    301:                                val = (val<<4) + c - 'a' + 10;
                    302:                        else if (c >= 'A' && c <= 'F')
                    303:                                val = (val<<4) + c - 'A' + 10;
                    304:                        else
                    305:                                return val*sign;
                    306:                }
                    307:        }
                    308:        
                    309: //
                    310: // check for character
                    311: //
                    312:        if (str[0] == '\'')
                    313:        {
                    314:                return sign * str[1];
                    315:        }
                    316:        
                    317: //
                    318: // assume decimal
                    319: //
                    320:        while (1)
                    321:        {
                    322:                c = *str++;
                    323:                if (c <'0' || c > '9')
                    324:                        return val*sign;
                    325:                val = val*10 + c - '0';
                    326:        }
                    327:        
                    328:        return 0;
                    329: }
                    330: 
                    331: 
                    332: float Q_atof (char *str)
                    333: {
1.1.1.3 ! root      334:        double                  val;
        !           335:        int             sign;
        !           336:        int             c;
        !           337:        int             decimal, total;
1.1       root      338:        
                    339:        if (*str == '-')
                    340:        {
                    341:                sign = -1;
                    342:                str++;
                    343:        }
                    344:        else
                    345:                sign = 1;
                    346:                
                    347:        val = 0;
                    348: 
                    349: //
                    350: // check for hex
                    351: //
                    352:        if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
                    353:        {
                    354:                str += 2;
                    355:                while (1)
                    356:                {
                    357:                        c = *str++;
                    358:                        if (c >= '0' && c <= '9')
                    359:                                val = (val*16) + c - '0';
                    360:                        else if (c >= 'a' && c <= 'f')
                    361:                                val = (val*16) + c - 'a' + 10;
                    362:                        else if (c >= 'A' && c <= 'F')
                    363:                                val = (val*16) + c - 'A' + 10;
                    364:                        else
                    365:                                return val*sign;
                    366:                }
                    367:        }
                    368:        
                    369: //
                    370: // check for character
                    371: //
                    372:        if (str[0] == '\'')
                    373:        {
                    374:                return sign * str[1];
                    375:        }
                    376:        
                    377: //
                    378: // assume decimal
                    379: //
                    380:        decimal = -1;
                    381:        total = 0;
                    382:        while (1)
                    383:        {
                    384:                c = *str++;
                    385:                if (c == '.')
                    386:                {
                    387:                        decimal = total;
                    388:                        continue;
                    389:                }
                    390:                if (c <'0' || c > '9')
                    391:                        break;
                    392:                val = val*10 + c - '0';
                    393:                total++;
                    394:        }
                    395: 
                    396:        if (decimal == -1)
                    397:                return val*sign;
                    398:        while (total > decimal)
                    399:        {
                    400:                val /= 10;
                    401:                total--;
                    402:        }
                    403:        
                    404:        return val*sign;
                    405: }
                    406: 
                    407: /*
                    408: ============================================================================
                    409: 
                    410:                                        BYTE ORDER FUNCTIONS
                    411: 
                    412: ============================================================================
                    413: */
                    414: 
1.1.1.3 ! root      415: qboolean        bigendien;
1.1       root      416: 
1.1.1.3 ! root      417: short   (*BigShort) (short l);
        !           418: short   (*LittleShort) (short l);
        !           419: int     (*BigLong) (int l);
        !           420: int     (*LittleLong) (int l);
        !           421: float   (*BigFloat) (float l);
        !           422: float   (*LittleFloat) (float l);
1.1       root      423: 
                    424: short   ShortSwap (short l)
                    425: {
                    426:        byte    b1,b2;
                    427: 
                    428:        b1 = l&255;
                    429:        b2 = (l>>8)&255;
                    430: 
                    431:        return (b1<<8) + b2;
                    432: }
                    433: 
1.1.1.3 ! root      434: short   ShortNoSwap (short l)
1.1       root      435: {
                    436:        return l;
                    437: }
                    438: 
                    439: int    LongSwap (int l)
                    440: {
                    441:        byte    b1,b2,b3,b4;
                    442: 
                    443:        b1 = l&255;
                    444:        b2 = (l>>8)&255;
                    445:        b3 = (l>>16)&255;
                    446:        b4 = (l>>24)&255;
                    447: 
                    448:        return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
                    449: }
                    450: 
1.1.1.3 ! root      451: int     LongNoSwap (int l)
1.1       root      452: {
                    453:        return l;
                    454: }
                    455: 
                    456: float FloatSwap (float f)
                    457: {
                    458:        union
                    459:        {
1.1.1.3 ! root      460:                float   f;
        !           461:                byte    b[4];
1.1       root      462:        } dat1, dat2;
                    463:        
                    464:        
                    465:        dat1.f = f;
                    466:        dat2.b[0] = dat1.b[3];
                    467:        dat2.b[1] = dat1.b[2];
                    468:        dat2.b[2] = dat1.b[1];
                    469:        dat2.b[3] = dat1.b[0];
                    470:        return dat2.f;
                    471: }
                    472: 
                    473: float FloatNoSwap (float f)
                    474: {
                    475:        return f;
                    476: }
                    477: 
                    478: /*
                    479: ==============================================================================
                    480: 
                    481:                        MESSAGE IO FUNCTIONS
                    482: 
                    483: Handles byte ordering and avoids alignment errors
                    484: ==============================================================================
                    485: */
                    486: 
                    487: //
                    488: // writing functions
                    489: //
                    490: 
                    491: void MSG_WriteChar (sizebuf_t *sb, int c)
                    492: {
1.1.1.3 ! root      493:        byte    *buf;
1.1       root      494:        
                    495: #ifdef PARANOID
                    496:        if (c < -128 || c > 127)
                    497:                Sys_Error ("MSG_WriteChar: range error");
                    498: #endif
                    499: 
                    500:        buf = SZ_GetSpace (sb, 1);
                    501:        buf[0] = c;
                    502: }
                    503: 
                    504: void MSG_WriteByte (sizebuf_t *sb, int c)
                    505: {
1.1.1.3 ! root      506:        byte    *buf;
1.1       root      507:        
                    508: #ifdef PARANOID
                    509:        if (c < 0 || c > 255)
                    510:                Sys_Error ("MSG_WriteByte: range error");
                    511: #endif
                    512: 
                    513:        buf = SZ_GetSpace (sb, 1);
                    514:        buf[0] = c;
                    515: }
                    516: 
                    517: void MSG_WriteShort (sizebuf_t *sb, int c)
                    518: {
1.1.1.3 ! root      519:        byte    *buf;
1.1       root      520:        
                    521: #ifdef PARANOID
                    522:        if (c < ((short)0x8000) || c > (short)0x7fff)
                    523:                Sys_Error ("MSG_WriteShort: range error");
                    524: #endif
                    525: 
                    526:        buf = SZ_GetSpace (sb, 2);
                    527:        buf[0] = c&0xff;
                    528:        buf[1] = c>>8;
                    529: }
                    530: 
                    531: void MSG_WriteLong (sizebuf_t *sb, int c)
                    532: {
1.1.1.3 ! root      533:        byte    *buf;
1.1       root      534:        
                    535:        buf = SZ_GetSpace (sb, 4);
                    536:        buf[0] = c&0xff;
                    537:        buf[1] = (c>>8)&0xff;
                    538:        buf[2] = (c>>16)&0xff;
                    539:        buf[3] = c>>24;
                    540: }
                    541: 
                    542: void MSG_WriteFloat (sizebuf_t *sb, float f)
                    543: {
                    544:        union
                    545:        {
1.1.1.3 ! root      546:                float   f;
        !           547:                int     l;
1.1       root      548:        } dat;
                    549:        
                    550:        
                    551:        dat.f = f;
                    552:        dat.l = LittleLong (dat.l);
                    553:        
                    554:        SZ_Write (sb, &dat.l, 4);
                    555: }
                    556: 
                    557: void MSG_WriteString (sizebuf_t *sb, char *s)
                    558: {
                    559:        if (!s)
                    560:                SZ_Write (sb, "", 1);
                    561:        else
                    562:                SZ_Write (sb, s, Q_strlen(s)+1);
                    563: }
                    564: 
                    565: void MSG_WriteCoord (sizebuf_t *sb, float f)
                    566: {
                    567:        MSG_WriteShort (sb, (int)(f*8));
                    568: }
                    569: 
                    570: void MSG_WriteAngle (sizebuf_t *sb, float f)
                    571: {
                    572:        MSG_WriteByte (sb, ((int)f*256/360) & 255);
                    573: }
                    574: 
                    575: //
                    576: // reading functions
                    577: //
1.1.1.3 ! root      578: int                     msg_readcount;
        !           579: qboolean        msg_badread;
1.1       root      580: 
                    581: void MSG_BeginReading (void)
                    582: {
                    583:        msg_readcount = 0;
                    584:        msg_badread = false;
                    585: }
                    586: 
                    587: // returns -1 and sets msg_badread if no more characters are available
                    588: int MSG_ReadChar (void)
                    589: {
1.1.1.3 ! root      590:        int     c;
1.1       root      591:        
                    592:        if (msg_readcount+1 > net_message.cursize)
                    593:        {
                    594:                msg_badread = true;
                    595:                return -1;
                    596:        }
                    597:                
                    598:        c = (signed char)net_message.data[msg_readcount];
                    599:        msg_readcount++;
                    600:        
                    601:        return c;
                    602: }
                    603: 
                    604: int MSG_ReadByte (void)
                    605: {
1.1.1.3 ! root      606:        int     c;
1.1       root      607:        
                    608:        if (msg_readcount+1 > net_message.cursize)
                    609:        {
                    610:                msg_badread = true;
                    611:                return -1;
                    612:        }
                    613:                
                    614:        c = (unsigned char)net_message.data[msg_readcount];
                    615:        msg_readcount++;
                    616:        
                    617:        return c;
                    618: }
                    619: 
                    620: int MSG_ReadShort (void)
                    621: {
1.1.1.3 ! root      622:        int     c;
1.1       root      623:        
                    624:        if (msg_readcount+2 > net_message.cursize)
                    625:        {
                    626:                msg_badread = true;
                    627:                return -1;
                    628:        }
                    629:                
                    630:        c = (short)(net_message.data[msg_readcount]
                    631:        + (net_message.data[msg_readcount+1]<<8));
                    632:        
                    633:        msg_readcount += 2;
                    634:        
                    635:        return c;
                    636: }
                    637: 
                    638: int MSG_ReadLong (void)
                    639: {
1.1.1.3 ! root      640:        int     c;
1.1       root      641:        
                    642:        if (msg_readcount+4 > net_message.cursize)
                    643:        {
                    644:                msg_badread = true;
                    645:                return -1;
                    646:        }
                    647:                
                    648:        c = net_message.data[msg_readcount]
                    649:        + (net_message.data[msg_readcount+1]<<8)
                    650:        + (net_message.data[msg_readcount+2]<<16)
                    651:        + (net_message.data[msg_readcount+3]<<24);
                    652:        
                    653:        msg_readcount += 4;
                    654:        
                    655:        return c;
                    656: }
                    657: 
                    658: float MSG_ReadFloat (void)
                    659: {
                    660:        union
                    661:        {
1.1.1.3 ! root      662:                byte    b[4];
        !           663:                float   f;
        !           664:                int     l;
1.1       root      665:        } dat;
                    666:        
1.1.1.3 ! root      667:        dat.b[0] =      net_message.data[msg_readcount];
        !           668:        dat.b[1] =      net_message.data[msg_readcount+1];
        !           669:        dat.b[2] =      net_message.data[msg_readcount+2];
        !           670:        dat.b[3] =      net_message.data[msg_readcount+3];
1.1       root      671:        msg_readcount += 4;
                    672:        
                    673:        dat.l = LittleLong (dat.l);
                    674: 
1.1.1.3 ! root      675:        return dat.f;   
1.1       root      676: }
                    677: 
                    678: char *MSG_ReadString (void)
                    679: {
1.1.1.3 ! root      680:        static char     string[2048];
        !           681:        int             l,c;
1.1       root      682:        
                    683:        l = 0;
                    684:        do
                    685:        {
                    686:                c = MSG_ReadChar ();
                    687:                if (c == -1 || c == 0)
                    688:                        break;
                    689:                string[l] = c;
                    690:                l++;
                    691:        } while (l < sizeof(string)-1);
                    692:        
                    693:        string[l] = 0;
                    694:        
                    695:        return string;
                    696: }
                    697: 
                    698: float MSG_ReadCoord (void)
                    699: {
                    700:        return MSG_ReadShort() * (1.0/8);
                    701: }
                    702: 
                    703: float MSG_ReadAngle (void)
                    704: {
                    705:        return MSG_ReadChar() * (360.0/256);
                    706: }
                    707: 
                    708: 
                    709: 
                    710: //===========================================================================
                    711: 
                    712: void SZ_Alloc (sizebuf_t *buf, int startsize)
                    713: {
                    714:        if (startsize < 256)
                    715:                startsize = 256;
                    716:        buf->data = Hunk_AllocName (startsize, "sizebuf");
                    717:        buf->maxsize = startsize;
                    718:        buf->cursize = 0;
                    719: }
                    720: 
                    721: 
                    722: void SZ_Free (sizebuf_t *buf)
                    723: {
1.1.1.3 ! root      724: //      Z_Free (buf->data);
        !           725: //      buf->data = NULL;
        !           726: //      buf->maxsize = 0;
1.1       root      727:        buf->cursize = 0;
                    728: }
                    729: 
                    730: void SZ_Clear (sizebuf_t *buf)
                    731: {
                    732:        buf->cursize = 0;
                    733: }
                    734: 
                    735: void *SZ_GetSpace (sizebuf_t *buf, int length)
                    736: {
1.1.1.3 ! root      737:        void    *data;
1.1       root      738:        
                    739:        if (buf->cursize + length > buf->maxsize)
                    740:        {
                    741:                if (!buf->allowoverflow)
                    742:                        Sys_Error ("SZ_GetSpace: overflow without allowoverflow set");
                    743:                
                    744:                if (length > buf->maxsize)
                    745:                        Sys_Error ("SZ_GetSpace: %i is > full buffer size", length);
                    746:                        
                    747:                buf->overflowed = true;
                    748:                Con_Printf ("SZ_GetSpace: overflow");
                    749:                SZ_Clear (buf); 
                    750:        }
                    751: 
                    752:        data = buf->data + buf->cursize;
                    753:        buf->cursize += length;
                    754:        
                    755:        return data;
                    756: }
                    757: 
                    758: void SZ_Write (sizebuf_t *buf, void *data, int length)
                    759: {
1.1.1.3 ! root      760:        Q_memcpy (SZ_GetSpace(buf,length),data,length);         
1.1       root      761: }
                    762: 
                    763: void SZ_Print (sizebuf_t *buf, char *data)
                    764: {
1.1.1.3 ! root      765:        int             len;
1.1       root      766:        
                    767:        len = Q_strlen(data)+1;
                    768: 
                    769: // byte * cast to keep VC++ happy
                    770:        if (buf->data[buf->cursize-1])
                    771:                Q_memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
                    772:        else
                    773:                Q_memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
                    774: }
                    775: 
                    776: 
                    777: //============================================================================
                    778: 
                    779: 
                    780: /*
                    781: ============
                    782: COM_SkipPath
                    783: ============
                    784: */
                    785: char *COM_SkipPath (char *pathname)
                    786: {
1.1.1.3 ! root      787:        char    *last;
1.1       root      788:        
                    789:        last = pathname;
                    790:        while (*pathname)
                    791:        {
                    792:                if (*pathname=='/')
                    793:                        last = pathname+1;
                    794:                pathname++;
                    795:        }
                    796:        return last;
                    797: }
                    798: 
                    799: /*
                    800: ============
                    801: COM_StripExtension
                    802: ============
                    803: */
                    804: void COM_StripExtension (char *in, char *out)
                    805: {
                    806:        while (*in && *in != '.')
                    807:                *out++ = *in++;
                    808:        *out = 0;
                    809: }
                    810: 
                    811: /*
                    812: ============
                    813: COM_FileExtension
                    814: ============
                    815: */
                    816: char *COM_FileExtension (char *in)
                    817: {
                    818:        static char exten[8];
1.1.1.3 ! root      819:        int             i;
1.1       root      820: 
                    821:        while (*in && *in != '.')
                    822:                in++;
                    823:        if (!*in)
                    824:                return "";
                    825:        in++;
                    826:        for (i=0 ; i<7 && *in ; i++,in++)
                    827:                exten[i] = *in;
                    828:        exten[i] = 0;
                    829:        return exten;
                    830: }
                    831: 
                    832: /*
                    833: ============
                    834: COM_FileBase
                    835: ============
                    836: */
                    837: void COM_FileBase (char *in, char *out)
                    838: {
                    839:        char *s, *s2;
                    840:        
                    841:        s = in + strlen(in) - 1;
                    842:        
                    843:        while (s != in && *s != '.')
                    844:                s--;
                    845:        
                    846:        for (s2 = s ; *s2 && *s2 != '/' ; s2--)
                    847:        ;
                    848:        
                    849:        if (s-s2 < 2)
                    850:                strcpy (out,"?model?");
                    851:        else
                    852:        {
                    853:                s--;
                    854:                strncpy (out,s2+1, s-s2);
                    855:                out[s-s2] = 0;
                    856:        }
                    857: }
                    858: 
                    859: 
                    860: /*
                    861: ==================
                    862: COM_DefaultExtension
                    863: ==================
                    864: */
                    865: void COM_DefaultExtension (char *path, char *extension)
                    866: {
                    867:        char    *src;
                    868: //
                    869: // if path doesn't have a .EXT, append extension
                    870: // (extension should include the .)
                    871: //
                    872:        src = path + strlen(path) - 1;
                    873: 
                    874:        while (*src != '/' && src != path)
                    875:        {
                    876:                if (*src == '.')
                    877:                        return;                 // it has an extension
                    878:                src--;
                    879:        }
                    880: 
                    881:        strcat (path, extension);
                    882: }
                    883: 
                    884: 
                    885: /*
                    886: ==============
                    887: COM_Parse
                    888: 
                    889: Parse a token out of a string
                    890: ==============
                    891: */
                    892: char *COM_Parse (char *data)
                    893: {
1.1.1.3 ! root      894:        int             c;
        !           895:        int             len;
1.1       root      896:        
                    897:        len = 0;
                    898:        com_token[0] = 0;
                    899:        
                    900:        if (!data)
                    901:                return NULL;
                    902:                
                    903: // skip whitespace
                    904: skipwhite:
                    905:        while ( (c = *data) <= ' ')
                    906:        {
                    907:                if (c == 0)
1.1.1.3 ! root      908:                        return NULL;                    // end of file;
1.1       root      909:                data++;
                    910:        }
                    911:        
                    912: // skip // comments
                    913:        if (c=='/' && data[1] == '/')
                    914:        {
                    915:                while (*data && *data != '\n')
                    916:                        data++;
                    917:                goto skipwhite;
                    918:        }
                    919:        
                    920: 
                    921: // handle quoted strings specially
                    922:        if (c == '\"')
                    923:        {
                    924:                data++;
                    925:                while (1)
                    926:                {
                    927:                        c = *data++;
                    928:                        if (c=='\"' || !c)
                    929:                        {
                    930:                                com_token[len] = 0;
                    931:                                return data;
                    932:                        }
                    933:                        com_token[len] = c;
                    934:                        len++;
                    935:                }
                    936:        }
                    937: 
                    938: // parse single characters
                    939:        if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
                    940:        {
                    941:                com_token[len] = c;
                    942:                len++;
                    943:                com_token[len] = 0;
                    944:                return data+1;
                    945:        }
                    946: 
                    947: // parse a regular word
                    948:        do
                    949:        {
                    950:                com_token[len] = c;
                    951:                data++;
                    952:                len++;
                    953:                c = *data;
                    954:        if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
                    955:                        break;
                    956:        } while (c>32);
                    957:        
                    958:        com_token[len] = 0;
                    959:        return data;
                    960: }
                    961: 
                    962: 
                    963: /*
                    964: ================
                    965: COM_CheckParm
                    966: 
                    967: Returns the position (1 to argc-1) in the program's argument list
                    968: where the given parameter apears, or 0 if not present
                    969: ================
                    970: */
                    971: int COM_CheckParm (char *parm)
                    972: {
1.1.1.3 ! root      973:        int             i;
1.1       root      974:        
                    975:        for (i=1 ; i<com_argc ; i++)
                    976:        {
                    977:                if (!com_argv[i])
1.1.1.3 ! root      978:                        continue;               // NEXTSTEP sometimes clears appkit vars.
1.1       root      979:                if (!Q_strcmp (parm,com_argv[i]))
                    980:                        return i;
                    981:        }
                    982:                
                    983:        return 0;
                    984: }
                    985: 
                    986: /*
                    987: ================
                    988: COM_CheckRegistered
                    989: 
                    990: Looks for the pop.txt file and verifies it.
                    991: Sets the "registered" cvar.
                    992: Immediately exits out if an alternate game was attempted to be started without
                    993: being registered.
                    994: ================
                    995: */
                    996: void COM_CheckRegistered (void)
                    997: {
1.1.1.3 ! root      998:        int             h;
        !           999:        unsigned short  check[128];
        !          1000:        int                     i;
1.1       root     1001: 
                   1002:        COM_OpenFile("gfx/pop.lmp", &h);
                   1003:        static_registered = 0;
                   1004: 
                   1005:        if (h == -1)
                   1006:        {
1.1.1.3 ! root     1007: #if WINDED
        !          1008:        Sys_Error ("This dedicated server requires a full registered copy of Quake");
        !          1009: #endif
1.1       root     1010:                Con_Printf ("Playing shareware version.\n");
1.1.1.3 ! root     1011:                if (com_modified)
        !          1012:                        Sys_Error ("You must have the registered version to use modified games");
        !          1013:                return;
1.1       root     1014:        }
                   1015: 
                   1016:        Sys_FileRead (h, check, sizeof(check));
                   1017:        COM_CloseFile (h);
                   1018:        
                   1019:        for (i=0 ; i<128 ; i++)
1.1.1.3 ! root     1020:                if (pop[i] != (unsigned short)BigShort (check[i]))
        !          1021:                        Sys_Error ("Corrupted data file.");
1.1       root     1022:        
1.1.1.3 ! root     1023:        Cvar_Set ("cmdline", com_cmdline);
1.1       root     1024:        Cvar_Set ("registered", "1");
                   1025:        static_registered = 1;
                   1026:        Con_Printf ("Playing registered version.\n");
                   1027: }
                   1028: 
                   1029: 
                   1030: void COM_Path_f (void);
                   1031: 
                   1032: 
                   1033: /*
                   1034: ================
                   1035: COM_InitArgv
                   1036: ================
                   1037: */
                   1038: void COM_InitArgv (int argc, char **argv)
                   1039: {
1.1.1.3 ! root     1040:        qboolean        safe;
        !          1041:        int             i, j, n;
        !          1042: 
        !          1043: // reconstitute the command line for the cmdline externally visible cvar
        !          1044:        n = 0;
        !          1045: 
        !          1046:        for (j=0 ; (j<MAX_NUM_ARGVS) && (j< argc) ; j++)
        !          1047:        {
        !          1048:                i = 0;
        !          1049: 
        !          1050:                while ((n < (CMDLINE_LENGTH - 1)) && argv[j][i])
        !          1051:                {
        !          1052:                        com_cmdline[n++] = argv[j][i++];
        !          1053:                }
        !          1054: 
        !          1055:                if (n < (CMDLINE_LENGTH - 1))
        !          1056:                        com_cmdline[n++] = ' ';
        !          1057:                else
        !          1058:                        break;
        !          1059:        }
        !          1060: 
        !          1061:        com_cmdline[n] = 0;
1.1       root     1062: 
                   1063:        safe = false;
                   1064: 
                   1065:        for (com_argc=0 ; (com_argc<MAX_NUM_ARGVS) && (com_argc < argc) ;
                   1066:                 com_argc++)
                   1067:        {
                   1068:                largv[com_argc] = argv[com_argc];
                   1069:                if (!Q_strcmp ("-safe", argv[com_argc]))
                   1070:                        safe = true;
                   1071:        }
                   1072: 
                   1073:        if (safe)
                   1074:        {
                   1075:        // force all the safe-mode switches. Note that we reserved extra space in
                   1076:        // case we need to add these, so we don't need an overflow check
                   1077:                for (i=0 ; i<NUM_SAFE_ARGVS ; i++)
                   1078:                {
                   1079:                        largv[com_argc] = safeargvs[i];
                   1080:                        com_argc++;
                   1081:                }
                   1082:        }
                   1083: 
                   1084:        largv[com_argc] = argvdummy;
                   1085:        com_argv = largv;
1.1.1.3 ! root     1086: 
        !          1087:        if (COM_CheckParm ("-rogue"))
        !          1088:        {
        !          1089:                rogue = true;
        !          1090:                standard_quake = false;
        !          1091:        }
        !          1092: 
        !          1093:        if (COM_CheckParm ("-hipnotic"))
        !          1094:        {
        !          1095:                hipnotic = true;
        !          1096:                standard_quake = false;
        !          1097:        }
1.1       root     1098: }
                   1099: 
                   1100: 
                   1101: /*
                   1102: ================
                   1103: COM_Init
                   1104: ================
                   1105: */
                   1106: void COM_Init (char *basedir)
                   1107: {
1.1.1.3 ! root     1108:        byte    swaptest[2] = {1,0};
1.1       root     1109: 
1.1.1.3 ! root     1110: // set the byte swapping variables in a portable manner 
1.1       root     1111:        if ( *(short *)swaptest == 1)
                   1112:        {
                   1113:                bigendien = false;
                   1114:                BigShort = ShortSwap;
                   1115:                LittleShort = ShortNoSwap;
                   1116:                BigLong = LongSwap;
                   1117:                LittleLong = LongNoSwap;
                   1118:                BigFloat = FloatSwap;
                   1119:                LittleFloat = FloatNoSwap;
                   1120:        }
                   1121:        else
                   1122:        {
                   1123:                bigendien = true;
                   1124:                BigShort = ShortNoSwap;
                   1125:                LittleShort = ShortSwap;
                   1126:                BigLong = LongNoSwap;
                   1127:                LittleLong = LongSwap;
                   1128:                BigFloat = FloatNoSwap;
                   1129:                LittleFloat = FloatSwap;
                   1130:        }
                   1131: 
                   1132:        Cvar_RegisterVariable (&registered);
1.1.1.3 ! root     1133:        Cvar_RegisterVariable (&cmdline);
1.1       root     1134:        Cmd_AddCommand ("path", COM_Path_f);
                   1135: 
                   1136:        COM_InitFilesystem ();
                   1137:        COM_CheckRegistered ();
                   1138: }
                   1139: 
                   1140: 
                   1141: /*
                   1142: ============
                   1143: va
                   1144: 
                   1145: does a varargs printf into a temp buffer, so I don't need to have
                   1146: varargs versions of all text functions.
                   1147: FIXME: make this buffer size safe someday
                   1148: ============
                   1149: */
1.1.1.3 ! root     1150: char    *va(char *format, ...)
1.1       root     1151: {
1.1.1.3 ! root     1152:        va_list         argptr;
        !          1153:        static char             string[1024];
1.1       root     1154:        
                   1155:        va_start (argptr, format);
                   1156:        vsprintf (string, format,argptr);
                   1157:        va_end (argptr);
                   1158: 
1.1.1.3 ! root     1159:        return string;  
1.1       root     1160: }
                   1161: 
                   1162: 
                   1163: /// just for debugging
1.1.1.3 ! root     1164: int     memsearch (byte *start, int count, int search)
1.1       root     1165: {
1.1.1.3 ! root     1166:        int             i;
1.1       root     1167:        
                   1168:        for (i=0 ; i<count ; i++)
                   1169:                if (start[i] == search)
                   1170:                        return i;
                   1171:        return -1;
                   1172: }
                   1173: 
                   1174: /*
                   1175: =============================================================================
                   1176: 
                   1177: QUAKE FILESYSTEM
                   1178: 
                   1179: =============================================================================
                   1180: */
                   1181: 
1.1.1.3 ! root     1182: int     com_filesize;
1.1       root     1183: 
                   1184: 
                   1185: //
                   1186: // in memory
                   1187: //
                   1188: 
                   1189: typedef struct
                   1190: {
1.1.1.3 ! root     1191:        char    name[MAX_QPATH];
        !          1192:        int             filepos, filelen;
1.1       root     1193: } packfile_t;
                   1194: 
                   1195: typedef struct pack_s
                   1196: {
1.1.1.3 ! root     1197:        char    filename[MAX_OSPATH];
        !          1198:        int             handle;
        !          1199:        int             numfiles;
        !          1200:        packfile_t      *files;
1.1       root     1201: } pack_t;
                   1202: 
                   1203: //
                   1204: // on disk
                   1205: //
                   1206: typedef struct
                   1207: {
1.1.1.3 ! root     1208:        char    name[56];
        !          1209:        int             filepos, filelen;
1.1       root     1210: } dpackfile_t;
                   1211: 
                   1212: typedef struct
                   1213: {
1.1.1.3 ! root     1214:        char    id[4];
        !          1215:        int             dirofs;
        !          1216:        int             dirlen;
1.1       root     1217: } dpackheader_t;
                   1218: 
1.1.1.3 ! root     1219: #define MAX_FILES_IN_PACK       2048
1.1       root     1220: 
1.1.1.3 ! root     1221: char    com_cachedir[MAX_OSPATH];
        !          1222: char    com_gamedir[MAX_OSPATH];
1.1       root     1223: 
                   1224: typedef struct searchpath_s
                   1225: {
1.1.1.3 ! root     1226:        char    filename[MAX_OSPATH];
        !          1227:        pack_t  *pack;          // only one of filename / pack will be used
1.1       root     1228:        struct searchpath_s *next;
                   1229: } searchpath_t;
                   1230: 
1.1.1.3 ! root     1231: searchpath_t    *com_searchpaths;
1.1       root     1232: 
                   1233: /*
                   1234: ============
                   1235: COM_Path_f
                   1236: 
                   1237: ============
                   1238: */
                   1239: void COM_Path_f (void)
                   1240: {
1.1.1.3 ! root     1241:        searchpath_t    *s;
1.1       root     1242:        
                   1243:        Con_Printf ("Current search path:\n");
                   1244:        for (s=com_searchpaths ; s ; s=s->next)
                   1245:        {
                   1246:                if (s->pack)
                   1247:                {
                   1248:                        Con_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles);
                   1249:                }
                   1250:                else
                   1251:                        Con_Printf ("%s\n", s->filename);
                   1252:        }
                   1253: }
                   1254: 
                   1255: /*
                   1256: ============
                   1257: COM_WriteFile
                   1258: 
                   1259: The filename will be prefixed by the current game directory
                   1260: ============
                   1261: */
                   1262: void COM_WriteFile (char *filename, void *data, int len)
                   1263: {
1.1.1.3 ! root     1264:        int             handle;
        !          1265:        char    name[MAX_OSPATH];
1.1       root     1266:        
                   1267:        sprintf (name, "%s/%s", com_gamedir, filename);
                   1268: 
                   1269:        handle = Sys_FileOpenWrite (name);
                   1270:        if (handle == -1)
                   1271:        {
                   1272:                Sys_Printf ("COM_WriteFile: failed on %s\n", name);
                   1273:                return;
                   1274:        }
                   1275:        
                   1276:        Sys_Printf ("COM_WriteFile: %s\n", name);
                   1277:        Sys_FileWrite (handle, data, len);
                   1278:        Sys_FileClose (handle);
                   1279: }
                   1280: 
                   1281: 
                   1282: /*
                   1283: ============
                   1284: COM_CreatePath
                   1285: 
                   1286: Only used for CopyFile
                   1287: ============
                   1288: */
1.1.1.3 ! root     1289: void    COM_CreatePath (char *path)
1.1       root     1290: {
1.1.1.3 ! root     1291:        char    *ofs;
1.1       root     1292:        
                   1293:        for (ofs = path+1 ; *ofs ; ofs++)
                   1294:        {
                   1295:                if (*ofs == '/')
1.1.1.3 ! root     1296:                {       // create the directory
1.1       root     1297:                        *ofs = 0;
                   1298:                        Sys_mkdir (path);
                   1299:                        *ofs = '/';
                   1300:                }
                   1301:        }
                   1302: }
                   1303: 
                   1304: 
                   1305: /*
                   1306: ===========
                   1307: COM_CopyFile
                   1308: 
                   1309: Copies a file over from the net to the local cache, creating any directories
                   1310: needed.  This is for the convenience of developers using ISDN from home.
                   1311: ===========
                   1312: */
                   1313: void COM_CopyFile (char *netpath, char *cachepath)
                   1314: {
1.1.1.3 ! root     1315:        int             in, out;
        !          1316:        int             remaining, count;
        !          1317:        char    buf[4096];
1.1       root     1318:        
1.1.1.3 ! root     1319:        remaining = Sys_FileOpenRead (netpath, &in);            
        !          1320:        COM_CreatePath (cachepath);     // create directories up to the cache file
1.1       root     1321:        out = Sys_FileOpenWrite (cachepath);
                   1322:        
                   1323:        while (remaining)
                   1324:        {
                   1325:                if (remaining < sizeof(buf))
                   1326:                        count = remaining;
                   1327:                else
                   1328:                        count = sizeof(buf);
                   1329:                Sys_FileRead (in, buf, count);
                   1330:                Sys_FileWrite (out, buf, count);
                   1331:                remaining -= count;
                   1332:        }
                   1333: 
                   1334:        Sys_FileClose (in);
1.1.1.3 ! root     1335:        Sys_FileClose (out);    
1.1       root     1336: }
                   1337: 
                   1338: /*
                   1339: ===========
                   1340: COM_FindFile
                   1341: 
                   1342: Finds the file in the search path.
                   1343: Sets com_filesize and one of handle or file
                   1344: ===========
                   1345: */
                   1346: int COM_FindFile (char *filename, int *handle, FILE **file)
                   1347: {
1.1.1.3 ! root     1348:        searchpath_t    *search;
        !          1349:        char            netpath[MAX_OSPATH];
        !          1350:        char            cachepath[MAX_OSPATH];
        !          1351:        pack_t          *pak;
        !          1352:        int                     i;
        !          1353:        int                     findtime, cachetime;
1.1       root     1354: 
                   1355:        if (file && handle)
                   1356:                Sys_Error ("COM_FindFile: both handle and file set");
                   1357:        if (!file && !handle)
                   1358:                Sys_Error ("COM_FindFile: neither handle or file set");
                   1359:                
                   1360: //
                   1361: // search through the path, one element at a time
                   1362: //
1.1.1.3 ! root     1363:        search = com_searchpaths;
        !          1364:        if (proghack)
        !          1365:        {       // gross hack to use quake 1 progs with quake 2 maps
        !          1366:                if (!strcmp(filename, "progs.dat"))
        !          1367:                        search = search->next;
        !          1368:        }
        !          1369: 
        !          1370:        for ( ; search ; search = search->next)
1.1       root     1371:        {
                   1372:        // is the element a pak file?
                   1373:                if (search->pack)
                   1374:                {
                   1375:                // look through all the pak file elements
                   1376:                        pak = search->pack;
                   1377:                        for (i=0 ; i<pak->numfiles ; i++)
                   1378:                                if (!strcmp (pak->files[i].name, filename))
1.1.1.3 ! root     1379:                                {       // found it!
1.1       root     1380:                                        Sys_Printf ("PackFile: %s : %s\n",pak->filename, filename);
                   1381:                                        if (handle)
                   1382:                                        {
                   1383:                                                *handle = pak->handle;
                   1384:                                                Sys_FileSeek (pak->handle, pak->files[i].filepos);
                   1385:                                        }
                   1386:                                        else
1.1.1.3 ! root     1387:                                        {       // open a new file on the pakfile
1.1       root     1388:                                                *file = fopen (pak->filename, "rb");
                   1389:                                                if (*file)
                   1390:                                                        fseek (*file, pak->files[i].filepos, SEEK_SET);
                   1391:                                        }
                   1392:                                        com_filesize = pak->files[i].filelen;
                   1393:                                        return com_filesize;
                   1394:                                }
                   1395:                }
                   1396:                else
1.1.1.3 ! root     1397:                {               
1.1       root     1398:        // check a file in the directory tree
                   1399:                        if (!static_registered)
1.1.1.3 ! root     1400:                        {       // if not a registered version, don't ever go beyond base
1.1       root     1401:                                if ( strchr (filename, '/') || strchr (filename,'\\'))
                   1402:                                        continue;
                   1403:                        }
                   1404:                        
                   1405:                        sprintf (netpath, "%s/%s",search->filename, filename);
                   1406:                        
                   1407:                        findtime = Sys_FileTime (netpath);
                   1408:                        if (findtime == -1)
                   1409:                                continue;
                   1410:                                
                   1411:                // see if the file needs to be updated in the cache
                   1412:                        if (!com_cachedir[0])
                   1413:                                strcpy (cachepath, netpath);
                   1414:                        else
                   1415:                        {       
1.1.1.3 ! root     1416: #if defined(_WIN32)
        !          1417:                                if ((strlen(netpath) < 2) || (netpath[1] != ':'))
        !          1418:                                        sprintf (cachepath,"%s%s", com_cachedir, netpath);
        !          1419:                                else
        !          1420:                                        sprintf (cachepath,"%s%s", com_cachedir, netpath+2);
        !          1421: #else
        !          1422:                                sprintf (cachepath,"%s%s", com_cachedir, netpath);
        !          1423: #endif
        !          1424: 
1.1       root     1425:                                cachetime = Sys_FileTime (cachepath);
                   1426:                        
                   1427:                                if (cachetime < findtime)
                   1428:                                        COM_CopyFile (netpath, cachepath);
                   1429:                                strcpy (netpath, cachepath);
                   1430:                        }       
                   1431: 
                   1432:                        Sys_Printf ("FindFile: %s\n",netpath);
                   1433:                        com_filesize = Sys_FileOpenRead (netpath, &i);
                   1434:                        if (handle)
                   1435:                                *handle = i;
                   1436:                        else
                   1437:                        {
                   1438:                                Sys_FileClose (i);
                   1439:                                *file = fopen (netpath, "rb");
                   1440:                        }
                   1441:                        return com_filesize;
                   1442:                }
                   1443:                
                   1444:        }
                   1445:        
                   1446:        Sys_Printf ("FindFile: can't find %s\n", filename);
                   1447:        
                   1448:        if (handle)
                   1449:                *handle = -1;
                   1450:        else
                   1451:                *file = NULL;
                   1452:        com_filesize = -1;
                   1453:        return -1;
                   1454: }
                   1455: 
                   1456: 
                   1457: /*
                   1458: ===========
                   1459: COM_OpenFile
                   1460: 
                   1461: filename never has a leading slash, but may contain directory walks
                   1462: returns a handle and a length
                   1463: it may actually be inside a pak file
                   1464: ===========
                   1465: */
                   1466: int COM_OpenFile (char *filename, int *handle)
                   1467: {
                   1468:        return COM_FindFile (filename, handle, NULL);
                   1469: }
                   1470: 
                   1471: /*
                   1472: ===========
                   1473: COM_FOpenFile
                   1474: 
                   1475: If the requested file is inside a packfile, a new FILE * will be opened
                   1476: into the file.
                   1477: ===========
                   1478: */
                   1479: int COM_FOpenFile (char *filename, FILE **file)
                   1480: {
                   1481:        return COM_FindFile (filename, NULL, file);
                   1482: }
                   1483: 
                   1484: /*
                   1485: ============
                   1486: COM_CloseFile
                   1487: 
                   1488: If it is a pak file handle, don't really close it
                   1489: ============
                   1490: */
                   1491: void COM_CloseFile (int h)
                   1492: {
1.1.1.3 ! root     1493:        searchpath_t    *s;
1.1       root     1494:        
                   1495:        for (s = com_searchpaths ; s ; s=s->next)
                   1496:                if (s->pack && s->pack->handle == h)
                   1497:                        return;
                   1498:                        
                   1499:        Sys_FileClose (h);
                   1500: }
                   1501: 
                   1502: 
                   1503: /*
                   1504: ============
                   1505: COM_LoadFile
                   1506: 
                   1507: Filename are reletive to the quake directory.
                   1508: Allways appends a 0 byte.
                   1509: ============
                   1510: */
                   1511: cache_user_t *loadcache;
1.1.1.3 ! root     1512: byte    *loadbuf;
        !          1513: int             loadsize;
1.1       root     1514: byte *COM_LoadFile (char *path, int usehunk)
                   1515: {
1.1.1.3 ! root     1516:        int             h;
        !          1517:        byte    *buf;
        !          1518:        char    base[32];
        !          1519:        int             len;
1.1       root     1520: 
1.1.1.3 ! root     1521:        buf = NULL;     // quiet compiler warning
1.1       root     1522: 
                   1523: // look for it in the filesystem or pack files
                   1524:        len = COM_OpenFile (path, &h);
                   1525:        if (h == -1)
                   1526:                return NULL;
                   1527:        
                   1528: // extract the filename base name for hunk tag
                   1529:        COM_FileBase (path, base);
                   1530:        
                   1531:        if (usehunk == 1)
                   1532:                buf = Hunk_AllocName (len+1, base);
                   1533:        else if (usehunk == 2)
                   1534:                buf = Hunk_TempAlloc (len+1);
                   1535:        else if (usehunk == 0)
                   1536:                buf = Z_Malloc (len+1);
                   1537:        else if (usehunk == 3)
                   1538:                buf = Cache_Alloc (loadcache, len+1, base);
                   1539:        else if (usehunk == 4)
                   1540:        {
                   1541:                if (len+1 > loadsize)
                   1542:                        buf = Hunk_TempAlloc (len+1);
                   1543:                else
                   1544:                        buf = loadbuf;
                   1545:        }
                   1546:        else
                   1547:                Sys_Error ("COM_LoadFile: bad usehunk");
                   1548: 
                   1549:        if (!buf)
                   1550:                Sys_Error ("COM_LoadFile: not enough space for %s", path);
                   1551:                
                   1552:        ((byte *)buf)[len] = 0;
                   1553: 
                   1554:        Draw_BeginDisc ();
1.1.1.3 ! root     1555:        Sys_FileRead (h, buf, len);                     
1.1       root     1556:        COM_CloseFile (h);
                   1557:        Draw_EndDisc ();
                   1558: 
                   1559:        return buf;
                   1560: }
                   1561: 
                   1562: byte *COM_LoadHunkFile (char *path)
                   1563: {
                   1564:        return COM_LoadFile (path, 1);
                   1565: }
                   1566: 
                   1567: byte *COM_LoadTempFile (char *path)
                   1568: {
                   1569:        return COM_LoadFile (path, 2);
                   1570: }
                   1571: 
                   1572: void COM_LoadCacheFile (char *path, struct cache_user_s *cu)
                   1573: {
                   1574:        loadcache = cu;
                   1575:        COM_LoadFile (path, 3);
                   1576: }
                   1577: 
                   1578: // uses temp hunk if larger than bufsize
                   1579: byte *COM_LoadStackFile (char *path, void *buffer, int bufsize)
                   1580: {
1.1.1.3 ! root     1581:        byte    *buf;
1.1       root     1582:        
                   1583:        loadbuf = (byte *)buffer;
                   1584:        loadsize = bufsize;
                   1585:        buf = COM_LoadFile (path, 4);
                   1586:        
                   1587:        return buf;
                   1588: }
                   1589: 
                   1590: /*
                   1591: =================
                   1592: COM_LoadPackFile
                   1593: 
                   1594: Takes an explicit (not game tree related) path to a pak file.
                   1595: 
                   1596: Loads the header and directory, adding the files at the beginning
                   1597: of the list so they override previous pack files.
                   1598: =================
                   1599: */
                   1600: pack_t *COM_LoadPackFile (char *packfile)
                   1601: {
1.1.1.3 ! root     1602:        dpackheader_t   header;
        !          1603:        int                             i;
        !          1604:        packfile_t              *newfiles;
        !          1605:        int                             numpackfiles;
        !          1606:        pack_t                  *pack;
        !          1607:        int                             packhandle;
        !          1608:        dpackfile_t             info[MAX_FILES_IN_PACK];
        !          1609:        unsigned short          crc;
1.1       root     1610: 
                   1611:        if (Sys_FileOpenRead (packfile, &packhandle) == -1)
                   1612:        {
1.1.1.3 ! root     1613: //              Con_Printf ("Couldn't open %s\n", packfile);
1.1       root     1614:                return NULL;
                   1615:        }
                   1616:        Sys_FileRead (packhandle, (void *)&header, sizeof(header));
                   1617:        if (header.id[0] != 'P' || header.id[1] != 'A'
                   1618:        || header.id[2] != 'C' || header.id[3] != 'K')
                   1619:                Sys_Error ("%s is not a packfile", packfile);
                   1620:        header.dirofs = LittleLong (header.dirofs);
                   1621:        header.dirlen = LittleLong (header.dirlen);
                   1622: 
                   1623:        numpackfiles = header.dirlen / sizeof(dpackfile_t);
                   1624: 
                   1625:        if (numpackfiles > MAX_FILES_IN_PACK)
                   1626:                Sys_Error ("%s has %i files", packfile, numpackfiles);
                   1627: 
                   1628:        if (numpackfiles != PAK0_COUNT)
1.1.1.3 ! root     1629:                com_modified = true;    // not the original file
1.1       root     1630: 
                   1631:        newfiles = Hunk_AllocName (numpackfiles * sizeof(packfile_t), "packfile");
                   1632: 
                   1633:        Sys_FileSeek (packhandle, header.dirofs);
                   1634:        Sys_FileRead (packhandle, (void *)info, header.dirlen);
                   1635: 
                   1636: // crc the directory to check for modifications
                   1637:        CRC_Init (&crc);
                   1638:        for (i=0 ; i<header.dirlen ; i++)
                   1639:                CRC_ProcessByte (&crc, ((byte *)info)[i]);
                   1640:        if (crc != PAK0_CRC)
                   1641:                com_modified = true;
                   1642: 
                   1643: // parse the directory
                   1644:        for (i=0 ; i<numpackfiles ; i++)
                   1645:        {
                   1646:                strcpy (newfiles[i].name, info[i].name);
                   1647:                newfiles[i].filepos = LittleLong(info[i].filepos);
                   1648:                newfiles[i].filelen = LittleLong(info[i].filelen);
                   1649:        }
                   1650: 
                   1651:        pack = Hunk_Alloc (sizeof (pack_t));
                   1652:        strcpy (pack->filename, packfile);
                   1653:        pack->handle = packhandle;
                   1654:        pack->numfiles = numpackfiles;
                   1655:        pack->files = newfiles;
                   1656:        
                   1657:        Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles);
                   1658:        return pack;
                   1659: }
                   1660: 
                   1661: 
                   1662: /*
                   1663: ================
                   1664: COM_AddGameDirectory
                   1665: 
                   1666: Sets com_gamedir, adds the directory to the head of the path,
                   1667: then loads and adds pak1.pak pak2.pak ... 
                   1668: ================
                   1669: */
                   1670: void COM_AddGameDirectory (char *dir)
                   1671: {
1.1.1.3 ! root     1672:        int                             i;
        !          1673:        searchpath_t    *search;
        !          1674:        pack_t                  *pak;
        !          1675:        char                    pakfile[MAX_OSPATH];
1.1       root     1676: 
                   1677:        strcpy (com_gamedir, dir);
                   1678: 
                   1679: //
                   1680: // add the directory to the search path
                   1681: //
                   1682:        search = Hunk_Alloc (sizeof(searchpath_t));
                   1683:        strcpy (search->filename, dir);
                   1684:        search->next = com_searchpaths;
                   1685:        com_searchpaths = search;
                   1686: 
                   1687: //
                   1688: // add any pak files in the format pak0.pak pak1.pak, ...
                   1689: //
                   1690:        for (i=0 ; ; i++)
                   1691:        {
                   1692:                sprintf (pakfile, "%s/pak%i.pak", dir, i);
                   1693:                pak = COM_LoadPackFile (pakfile);
                   1694:                if (!pak)
                   1695:                        break;
                   1696:                search = Hunk_Alloc (sizeof(searchpath_t));
                   1697:                search->pack = pak;
                   1698:                search->next = com_searchpaths;
1.1.1.3 ! root     1699:                com_searchpaths = search;               
1.1       root     1700:        }
                   1701: 
                   1702: //
                   1703: // add the contents of the parms.txt file to the end of the command line
                   1704: //
                   1705: 
                   1706: }
                   1707: 
                   1708: /*
                   1709: ================
                   1710: COM_InitFilesystem
                   1711: ================
                   1712: */
                   1713: void COM_InitFilesystem (void)
                   1714: {
1.1.1.3 ! root     1715:        int             i, j;
        !          1716:        char    basedir[MAX_OSPATH];
        !          1717:        searchpath_t    *search;
1.1       root     1718: 
                   1719: //
                   1720: // -basedir <path>
1.1.1.3 ! root     1721: // Overrides the system supplied base directory (under GAMENAME)
1.1       root     1722: //
                   1723:        i = COM_CheckParm ("-basedir");
                   1724:        if (i && i < com_argc-1)
                   1725:                strcpy (basedir, com_argv[i+1]);
                   1726:        else
                   1727:                strcpy (basedir, host_parms.basedir);
                   1728: 
1.1.1.3 ! root     1729:        j = strlen (basedir);
        !          1730: 
        !          1731:        if (j > 0)
        !          1732:        {
        !          1733:                if ((basedir[j-1] == '\\') || (basedir[j-1] == '/'))
        !          1734:                        basedir[j-1] = 0;
        !          1735:        }
        !          1736: 
1.1       root     1737: //
                   1738: // -cachedir <path>
                   1739: // Overrides the system supplied cache directory (NULL or /qcache)
                   1740: // -cachedir - will disable caching.
                   1741: //
                   1742:        i = COM_CheckParm ("-cachedir");
                   1743:        if (i && i < com_argc-1)
                   1744:        {
                   1745:                if (com_argv[i+1][0] == '-')
                   1746:                        com_cachedir[0] = 0;
                   1747:                else
                   1748:                        strcpy (com_cachedir, com_argv[i+1]);
                   1749:        }
                   1750:        else if (host_parms.cachedir)
                   1751:                strcpy (com_cachedir, host_parms.cachedir);
                   1752:        else
                   1753:                com_cachedir[0] = 0;
                   1754: 
                   1755: //
1.1.1.3 ! root     1756: // start up with GAMENAME by default (id1)
1.1       root     1757: //
1.1.1.3 ! root     1758:        COM_AddGameDirectory (va("%s/"GAMENAME, basedir) );
        !          1759: 
        !          1760:        if (COM_CheckParm ("-rogue"))
        !          1761:                COM_AddGameDirectory (va("%s/rogue", basedir) );
        !          1762:        if (COM_CheckParm ("-hipnotic"))
        !          1763:                COM_AddGameDirectory (va("%s/hipnotic", basedir) );
1.1       root     1764: 
                   1765: //
                   1766: // -game <gamedir>
                   1767: // Adds basedir/gamedir as an override game
                   1768: //
                   1769:        i = COM_CheckParm ("-game");
                   1770:        if (i && i < com_argc-1)
                   1771:        {
                   1772:                com_modified = true;
                   1773:                COM_AddGameDirectory (va("%s/%s", basedir, com_argv[i+1]));
                   1774:        }
                   1775: 
                   1776: //
                   1777: // -path <dir or packfile> [<dir or packfile>] ...
                   1778: // Fully specifies the exact serach path, overriding the generated one
                   1779: //
                   1780:        i = COM_CheckParm ("-path");
                   1781:        if (i)
                   1782:        {
                   1783:                com_modified = true;
                   1784:                com_searchpaths = NULL;
                   1785:                while (++i < com_argc)
                   1786:                {
                   1787:                        if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-')
                   1788:                                break;
                   1789:                        
                   1790:                        search = Hunk_Alloc (sizeof(searchpath_t));
                   1791:                        if ( !strcmp(COM_FileExtension(com_argv[i]), "pak") )
                   1792:                        {
                   1793:                                search->pack = COM_LoadPackFile (com_argv[i]);
                   1794:                                if (!search->pack)
                   1795:                                        Sys_Error ("Couldn't load packfile: %s", com_argv[i]);
                   1796:                        }
                   1797:                        else
                   1798:                                strcpy (search->filename, com_argv[i]);
                   1799:                        search->next = com_searchpaths;
                   1800:                        com_searchpaths = search;
                   1801:                }
                   1802:        }
1.1.1.3 ! root     1803: 
        !          1804:        if (COM_CheckParm ("-proghack"))
        !          1805:                proghack = true;
1.1       root     1806: }
                   1807: 
                   1808: 

unix.superglobalmegacorp.com

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