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