File: client\cl_cin.c

    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 */
   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);
  457         size = LittleLong(size);
  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 ();
  595                 cls.state = ca_active;
  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 }
  651