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 */
SCR_LoadPCX(char * filename,byte ** pic,byte ** palette,int * width,int * height)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 */
SCR_StopCinematic(void)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 		ref.CinematicSetPalette(NULL);
169 		cl.cinematicpalette_active = qfalse;
170 	}
171 	if (cl.cinematic_file)
172 	{
173 		FS_FCloseFile( cl.cinematic_file );
174 		cl.cinematic_file = 0;
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 = qfalse;
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 */
SCR_FinishCinematic(void)198 void SCR_FinishCinematic (void)
199 {
200 	if( cls.state < ca_connected || cls.demoplayback ) {
201 		return;
202 	}
203 	// tell the server to advance to the next map / cinematic
204 	CL_ClientCommand( va( "nextserver %i\n", cl.servercount ) );
205 }
206 
207 //==========================================================================
208 
209 /*
210 ==================
211 SmallestNode1
212 ==================
213 */
SmallestNode1(int numhnodes)214 int	SmallestNode1 (int numhnodes)
215 {
216 	int		i;
217 	int		best, bestnode;
218 
219 	best = 99999999;
220 	bestnode = -1;
221 	for (i=0 ; i<numhnodes ; i++)
222 	{
223 		if (cin.h_used[i])
224 			continue;
225 		if (!cin.h_count[i])
226 			continue;
227 		if (cin.h_count[i] < best)
228 		{
229 			best = cin.h_count[i];
230 			bestnode = i;
231 		}
232 	}
233 
234 	if (bestnode == -1)
235 		return -1;
236 
237 	cin.h_used[bestnode] = qtrue;
238 	return bestnode;
239 }
240 
241 
242 /*
243 ==================
244 Huff1TableInit
245 
246 Reads the 64k counts table and initializes the node trees
247 ==================
248 */
Huff1TableInit(void)249 void Huff1TableInit (void)
250 {
251 	int		prev;
252 	int		j;
253 	int		*node, *nodebase;
254 	byte	counts[256];
255 	int		numhnodes;
256 
257 	cin.hnodes1 = Z_Malloc (256*256*2*4);
258 	memset (cin.hnodes1, 0, 256*256*2*4);
259 
260 	for (prev=0 ; prev<256 ; prev++)
261 	{
262 		memset (cin.h_count,0,sizeof(cin.h_count));
263 		memset (cin.h_used,0,sizeof(cin.h_used));
264 
265 		// read a row of counts
266 		FS_Read (counts, sizeof(counts), cl.cinematic_file);
267 		for (j=0 ; j<256 ; j++)
268 			cin.h_count[j] = counts[j];
269 
270 		// build the nodes
271 		numhnodes = 256;
272 		nodebase = cin.hnodes1 + prev*256*2;
273 
274 		while (numhnodes != 511)
275 		{
276 			node = nodebase + (numhnodes-256)*2;
277 
278 			// pick two lowest counts
279 			node[0] = SmallestNode1 (numhnodes);
280 			if (node[0] == -1)
281 				break;	// no more
282 
283 			node[1] = SmallestNode1 (numhnodes);
284 			if (node[1] == -1)
285 				break;
286 
287 			cin.h_count[numhnodes] = cin.h_count[node[0]] + cin.h_count[node[1]];
288 			numhnodes++;
289 		}
290 
291 		cin.numhnodes1[prev] = numhnodes-1;
292 	}
293 }
294 
295 /*
296 ==================
297 Huff1Decompress
298 ==================
299 */
Huff1Decompress(cblock_t in)300 cblock_t Huff1Decompress (cblock_t in)
301 {
302 	byte		*input;
303 	byte		*out_p;
304 	int			nodenum;
305 	int			count;
306 	cblock_t	out;
307 	int			inbyte;
308 	int			*hnodes, *hnodesbase;
309 //int		i;
310 
311 	// get decompressed count
312 	count = in.data[0] + (in.data[1]<<8) + (in.data[2]<<16) + (in.data[3]<<24);
313 	input = in.data + 4;
314 	out_p = out.data = Z_Malloc (count);
315 
316 	// read bits
317 
318 	hnodesbase = cin.hnodes1 - 256*2;	// nodes 0-255 aren't stored
319 
320 	hnodes = hnodesbase;
321 	nodenum = cin.numhnodes1[0];
322 	while (count)
323 	{
324 		inbyte = *input++;
325 		//-----------
326 		if (nodenum < 256)
327 		{
328 			hnodes = hnodesbase + (nodenum<<9);
329 			*out_p++ = nodenum;
330 			if (!--count)
331 				break;
332 			nodenum = cin.numhnodes1[nodenum];
333 		}
334 		nodenum = hnodes[nodenum*2 + (inbyte&1)];
335 		inbyte >>=1;
336 		//-----------
337 		if (nodenum < 256)
338 		{
339 			hnodes = hnodesbase + (nodenum<<9);
340 			*out_p++ = nodenum;
341 			if (!--count)
342 				break;
343 			nodenum = cin.numhnodes1[nodenum];
344 		}
345 		nodenum = hnodes[nodenum*2 + (inbyte&1)];
346 		inbyte >>=1;
347 		//-----------
348 		if (nodenum < 256)
349 		{
350 			hnodes = hnodesbase + (nodenum<<9);
351 			*out_p++ = nodenum;
352 			if (!--count)
353 				break;
354 			nodenum = cin.numhnodes1[nodenum];
355 		}
356 		nodenum = hnodes[nodenum*2 + (inbyte&1)];
357 		inbyte >>=1;
358 		//-----------
359 		if (nodenum < 256)
360 		{
361 			hnodes = hnodesbase + (nodenum<<9);
362 			*out_p++ = nodenum;
363 			if (!--count)
364 				break;
365 			nodenum = cin.numhnodes1[nodenum];
366 		}
367 		nodenum = hnodes[nodenum*2 + (inbyte&1)];
368 		inbyte >>=1;
369 		//-----------
370 		if (nodenum < 256)
371 		{
372 			hnodes = hnodesbase + (nodenum<<9);
373 			*out_p++ = nodenum;
374 			if (!--count)
375 				break;
376 			nodenum = cin.numhnodes1[nodenum];
377 		}
378 		nodenum = hnodes[nodenum*2 + (inbyte&1)];
379 		inbyte >>=1;
380 		//-----------
381 		if (nodenum < 256)
382 		{
383 			hnodes = hnodesbase + (nodenum<<9);
384 			*out_p++ = nodenum;
385 			if (!--count)
386 				break;
387 			nodenum = cin.numhnodes1[nodenum];
388 		}
389 		nodenum = hnodes[nodenum*2 + (inbyte&1)];
390 		inbyte >>=1;
391 		//-----------
392 		if (nodenum < 256)
393 		{
394 			hnodes = hnodesbase + (nodenum<<9);
395 			*out_p++ = nodenum;
396 			if (!--count)
397 				break;
398 			nodenum = cin.numhnodes1[nodenum];
399 		}
400 		nodenum = hnodes[nodenum*2 + (inbyte&1)];
401 		inbyte >>=1;
402 		//-----------
403 		if (nodenum < 256)
404 		{
405 			hnodes = hnodesbase + (nodenum<<9);
406 			*out_p++ = nodenum;
407 			if (!--count)
408 				break;
409 			nodenum = cin.numhnodes1[nodenum];
410 		}
411 		nodenum = hnodes[nodenum*2 + (inbyte&1)];
412 		inbyte >>=1;
413 	}
414 
415 	if (input - in.data != in.count && input - in.data != in.count+1)
416 	{
417 		Com_Printf ("Decompression overread by %i", (input - in.data) - in.count);
418 	}
419 	out.count = out_p - out.data;
420 
421 	return out;
422 }
423 
424 /*
425 ==================
426 SCR_ReadNextFrame
427 ==================
428 */
SCR_ReadNextFrame(void)429 byte *SCR_ReadNextFrame (void)
430 {
431 	int		r;
432 	int		command;
433 	byte	samples[22050/14*4];
434 	byte	compressed[0x20000];
435 	int		size;
436 	byte	*pic;
437 	cblock_t	in, huf1;
438 	int		start, end, count;
439 
440 	// read the next frame
441 	r = FS_Read( &command, 4, cl.cinematic_file );
442 
443 	if (r != 4)
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 */
SCR_RunCinematic(void)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_MENU|KEY_CONSOLE))
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 qtrue if a cinematic is active, meaning the view rendering
538 should be skipped
539 ==================
540 */
SCR_DrawCinematic(void)541 qboolean SCR_DrawCinematic (void)
542 {
543 	if (cl.cinematictime <= 0)
544 	{
545 		return qfalse;
546 	}
547 
548 	if (cls.key_dest & KEY_MENU)
549 	{	// blank screen and pause if menu is up
550 		ref.CinematicSetPalette(NULL);
551 		cl.cinematicpalette_active = qfalse;
552 		return qtrue;
553 	}
554 
555 	if (!cl.cinematicpalette_active)
556 	{
557 		ref.CinematicSetPalette(cl.cinematicpalette);
558 		cl.cinematicpalette_active = qtrue;
559 	}
560 
561 	if (!cin.pic)
562 		return qtrue;
563 
564 	ref.DrawStretchRaw (0, 0, scr_glconfig.vidWidth, scr_glconfig.vidHeight,
565 		cin.width, cin.height, cin.pic);
566 
567 	return qtrue;
568 }
569 
570 /*
571 ==================
572 SCR_PlayCinematic
573 
574 ==================
575 */
SCR_PlayCinematic(const char * arg)576 void SCR_PlayCinematic (const char *arg)
577 {
578 	int		width, height;
579 	byte	*palette;
580 	char	name[MAX_QPATH], *dot;
581 	int		old_khz;
582 
583 	Com_DPrintf( "SCR_PlayCinematic( %s )\n", arg );
584 
585 	// make sure CD isn't playing music
586 	CDAudio_Stop();
587 
588 	cl.cinematicframe = 0;
589 	dot = strstr (arg, ".");
590 	if (dot && !strcmp (dot, ".pcx"))
591 	{	// static pcx image
592 		Com_sprintf (name, sizeof(name), "pics/%s", arg);
593 		SCR_LoadPCX (name, &cin.pic, &palette, &cin.width, &cin.height);
594 		cl.cinematicframe = -1;
595 		cl.cinematictime = 1;
596 		SCR_EndLoadingPlaque ();
597 		cls.state = ca_cinematic;
598 		if (!cin.pic)
599 		{
600 			Com_Printf ("%s not found.\n", name);
601 			cl.cinematictime = 0;
602 		}
603 		else
604 		{
605 			memcpy (cl.cinematicpalette, palette, sizeof(cl.cinematicpalette));
606 			Z_Free (palette);
607 		}
608 
609 		Con_Close();
610 		return;
611 	}
612 
613 	Com_sprintf (name, sizeof(name), "video/%s", arg);
614 	FS_FOpenFile (name, &cl.cinematic_file, FS_MODE_READ);
615 	if (!cl.cinematic_file)
616 	{
617 //		Com_Error (ERR_DROP, "Cinematic %s not found.\n", name);
618 		SCR_FinishCinematic ();
619 		cl.cinematictime = 0;	// done
620 		return;
621 	}
622 
623 	SCR_EndLoadingPlaque ();
624 
625 	cls.state = ca_cinematic;
626 
627 	FS_Read (&width, 4, cl.cinematic_file);
628 	FS_Read (&height, 4, cl.cinematic_file);
629 	cin.width = LittleLong(width);
630 	cin.height = LittleLong(height);
631 
632 	FS_Read (&cin.s_rate, 4, cl.cinematic_file);
633 	cin.s_rate = LittleLong(cin.s_rate);
634 	FS_Read (&cin.s_width, 4, cl.cinematic_file);
635 	cin.s_width = LittleLong(cin.s_width);
636 	FS_Read (&cin.s_channels, 4, cl.cinematic_file);
637 	cin.s_channels = LittleLong(cin.s_channels);
638 
639 	Huff1TableInit ();
640 
641 	// switch up to 22 khz sound if necessary
642 	old_khz = Cvar_VariableValue ("s_khz");
643 	if (old_khz != cin.s_rate/1000)
644 	{
645 		cin.restart_sound = qtrue;
646 		Cvar_SetValue ("s_khz", cin.s_rate/1000);
647 		CL_Snd_Restart_f ();
648 		Cvar_SetValue ("s_khz", old_khz);
649 	}
650 
651 	cl.cinematicframe = 0;
652 	cin.pic = SCR_ReadNextFrame ();
653 	cl.cinematictime = Sys_Milliseconds ();
654 
655 	Con_Close();
656 }
657