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 }