Annotation of quake2/client/cl_cin.c, revision 1.1

1.1     ! root        1: #include "client.h"
        !             2: 
        !             3: typedef struct
        !             4: {
        !             5:        byte    *data;
        !             6:        int             count;
        !             7: } cblock_t;
        !             8: 
        !             9: typedef struct
        !            10: {
        !            11:        qboolean        restart_sound;
        !            12:        int             s_rate;
        !            13:        int             s_width;
        !            14:        int             s_channels;
        !            15: 
        !            16:        int             width;
        !            17:        int             height;
        !            18:        byte    *pic;
        !            19:        byte    *pic_pending;
        !            20: 
        !            21:        // order 1 huffman stuff
        !            22:        int             *hnodes1;       // [256][256][2];
        !            23:        int             numhnodes1[256];
        !            24: 
        !            25:        int             h_used[512];
        !            26:        int             h_count[512];
        !            27: } cinematics_t;
        !            28: 
        !            29: cinematics_t   cin;
        !            30: 
        !            31: /*
        !            32: =================================================================
        !            33: 
        !            34: PCX LOADING
        !            35: 
        !            36: =================================================================
        !            37: */
        !            38: 
        !            39: 
        !            40: /*
        !            41: ==============
        !            42: SCR_LoadPCX
        !            43: ==============
        !            44: */
        !            45: void SCR_LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
        !            46: {
        !            47:        byte    *raw;
        !            48:        pcx_t   *pcx;
        !            49:        int             x, y;
        !            50:        int             len;
        !            51:        int             dataByte, runLength;
        !            52:        byte    *out, *pix;
        !            53: 
        !            54:        *pic = NULL;
        !            55: 
        !            56:        //
        !            57:        // load the file
        !            58:        //
        !            59:        len = FS_LoadFile (filename, (void **)&raw);
        !            60:        if (!raw)
        !            61:                return; // Com_Printf ("Bad pcx file %s\n", filename);
        !            62: 
        !            63:        //
        !            64:        // parse the PCX file
        !            65:        //
        !            66:        pcx = (pcx_t *)raw;
        !            67:        raw = &pcx->data;
        !            68: 
        !            69:        if (pcx->manufacturer != 0x0a
        !            70:                || pcx->version != 5
        !            71:                || pcx->encoding != 1
        !            72:                || pcx->bits_per_pixel != 8
        !            73:                || pcx->xmax >= 640
        !            74:                || pcx->ymax >= 480)
        !            75:        {
        !            76:                Com_Printf ("Bad pcx file %s\n", filename);
        !            77:                return;
        !            78:        }
        !            79: 
        !            80:        out = Z_Malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
        !            81: 
        !            82:        *pic = out;
        !            83: 
        !            84:        pix = out;
        !            85: 
        !            86:        if (palette)
        !            87:        {
        !            88:                *palette = Z_Malloc(768);
        !            89:                memcpy (*palette, (byte *)pcx + len - 768, 768);
        !            90:        }
        !            91: 
        !            92:        if (width)
        !            93:                *width = pcx->xmax+1;
        !            94:        if (height)
        !            95:                *height = pcx->ymax+1;
        !            96: 
        !            97:        for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
        !            98:        {
        !            99:                for (x=0 ; x<=pcx->xmax ; )
        !           100:                {
        !           101:                        dataByte = *raw++;
        !           102: 
        !           103:                        if((dataByte & 0xC0) == 0xC0)
        !           104:                        {
        !           105:                                runLength = dataByte & 0x3F;
        !           106:                                dataByte = *raw++;
        !           107:                        }
        !           108:                        else
        !           109:                                runLength = 1;
        !           110: 
        !           111:                        while(runLength-- > 0)
        !           112:                                pix[x++] = dataByte;
        !           113:                }
        !           114: 
        !           115:        }
        !           116: 
        !           117:        if ( raw - (byte *)pcx > len)
        !           118:        {
        !           119:                Com_Printf ("PCX file %s was malformed", filename);
        !           120:                Z_Free (*pic);
        !           121:                *pic = NULL;
        !           122:        }
        !           123: 
        !           124:        FS_FreeFile (pcx);
        !           125: }
        !           126: 
        !           127: //=============================================================
        !           128: 
        !           129: /*
        !           130: ==================
        !           131: SCR_StopCinematic
        !           132: ==================
        !           133: */
        !           134: void SCR_StopCinematic (void)
        !           135: {
        !           136:        cl.cinematictime = 0;   // done
        !           137:        if (cin.pic)
        !           138:        {
        !           139:                Z_Free (cin.pic);
        !           140:                cin.pic = NULL;
        !           141:        }
        !           142:        if (cin.pic_pending)
        !           143:        {
        !           144:                Z_Free (cin.pic_pending);
        !           145:                cin.pic_pending = NULL;
        !           146:        }
        !           147:        if (cl.cinematicpalette_active)
        !           148:        {
        !           149:                re.CinematicSetPalette(NULL);
        !           150:                cl.cinematicpalette_active = false;
        !           151:        }
        !           152:        if (cl.cinematic_file)
        !           153:        {
        !           154:                fclose (cl.cinematic_file);
        !           155:                cl.cinematic_file = NULL;
        !           156:        }
        !           157:        if (cin.hnodes1)
        !           158:        {
        !           159:                Z_Free (cin.hnodes1);
        !           160:                cin.hnodes1 = NULL;
        !           161:        }
        !           162: 
        !           163:        // switch back down to 11 khz sound if necessary
        !           164:        if (cin.restart_sound)
        !           165:        {
        !           166:                cin.restart_sound = false;
        !           167:                CL_Snd_Restart_f ();
        !           168:        }
        !           169: 
        !           170: }
        !           171: 
        !           172: /*
        !           173: ====================
        !           174: SCR_FinishCinematic
        !           175: 
        !           176: Called when either the cinematic completes, or it is aborted
        !           177: ====================
        !           178: */
        !           179: void SCR_FinishCinematic (void)
        !           180: {
        !           181:        // tell the server to advance to the next map / cinematic
        !           182:        MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
        !           183:        SZ_Print (&cls.netchan.message, va("nextserver %i\n", cl.servercount));
        !           184: }
        !           185: 
        !           186: //==========================================================================
        !           187: 
        !           188: /*
        !           189: ==================
        !           190: SmallestNode1
        !           191: ==================
        !           192: */
        !           193: int    SmallestNode1 (int numhnodes)
        !           194: {
        !           195:        int             i;
        !           196:        int             best, bestnode;
        !           197: 
        !           198:        best = 99999999;
        !           199:        bestnode = -1;
        !           200:        for (i=0 ; i<numhnodes ; i++)
        !           201:        {
        !           202:                if (cin.h_used[i])
        !           203:                        continue;
        !           204:                if (!cin.h_count[i])
        !           205:                        continue;
        !           206:                if (cin.h_count[i] < best)
        !           207:                {
        !           208:                        best = cin.h_count[i];
        !           209:                        bestnode = i;
        !           210:                }
        !           211:        }
        !           212: 
        !           213:        if (bestnode == -1)
        !           214:                return -1;
        !           215: 
        !           216:        cin.h_used[bestnode] = true;
        !           217:        return bestnode;
        !           218: }
        !           219: 
        !           220: 
        !           221: /*
        !           222: ==================
        !           223: Huff1TableInit
        !           224: 
        !           225: Reads the 64k counts table and initializes the node trees
        !           226: ==================
        !           227: */
        !           228: void Huff1TableInit (void)
        !           229: {
        !           230:        int             prev;
        !           231:        int             j;
        !           232:        int             *node, *nodebase;
        !           233:        byte    counts[256];
        !           234:        int             numhnodes;
        !           235: 
        !           236:        cin.hnodes1 = Z_Malloc (256*256*2*4);
        !           237:        memset (cin.hnodes1, 0, 256*256*2*4);
        !           238: 
        !           239:        for (prev=0 ; prev<256 ; prev++)
        !           240:        {
        !           241:                memset (cin.h_count,0,sizeof(cin.h_count));
        !           242:                memset (cin.h_used,0,sizeof(cin.h_used));
        !           243: 
        !           244:                // read a row of counts
        !           245:                FS_Read (counts, sizeof(counts), cl.cinematic_file);
        !           246:                for (j=0 ; j<256 ; j++)
        !           247:                        cin.h_count[j] = counts[j];
        !           248: 
        !           249:                // build the nodes
        !           250:                numhnodes = 256;
        !           251:                nodebase = cin.hnodes1 + prev*256*2;
        !           252: 
        !           253:                while (numhnodes != 511)
        !           254:                {
        !           255:                        node = nodebase + (numhnodes-256)*2;
        !           256: 
        !           257:                        // pick two lowest counts
        !           258:                        node[0] = SmallestNode1 (numhnodes);
        !           259:                        if (node[0] == -1)
        !           260:                                break;  // no more
        !           261: 
        !           262:                        node[1] = SmallestNode1 (numhnodes);
        !           263:                        if (node[1] == -1)
        !           264:                                break;
        !           265: 
        !           266:                        cin.h_count[numhnodes] = cin.h_count[node[0]] + cin.h_count[node[1]];
        !           267:                        numhnodes++;
        !           268:                }
        !           269: 
        !           270:                cin.numhnodes1[prev] = numhnodes-1;
        !           271:        }
        !           272: }
        !           273: 
        !           274: /*
        !           275: ==================
        !           276: Huff1Decompress
        !           277: ==================
        !           278: */
        !           279: cblock_t Huff1Decompress (cblock_t in)
        !           280: {
        !           281:        byte            *input;
        !           282:        byte            *out_p;
        !           283:        int                     nodenum;
        !           284:        int                     count;
        !           285:        cblock_t        out;
        !           286:        int                     inbyte;
        !           287:        int                     *hnodes, *hnodesbase;
        !           288: //int          i;
        !           289: 
        !           290:        // get decompressed count
        !           291:        count = in.data[0] + (in.data[1]<<8) + (in.data[2]<<16) + (in.data[3]<<24);
        !           292:        input = in.data + 4;
        !           293:        out_p = out.data = Z_Malloc (count);
        !           294: 
        !           295:        // read bits
        !           296: 
        !           297:        hnodesbase = cin.hnodes1 - 256*2;       // nodes 0-255 aren't stored
        !           298: 
        !           299:        hnodes = hnodesbase;
        !           300:        nodenum = cin.numhnodes1[0];
        !           301:        while (count)
        !           302:        {
        !           303:                inbyte = *input++;
        !           304:                //-----------
        !           305:                if (nodenum < 256)
        !           306:                {
        !           307:                        hnodes = hnodesbase + (nodenum<<9);
        !           308:                        *out_p++ = nodenum;
        !           309:                        if (!--count)
        !           310:                                break;
        !           311:                        nodenum = cin.numhnodes1[nodenum];
        !           312:                }
        !           313:                nodenum = hnodes[nodenum*2 + (inbyte&1)];
        !           314:                inbyte >>=1;
        !           315:                //-----------
        !           316:                if (nodenum < 256)
        !           317:                {
        !           318:                        hnodes = hnodesbase + (nodenum<<9);
        !           319:                        *out_p++ = nodenum;
        !           320:                        if (!--count)
        !           321:                                break;
        !           322:                        nodenum = cin.numhnodes1[nodenum];
        !           323:                }
        !           324:                nodenum = hnodes[nodenum*2 + (inbyte&1)];
        !           325:                inbyte >>=1;
        !           326:                //-----------
        !           327:                if (nodenum < 256)
        !           328:                {
        !           329:                        hnodes = hnodesbase + (nodenum<<9);
        !           330:                        *out_p++ = nodenum;
        !           331:                        if (!--count)
        !           332:                                break;
        !           333:                        nodenum = cin.numhnodes1[nodenum];
        !           334:                }
        !           335:                nodenum = hnodes[nodenum*2 + (inbyte&1)];
        !           336:                inbyte >>=1;
        !           337:                //-----------
        !           338:                if (nodenum < 256)
        !           339:                {
        !           340:                        hnodes = hnodesbase + (nodenum<<9);
        !           341:                        *out_p++ = nodenum;
        !           342:                        if (!--count)
        !           343:                                break;
        !           344:                        nodenum = cin.numhnodes1[nodenum];
        !           345:                }
        !           346:                nodenum = hnodes[nodenum*2 + (inbyte&1)];
        !           347:                inbyte >>=1;
        !           348:                //-----------
        !           349:                if (nodenum < 256)
        !           350:                {
        !           351:                        hnodes = hnodesbase + (nodenum<<9);
        !           352:                        *out_p++ = nodenum;
        !           353:                        if (!--count)
        !           354:                                break;
        !           355:                        nodenum = cin.numhnodes1[nodenum];
        !           356:                }
        !           357:                nodenum = hnodes[nodenum*2 + (inbyte&1)];
        !           358:                inbyte >>=1;
        !           359:                //-----------
        !           360:                if (nodenum < 256)
        !           361:                {
        !           362:                        hnodes = hnodesbase + (nodenum<<9);
        !           363:                        *out_p++ = nodenum;
        !           364:                        if (!--count)
        !           365:                                break;
        !           366:                        nodenum = cin.numhnodes1[nodenum];
        !           367:                }
        !           368:                nodenum = hnodes[nodenum*2 + (inbyte&1)];
        !           369:                inbyte >>=1;
        !           370:                //-----------
        !           371:                if (nodenum < 256)
        !           372:                {
        !           373:                        hnodes = hnodesbase + (nodenum<<9);
        !           374:                        *out_p++ = nodenum;
        !           375:                        if (!--count)
        !           376:                                break;
        !           377:                        nodenum = cin.numhnodes1[nodenum];
        !           378:                }
        !           379:                nodenum = hnodes[nodenum*2 + (inbyte&1)];
        !           380:                inbyte >>=1;
        !           381:                //-----------
        !           382:                if (nodenum < 256)
        !           383:                {
        !           384:                        hnodes = hnodesbase + (nodenum<<9);
        !           385:                        *out_p++ = nodenum;
        !           386:                        if (!--count)
        !           387:                                break;
        !           388:                        nodenum = cin.numhnodes1[nodenum];
        !           389:                }
        !           390:                nodenum = hnodes[nodenum*2 + (inbyte&1)];
        !           391:                inbyte >>=1;
        !           392:        }
        !           393: 
        !           394:        if (input - in.data != in.count && input - in.data != in.count+1)
        !           395:        {
        !           396:                Com_Printf ("Decompression overread by %i", (input - in.data) - in.count);
        !           397:        }
        !           398:        out.count = out_p - out.data;
        !           399: 
        !           400:        return out;
        !           401: }
        !           402: 
        !           403: /*
        !           404: ==================
        !           405: SCR_ReadNextFrame
        !           406: ==================
        !           407: */
        !           408: byte *SCR_ReadNextFrame (void)
        !           409: {
        !           410:        int             r;
        !           411:        int             command;
        !           412:        byte    samples[22050/14*4];
        !           413:        byte    compressed[0x20000];
        !           414:        int             size;
        !           415:        byte    *pic;
        !           416:        cblock_t        in, huf1;
        !           417:        int             start, end, count;
        !           418: 
        !           419:        // read the next frame
        !           420:        r = fread (&command, 4, 1, cl.cinematic_file);
        !           421:        if (r == 0)             // we'll give it one more chance
        !           422:                r = fread (&command, 4, 1, cl.cinematic_file);
        !           423: 
        !           424:        if (r != 1)
        !           425:                return NULL;
        !           426:        command = LittleLong(command);
        !           427:        if (command == 2)
        !           428:                return NULL;    // last frame marker
        !           429: 
        !           430:        if (command == 1)
        !           431:        {       // read palette
        !           432:                FS_Read (cl.cinematicpalette, sizeof(cl.cinematicpalette), cl.cinematic_file);
        !           433:                cl.cinematicpalette_active=0;   // dubious....  exposes an edge case
        !           434:        }
        !           435: 
        !           436:        // decompress the next frame
        !           437:        FS_Read (&size, 4, cl.cinematic_file);
        !           438:        if (size > sizeof(compressed) || size < 1)
        !           439:                Com_Error (ERR_DROP, "Bad compressed frame size");
        !           440:        FS_Read (compressed, size, cl.cinematic_file);
        !           441: 
        !           442:        // read sound
        !           443:        start = cl.cinematicframe*cin.s_rate/14;
        !           444:        end = (cl.cinematicframe+1)*cin.s_rate/14;
        !           445:        count = end - start;
        !           446: 
        !           447:        FS_Read (samples, count*cin.s_width*cin.s_channels, cl.cinematic_file);
        !           448: 
        !           449:        S_RawSamples (count, cin.s_rate, cin.s_width, cin.s_channels, samples);
        !           450: 
        !           451:        in.data = compressed;
        !           452:        in.count = size;
        !           453: 
        !           454:        huf1 = Huff1Decompress (in);
        !           455: 
        !           456:        pic = huf1.data;
        !           457: 
        !           458:        cl.cinematicframe++;
        !           459: 
        !           460:        return pic;
        !           461: }
        !           462: 
        !           463: 
        !           464: /*
        !           465: ==================
        !           466: SCR_RunCinematic
        !           467: 
        !           468: ==================
        !           469: */
        !           470: void SCR_RunCinematic (void)
        !           471: {
        !           472:        int             frame;
        !           473: 
        !           474:        if (cl.cinematictime <= 0)
        !           475:        {
        !           476:                SCR_StopCinematic ();
        !           477:                return;
        !           478:        }
        !           479: 
        !           480:        if (cl.cinematicframe == -1)
        !           481:                return;         // static image
        !           482: 
        !           483:        if (cls.key_dest != key_game)
        !           484:        {       // pause if menu or console is up
        !           485:                cl.cinematictime = cls.realtime - cl.cinematicframe*1000/14;
        !           486:                return;
        !           487:        }
        !           488: 
        !           489:        frame = (cls.realtime - cl.cinematictime)*14.0/1000;
        !           490:        if (frame <= cl.cinematicframe)
        !           491:                return;
        !           492:        if (frame > cl.cinematicframe+1)
        !           493:        {
        !           494:                Com_Printf ("Dropped frame: %i > %i\n", frame, cl.cinematicframe+1);
        !           495:                cl.cinematictime = cls.realtime - cl.cinematicframe*1000/14;
        !           496:        }
        !           497:        if (cin.pic)
        !           498:                Z_Free (cin.pic);
        !           499:        cin.pic = cin.pic_pending;
        !           500:        cin.pic_pending = NULL;
        !           501:        cin.pic_pending = SCR_ReadNextFrame ();
        !           502:        if (!cin.pic_pending)
        !           503:        {
        !           504:                SCR_StopCinematic ();
        !           505:                SCR_FinishCinematic ();
        !           506:                cl.cinematictime = 1;   // hack to get the black screen behind loading
        !           507:                SCR_BeginLoadingPlaque ();
        !           508:                cl.cinematictime = 0;
        !           509:                return;
        !           510:        }
        !           511: }
        !           512: 
        !           513: /*
        !           514: ==================
        !           515: SCR_DrawCinematic
        !           516: 
        !           517: Returns true if a cinematic is active, meaning the view rendering
        !           518: should be skipped
        !           519: ==================
        !           520: */
        !           521: qboolean SCR_DrawCinematic (void)
        !           522: {
        !           523:        if (cl.cinematictime <= 0)
        !           524:        {
        !           525:                return false;
        !           526:        }
        !           527: 
        !           528:        if (cls.key_dest == key_menu)
        !           529:        {       // blank screen and pause if menu is up
        !           530:                re.CinematicSetPalette(NULL);
        !           531:                cl.cinematicpalette_active = false;
        !           532:                return true;
        !           533:        }
        !           534: 
        !           535:        if (!cl.cinematicpalette_active)
        !           536:        {
        !           537:                re.CinematicSetPalette(cl.cinematicpalette);
        !           538:                cl.cinematicpalette_active = true;
        !           539:        }
        !           540: 
        !           541:        if (!cin.pic)
        !           542:                return true;
        !           543: 
        !           544:        re.DrawStretchRaw (0, 0, viddef.width, viddef.height,
        !           545:                cin.width, cin.height, cin.pic);
        !           546: 
        !           547:        return true;
        !           548: }
        !           549: 
        !           550: /*
        !           551: ==================
        !           552: SCR_PlayCinematic
        !           553: 
        !           554: ==================
        !           555: */
        !           556: void SCR_PlayCinematic (char *arg)
        !           557: {
        !           558:        int             width, height;
        !           559:        byte    *palette;
        !           560:        char    name[MAX_OSPATH], *dot;
        !           561:        int             old_khz;
        !           562: 
        !           563:        // make sure CD isn't playing music
        !           564:        CDAudio_Stop();
        !           565: 
        !           566:        cl.cinematicframe = 0;
        !           567:        dot = strstr (arg, ".");
        !           568:        if (dot && !strcmp (dot, ".pcx"))
        !           569:        {       // static pcx image
        !           570:                Com_sprintf (name, sizeof(name), "pics/%s", arg);
        !           571:                SCR_LoadPCX (name, &cin.pic, &palette, &cin.width, &cin.height);
        !           572:                cl.cinematicframe = -1;
        !           573:                cl.cinematictime = 1;
        !           574:                SCR_EndLoadingPlaque ();
        !           575:                if (!cin.pic)
        !           576:                {
        !           577:                        Com_Printf ("%s not found.\n", name);
        !           578:                        cl.cinematictime = 0;
        !           579:                }
        !           580:                else
        !           581:                {
        !           582:                        memcpy (cl.cinematicpalette, palette, sizeof(cl.cinematicpalette));
        !           583:                        Z_Free (palette);
        !           584:                }
        !           585:                return;
        !           586:        }
        !           587: 
        !           588:        Com_sprintf (name, sizeof(name), "video/%s", arg);
        !           589:        FS_FOpenFile (name, &cl.cinematic_file);
        !           590:        if (!cl.cinematic_file)
        !           591:        {
        !           592: //             Com_Error (ERR_DROP, "Cinematic %s not found.\n", name);
        !           593:                SCR_FinishCinematic ();
        !           594:                cl.cinematictime = 0;   // done
        !           595:                return;
        !           596:        }
        !           597: 
        !           598:        SCR_EndLoadingPlaque ();
        !           599: 
        !           600:        cls.state = ca_active;
        !           601: 
        !           602:        FS_Read (&width, 4, cl.cinematic_file);
        !           603:        FS_Read (&height, 4, cl.cinematic_file);
        !           604:        cin.width = LittleLong(width);
        !           605:        cin.height = LittleLong(height);
        !           606: 
        !           607:        FS_Read (&cin.s_rate, 4, cl.cinematic_file);
        !           608:        cin.s_rate = LittleLong(cin.s_rate);
        !           609:        FS_Read (&cin.s_width, 4, cl.cinematic_file);
        !           610:        cin.s_width = LittleLong(cin.s_width);
        !           611:        FS_Read (&cin.s_channels, 4, cl.cinematic_file);
        !           612:        cin.s_channels = LittleLong(cin.s_channels);
        !           613: 
        !           614:        Huff1TableInit ();
        !           615: 
        !           616:        // switch up to 22 khz sound if necessary
        !           617:        old_khz = Cvar_VariableValue ("s_khz");
        !           618:        if (old_khz != cin.s_rate/1000)
        !           619:        {
        !           620:                cin.restart_sound = true;
        !           621:                Cvar_SetValue ("s_khz", cin.s_rate/1000);
        !           622:                CL_Snd_Restart_f ();
        !           623:                Cvar_SetValue ("s_khz", old_khz);
        !           624:        }
        !           625: 
        !           626:        cl.cinematicframe = 0;
        !           627:        cin.pic = SCR_ReadNextFrame ();
        !           628:        cl.cinematictime = Sys_Milliseconds ();
        !           629: }

unix.superglobalmegacorp.com

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