Annotation of quake1/common.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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