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

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

unix.superglobalmegacorp.com

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