cl_cin.c 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. /*****************************************************************************
  19. * name: cl_cin.c
  20. *
  21. * desc: video and cinematic playback
  22. *
  23. * $Archive: /MissionPack/code/client/cl_cin.c $
  24. *
  25. * cl_glconfig.hwtype trtypes 3dfx/ragepro need 256x256
  26. *
  27. *****************************************************************************/
  28. #include "client.h"
  29. #include "snd_local.h"
  30. #define MAXSIZE 8
  31. #define MINSIZE 4
  32. #define DEFAULT_CIN_WIDTH 512
  33. #define DEFAULT_CIN_HEIGHT 512
  34. #define ROQ_QUAD 0x1000
  35. #define ROQ_QUAD_INFO 0x1001
  36. #define ROQ_CODEBOOK 0x1002
  37. #define ROQ_QUAD_VQ 0x1011
  38. #define ROQ_QUAD_JPEG 0x1012
  39. #define ROQ_QUAD_HANG 0x1013
  40. #define ROQ_PACKET 0x1030
  41. #define ZA_SOUND_MONO 0x1020
  42. #define ZA_SOUND_STEREO 0x1021
  43. #define MAX_VIDEO_HANDLES 16
  44. extern glconfig_t glConfig;
  45. extern int s_paintedtime;
  46. extern int s_rawend;
  47. static void RoQ_init( void );
  48. /******************************************************************************
  49. *
  50. * Class: trFMV
  51. *
  52. * Description: RoQ/RnR manipulation routines
  53. * not entirely complete for first run
  54. *
  55. ******************************************************************************/
  56. static long ROQ_YY_tab[256];
  57. static long ROQ_UB_tab[256];
  58. static long ROQ_UG_tab[256];
  59. static long ROQ_VG_tab[256];
  60. static long ROQ_VR_tab[256];
  61. static unsigned short vq2[256*16*4];
  62. static unsigned short vq4[256*64*4];
  63. static unsigned short vq8[256*256*4];
  64. typedef struct {
  65. byte linbuf[DEFAULT_CIN_WIDTH*DEFAULT_CIN_HEIGHT*4*2];
  66. byte file[65536];
  67. short sqrTable[256];
  68. unsigned int mcomp[256];
  69. byte *qStatus[2][32768];
  70. long oldXOff, oldYOff, oldysize, oldxsize;
  71. int currentHandle;
  72. } cinematics_t;
  73. typedef struct {
  74. char fileName[MAX_OSPATH];
  75. int CIN_WIDTH, CIN_HEIGHT;
  76. int xpos, ypos, width, height;
  77. qboolean looping, holdAtEnd, dirty, alterGameState, silent, shader;
  78. fileHandle_t iFile;
  79. e_status status;
  80. unsigned int startTime;
  81. unsigned int lastTime;
  82. long tfps;
  83. long RoQPlayed;
  84. long ROQSize;
  85. unsigned int RoQFrameSize;
  86. long onQuad;
  87. long numQuads;
  88. long samplesPerLine;
  89. unsigned int roq_id;
  90. long screenDelta;
  91. void ( *VQ0)(byte *status, void *qdata );
  92. void ( *VQ1)(byte *status, void *qdata );
  93. void ( *VQNormal)(byte *status, void *qdata );
  94. void ( *VQBuffer)(byte *status, void *qdata );
  95. long samplesPerPixel; // defaults to 2
  96. byte* gray;
  97. unsigned int xsize, ysize, maxsize, minsize;
  98. qboolean half, smootheddouble, inMemory;
  99. long normalBuffer0;
  100. long roq_flags;
  101. long roqF0;
  102. long roqF1;
  103. long t[2];
  104. long roqFPS;
  105. int playonwalls;
  106. byte* buf;
  107. long drawX, drawY;
  108. } cin_cache;
  109. static cinematics_t cin;
  110. static cin_cache cinTable[MAX_VIDEO_HANDLES];
  111. static int currentHandle = -1;
  112. static int CL_handle = -1;
  113. extern int s_soundtime; // sample PAIRS
  114. extern int s_paintedtime; // sample PAIRS
  115. void CIN_CloseAllVideos(void) {
  116. int i;
  117. for ( i = 0 ; i < MAX_VIDEO_HANDLES ; i++ ) {
  118. if (cinTable[i].fileName[0] != 0 ) {
  119. CIN_StopCinematic(i);
  120. }
  121. }
  122. }
  123. static int CIN_HandleForVideo(void) {
  124. int i;
  125. for ( i = 0 ; i < MAX_VIDEO_HANDLES ; i++ ) {
  126. if ( cinTable[i].fileName[0] == 0 ) {
  127. return i;
  128. }
  129. }
  130. Com_Error( ERR_DROP, "CIN_HandleForVideo: none free" );
  131. return -1;
  132. }
  133. extern int CL_ScaledMilliseconds(void);
  134. //-----------------------------------------------------------------------------
  135. // RllSetupTable
  136. //
  137. // Allocates and initializes the square table.
  138. //
  139. // Parameters: None
  140. //
  141. // Returns: Nothing
  142. //-----------------------------------------------------------------------------
  143. static void RllSetupTable()
  144. {
  145. int z;
  146. for (z=0;z<128;z++) {
  147. cin.sqrTable[z] = (short)(z*z);
  148. cin.sqrTable[z+128] = (short)(-cin.sqrTable[z]);
  149. }
  150. }
  151. //-----------------------------------------------------------------------------
  152. // RllDecodeMonoToMono
  153. //
  154. // Decode mono source data into a mono buffer.
  155. //
  156. // Parameters: from -> buffer holding encoded data
  157. // to -> buffer to hold decoded data
  158. // size = number of bytes of input (= # of shorts of output)
  159. // signedOutput = 0 for unsigned output, non-zero for signed output
  160. // flag = flags from asset header
  161. //
  162. // Returns: Number of samples placed in output buffer
  163. //-----------------------------------------------------------------------------
  164. long RllDecodeMonoToMono(unsigned char *from,short *to,unsigned int size,char signedOutput ,unsigned short flag)
  165. {
  166. unsigned int z;
  167. int prev;
  168. if (signedOutput)
  169. prev = flag - 0x8000;
  170. else
  171. prev = flag;
  172. for (z=0;z<size;z++) {
  173. prev = to[z] = (short)(prev + cin.sqrTable[from[z]]);
  174. }
  175. return size; //*sizeof(short));
  176. }
  177. //-----------------------------------------------------------------------------
  178. // RllDecodeMonoToStereo
  179. //
  180. // Decode mono source data into a stereo buffer. Output is 4 times the number
  181. // of bytes in the input.
  182. //
  183. // Parameters: from -> buffer holding encoded data
  184. // to -> buffer to hold decoded data
  185. // size = number of bytes of input (= 1/4 # of bytes of output)
  186. // signedOutput = 0 for unsigned output, non-zero for signed output
  187. // flag = flags from asset header
  188. //
  189. // Returns: Number of samples placed in output buffer
  190. //-----------------------------------------------------------------------------
  191. long RllDecodeMonoToStereo(unsigned char *from,short *to,unsigned int size,char signedOutput,unsigned short flag)
  192. {
  193. unsigned int z;
  194. int prev;
  195. if (signedOutput)
  196. prev = flag - 0x8000;
  197. else
  198. prev = flag;
  199. for (z = 0; z < size; z++) {
  200. prev = (short)(prev + cin.sqrTable[from[z]]);
  201. to[z*2+0] = to[z*2+1] = (short)(prev);
  202. }
  203. return size; // * 2 * sizeof(short));
  204. }
  205. //-----------------------------------------------------------------------------
  206. // RllDecodeStereoToStereo
  207. //
  208. // Decode stereo source data into a stereo buffer.
  209. //
  210. // Parameters: from -> buffer holding encoded data
  211. // to -> buffer to hold decoded data
  212. // size = number of bytes of input (= 1/2 # of bytes of output)
  213. // signedOutput = 0 for unsigned output, non-zero for signed output
  214. // flag = flags from asset header
  215. //
  216. // Returns: Number of samples placed in output buffer
  217. //-----------------------------------------------------------------------------
  218. long RllDecodeStereoToStereo(unsigned char *from,short *to,unsigned int size,char signedOutput, unsigned short flag)
  219. {
  220. unsigned int z;
  221. unsigned char *zz = from;
  222. int prevL, prevR;
  223. if (signedOutput) {
  224. prevL = (flag & 0xff00) - 0x8000;
  225. prevR = ((flag & 0x00ff) << 8) - 0x8000;
  226. } else {
  227. prevL = flag & 0xff00;
  228. prevR = (flag & 0x00ff) << 8;
  229. }
  230. for (z=0;z<size;z+=2) {
  231. prevL = (short)(prevL + cin.sqrTable[*zz++]);
  232. prevR = (short)(prevR + cin.sqrTable[*zz++]);
  233. to[z+0] = (short)(prevL);
  234. to[z+1] = (short)(prevR);
  235. }
  236. return (size>>1); //*sizeof(short));
  237. }
  238. //-----------------------------------------------------------------------------
  239. // RllDecodeStereoToMono
  240. //
  241. // Decode stereo source data into a mono buffer.
  242. //
  243. // Parameters: from -> buffer holding encoded data
  244. // to -> buffer to hold decoded data
  245. // size = number of bytes of input (= # of bytes of output)
  246. // signedOutput = 0 for unsigned output, non-zero for signed output
  247. // flag = flags from asset header
  248. //
  249. // Returns: Number of samples placed in output buffer
  250. //-----------------------------------------------------------------------------
  251. long RllDecodeStereoToMono(unsigned char *from,short *to,unsigned int size,char signedOutput, unsigned short flag)
  252. {
  253. unsigned int z;
  254. int prevL,prevR;
  255. if (signedOutput) {
  256. prevL = (flag & 0xff00) - 0x8000;
  257. prevR = ((flag & 0x00ff) << 8) -0x8000;
  258. } else {
  259. prevL = flag & 0xff00;
  260. prevR = (flag & 0x00ff) << 8;
  261. }
  262. for (z=0;z<size;z+=1) {
  263. prevL= prevL + cin.sqrTable[from[z*2]];
  264. prevR = prevR + cin.sqrTable[from[z*2+1]];
  265. to[z] = (short)((prevL + prevR)/2);
  266. }
  267. return size;
  268. }
  269. /******************************************************************************
  270. *
  271. * Function:
  272. *
  273. * Description:
  274. *
  275. ******************************************************************************/
  276. static void move8_32( byte *src, byte *dst, int spl )
  277. {
  278. double *dsrc, *ddst;
  279. int dspl;
  280. dsrc = (double *)src;
  281. ddst = (double *)dst;
  282. dspl = spl>>3;
  283. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  284. dsrc += dspl; ddst += dspl;
  285. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  286. dsrc += dspl; ddst += dspl;
  287. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  288. dsrc += dspl; ddst += dspl;
  289. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  290. dsrc += dspl; ddst += dspl;
  291. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  292. dsrc += dspl; ddst += dspl;
  293. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  294. dsrc += dspl; ddst += dspl;
  295. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  296. dsrc += dspl; ddst += dspl;
  297. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  298. }
  299. /******************************************************************************
  300. *
  301. * Function:
  302. *
  303. * Description:
  304. *
  305. ******************************************************************************/
  306. static void move4_32( byte *src, byte *dst, int spl )
  307. {
  308. double *dsrc, *ddst;
  309. int dspl;
  310. dsrc = (double *)src;
  311. ddst = (double *)dst;
  312. dspl = spl>>3;
  313. ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
  314. dsrc += dspl; ddst += dspl;
  315. ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
  316. dsrc += dspl; ddst += dspl;
  317. ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
  318. dsrc += dspl; ddst += dspl;
  319. ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
  320. }
  321. /******************************************************************************
  322. *
  323. * Function:
  324. *
  325. * Description:
  326. *
  327. ******************************************************************************/
  328. static void blit8_32( byte *src, byte *dst, int spl )
  329. {
  330. double *dsrc, *ddst;
  331. int dspl;
  332. dsrc = (double *)src;
  333. ddst = (double *)dst;
  334. dspl = spl>>3;
  335. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  336. dsrc += 4; ddst += dspl;
  337. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  338. dsrc += 4; ddst += dspl;
  339. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  340. dsrc += 4; ddst += dspl;
  341. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  342. dsrc += 4; ddst += dspl;
  343. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  344. dsrc += 4; ddst += dspl;
  345. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  346. dsrc += 4; ddst += dspl;
  347. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  348. dsrc += 4; ddst += dspl;
  349. ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
  350. }
  351. /******************************************************************************
  352. *
  353. * Function:
  354. *
  355. * Description:
  356. *
  357. ******************************************************************************/
  358. #define movs double
  359. static void blit4_32( byte *src, byte *dst, int spl )
  360. {
  361. movs *dsrc, *ddst;
  362. int dspl;
  363. dsrc = (movs *)src;
  364. ddst = (movs *)dst;
  365. dspl = spl>>3;
  366. ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
  367. dsrc += 2; ddst += dspl;
  368. ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
  369. dsrc += 2; ddst += dspl;
  370. ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
  371. dsrc += 2; ddst += dspl;
  372. ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
  373. }
  374. /******************************************************************************
  375. *
  376. * Function:
  377. *
  378. * Description:
  379. *
  380. ******************************************************************************/
  381. static void blit2_32( byte *src, byte *dst, int spl )
  382. {
  383. double *dsrc, *ddst;
  384. int dspl;
  385. dsrc = (double *)src;
  386. ddst = (double *)dst;
  387. dspl = spl>>3;
  388. ddst[0] = dsrc[0];
  389. ddst[dspl] = dsrc[1];
  390. }
  391. /******************************************************************************
  392. *
  393. * Function:
  394. *
  395. * Description:
  396. *
  397. ******************************************************************************/
  398. static void blitVQQuad32fs( byte **status, unsigned char *data )
  399. {
  400. unsigned short newd, celdata, code;
  401. unsigned int index, i;
  402. int spl;
  403. newd = 0;
  404. celdata = 0;
  405. index = 0;
  406. spl = cinTable[currentHandle].samplesPerLine;
  407. do {
  408. if (!newd) {
  409. newd = 7;
  410. celdata = data[0] + data[1]*256;
  411. data += 2;
  412. } else {
  413. newd--;
  414. }
  415. code = (unsigned short)(celdata&0xc000);
  416. celdata <<= 2;
  417. switch (code) {
  418. case 0x8000: // vq code
  419. blit8_32( (byte *)&vq8[(*data)*128], status[index], spl );
  420. data++;
  421. index += 5;
  422. break;
  423. case 0xc000: // drop
  424. index++; // skip 8x8
  425. for(i=0;i<4;i++) {
  426. if (!newd) {
  427. newd = 7;
  428. celdata = data[0] + data[1]*256;
  429. data += 2;
  430. } else {
  431. newd--;
  432. }
  433. code = (unsigned short)(celdata&0xc000); celdata <<= 2;
  434. switch (code) { // code in top two bits of code
  435. case 0x8000: // 4x4 vq code
  436. blit4_32( (byte *)&vq4[(*data)*32], status[index], spl );
  437. data++;
  438. break;
  439. case 0xc000: // 2x2 vq code
  440. blit2_32( (byte *)&vq2[(*data)*8], status[index], spl );
  441. data++;
  442. blit2_32( (byte *)&vq2[(*data)*8], status[index]+8, spl );
  443. data++;
  444. blit2_32( (byte *)&vq2[(*data)*8], status[index]+spl*2, spl );
  445. data++;
  446. blit2_32( (byte *)&vq2[(*data)*8], status[index]+spl*2+8, spl );
  447. data++;
  448. break;
  449. case 0x4000: // motion compensation
  450. move4_32( status[index] + cin.mcomp[(*data)], status[index], spl );
  451. data++;
  452. break;
  453. }
  454. index++;
  455. }
  456. break;
  457. case 0x4000: // motion compensation
  458. move8_32( status[index] + cin.mcomp[(*data)], status[index], spl );
  459. data++;
  460. index += 5;
  461. break;
  462. case 0x0000:
  463. index += 5;
  464. break;
  465. }
  466. } while ( status[index] != NULL );
  467. }
  468. /******************************************************************************
  469. *
  470. * Function:
  471. *
  472. * Description:
  473. *
  474. ******************************************************************************/
  475. static void ROQ_GenYUVTables( void )
  476. {
  477. float t_ub,t_vr,t_ug,t_vg;
  478. long i;
  479. t_ub = (1.77200f/2.0f) * (float)(1<<6) + 0.5f;
  480. t_vr = (1.40200f/2.0f) * (float)(1<<6) + 0.5f;
  481. t_ug = (0.34414f/2.0f) * (float)(1<<6) + 0.5f;
  482. t_vg = (0.71414f/2.0f) * (float)(1<<6) + 0.5f;
  483. for(i=0;i<256;i++) {
  484. float x = (float)(2 * i - 255);
  485. ROQ_UB_tab[i] = (long)( ( t_ub * x) + (1<<5));
  486. ROQ_VR_tab[i] = (long)( ( t_vr * x) + (1<<5));
  487. ROQ_UG_tab[i] = (long)( (-t_ug * x) );
  488. ROQ_VG_tab[i] = (long)( (-t_vg * x) + (1<<5));
  489. ROQ_YY_tab[i] = (long)( (i << 6) | (i >> 2) );
  490. }
  491. }
  492. #define VQ2TO4(a,b,c,d) { \
  493. *c++ = a[0]; \
  494. *d++ = a[0]; \
  495. *d++ = a[0]; \
  496. *c++ = a[1]; \
  497. *d++ = a[1]; \
  498. *d++ = a[1]; \
  499. *c++ = b[0]; \
  500. *d++ = b[0]; \
  501. *d++ = b[0]; \
  502. *c++ = b[1]; \
  503. *d++ = b[1]; \
  504. *d++ = b[1]; \
  505. *d++ = a[0]; \
  506. *d++ = a[0]; \
  507. *d++ = a[1]; \
  508. *d++ = a[1]; \
  509. *d++ = b[0]; \
  510. *d++ = b[0]; \
  511. *d++ = b[1]; \
  512. *d++ = b[1]; \
  513. a += 2; b += 2; }
  514. #define VQ2TO2(a,b,c,d) { \
  515. *c++ = *a; \
  516. *d++ = *a; \
  517. *d++ = *a; \
  518. *c++ = *b; \
  519. *d++ = *b; \
  520. *d++ = *b; \
  521. *d++ = *a; \
  522. *d++ = *a; \
  523. *d++ = *b; \
  524. *d++ = *b; \
  525. a++; b++; }
  526. /******************************************************************************
  527. *
  528. * Function:
  529. *
  530. * Description:
  531. *
  532. ******************************************************************************/
  533. static unsigned short yuv_to_rgb( long y, long u, long v )
  534. {
  535. long r,g,b,YY = (long)(ROQ_YY_tab[(y)]);
  536. r = (YY + ROQ_VR_tab[v]) >> 9;
  537. g = (YY + ROQ_UG_tab[u] + ROQ_VG_tab[v]) >> 8;
  538. b = (YY + ROQ_UB_tab[u]) >> 9;
  539. if (r<0) r = 0; if (g<0) g = 0; if (b<0) b = 0;
  540. if (r > 31) r = 31; if (g > 63) g = 63; if (b > 31) b = 31;
  541. return (unsigned short)((r<<11)+(g<<5)+(b));
  542. }
  543. /******************************************************************************
  544. *
  545. * Function:
  546. *
  547. * Description:
  548. *
  549. ******************************************************************************/
  550. #if defined(MACOS_X)
  551. static inline unsigned int yuv_to_rgb24( long y, long u, long v )
  552. {
  553. long r,g,b,YY;
  554. YY = (long)(ROQ_YY_tab[(y)]);
  555. r = (YY + ROQ_VR_tab[v]) >> 6;
  556. g = (YY + ROQ_UG_tab[u] + ROQ_VG_tab[v]) >> 6;
  557. b = (YY + ROQ_UB_tab[u]) >> 6;
  558. if (r<0) r = 0; if (g<0) g = 0; if (b<0) b = 0;
  559. if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
  560. return ((r<<24)|(g<<16)|(b<<8))|(255); //+(255<<24));
  561. }
  562. #else
  563. static unsigned int yuv_to_rgb24( long y, long u, long v )
  564. {
  565. long r,g,b,YY = (long)(ROQ_YY_tab[(y)]);
  566. r = (YY + ROQ_VR_tab[v]) >> 6;
  567. g = (YY + ROQ_UG_tab[u] + ROQ_VG_tab[v]) >> 6;
  568. b = (YY + ROQ_UB_tab[u]) >> 6;
  569. if (r<0) r = 0; if (g<0) g = 0; if (b<0) b = 0;
  570. if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
  571. return LittleLong ((r)|(g<<8)|(b<<16)|(255<<24));
  572. }
  573. #endif
  574. /******************************************************************************
  575. *
  576. * Function:
  577. *
  578. * Description:
  579. *
  580. ******************************************************************************/
  581. static void decodeCodeBook( byte *input, unsigned short roq_flags )
  582. {
  583. long i, j, two, four;
  584. unsigned short *aptr, *bptr, *cptr, *dptr;
  585. long y0,y1,y2,y3,cr,cb;
  586. byte *bbptr, *baptr, *bcptr, *bdptr;
  587. unsigned int *iaptr, *ibptr, *icptr, *idptr;
  588. if (!roq_flags) {
  589. two = four = 256;
  590. } else {
  591. two = roq_flags>>8;
  592. if (!two) two = 256;
  593. four = roq_flags&0xff;
  594. }
  595. four *= 2;
  596. bptr = (unsigned short *)vq2;
  597. if (!cinTable[currentHandle].half) {
  598. if (!cinTable[currentHandle].smootheddouble) {
  599. //
  600. // normal height
  601. //
  602. if (cinTable[currentHandle].samplesPerPixel==2) {
  603. for(i=0;i<two;i++) {
  604. y0 = (long)*input++;
  605. y1 = (long)*input++;
  606. y2 = (long)*input++;
  607. y3 = (long)*input++;
  608. cr = (long)*input++;
  609. cb = (long)*input++;
  610. *bptr++ = yuv_to_rgb( y0, cr, cb );
  611. *bptr++ = yuv_to_rgb( y1, cr, cb );
  612. *bptr++ = yuv_to_rgb( y2, cr, cb );
  613. *bptr++ = yuv_to_rgb( y3, cr, cb );
  614. }
  615. cptr = (unsigned short *)vq4;
  616. dptr = (unsigned short *)vq8;
  617. for(i=0;i<four;i++) {
  618. aptr = (unsigned short *)vq2 + (*input++)*4;
  619. bptr = (unsigned short *)vq2 + (*input++)*4;
  620. for(j=0;j<2;j++)
  621. VQ2TO4(aptr,bptr,cptr,dptr);
  622. }
  623. } else if (cinTable[currentHandle].samplesPerPixel==4) {
  624. ibptr = (unsigned int *)bptr;
  625. for(i=0;i<two;i++) {
  626. y0 = (long)*input++;
  627. y1 = (long)*input++;
  628. y2 = (long)*input++;
  629. y3 = (long)*input++;
  630. cr = (long)*input++;
  631. cb = (long)*input++;
  632. *ibptr++ = yuv_to_rgb24( y0, cr, cb );
  633. *ibptr++ = yuv_to_rgb24( y1, cr, cb );
  634. *ibptr++ = yuv_to_rgb24( y2, cr, cb );
  635. *ibptr++ = yuv_to_rgb24( y3, cr, cb );
  636. }
  637. icptr = (unsigned int *)vq4;
  638. idptr = (unsigned int *)vq8;
  639. for(i=0;i<four;i++) {
  640. iaptr = (unsigned int *)vq2 + (*input++)*4;
  641. ibptr = (unsigned int *)vq2 + (*input++)*4;
  642. for(j=0;j<2;j++)
  643. VQ2TO4(iaptr, ibptr, icptr, idptr);
  644. }
  645. } else if (cinTable[currentHandle].samplesPerPixel==1) {
  646. bbptr = (byte *)bptr;
  647. for(i=0;i<two;i++) {
  648. *bbptr++ = cinTable[currentHandle].gray[*input++];
  649. *bbptr++ = cinTable[currentHandle].gray[*input++];
  650. *bbptr++ = cinTable[currentHandle].gray[*input++];
  651. *bbptr++ = cinTable[currentHandle].gray[*input]; input +=3;
  652. }
  653. bcptr = (byte *)vq4;
  654. bdptr = (byte *)vq8;
  655. for(i=0;i<four;i++) {
  656. baptr = (byte *)vq2 + (*input++)*4;
  657. bbptr = (byte *)vq2 + (*input++)*4;
  658. for(j=0;j<2;j++)
  659. VQ2TO4(baptr,bbptr,bcptr,bdptr);
  660. }
  661. }
  662. } else {
  663. //
  664. // double height, smoothed
  665. //
  666. if (cinTable[currentHandle].samplesPerPixel==2) {
  667. for(i=0;i<two;i++) {
  668. y0 = (long)*input++;
  669. y1 = (long)*input++;
  670. y2 = (long)*input++;
  671. y3 = (long)*input++;
  672. cr = (long)*input++;
  673. cb = (long)*input++;
  674. *bptr++ = yuv_to_rgb( y0, cr, cb );
  675. *bptr++ = yuv_to_rgb( y1, cr, cb );
  676. *bptr++ = yuv_to_rgb( ((y0*3)+y2)/4, cr, cb );
  677. *bptr++ = yuv_to_rgb( ((y1*3)+y3)/4, cr, cb );
  678. *bptr++ = yuv_to_rgb( (y0+(y2*3))/4, cr, cb );
  679. *bptr++ = yuv_to_rgb( (y1+(y3*3))/4, cr, cb );
  680. *bptr++ = yuv_to_rgb( y2, cr, cb );
  681. *bptr++ = yuv_to_rgb( y3, cr, cb );
  682. }
  683. cptr = (unsigned short *)vq4;
  684. dptr = (unsigned short *)vq8;
  685. for(i=0;i<four;i++) {
  686. aptr = (unsigned short *)vq2 + (*input++)*8;
  687. bptr = (unsigned short *)vq2 + (*input++)*8;
  688. for(j=0;j<2;j++) {
  689. VQ2TO4(aptr,bptr,cptr,dptr);
  690. VQ2TO4(aptr,bptr,cptr,dptr);
  691. }
  692. }
  693. } else if (cinTable[currentHandle].samplesPerPixel==4) {
  694. ibptr = (unsigned int *)bptr;
  695. for(i=0;i<two;i++) {
  696. y0 = (long)*input++;
  697. y1 = (long)*input++;
  698. y2 = (long)*input++;
  699. y3 = (long)*input++;
  700. cr = (long)*input++;
  701. cb = (long)*input++;
  702. *ibptr++ = yuv_to_rgb24( y0, cr, cb );
  703. *ibptr++ = yuv_to_rgb24( y1, cr, cb );
  704. *ibptr++ = yuv_to_rgb24( ((y0*3)+y2)/4, cr, cb );
  705. *ibptr++ = yuv_to_rgb24( ((y1*3)+y3)/4, cr, cb );
  706. *ibptr++ = yuv_to_rgb24( (y0+(y2*3))/4, cr, cb );
  707. *ibptr++ = yuv_to_rgb24( (y1+(y3*3))/4, cr, cb );
  708. *ibptr++ = yuv_to_rgb24( y2, cr, cb );
  709. *ibptr++ = yuv_to_rgb24( y3, cr, cb );
  710. }
  711. icptr = (unsigned int *)vq4;
  712. idptr = (unsigned int *)vq8;
  713. for(i=0;i<four;i++) {
  714. iaptr = (unsigned int *)vq2 + (*input++)*8;
  715. ibptr = (unsigned int *)vq2 + (*input++)*8;
  716. for(j=0;j<2;j++) {
  717. VQ2TO4(iaptr, ibptr, icptr, idptr);
  718. VQ2TO4(iaptr, ibptr, icptr, idptr);
  719. }
  720. }
  721. } else if (cinTable[currentHandle].samplesPerPixel==1) {
  722. bbptr = (byte *)bptr;
  723. for(i=0;i<two;i++) {
  724. y0 = (long)*input++;
  725. y1 = (long)*input++;
  726. y2 = (long)*input++;
  727. y3 = (long)*input; input+= 3;
  728. *bbptr++ = cinTable[currentHandle].gray[y0];
  729. *bbptr++ = cinTable[currentHandle].gray[y1];
  730. *bbptr++ = cinTable[currentHandle].gray[((y0*3)+y2)/4];
  731. *bbptr++ = cinTable[currentHandle].gray[((y1*3)+y3)/4];
  732. *bbptr++ = cinTable[currentHandle].gray[(y0+(y2*3))/4];
  733. *bbptr++ = cinTable[currentHandle].gray[(y1+(y3*3))/4];
  734. *bbptr++ = cinTable[currentHandle].gray[y2];
  735. *bbptr++ = cinTable[currentHandle].gray[y3];
  736. }
  737. bcptr = (byte *)vq4;
  738. bdptr = (byte *)vq8;
  739. for(i=0;i<four;i++) {
  740. baptr = (byte *)vq2 + (*input++)*8;
  741. bbptr = (byte *)vq2 + (*input++)*8;
  742. for(j=0;j<2;j++) {
  743. VQ2TO4(baptr,bbptr,bcptr,bdptr);
  744. VQ2TO4(baptr,bbptr,bcptr,bdptr);
  745. }
  746. }
  747. }
  748. }
  749. } else {
  750. //
  751. // 1/4 screen
  752. //
  753. if (cinTable[currentHandle].samplesPerPixel==2) {
  754. for(i=0;i<two;i++) {
  755. y0 = (long)*input; input+=2;
  756. y2 = (long)*input; input+=2;
  757. cr = (long)*input++;
  758. cb = (long)*input++;
  759. *bptr++ = yuv_to_rgb( y0, cr, cb );
  760. *bptr++ = yuv_to_rgb( y2, cr, cb );
  761. }
  762. cptr = (unsigned short *)vq4;
  763. dptr = (unsigned short *)vq8;
  764. for(i=0;i<four;i++) {
  765. aptr = (unsigned short *)vq2 + (*input++)*2;
  766. bptr = (unsigned short *)vq2 + (*input++)*2;
  767. for(j=0;j<2;j++) {
  768. VQ2TO2(aptr,bptr,cptr,dptr);
  769. }
  770. }
  771. } else if (cinTable[currentHandle].samplesPerPixel == 1) {
  772. bbptr = (byte *)bptr;
  773. for(i=0;i<two;i++) {
  774. *bbptr++ = cinTable[currentHandle].gray[*input]; input+=2;
  775. *bbptr++ = cinTable[currentHandle].gray[*input]; input+=4;
  776. }
  777. bcptr = (byte *)vq4;
  778. bdptr = (byte *)vq8;
  779. for(i=0;i<four;i++) {
  780. baptr = (byte *)vq2 + (*input++)*2;
  781. bbptr = (byte *)vq2 + (*input++)*2;
  782. for(j=0;j<2;j++) {
  783. VQ2TO2(baptr,bbptr,bcptr,bdptr);
  784. }
  785. }
  786. } else if (cinTable[currentHandle].samplesPerPixel == 4) {
  787. ibptr = (unsigned int *) bptr;
  788. for(i=0;i<two;i++) {
  789. y0 = (long)*input; input+=2;
  790. y2 = (long)*input; input+=2;
  791. cr = (long)*input++;
  792. cb = (long)*input++;
  793. *ibptr++ = yuv_to_rgb24( y0, cr, cb );
  794. *ibptr++ = yuv_to_rgb24( y2, cr, cb );
  795. }
  796. icptr = (unsigned int *)vq4;
  797. idptr = (unsigned int *)vq8;
  798. for(i=0;i<four;i++) {
  799. iaptr = (unsigned int *)vq2 + (*input++)*2;
  800. ibptr = (unsigned int *)vq2 + (*input++)*2;
  801. for(j=0;j<2;j++) {
  802. VQ2TO2(iaptr,ibptr,icptr,idptr);
  803. }
  804. }
  805. }
  806. }
  807. }
  808. /******************************************************************************
  809. *
  810. * Function:
  811. *
  812. * Description:
  813. *
  814. ******************************************************************************/
  815. static void recurseQuad( long startX, long startY, long quadSize, long xOff, long yOff )
  816. {
  817. byte *scroff;
  818. long bigx, bigy, lowx, lowy, useY;
  819. long offset;
  820. offset = cinTable[currentHandle].screenDelta;
  821. lowx = lowy = 0;
  822. bigx = cinTable[currentHandle].xsize;
  823. bigy = cinTable[currentHandle].ysize;
  824. if (bigx > cinTable[currentHandle].CIN_WIDTH) bigx = cinTable[currentHandle].CIN_WIDTH;
  825. if (bigy > cinTable[currentHandle].CIN_HEIGHT) bigy = cinTable[currentHandle].CIN_HEIGHT;
  826. if ( (startX >= lowx) && (startX+quadSize) <= (bigx) && (startY+quadSize) <= (bigy) && (startY >= lowy) && quadSize <= MAXSIZE) {
  827. useY = startY;
  828. scroff = cin.linbuf + (useY+((cinTable[currentHandle].CIN_HEIGHT-bigy)>>1)+yOff)*(cinTable[currentHandle].samplesPerLine) + (((startX+xOff))*cinTable[currentHandle].samplesPerPixel);
  829. cin.qStatus[0][cinTable[currentHandle].onQuad ] = scroff;
  830. cin.qStatus[1][cinTable[currentHandle].onQuad++] = scroff+offset;
  831. }
  832. if ( quadSize != MINSIZE ) {
  833. quadSize >>= 1;
  834. recurseQuad( startX, startY , quadSize, xOff, yOff );
  835. recurseQuad( startX+quadSize, startY , quadSize, xOff, yOff );
  836. recurseQuad( startX, startY+quadSize , quadSize, xOff, yOff );
  837. recurseQuad( startX+quadSize, startY+quadSize , quadSize, xOff, yOff );
  838. }
  839. }
  840. /******************************************************************************
  841. *
  842. * Function:
  843. *
  844. * Description:
  845. *
  846. ******************************************************************************/
  847. static void setupQuad( long xOff, long yOff )
  848. {
  849. long numQuadCels, i,x,y;
  850. byte *temp;
  851. if (xOff == cin.oldXOff && yOff == cin.oldYOff && cinTable[currentHandle].ysize == cin.oldysize && cinTable[currentHandle].xsize == cin.oldxsize) {
  852. return;
  853. }
  854. cin.oldXOff = xOff;
  855. cin.oldYOff = yOff;
  856. cin.oldysize = cinTable[currentHandle].ysize;
  857. cin.oldxsize = cinTable[currentHandle].xsize;
  858. numQuadCels = (cinTable[currentHandle].CIN_WIDTH*cinTable[currentHandle].CIN_HEIGHT) / (16);
  859. numQuadCels += numQuadCels/4 + numQuadCels/16;
  860. numQuadCels += 64; // for overflow
  861. numQuadCels = (cinTable[currentHandle].xsize*cinTable[currentHandle].ysize) / (16);
  862. numQuadCels += numQuadCels/4;
  863. numQuadCels += 64; // for overflow
  864. cinTable[currentHandle].onQuad = 0;
  865. for(y=0;y<(long)cinTable[currentHandle].ysize;y+=16)
  866. for(x=0;x<(long)cinTable[currentHandle].xsize;x+=16)
  867. recurseQuad( x, y, 16, xOff, yOff );
  868. temp = NULL;
  869. for(i=(numQuadCels-64);i<numQuadCels;i++) {
  870. cin.qStatus[0][i] = temp; // eoq
  871. cin.qStatus[1][i] = temp; // eoq
  872. }
  873. }
  874. /******************************************************************************
  875. *
  876. * Function:
  877. *
  878. * Description:
  879. *
  880. ******************************************************************************/
  881. static void readQuadInfo( byte *qData )
  882. {
  883. if (currentHandle < 0) return;
  884. cinTable[currentHandle].xsize = qData[0]+qData[1]*256;
  885. cinTable[currentHandle].ysize = qData[2]+qData[3]*256;
  886. cinTable[currentHandle].maxsize = qData[4]+qData[5]*256;
  887. cinTable[currentHandle].minsize = qData[6]+qData[7]*256;
  888. cinTable[currentHandle].CIN_HEIGHT = cinTable[currentHandle].ysize;
  889. cinTable[currentHandle].CIN_WIDTH = cinTable[currentHandle].xsize;
  890. cinTable[currentHandle].samplesPerLine = cinTable[currentHandle].CIN_WIDTH*cinTable[currentHandle].samplesPerPixel;
  891. cinTable[currentHandle].screenDelta = cinTable[currentHandle].CIN_HEIGHT*cinTable[currentHandle].samplesPerLine;
  892. cinTable[currentHandle].half = qfalse;
  893. cinTable[currentHandle].smootheddouble = qfalse;
  894. cinTable[currentHandle].VQ0 = cinTable[currentHandle].VQNormal;
  895. cinTable[currentHandle].VQ1 = cinTable[currentHandle].VQBuffer;
  896. cinTable[currentHandle].t[0] = (0 - (unsigned int)cin.linbuf)+(unsigned int)cin.linbuf+cinTable[currentHandle].screenDelta;
  897. cinTable[currentHandle].t[1] = (0 - ((unsigned int)cin.linbuf + cinTable[currentHandle].screenDelta))+(unsigned int)cin.linbuf;
  898. cinTable[currentHandle].drawX = cinTable[currentHandle].CIN_WIDTH;
  899. cinTable[currentHandle].drawY = cinTable[currentHandle].CIN_HEIGHT;
  900. // rage pro is very slow at 512 wide textures, voodoo can't do it at all
  901. if ( glConfig.hardwareType == GLHW_RAGEPRO || glConfig.maxTextureSize <= 256) {
  902. if (cinTable[currentHandle].drawX>256) {
  903. cinTable[currentHandle].drawX = 256;
  904. }
  905. if (cinTable[currentHandle].drawY>256) {
  906. cinTable[currentHandle].drawY = 256;
  907. }
  908. if (cinTable[currentHandle].CIN_WIDTH != 256 || cinTable[currentHandle].CIN_HEIGHT != 256) {
  909. Com_Printf("HACK: approxmimating cinematic for Rage Pro or Voodoo\n");
  910. }
  911. }
  912. #if defined(MACOS_X)
  913. cinTable[currentHandle].drawX = 256;
  914. cinTable[currentHandle].drawX = 256;
  915. #endif
  916. }
  917. /******************************************************************************
  918. *
  919. * Function:
  920. *
  921. * Description:
  922. *
  923. ******************************************************************************/
  924. static void RoQPrepMcomp( long xoff, long yoff )
  925. {
  926. long i, j, x, y, temp, temp2;
  927. i=cinTable[currentHandle].samplesPerLine; j=cinTable[currentHandle].samplesPerPixel;
  928. if ( cinTable[currentHandle].xsize == (cinTable[currentHandle].ysize*4) && !cinTable[currentHandle].half ) { j = j+j; i = i+i; }
  929. for(y=0;y<16;y++) {
  930. temp2 = (y+yoff-8)*i;
  931. for(x=0;x<16;x++) {
  932. temp = (x+xoff-8)*j;
  933. cin.mcomp[(x*16)+y] = cinTable[currentHandle].normalBuffer0-(temp2+temp);
  934. }
  935. }
  936. }
  937. /******************************************************************************
  938. *
  939. * Function:
  940. *
  941. * Description:
  942. *
  943. ******************************************************************************/
  944. static void initRoQ()
  945. {
  946. if (currentHandle < 0) return;
  947. cinTable[currentHandle].VQNormal = (void (*)(byte *, void *))blitVQQuad32fs;
  948. cinTable[currentHandle].VQBuffer = (void (*)(byte *, void *))blitVQQuad32fs;
  949. cinTable[currentHandle].samplesPerPixel = 4;
  950. ROQ_GenYUVTables();
  951. RllSetupTable();
  952. }
  953. /******************************************************************************
  954. *
  955. * Function:
  956. *
  957. * Description:
  958. *
  959. ******************************************************************************/
  960. /*
  961. static byte* RoQFetchInterlaced( byte *source ) {
  962. int x, *src, *dst;
  963. if (currentHandle < 0) return NULL;
  964. src = (int *)source;
  965. dst = (int *)cinTable[currentHandle].buf2;
  966. for(x=0;x<256*256;x++) {
  967. *dst = *src;
  968. dst++; src += 2;
  969. }
  970. return cinTable[currentHandle].buf2;
  971. }
  972. */
  973. static void RoQReset() {
  974. if (currentHandle < 0) return;
  975. Sys_EndStreamedFile(cinTable[currentHandle].iFile);
  976. FS_FCloseFile( cinTable[currentHandle].iFile );
  977. FS_FOpenFileRead (cinTable[currentHandle].fileName, &cinTable[currentHandle].iFile, qtrue);
  978. // let the background thread start reading ahead
  979. Sys_BeginStreamedFile( cinTable[currentHandle].iFile, 0x10000 );
  980. Sys_StreamedRead (cin.file, 16, 1, cinTable[currentHandle].iFile);
  981. RoQ_init();
  982. cinTable[currentHandle].status = FMV_LOOPED;
  983. }
  984. /******************************************************************************
  985. *
  986. * Function:
  987. *
  988. * Description:
  989. *
  990. ******************************************************************************/
  991. static void RoQInterrupt(void)
  992. {
  993. byte *framedata;
  994. short sbuf[32768];
  995. int ssize;
  996. if (currentHandle < 0) return;
  997. Sys_StreamedRead( cin.file, cinTable[currentHandle].RoQFrameSize+8, 1, cinTable[currentHandle].iFile );
  998. if ( cinTable[currentHandle].RoQPlayed >= cinTable[currentHandle].ROQSize ) {
  999. if (cinTable[currentHandle].holdAtEnd==qfalse) {
  1000. if (cinTable[currentHandle].looping) {
  1001. RoQReset();
  1002. } else {
  1003. cinTable[currentHandle].status = FMV_EOF;
  1004. }
  1005. } else {
  1006. cinTable[currentHandle].status = FMV_IDLE;
  1007. }
  1008. return;
  1009. }
  1010. framedata = cin.file;
  1011. //
  1012. // new frame is ready
  1013. //
  1014. redump:
  1015. switch(cinTable[currentHandle].roq_id)
  1016. {
  1017. case ROQ_QUAD_VQ:
  1018. if ((cinTable[currentHandle].numQuads&1)) {
  1019. cinTable[currentHandle].normalBuffer0 = cinTable[currentHandle].t[1];
  1020. RoQPrepMcomp( cinTable[currentHandle].roqF0, cinTable[currentHandle].roqF1 );
  1021. cinTable[currentHandle].VQ1( (byte *)cin.qStatus[1], framedata);
  1022. cinTable[currentHandle].buf = cin.linbuf + cinTable[currentHandle].screenDelta;
  1023. } else {
  1024. cinTable[currentHandle].normalBuffer0 = cinTable[currentHandle].t[0];
  1025. RoQPrepMcomp( cinTable[currentHandle].roqF0, cinTable[currentHandle].roqF1 );
  1026. cinTable[currentHandle].VQ0( (byte *)cin.qStatus[0], framedata );
  1027. cinTable[currentHandle].buf = cin.linbuf;
  1028. }
  1029. if (cinTable[currentHandle].numQuads == 0) { // first frame
  1030. Com_Memcpy(cin.linbuf+cinTable[currentHandle].screenDelta, cin.linbuf, cinTable[currentHandle].samplesPerLine*cinTable[currentHandle].ysize);
  1031. }
  1032. cinTable[currentHandle].numQuads++;
  1033. cinTable[currentHandle].dirty = qtrue;
  1034. break;
  1035. case ROQ_CODEBOOK:
  1036. decodeCodeBook( framedata, (unsigned short)cinTable[currentHandle].roq_flags );
  1037. break;
  1038. case ZA_SOUND_MONO:
  1039. if (!cinTable[currentHandle].silent) {
  1040. ssize = RllDecodeMonoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
  1041. S_RawSamples( ssize, 22050, 2, 1, (byte *)sbuf, 1.0f );
  1042. }
  1043. break;
  1044. case ZA_SOUND_STEREO:
  1045. if (!cinTable[currentHandle].silent) {
  1046. if (cinTable[currentHandle].numQuads == -1) {
  1047. S_Update();
  1048. s_rawend = s_soundtime;
  1049. }
  1050. ssize = RllDecodeStereoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
  1051. S_RawSamples( ssize, 22050, 2, 2, (byte *)sbuf, 1.0f );
  1052. }
  1053. break;
  1054. case ROQ_QUAD_INFO:
  1055. if (cinTable[currentHandle].numQuads == -1) {
  1056. readQuadInfo( framedata );
  1057. setupQuad( 0, 0 );
  1058. // we need to use CL_ScaledMilliseconds because of the smp mode calls from the renderer
  1059. cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds()*com_timescale->value;
  1060. }
  1061. if (cinTable[currentHandle].numQuads != 1) cinTable[currentHandle].numQuads = 0;
  1062. break;
  1063. case ROQ_PACKET:
  1064. cinTable[currentHandle].inMemory = cinTable[currentHandle].roq_flags;
  1065. cinTable[currentHandle].RoQFrameSize = 0; // for header
  1066. break;
  1067. case ROQ_QUAD_HANG:
  1068. cinTable[currentHandle].RoQFrameSize = 0;
  1069. break;
  1070. case ROQ_QUAD_JPEG:
  1071. break;
  1072. default:
  1073. cinTable[currentHandle].status = FMV_EOF;
  1074. break;
  1075. }
  1076. //
  1077. // read in next frame data
  1078. //
  1079. if ( cinTable[currentHandle].RoQPlayed >= cinTable[currentHandle].ROQSize ) {
  1080. if (cinTable[currentHandle].holdAtEnd==qfalse) {
  1081. if (cinTable[currentHandle].looping) {
  1082. RoQReset();
  1083. } else {
  1084. cinTable[currentHandle].status = FMV_EOF;
  1085. }
  1086. } else {
  1087. cinTable[currentHandle].status = FMV_IDLE;
  1088. }
  1089. return;
  1090. }
  1091. framedata += cinTable[currentHandle].RoQFrameSize;
  1092. cinTable[currentHandle].roq_id = framedata[0] + framedata[1]*256;
  1093. cinTable[currentHandle].RoQFrameSize = framedata[2] + framedata[3]*256 + framedata[4]*65536;
  1094. cinTable[currentHandle].roq_flags = framedata[6] + framedata[7]*256;
  1095. cinTable[currentHandle].roqF0 = (char)framedata[7];
  1096. cinTable[currentHandle].roqF1 = (char)framedata[6];
  1097. if (cinTable[currentHandle].RoQFrameSize>65536||cinTable[currentHandle].roq_id==0x1084) {
  1098. Com_DPrintf("roq_size>65536||roq_id==0x1084\n");
  1099. cinTable[currentHandle].status = FMV_EOF;
  1100. if (cinTable[currentHandle].looping) {
  1101. RoQReset();
  1102. }
  1103. return;
  1104. }
  1105. if (cinTable[currentHandle].inMemory && (cinTable[currentHandle].status != FMV_EOF)) { cinTable[currentHandle].inMemory--; framedata += 8; goto redump; }
  1106. //
  1107. // one more frame hits the dust
  1108. //
  1109. // assert(cinTable[currentHandle].RoQFrameSize <= 65536);
  1110. // r = Sys_StreamedRead( cin.file, cinTable[currentHandle].RoQFrameSize+8, 1, cinTable[currentHandle].iFile );
  1111. cinTable[currentHandle].RoQPlayed += cinTable[currentHandle].RoQFrameSize+8;
  1112. }
  1113. /******************************************************************************
  1114. *
  1115. * Function:
  1116. *
  1117. * Description:
  1118. *
  1119. ******************************************************************************/
  1120. static void RoQ_init( void )
  1121. {
  1122. // we need to use CL_ScaledMilliseconds because of the smp mode calls from the renderer
  1123. cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds()*com_timescale->value;
  1124. cinTable[currentHandle].RoQPlayed = 24;
  1125. /* get frame rate */
  1126. cinTable[currentHandle].roqFPS = cin.file[ 6] + cin.file[ 7]*256;
  1127. if (!cinTable[currentHandle].roqFPS) cinTable[currentHandle].roqFPS = 30;
  1128. cinTable[currentHandle].numQuads = -1;
  1129. cinTable[currentHandle].roq_id = cin.file[ 8] + cin.file[ 9]*256;
  1130. cinTable[currentHandle].RoQFrameSize = cin.file[10] + cin.file[11]*256 + cin.file[12]*65536;
  1131. cinTable[currentHandle].roq_flags = cin.file[14] + cin.file[15]*256;
  1132. if (cinTable[currentHandle].RoQFrameSize > 65536 || !cinTable[currentHandle].RoQFrameSize) {
  1133. return;
  1134. }
  1135. }
  1136. /******************************************************************************
  1137. *
  1138. * Function:
  1139. *
  1140. * Description:
  1141. *
  1142. ******************************************************************************/
  1143. static void RoQShutdown( void ) {
  1144. const char *s;
  1145. if (!cinTable[currentHandle].buf) {
  1146. return;
  1147. }
  1148. if ( cinTable[currentHandle].status == FMV_IDLE ) {
  1149. return;
  1150. }
  1151. Com_DPrintf("finished cinematic\n");
  1152. cinTable[currentHandle].status = FMV_IDLE;
  1153. if (cinTable[currentHandle].iFile) {
  1154. Sys_EndStreamedFile( cinTable[currentHandle].iFile );
  1155. FS_FCloseFile( cinTable[currentHandle].iFile );
  1156. cinTable[currentHandle].iFile = 0;
  1157. }
  1158. if (cinTable[currentHandle].alterGameState) {
  1159. cls.state = CA_DISCONNECTED;
  1160. // we can't just do a vstr nextmap, because
  1161. // if we are aborting the intro cinematic with
  1162. // a devmap command, nextmap would be valid by
  1163. // the time it was referenced
  1164. s = Cvar_VariableString( "nextmap" );
  1165. if ( s[0] ) {
  1166. Cbuf_ExecuteText( EXEC_APPEND, va("%s\n", s) );
  1167. Cvar_Set( "nextmap", "" );
  1168. }
  1169. CL_handle = -1;
  1170. }
  1171. cinTable[currentHandle].fileName[0] = 0;
  1172. currentHandle = -1;
  1173. }
  1174. /*
  1175. ==================
  1176. SCR_StopCinematic
  1177. ==================
  1178. */
  1179. e_status CIN_StopCinematic(int handle) {
  1180. if (handle < 0 || handle>= MAX_VIDEO_HANDLES || cinTable[handle].status == FMV_EOF) return FMV_EOF;
  1181. currentHandle = handle;
  1182. Com_DPrintf("trFMV::stop(), closing %s\n", cinTable[currentHandle].fileName);
  1183. if (!cinTable[currentHandle].buf) {
  1184. return FMV_EOF;
  1185. }
  1186. if (cinTable[currentHandle].alterGameState) {
  1187. if ( cls.state != CA_CINEMATIC ) {
  1188. return cinTable[currentHandle].status;
  1189. }
  1190. }
  1191. cinTable[currentHandle].status = FMV_EOF;
  1192. RoQShutdown();
  1193. return FMV_EOF;
  1194. }
  1195. /*
  1196. ==================
  1197. SCR_RunCinematic
  1198. Fetch and decompress the pending frame
  1199. ==================
  1200. */
  1201. e_status CIN_RunCinematic (int handle)
  1202. {
  1203. // bk001204 - init
  1204. int start = 0;
  1205. int thisTime = 0;
  1206. if (handle < 0 || handle>= MAX_VIDEO_HANDLES || cinTable[handle].status == FMV_EOF) return FMV_EOF;
  1207. if (cin.currentHandle != handle) {
  1208. currentHandle = handle;
  1209. cin.currentHandle = currentHandle;
  1210. cinTable[currentHandle].status = FMV_EOF;
  1211. RoQReset();
  1212. }
  1213. if (cinTable[handle].playonwalls < -1)
  1214. {
  1215. return cinTable[handle].status;
  1216. }
  1217. currentHandle = handle;
  1218. if (cinTable[currentHandle].alterGameState) {
  1219. if ( cls.state != CA_CINEMATIC ) {
  1220. return cinTable[currentHandle].status;
  1221. }
  1222. }
  1223. if (cinTable[currentHandle].status == FMV_IDLE) {
  1224. return cinTable[currentHandle].status;
  1225. }
  1226. // we need to use CL_ScaledMilliseconds because of the smp mode calls from the renderer
  1227. thisTime = CL_ScaledMilliseconds()*com_timescale->value;
  1228. if (cinTable[currentHandle].shader && (abs(thisTime - cinTable[currentHandle].lastTime))>100) {
  1229. cinTable[currentHandle].startTime += thisTime - cinTable[currentHandle].lastTime;
  1230. }
  1231. // we need to use CL_ScaledMilliseconds because of the smp mode calls from the renderer
  1232. cinTable[currentHandle].tfps = ((((CL_ScaledMilliseconds()*com_timescale->value) - cinTable[currentHandle].startTime)*3)/100);
  1233. start = cinTable[currentHandle].startTime;
  1234. while( (cinTable[currentHandle].tfps != cinTable[currentHandle].numQuads)
  1235. && (cinTable[currentHandle].status == FMV_PLAY) )
  1236. {
  1237. RoQInterrupt();
  1238. if (start != cinTable[currentHandle].startTime) {
  1239. // we need to use CL_ScaledMilliseconds because of the smp mode calls from the renderer
  1240. cinTable[currentHandle].tfps = ((((CL_ScaledMilliseconds()*com_timescale->value)
  1241. - cinTable[currentHandle].startTime)*3)/100);
  1242. start = cinTable[currentHandle].startTime;
  1243. }
  1244. }
  1245. cinTable[currentHandle].lastTime = thisTime;
  1246. if (cinTable[currentHandle].status == FMV_LOOPED) {
  1247. cinTable[currentHandle].status = FMV_PLAY;
  1248. }
  1249. if (cinTable[currentHandle].status == FMV_EOF) {
  1250. if (cinTable[currentHandle].looping) {
  1251. RoQReset();
  1252. } else {
  1253. RoQShutdown();
  1254. }
  1255. }
  1256. return cinTable[currentHandle].status;
  1257. }
  1258. /*
  1259. ==================
  1260. CL_PlayCinematic
  1261. ==================
  1262. */
  1263. int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBits ) {
  1264. unsigned short RoQID;
  1265. char name[MAX_OSPATH];
  1266. int i;
  1267. if (strstr(arg, "/") == NULL && strstr(arg, "\\") == NULL) {
  1268. Com_sprintf (name, sizeof(name), "video/%s", arg);
  1269. } else {
  1270. Com_sprintf (name, sizeof(name), "%s", arg);
  1271. }
  1272. if (!(systemBits & CIN_system)) {
  1273. for ( i = 0 ; i < MAX_VIDEO_HANDLES ; i++ ) {
  1274. if (!strcmp(cinTable[i].fileName, name) ) {
  1275. return i;
  1276. }
  1277. }
  1278. }
  1279. Com_DPrintf("SCR_PlayCinematic( %s )\n", arg);
  1280. Com_Memset(&cin, 0, sizeof(cinematics_t) );
  1281. currentHandle = CIN_HandleForVideo();
  1282. cin.currentHandle = currentHandle;
  1283. strcpy(cinTable[currentHandle].fileName, name);
  1284. cinTable[currentHandle].ROQSize = 0;
  1285. cinTable[currentHandle].ROQSize = FS_FOpenFileRead (cinTable[currentHandle].fileName, &cinTable[currentHandle].iFile, qtrue);
  1286. if (cinTable[currentHandle].ROQSize<=0) {
  1287. Com_DPrintf("play(%s), ROQSize<=0\n", arg);
  1288. cinTable[currentHandle].fileName[0] = 0;
  1289. return -1;
  1290. }
  1291. CIN_SetExtents(currentHandle, x, y, w, h);
  1292. CIN_SetLooping(currentHandle, (systemBits & CIN_loop)!=0);
  1293. cinTable[currentHandle].CIN_HEIGHT = DEFAULT_CIN_HEIGHT;
  1294. cinTable[currentHandle].CIN_WIDTH = DEFAULT_CIN_WIDTH;
  1295. cinTable[currentHandle].holdAtEnd = (systemBits & CIN_hold) != 0;
  1296. cinTable[currentHandle].alterGameState = (systemBits & CIN_system) != 0;
  1297. cinTable[currentHandle].playonwalls = 1;
  1298. cinTable[currentHandle].silent = (systemBits & CIN_silent) != 0;
  1299. cinTable[currentHandle].shader = (systemBits & CIN_shader) != 0;
  1300. if (cinTable[currentHandle].alterGameState) {
  1301. // close the menu
  1302. if ( uivm ) {
  1303. VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NONE );
  1304. }
  1305. } else {
  1306. cinTable[currentHandle].playonwalls = cl_inGameVideo->integer;
  1307. }
  1308. initRoQ();
  1309. FS_Read (cin.file, 16, cinTable[currentHandle].iFile);
  1310. RoQID = (unsigned short)(cin.file[0]) + (unsigned short)(cin.file[1])*256;
  1311. if (RoQID == 0x1084)
  1312. {
  1313. RoQ_init();
  1314. // FS_Read (cin.file, cinTable[currentHandle].RoQFrameSize+8, cinTable[currentHandle].iFile);
  1315. // let the background thread start reading ahead
  1316. Sys_BeginStreamedFile( cinTable[currentHandle].iFile, 0x10000 );
  1317. cinTable[currentHandle].status = FMV_PLAY;
  1318. Com_DPrintf("trFMV::play(), playing %s\n", arg);
  1319. if (cinTable[currentHandle].alterGameState) {
  1320. cls.state = CA_CINEMATIC;
  1321. }
  1322. Con_Close();
  1323. s_rawend = s_soundtime;
  1324. return currentHandle;
  1325. }
  1326. Com_DPrintf("trFMV::play(), invalid RoQ ID\n");
  1327. RoQShutdown();
  1328. return -1;
  1329. }
  1330. void CIN_SetExtents (int handle, int x, int y, int w, int h) {
  1331. if (handle < 0 || handle>= MAX_VIDEO_HANDLES || cinTable[handle].status == FMV_EOF) return;
  1332. cinTable[handle].xpos = x;
  1333. cinTable[handle].ypos = y;
  1334. cinTable[handle].width = w;
  1335. cinTable[handle].height = h;
  1336. cinTable[handle].dirty = qtrue;
  1337. }
  1338. void CIN_SetLooping(int handle, qboolean loop) {
  1339. if (handle < 0 || handle>= MAX_VIDEO_HANDLES || cinTable[handle].status == FMV_EOF) return;
  1340. cinTable[handle].looping = loop;
  1341. }
  1342. /*
  1343. ==================
  1344. SCR_DrawCinematic
  1345. ==================
  1346. */
  1347. void CIN_DrawCinematic (int handle) {
  1348. float x, y, w, h;
  1349. byte *buf;
  1350. if (handle < 0 || handle>= MAX_VIDEO_HANDLES || cinTable[handle].status == FMV_EOF) return;
  1351. if (!cinTable[handle].buf) {
  1352. return;
  1353. }
  1354. x = cinTable[handle].xpos;
  1355. y = cinTable[handle].ypos;
  1356. w = cinTable[handle].width;
  1357. h = cinTable[handle].height;
  1358. buf = cinTable[handle].buf;
  1359. SCR_AdjustFrom640( &x, &y, &w, &h );
  1360. if (cinTable[handle].dirty && (cinTable[handle].CIN_WIDTH != cinTable[handle].drawX || cinTable[handle].CIN_HEIGHT != cinTable[handle].drawY)) {
  1361. int ix, iy, *buf2, *buf3, xm, ym, ll;
  1362. xm = cinTable[handle].CIN_WIDTH/256;
  1363. ym = cinTable[handle].CIN_HEIGHT/256;
  1364. ll = 8;
  1365. if (cinTable[handle].CIN_WIDTH==512) {
  1366. ll = 9;
  1367. }
  1368. buf3 = (int*)buf;
  1369. buf2 = Hunk_AllocateTempMemory( 256*256*4 );
  1370. if (xm==2 && ym==2) {
  1371. byte *bc2, *bc3;
  1372. int ic, iiy;
  1373. bc2 = (byte *)buf2;
  1374. bc3 = (byte *)buf3;
  1375. for (iy = 0; iy<256; iy++) {
  1376. iiy = iy<<12;
  1377. for (ix = 0; ix<2048; ix+=8) {
  1378. for(ic = ix;ic<(ix+4);ic++) {
  1379. *bc2=(bc3[iiy+ic]+bc3[iiy+4+ic]+bc3[iiy+2048+ic]+bc3[iiy+2048+4+ic])>>2;
  1380. bc2++;
  1381. }
  1382. }
  1383. }
  1384. } else if (xm==2 && ym==1) {
  1385. byte *bc2, *bc3;
  1386. int ic, iiy;
  1387. bc2 = (byte *)buf2;
  1388. bc3 = (byte *)buf3;
  1389. for (iy = 0; iy<256; iy++) {
  1390. iiy = iy<<11;
  1391. for (ix = 0; ix<2048; ix+=8) {
  1392. for(ic = ix;ic<(ix+4);ic++) {
  1393. *bc2=(bc3[iiy+ic]+bc3[iiy+4+ic])>>1;
  1394. bc2++;
  1395. }
  1396. }
  1397. }
  1398. } else {
  1399. for (iy = 0; iy<256; iy++) {
  1400. for (ix = 0; ix<256; ix++) {
  1401. buf2[(iy<<8)+ix] = buf3[((iy*ym)<<ll) + (ix*xm)];
  1402. }
  1403. }
  1404. }
  1405. re.DrawStretchRaw( x, y, w, h, 256, 256, (byte *)buf2, handle, qtrue);
  1406. cinTable[handle].dirty = qfalse;
  1407. Hunk_FreeTempMemory(buf2);
  1408. return;
  1409. }
  1410. re.DrawStretchRaw( x, y, w, h, cinTable[handle].drawX, cinTable[handle].drawY, buf, handle, cinTable[handle].dirty);
  1411. cinTable[handle].dirty = qfalse;
  1412. }
  1413. void CL_PlayCinematic_f(void) {
  1414. char *arg, *s;
  1415. qboolean holdatend;
  1416. int bits = CIN_system;
  1417. Com_DPrintf("CL_PlayCinematic_f\n");
  1418. if (cls.state == CA_CINEMATIC) {
  1419. SCR_StopCinematic();
  1420. }
  1421. arg = Cmd_Argv( 1 );
  1422. s = Cmd_Argv(2);
  1423. holdatend = qfalse;
  1424. if ((s && s[0] == '1') || Q_stricmp(arg,"demoend.roq")==0 || Q_stricmp(arg,"end.roq")==0) {
  1425. bits |= CIN_hold;
  1426. }
  1427. if (s && s[0] == '2') {
  1428. bits |= CIN_loop;
  1429. }
  1430. S_StopAllSounds ();
  1431. CL_handle = CIN_PlayCinematic( arg, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, bits );
  1432. if (CL_handle >= 0) {
  1433. do {
  1434. SCR_RunCinematic();
  1435. } while (cinTable[currentHandle].buf == NULL && cinTable[currentHandle].status == FMV_PLAY); // wait for first frame (load codebook and sound)
  1436. }
  1437. }
  1438. void SCR_DrawCinematic (void) {
  1439. if (CL_handle >= 0 && CL_handle < MAX_VIDEO_HANDLES) {
  1440. CIN_DrawCinematic(CL_handle);
  1441. }
  1442. }
  1443. void SCR_RunCinematic (void)
  1444. {
  1445. if (CL_handle >= 0 && CL_handle < MAX_VIDEO_HANDLES) {
  1446. CIN_RunCinematic(CL_handle);
  1447. }
  1448. }
  1449. void SCR_StopCinematic(void) {
  1450. if (CL_handle >= 0 && CL_handle < MAX_VIDEO_HANDLES) {
  1451. CIN_StopCinematic(CL_handle);
  1452. S_StopAllSounds ();
  1453. CL_handle = -1;
  1454. }
  1455. }
  1456. void CIN_UploadCinematic(int handle) {
  1457. if (handle >= 0 && handle < MAX_VIDEO_HANDLES) {
  1458. if (!cinTable[handle].buf) {
  1459. return;
  1460. }
  1461. if (cinTable[handle].playonwalls <= 0 && cinTable[handle].dirty) {
  1462. if (cinTable[handle].playonwalls == 0) {
  1463. cinTable[handle].playonwalls = -1;
  1464. } else {
  1465. if (cinTable[handle].playonwalls == -1) {
  1466. cinTable[handle].playonwalls = -2;
  1467. } else {
  1468. cinTable[handle].dirty = qfalse;
  1469. }
  1470. }
  1471. }
  1472. re.UploadCinematic( 256, 256, 256, 256, cinTable[handle].buf, handle, cinTable[handle].dirty);
  1473. if (cl_inGameVideo->integer == 0 && cinTable[handle].playonwalls == 1) {
  1474. cinTable[handle].playonwalls--;
  1475. }
  1476. }
  1477. }