cl_cin.c 13 KB

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