|
|
1.1.1.3 ! root 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: */ 1.1 root 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); 1.1.1.2 root 457: size = LittleLong(size); 1.1 root 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 (); 1.1.1.2 root 595: cls.state = ca_active; 1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.