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