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