Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

cl_cin.c (12823B)


      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 }