]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/renderer/Cinematic.cpp
Use the same OpenAL headers on all platforms.
[icculus/iodoom3.git] / neo / renderer / Cinematic.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #define JPEG_INTERNALS
33 extern "C" {
34 #include "jpeg-6/jpeglib.h"
35 }
36
37 #include "tr_local.h"
38
39 #define CIN_system      1
40 #define CIN_loop        2
41 #define CIN_hold        4
42 #define CIN_silent      8
43 #define CIN_shader      16
44
45 class idCinematicLocal : public idCinematic {
46 public:
47                                                         idCinematicLocal();
48         virtual                                 ~idCinematicLocal();
49
50         virtual bool                    InitFromFile( const char *qpath, bool looping );
51         virtual cinData_t               ImageForTime( int milliseconds );
52         virtual int                             AnimationLength();
53         virtual void                    Close();
54         virtual void                    ResetTime(int time);
55
56 private:
57         unsigned int                    mcomp[256];
58         byte **                                 qStatus[2];
59         idStr                                   fileName;
60         int                                             CIN_WIDTH, CIN_HEIGHT;
61         idFile *                                iFile;
62         cinStatus_t                             status;
63         long                                    tfps;
64         long                                    RoQPlayed;
65         long                                    ROQSize;
66         unsigned int                    RoQFrameSize;
67         long                                    onQuad;
68         long                                    numQuads;
69         long                                    samplesPerLine;
70         unsigned int                    roq_id;
71         long                                    screenDelta;
72         byte *                                  buf;
73         long                                    samplesPerPixel;                                // defaults to 2
74         unsigned int                    xsize, ysize, maxsize, minsize;
75         long                                    normalBuffer0;
76         long                                    roq_flags;
77         long                                    roqF0;
78         long                                    roqF1;
79         long                                    t[2];
80         long                                    roqFPS;
81         long                                    drawX, drawY;
82
83         int                                             animationLength;
84         int                                             startTime;
85         float                                   frameRate;
86
87         byte *                                  image;
88
89         bool                                    looping;
90         bool                                    dirty;
91         bool                                    half;
92         bool                                    smootheddouble;
93         bool                                    inMemory;
94
95         void                                    RoQ_init( void );
96         void                                    blitVQQuad32fs( byte **status, unsigned char *data );
97         void                                    RoQShutdown( void );
98         void                                    RoQInterrupt(void);
99
100         void                                    move8_32( byte *src, byte *dst, int spl );
101         void                                    move4_32( byte *src, byte *dst, int spl );
102         void                                    blit8_32( byte *src, byte *dst, int spl );
103         void                                    blit4_32( byte *src, byte *dst, int spl );
104         void                                    blit2_32( byte *src, byte *dst, int spl );
105
106         unsigned short                  yuv_to_rgb( long y, long u, long v );
107         unsigned int                    yuv_to_rgb24( long y, long u, long v );
108
109         void                                    decodeCodeBook( byte *input, unsigned short roq_flags );
110         void                                    recurseQuad( long startX, long startY, long quadSize, long xOff, long yOff );
111         void                                    setupQuad( long xOff, long yOff );
112         void                                    readQuadInfo( byte *qData );
113         void                                    RoQPrepMcomp( long xoff, long yoff );
114         void                                    RoQReset();
115 };
116
117 const int DEFAULT_CIN_WIDTH             = 512;
118 const int DEFAULT_CIN_HEIGHT    = 512;
119 const int MAXSIZE                               =       8;
120 const int MINSIZE                               =       4;
121
122 const int ROQ_FILE                              = 0x1084;
123 const int ROQ_QUAD                              = 0x1000;
124 const int ROQ_QUAD_INFO                 = 0x1001;
125 const int ROQ_CODEBOOK                  = 0x1002;
126 const int ROQ_QUAD_VQ                   = 0x1011;
127 const int ROQ_QUAD_JPEG                 = 0x1012;
128 const int ROQ_QUAD_HANG                 = 0x1013;
129 const int ROQ_PACKET                    = 0x1030;
130 const int ZA_SOUND_MONO                 = 0x1020;
131 const int ZA_SOUND_STEREO               = 0x1021;
132
133 // temporary buffers used by all cinematics
134 static long                             ROQ_YY_tab[256];
135 static long                             ROQ_UB_tab[256];
136 static long                             ROQ_UG_tab[256];
137 static long                             ROQ_VG_tab[256];
138 static long                             ROQ_VR_tab[256];
139 static byte *                   file = NULL;
140 static unsigned short * vq2 = NULL;
141 static unsigned short * vq4 = NULL;
142 static unsigned short * vq8 = NULL;
143
144
145
146 //===========================================
147
148 /*
149 ==============
150 idCinematicLocal::InitCinematic
151 ==============
152 */
153 void idCinematic::InitCinematic( void ) {
154         float t_ub,t_vr,t_ug,t_vg;
155         long i;
156
157         // generate YUV tables
158         t_ub = (1.77200f/2.0f) * (float)(1<<6) + 0.5f;
159         t_vr = (1.40200f/2.0f) * (float)(1<<6) + 0.5f;
160         t_ug = (0.34414f/2.0f) * (float)(1<<6) + 0.5f;
161         t_vg = (0.71414f/2.0f) * (float)(1<<6) + 0.5f;
162         for( i = 0; i < 256; i++ ) {
163                 float x = (float)(2 * i - 255);
164         
165                 ROQ_UB_tab[i] = (long)( ( t_ub * x) + (1<<5));
166                 ROQ_VR_tab[i] = (long)( ( t_vr * x) + (1<<5));
167                 ROQ_UG_tab[i] = (long)( (-t_ug * x)              );
168                 ROQ_VG_tab[i] = (long)( (-t_vg * x) + (1<<5));
169                 ROQ_YY_tab[i] = (long)( (i << 6) | (i >> 2) );
170         }
171
172         file = (byte *)Mem_Alloc( 65536 );
173         vq2 = (word *)Mem_Alloc( 256*16*4 * sizeof( word ) );
174         vq4 = (word *)Mem_Alloc( 256*64*4 * sizeof( word ) );
175         vq8 = (word *)Mem_Alloc( 256*256*4 * sizeof( word ) );
176 }
177
178 /*
179 ==============
180 idCinematicLocal::ShutdownCinematic
181 ==============
182 */
183 void idCinematic::ShutdownCinematic( void ) {
184         Mem_Free( file );
185         file = NULL;
186         Mem_Free( vq2 );
187         vq2 = NULL;
188         Mem_Free( vq4 );
189         vq4 = NULL;
190         Mem_Free( vq8 );
191         vq8 = NULL;
192 }
193
194 /*
195 ==============
196 idCinematicLocal::Alloc
197 ==============
198 */
199 idCinematic *idCinematic::Alloc() {
200         return new idCinematicLocal;
201 }
202
203 /*
204 ==============
205 idCinematicLocal::~idCinematic
206 ==============
207 */
208 idCinematic::~idCinematic( ) {
209         Close();
210 }
211
212 /*
213 ==============
214 idCinematicLocal::InitFromFile
215 ==============
216 */
217 bool idCinematic::InitFromFile( const char *qpath, bool looping ) {
218         return false;
219 }
220
221 /*
222 ==============
223 idCinematicLocal::AnimationLength
224 ==============
225 */
226 int idCinematic::AnimationLength() {
227         return 0;
228 }
229
230 /*
231 ==============
232 idCinematicLocal::ResetTime
233 ==============
234 */
235 void idCinematic::ResetTime(int milliseconds) {
236 }
237
238 /*
239 ==============
240 idCinematicLocal::ImageForTime
241 ==============
242 */
243 cinData_t idCinematic::ImageForTime( int milliseconds ) {
244         cinData_t c;
245         memset( &c, 0, sizeof( c ) );
246         return c;
247 }
248
249 /*
250 ==============
251 idCinematicLocal::Close
252 ==============
253 */
254 void idCinematic::Close() {
255 }
256
257 //===========================================
258
259 /*
260 ==============
261 idCinematicLocal::idCinematicLocal
262 ==============
263 */
264 idCinematicLocal::idCinematicLocal() {
265         image = NULL;
266         status = FMV_EOF;
267         buf = NULL;
268         iFile = NULL;
269
270         qStatus[0] = (byte **)Mem_Alloc( 32768 * sizeof( byte *) );
271         qStatus[1] = (byte **)Mem_Alloc( 32768 * sizeof( byte *) );
272 }
273
274 /*
275 ==============
276 idCinematicLocal::~idCinematicLocal
277 ==============
278 */
279 idCinematicLocal::~idCinematicLocal() {
280         Close();
281
282         Mem_Free( qStatus[0] );
283         qStatus[0] = NULL;
284         Mem_Free( qStatus[1] );
285         qStatus[1] = NULL;
286 }
287
288 /*
289 ==============
290 idCinematicLocal::InitFromFile
291 ==============
292 */
293 bool idCinematicLocal::InitFromFile( const char *qpath, bool amilooping ) {
294         unsigned short RoQID;
295
296         Close();
297
298         inMemory = 0;
299         animationLength = 100000;
300
301         if ( strstr( qpath, "/" ) == NULL && strstr( qpath, "\\" ) == NULL ) {
302                 sprintf( fileName, "video/%s", qpath );
303         } else {
304                 sprintf( fileName, "%s", qpath );
305         }
306
307         iFile = fileSystem->OpenFileRead( fileName );
308
309         if ( !iFile ) {
310                 return false;
311         }
312
313         ROQSize = iFile->Length();
314
315         looping = amilooping;
316
317         CIN_HEIGHT = DEFAULT_CIN_HEIGHT;
318         CIN_WIDTH  =  DEFAULT_CIN_WIDTH;
319         samplesPerPixel = 4;
320         startTime = 0;  //Sys_Milliseconds();
321         buf = NULL;
322
323         iFile->Read( file, 16 );
324
325         RoQID = (unsigned short)(file[0]) + (unsigned short)(file[1])*256;
326
327         frameRate = file[6];
328         if ( frameRate == 32.0f ) {
329                 frameRate = 1000.0f / 32.0f;
330         }
331
332         if ( RoQID == ROQ_FILE ) {
333                 RoQ_init();
334                 status = FMV_PLAY;
335                 ImageForTime( 0 );
336                 status = ( looping ) ? FMV_PLAY : FMV_IDLE;
337                 return true;
338         }
339
340         RoQShutdown();
341         return false;
342 }
343
344 /*
345 ==============
346 idCinematicLocal::Close
347 ==============
348 */
349 void idCinematicLocal::Close() {
350         if ( image ) {
351                 Mem_Free( (void *)image );
352                 image = NULL;
353                 buf = NULL;
354                 status = FMV_EOF;
355         }
356         RoQShutdown();
357 }
358
359 /*
360 ==============
361 idCinematicLocal::AnimationLength
362 ==============
363 */
364 int idCinematicLocal::AnimationLength() { 
365         return animationLength; 
366 }
367
368 /*
369 ==============
370 idCinematicLocal::ResetTime
371 ==============
372 */
373 void idCinematicLocal::ResetTime(int time) {
374         startTime = ( backEnd.viewDef ) ? 1000 * backEnd.viewDef->floatTime : -1;
375         status = FMV_PLAY;
376 }
377
378 /*
379 ==============
380 idCinematicLocal::ImageForTime
381 ==============
382 */
383 cinData_t idCinematicLocal::ImageForTime( int thisTime ) {
384         cinData_t       cinData;
385
386         if ( thisTime < 0 ) {
387                 thisTime = 0;
388         }
389
390         memset( &cinData, 0, sizeof(cinData) );
391
392         if ( r_skipROQ.GetBool() ) {
393                 return cinData;
394         }
395
396         if ( status == FMV_EOF || status == FMV_IDLE ) {
397                 return cinData;
398         }
399
400         if ( buf == NULL || startTime == -1 ) {
401                 if ( startTime == -1 ) {
402                         RoQReset();
403                 }
404                 startTime = thisTime;
405         }
406
407         tfps = ( ( thisTime - startTime ) * frameRate ) / 1000;
408
409         if ( tfps < 0 ) {
410                 tfps = 0;
411         }
412
413         if ( tfps < numQuads ) {
414                 RoQReset();
415                 buf = NULL;
416                 status = FMV_PLAY;
417         }
418
419         if ( buf == NULL ) {
420                 while( buf == NULL ) {
421                         RoQInterrupt();
422                 }
423         } else {
424                 while( (tfps != numQuads && status == FMV_PLAY) ) {
425                         RoQInterrupt();
426                 }
427         }
428
429         if ( status == FMV_LOOPED ) {
430                 status = FMV_PLAY;
431                 while( buf == NULL && status == FMV_PLAY ) {
432                         RoQInterrupt();
433                 }
434                 startTime = thisTime;
435         }
436
437         if ( status == FMV_EOF ) {
438                 if ( looping ) {
439                         RoQReset();
440                         buf = NULL;
441                         if ( status == FMV_LOOPED ) {
442                                 status = FMV_PLAY;
443                         }
444                         while ( buf == NULL && status == FMV_PLAY ) {
445                                 RoQInterrupt();
446                         }
447                         startTime = thisTime;
448                 } else {
449                         status = FMV_IDLE;
450                         RoQShutdown();
451                 }
452         }
453
454         cinData.imageWidth = CIN_WIDTH;
455         cinData.imageHeight = CIN_HEIGHT;
456         cinData.status = status;
457         cinData.image = buf;
458
459         return cinData;
460 }
461
462 /*
463 ==============
464 idCinematicLocal::move8_32
465 ==============
466 */
467 void idCinematicLocal::move8_32( byte *src, byte *dst, int spl ) {
468 #if 1
469         int *dsrc, *ddst;
470         int dspl;
471
472         dsrc = (int *)src;
473         ddst = (int *)dst;
474         dspl = spl>>2;
475
476         ddst[0*dspl+0] = dsrc[0*dspl+0];
477         ddst[0*dspl+1] = dsrc[0*dspl+1];
478         ddst[0*dspl+2] = dsrc[0*dspl+2];
479         ddst[0*dspl+3] = dsrc[0*dspl+3];
480         ddst[0*dspl+4] = dsrc[0*dspl+4];
481         ddst[0*dspl+5] = dsrc[0*dspl+5];
482         ddst[0*dspl+6] = dsrc[0*dspl+6];
483         ddst[0*dspl+7] = dsrc[0*dspl+7];
484
485         ddst[1*dspl+0] = dsrc[1*dspl+0];
486         ddst[1*dspl+1] = dsrc[1*dspl+1];
487         ddst[1*dspl+2] = dsrc[1*dspl+2];
488         ddst[1*dspl+3] = dsrc[1*dspl+3];
489         ddst[1*dspl+4] = dsrc[1*dspl+4];
490         ddst[1*dspl+5] = dsrc[1*dspl+5];
491         ddst[1*dspl+6] = dsrc[1*dspl+6];
492         ddst[1*dspl+7] = dsrc[1*dspl+7];
493
494         ddst[2*dspl+0] = dsrc[2*dspl+0];
495         ddst[2*dspl+1] = dsrc[2*dspl+1];
496         ddst[2*dspl+2] = dsrc[2*dspl+2];
497         ddst[2*dspl+3] = dsrc[2*dspl+3];
498         ddst[2*dspl+4] = dsrc[2*dspl+4];
499         ddst[2*dspl+5] = dsrc[2*dspl+5];
500         ddst[2*dspl+6] = dsrc[2*dspl+6];
501         ddst[2*dspl+7] = dsrc[2*dspl+7];
502
503         ddst[3*dspl+0] = dsrc[3*dspl+0];
504         ddst[3*dspl+1] = dsrc[3*dspl+1];
505         ddst[3*dspl+2] = dsrc[3*dspl+2];
506         ddst[3*dspl+3] = dsrc[3*dspl+3];
507         ddst[3*dspl+4] = dsrc[3*dspl+4];
508         ddst[3*dspl+5] = dsrc[3*dspl+5];
509         ddst[3*dspl+6] = dsrc[3*dspl+6];
510         ddst[3*dspl+7] = dsrc[3*dspl+7];
511
512         ddst[4*dspl+0] = dsrc[4*dspl+0];
513         ddst[4*dspl+1] = dsrc[4*dspl+1];
514         ddst[4*dspl+2] = dsrc[4*dspl+2];
515         ddst[4*dspl+3] = dsrc[4*dspl+3];
516         ddst[4*dspl+4] = dsrc[4*dspl+4];
517         ddst[4*dspl+5] = dsrc[4*dspl+5];
518         ddst[4*dspl+6] = dsrc[4*dspl+6];
519         ddst[4*dspl+7] = dsrc[4*dspl+7];
520
521         ddst[5*dspl+0] = dsrc[5*dspl+0];
522         ddst[5*dspl+1] = dsrc[5*dspl+1];
523         ddst[5*dspl+2] = dsrc[5*dspl+2];
524         ddst[5*dspl+3] = dsrc[5*dspl+3];
525         ddst[5*dspl+4] = dsrc[5*dspl+4];
526         ddst[5*dspl+5] = dsrc[5*dspl+5];
527         ddst[5*dspl+6] = dsrc[5*dspl+6];
528         ddst[5*dspl+7] = dsrc[5*dspl+7];
529
530         ddst[6*dspl+0] = dsrc[6*dspl+0];
531         ddst[6*dspl+1] = dsrc[6*dspl+1];
532         ddst[6*dspl+2] = dsrc[6*dspl+2];
533         ddst[6*dspl+3] = dsrc[6*dspl+3];
534         ddst[6*dspl+4] = dsrc[6*dspl+4];
535         ddst[6*dspl+5] = dsrc[6*dspl+5];
536         ddst[6*dspl+6] = dsrc[6*dspl+6];
537         ddst[6*dspl+7] = dsrc[6*dspl+7];
538
539         ddst[7*dspl+0] = dsrc[7*dspl+0];
540         ddst[7*dspl+1] = dsrc[7*dspl+1];
541         ddst[7*dspl+2] = dsrc[7*dspl+2];
542         ddst[7*dspl+3] = dsrc[7*dspl+3];
543         ddst[7*dspl+4] = dsrc[7*dspl+4];
544         ddst[7*dspl+5] = dsrc[7*dspl+5];
545         ddst[7*dspl+6] = dsrc[7*dspl+6];
546         ddst[7*dspl+7] = dsrc[7*dspl+7];
547 #else
548         double *dsrc, *ddst;
549         int dspl;
550
551         dsrc = (double *)src;
552         ddst = (double *)dst;
553         dspl = spl>>3;
554
555         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
556         dsrc += dspl; ddst += dspl;
557         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
558         dsrc += dspl; ddst += dspl;
559         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
560         dsrc += dspl; ddst += dspl;
561         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
562         dsrc += dspl; ddst += dspl;
563         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
564         dsrc += dspl; ddst += dspl;
565         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
566         dsrc += dspl; ddst += dspl;
567         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
568         dsrc += dspl; ddst += dspl;
569         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
570 #endif
571 }
572
573 /*
574 ==============
575 idCinematicLocal::move4_32
576 ==============
577 */
578 void idCinematicLocal::move4_32( byte *src, byte *dst, int spl  ) {
579 #if 1
580         int *dsrc, *ddst;
581         int dspl;
582
583         dsrc = (int *)src;
584         ddst = (int *)dst;
585         dspl = spl>>2;
586
587         ddst[0*dspl+0] = dsrc[0*dspl+0];
588         ddst[0*dspl+1] = dsrc[0*dspl+1];
589         ddst[0*dspl+2] = dsrc[0*dspl+2];
590         ddst[0*dspl+3] = dsrc[0*dspl+3];
591
592         ddst[1*dspl+0] = dsrc[1*dspl+0];
593         ddst[1*dspl+1] = dsrc[1*dspl+1];
594         ddst[1*dspl+2] = dsrc[1*dspl+2];
595         ddst[1*dspl+3] = dsrc[1*dspl+3];
596
597         ddst[2*dspl+0] = dsrc[2*dspl+0];
598         ddst[2*dspl+1] = dsrc[2*dspl+1];
599         ddst[2*dspl+2] = dsrc[2*dspl+2];
600         ddst[2*dspl+3] = dsrc[2*dspl+3];
601
602         ddst[3*dspl+0] = dsrc[3*dspl+0];
603         ddst[3*dspl+1] = dsrc[3*dspl+1];
604         ddst[3*dspl+2] = dsrc[3*dspl+2];
605         ddst[3*dspl+3] = dsrc[3*dspl+3];
606 #else
607         double *dsrc, *ddst;
608         int dspl;
609
610         dsrc = (double *)src;
611         ddst = (double *)dst;
612         dspl = spl>>3;
613
614         ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
615         dsrc += dspl; ddst += dspl;
616         ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
617         dsrc += dspl; ddst += dspl;
618         ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
619         dsrc += dspl; ddst += dspl;
620         ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
621 #endif
622 }
623
624 /*
625 ==============
626 idCinematicLocal::blit8_32
627 ==============
628 */
629 void idCinematicLocal::blit8_32( byte *src, byte *dst, int spl  ) {
630 #if 1
631         int *dsrc, *ddst;
632         int dspl;
633
634         dsrc = (int *)src;
635         ddst = (int *)dst;
636         dspl = spl>>2;
637
638         ddst[0*dspl+0] = dsrc[ 0];
639         ddst[0*dspl+1] = dsrc[ 1];
640         ddst[0*dspl+2] = dsrc[ 2];
641         ddst[0*dspl+3] = dsrc[ 3];
642         ddst[0*dspl+4] = dsrc[ 4];
643         ddst[0*dspl+5] = dsrc[ 5];
644         ddst[0*dspl+6] = dsrc[ 6];
645         ddst[0*dspl+7] = dsrc[ 7];
646
647         ddst[1*dspl+0] = dsrc[ 8];
648         ddst[1*dspl+1] = dsrc[ 9];
649         ddst[1*dspl+2] = dsrc[10];
650         ddst[1*dspl+3] = dsrc[11];
651         ddst[1*dspl+4] = dsrc[12];
652         ddst[1*dspl+5] = dsrc[13];
653         ddst[1*dspl+6] = dsrc[14];
654         ddst[1*dspl+7] = dsrc[15];
655
656         ddst[2*dspl+0] = dsrc[16];
657         ddst[2*dspl+1] = dsrc[17];
658         ddst[2*dspl+2] = dsrc[18];
659         ddst[2*dspl+3] = dsrc[19];
660         ddst[2*dspl+4] = dsrc[20];
661         ddst[2*dspl+5] = dsrc[21];
662         ddst[2*dspl+6] = dsrc[22];
663         ddst[2*dspl+7] = dsrc[23];
664
665         ddst[3*dspl+0] = dsrc[24];
666         ddst[3*dspl+1] = dsrc[25];
667         ddst[3*dspl+2] = dsrc[26];
668         ddst[3*dspl+3] = dsrc[27];
669         ddst[3*dspl+4] = dsrc[28];
670         ddst[3*dspl+5] = dsrc[29];
671         ddst[3*dspl+6] = dsrc[30];
672         ddst[3*dspl+7] = dsrc[31];
673
674         ddst[4*dspl+0] = dsrc[32];
675         ddst[4*dspl+1] = dsrc[33];
676         ddst[4*dspl+2] = dsrc[34];
677         ddst[4*dspl+3] = dsrc[35];
678         ddst[4*dspl+4] = dsrc[36];
679         ddst[4*dspl+5] = dsrc[37];
680         ddst[4*dspl+6] = dsrc[38];
681         ddst[4*dspl+7] = dsrc[39];
682
683         ddst[5*dspl+0] = dsrc[40];
684         ddst[5*dspl+1] = dsrc[41];
685         ddst[5*dspl+2] = dsrc[42];
686         ddst[5*dspl+3] = dsrc[43];
687         ddst[5*dspl+4] = dsrc[44];
688         ddst[5*dspl+5] = dsrc[45];
689         ddst[5*dspl+6] = dsrc[46];
690         ddst[5*dspl+7] = dsrc[47];
691
692         ddst[6*dspl+0] = dsrc[48];
693         ddst[6*dspl+1] = dsrc[49];
694         ddst[6*dspl+2] = dsrc[50];
695         ddst[6*dspl+3] = dsrc[51];
696         ddst[6*dspl+4] = dsrc[52];
697         ddst[6*dspl+5] = dsrc[53];
698         ddst[6*dspl+6] = dsrc[54];
699         ddst[6*dspl+7] = dsrc[55];
700
701         ddst[7*dspl+0] = dsrc[56];
702         ddst[7*dspl+1] = dsrc[57];
703         ddst[7*dspl+2] = dsrc[58];
704         ddst[7*dspl+3] = dsrc[59];
705         ddst[7*dspl+4] = dsrc[60];
706         ddst[7*dspl+5] = dsrc[61];
707         ddst[7*dspl+6] = dsrc[62];
708         ddst[7*dspl+7] = dsrc[63];
709 #else
710         double *dsrc, *ddst;
711         int dspl;
712
713         dsrc = (double *)src;
714         ddst = (double *)dst;
715         dspl = spl>>3;
716
717         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
718         dsrc += 4; ddst += dspl;
719         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
720         dsrc += 4; ddst += dspl;
721         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
722         dsrc += 4; ddst += dspl;
723         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
724         dsrc += 4; ddst += dspl;
725         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
726         dsrc += 4; ddst += dspl;
727         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
728         dsrc += 4; ddst += dspl;
729         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
730         dsrc += 4; ddst += dspl;
731         ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
732 #endif
733 }
734
735 /*
736 ==============
737 idCinematicLocal::blit4_32
738 ==============
739 */
740 void idCinematicLocal::blit4_32( byte *src, byte *dst, int spl  ) {
741 #if 1
742         int *dsrc, *ddst;
743         int dspl;
744
745         dsrc = (int *)src;
746         ddst = (int *)dst;
747         dspl = spl>>2;
748
749         ddst[0*dspl+0] = dsrc[ 0];
750         ddst[0*dspl+1] = dsrc[ 1];
751         ddst[0*dspl+2] = dsrc[ 2];
752         ddst[0*dspl+3] = dsrc[ 3];
753         ddst[1*dspl+0] = dsrc[ 4];
754         ddst[1*dspl+1] = dsrc[ 5];
755         ddst[1*dspl+2] = dsrc[ 6];
756         ddst[1*dspl+3] = dsrc[ 7];
757         ddst[2*dspl+0] = dsrc[ 8];
758         ddst[2*dspl+1] = dsrc[ 9];
759         ddst[2*dspl+2] = dsrc[10];
760         ddst[2*dspl+3] = dsrc[11];
761         ddst[3*dspl+0] = dsrc[12];
762         ddst[3*dspl+1] = dsrc[13];
763         ddst[3*dspl+2] = dsrc[14];
764         ddst[3*dspl+3] = dsrc[15];
765 #else
766         double *dsrc, *ddst;
767         int dspl;
768
769         dsrc = (double *)src;
770         ddst = (double *)dst;
771         dspl = spl>>3;
772
773         ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
774         dsrc += 2; ddst += dspl;
775         ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
776         dsrc += 2; ddst += dspl;
777         ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
778         dsrc += 2; ddst += dspl;
779         ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
780 #endif
781 }
782
783 /*
784 ==============
785 idCinematicLocal::blit2_32
786 ==============
787 */
788 void idCinematicLocal::blit2_32( byte *src, byte *dst, int spl  ) {
789 #if 1
790         int *dsrc, *ddst;
791         int dspl;
792
793         dsrc = (int *)src;
794         ddst = (int *)dst;
795         dspl = spl>>2;
796
797         ddst[0*dspl+0] = dsrc[0];
798         ddst[0*dspl+1] = dsrc[1];
799         ddst[1*dspl+0] = dsrc[2];
800         ddst[1*dspl+1] = dsrc[3];
801 #else
802         double *dsrc, *ddst;
803         int dspl;
804
805         dsrc = (double *)src;
806         ddst = (double *)dst;
807         dspl = spl>>3;
808
809         ddst[0] = dsrc[0];
810         ddst[dspl] = dsrc[1];
811 #endif
812 }
813
814 /*
815 ==============
816 idCinematicLocal::blitVQQuad32fs
817 ==============
818 */
819 void idCinematicLocal::blitVQQuad32fs( byte **status, unsigned char *data ) {
820         unsigned short  newd, celdata, code;
821         unsigned int    index, i;
822
823         newd    = 0;
824         celdata = 0;
825         index   = 0;
826         
827         do {
828                 if (!newd) { 
829                         newd = 7;
830                         celdata = data[0] + data[1]*256;
831                         data += 2;
832                 } else {
833                         newd--;
834                 }
835
836                 code = (unsigned short)(celdata&0xc000); 
837                 celdata <<= 2;
838                 
839                 switch (code) {
840                         case    0x8000:                                                                                                 // vq code
841                                 blit8_32( (byte *)&vq8[(*data)*128], status[index], samplesPerLine );
842                                 data++;
843                                 index += 5;
844                                 break;
845                         case    0xc000:                                                                                                 // drop
846                                 index++;                                                                                                        // skip 8x8
847                                 for(i=0;i<4;i++) {
848                                         if (!newd) { 
849                                                 newd = 7;
850                                                 celdata = data[0] + data[1]*256;
851                                                 data += 2;
852                                         } else {
853                                                 newd--;
854                                         }
855                                                 
856                                         code = (unsigned short)(celdata&0xc000); celdata <<= 2; 
857
858                                         switch (code) {                                                                                 // code in top two bits of code
859                                                 case    0x8000:                                                                         // 4x4 vq code
860                                                         blit4_32( (byte *)&vq4[(*data)*32], status[index], samplesPerLine );
861                                                         data++;
862                                                         break;
863                                                 case    0xc000:                                                                         // 2x2 vq code
864                                                         blit2_32( (byte *)&vq2[(*data)*8], status[index], samplesPerLine );
865                                                         data++;
866                                                         blit2_32( (byte *)&vq2[(*data)*8], status[index]+8, samplesPerLine );
867                                                         data++;
868                                                         blit2_32( (byte *)&vq2[(*data)*8], status[index]+samplesPerLine*2, samplesPerLine );
869                                                         data++;
870                                                         blit2_32( (byte *)&vq2[(*data)*8], status[index]+samplesPerLine*2+8, samplesPerLine );
871                                                         data++;
872                                                         break;
873                                                 case    0x4000:                                                                         // motion compensation
874                                                         move4_32( status[index] + mcomp[(*data)], status[index], samplesPerLine );
875                                                         data++;
876                                                         break;
877                                         }
878                                         index++;
879                                 }
880                                 break;
881                         case    0x4000:                                                                                                 // motion compensation
882                                 move8_32( status[index] + mcomp[(*data)], status[index], samplesPerLine );
883                                 data++;
884                                 index += 5;
885                                 break;
886                         case    0x0000:
887                                 index += 5;
888                                 break;
889                 }
890         } while ( status[index] != NULL );
891 }
892
893 #define VQ2TO4(a,b,c,d) { \
894         *c++ = a[0];    \
895         *d++ = a[0];    \
896         *d++ = a[0];    \
897         *c++ = a[1];    \
898         *d++ = a[1];    \
899         *d++ = a[1];    \
900         *c++ = b[0];    \
901         *d++ = b[0];    \
902         *d++ = b[0];    \
903         *c++ = b[1];    \
904         *d++ = b[1];    \
905         *d++ = b[1];    \
906         *d++ = a[0];    \
907         *d++ = a[0];    \
908         *d++ = a[1];    \
909         *d++ = a[1];    \
910         *d++ = b[0];    \
911         *d++ = b[0];    \
912         *d++ = b[1];    \
913         *d++ = b[1];    \
914         a += 2; b += 2; }
915  
916 #define VQ2TO2(a,b,c,d) { \
917         *c++ = *a;      \
918         *d++ = *a;      \
919         *d++ = *a;      \
920         *c++ = *b;      \
921         *d++ = *b;      \
922         *d++ = *b;      \
923         *d++ = *a;      \
924         *d++ = *a;      \
925         *d++ = *b;      \
926         *d++ = *b;      \
927         a++; b++; }
928
929 /*
930 ==============
931 idCinematicLocal::yuv_to_rgb
932 ==============
933 */
934 unsigned short idCinematicLocal::yuv_to_rgb( long y, long u, long v ) { 
935         long r,g,b,YY = (long)(ROQ_YY_tab[(y)]);
936
937         r = (YY + ROQ_VR_tab[v]) >> 9;
938         g = (YY + ROQ_UG_tab[u] + ROQ_VG_tab[v]) >> 8;
939         b = (YY + ROQ_UB_tab[u]) >> 9;
940         
941         if (r<0) r = 0; if (g<0) g = 0; if (b<0) b = 0;
942         if (r > 31) r = 31; if (g > 63) g = 63; if (b > 31) b = 31;
943
944         return (unsigned short)((r<<11)+(g<<5)+(b));
945 }
946
947 /*
948 ==============
949 idCinematicLocal::yuv_to_rgb24
950 ==============
951 */
952 unsigned int idCinematicLocal::yuv_to_rgb24( long y, long u, long v ) { 
953         long r,g,b,YY = (long)(ROQ_YY_tab[(y)]);
954
955         r = (YY + ROQ_VR_tab[v]) >> 6;
956         g = (YY + ROQ_UG_tab[u] + ROQ_VG_tab[v]) >> 6;
957         b = (YY + ROQ_UB_tab[u]) >> 6;
958         
959         if (r<0) r = 0; if (g<0) g = 0; if (b<0) b = 0;
960         if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
961         
962         return LittleLong((r)+(g<<8)+(b<<16));
963 }
964
965 /*
966 ==============
967 idCinematicLocal::decodeCodeBook
968 ==============
969 */
970 void idCinematicLocal::decodeCodeBook( byte *input, unsigned short roq_flags ) {
971         long    i, j, two, four;
972         unsigned short  *aptr, *bptr, *cptr, *dptr;
973         long    y0,y1,y2,y3,cr,cb;
974         unsigned int *iaptr, *ibptr, *icptr, *idptr;
975
976         if (!roq_flags) {
977                 two = four = 256;
978         } else {
979                 two  = roq_flags>>8;
980                 if (!two) two = 256;
981                 four = roq_flags&0xff;
982         }
983
984         four *= 2;
985
986         bptr = (unsigned short *)vq2;
987
988         if (!half) {
989                 if (!smootheddouble) {
990 //
991 // normal height
992 //
993                         if (samplesPerPixel==2) {
994                                 for(i=0;i<two;i++) {
995                                         y0 = (long)*input++;
996                                         y1 = (long)*input++;
997                                         y2 = (long)*input++;
998                                         y3 = (long)*input++;
999                                         cr = (long)*input++;
1000                                         cb = (long)*input++;
1001                                         *bptr++ = yuv_to_rgb( y0, cr, cb );
1002                                         *bptr++ = yuv_to_rgb( y1, cr, cb );
1003                                         *bptr++ = yuv_to_rgb( y2, cr, cb );
1004                                         *bptr++ = yuv_to_rgb( y3, cr, cb );
1005                                 }
1006
1007                                 cptr = (unsigned short *)vq4;
1008                                 dptr = (unsigned short *)vq8;
1009                 
1010                                 for(i=0;i<four;i++) {
1011                                         aptr = (unsigned short *)vq2 + (*input++)*4;
1012                                         bptr = (unsigned short *)vq2 + (*input++)*4;
1013                                         for(j=0;j<2;j++)
1014                                                 VQ2TO4(aptr,bptr,cptr,dptr);
1015                                 }
1016                         } else if (samplesPerPixel==4) {
1017                                 ibptr = (unsigned int *)bptr;
1018                                 for(i=0;i<two;i++) {
1019                                         y0 = (long)*input++;
1020                                         y1 = (long)*input++;
1021                                         y2 = (long)*input++;
1022                                         y3 = (long)*input++;
1023                                         cr = (long)*input++;
1024                                         cb = (long)*input++;
1025                                         *ibptr++ = yuv_to_rgb24( y0, cr, cb );
1026                                         *ibptr++ = yuv_to_rgb24( y1, cr, cb );
1027                                         *ibptr++ = yuv_to_rgb24( y2, cr, cb );
1028                                         *ibptr++ = yuv_to_rgb24( y3, cr, cb );
1029                                 }
1030
1031                                 icptr = (unsigned int *)vq4;
1032                                 idptr = (unsigned int *)vq8;
1033         
1034                                 for(i=0;i<four;i++) {
1035                                         iaptr = (unsigned int *)vq2 + (*input++)*4;
1036                                         ibptr = (unsigned int *)vq2 + (*input++)*4;
1037                                         for(j=0;j<2;j++) 
1038                                                 VQ2TO4(iaptr, ibptr, icptr, idptr);
1039                                 }
1040                         }
1041                 } else {
1042 //
1043 // double height, smoothed
1044 //
1045                         if (samplesPerPixel==2) {
1046                                 for(i=0;i<two;i++) {
1047                                         y0 = (long)*input++;
1048                                         y1 = (long)*input++;
1049                                         y2 = (long)*input++;
1050                                         y3 = (long)*input++;
1051                                         cr = (long)*input++;
1052                                         cb = (long)*input++;
1053                                         *bptr++ = yuv_to_rgb( y0, cr, cb );
1054                                         *bptr++ = yuv_to_rgb( y1, cr, cb );
1055                                         *bptr++ = yuv_to_rgb( ((y0*3)+y2)/4, cr, cb );
1056                                         *bptr++ = yuv_to_rgb( ((y1*3)+y3)/4, cr, cb );
1057                                         *bptr++ = yuv_to_rgb( (y0+(y2*3))/4, cr, cb );
1058                                         *bptr++ = yuv_to_rgb( (y1+(y3*3))/4, cr, cb );
1059                                         *bptr++ = yuv_to_rgb( y2, cr, cb );
1060                                         *bptr++ = yuv_to_rgb( y3, cr, cb );
1061                                 }
1062
1063                                 cptr = (unsigned short *)vq4;
1064                                 dptr = (unsigned short *)vq8;
1065                 
1066                                 for(i=0;i<four;i++) {
1067                                         aptr = (unsigned short *)vq2 + (*input++)*8;
1068                                         bptr = (unsigned short *)vq2 + (*input++)*8;
1069                                         for(j=0;j<2;j++) {
1070                                                 VQ2TO4(aptr,bptr,cptr,dptr);
1071                                                 VQ2TO4(aptr,bptr,cptr,dptr);
1072                                         }
1073                                 }
1074                         } else if (samplesPerPixel==4) {
1075                                 ibptr = (unsigned int *)bptr;
1076                                 for(i=0;i<two;i++) {
1077                                         y0 = (long)*input++;
1078                                         y1 = (long)*input++;
1079                                         y2 = (long)*input++;
1080                                         y3 = (long)*input++;
1081                                         cr = (long)*input++;
1082                                         cb = (long)*input++;
1083                                         *ibptr++ = yuv_to_rgb24( y0, cr, cb );
1084                                         *ibptr++ = yuv_to_rgb24( y1, cr, cb );
1085                                         *ibptr++ = yuv_to_rgb24( ((y0*3)+y2)/4, cr, cb );
1086                                         *ibptr++ = yuv_to_rgb24( ((y1*3)+y3)/4, cr, cb );
1087                                         *ibptr++ = yuv_to_rgb24( (y0+(y2*3))/4, cr, cb );
1088                                         *ibptr++ = yuv_to_rgb24( (y1+(y3*3))/4, cr, cb );
1089                                         *ibptr++ = yuv_to_rgb24( y2, cr, cb );
1090                                         *ibptr++ = yuv_to_rgb24( y3, cr, cb );
1091                                 }
1092
1093                                 icptr = (unsigned int *)vq4;
1094                                 idptr = (unsigned int *)vq8;
1095         
1096                                 for(i=0;i<four;i++) {
1097                                         iaptr = (unsigned int *)vq2 + (*input++)*8;
1098                                         ibptr = (unsigned int *)vq2 + (*input++)*8;
1099                                         for(j=0;j<2;j++) {
1100                                                 VQ2TO4(iaptr, ibptr, icptr, idptr);
1101                                                 VQ2TO4(iaptr, ibptr, icptr, idptr);
1102                                         }
1103                                 }
1104                         }                       
1105                 }
1106         } else {
1107 //
1108 // 1/4 screen
1109 //
1110                 if (samplesPerPixel==2) {
1111                         for(i=0;i<two;i++) {
1112                                 y0 = (long)*input; input+=2;
1113                                 y2 = (long)*input; input+=2;
1114                                 cr = (long)*input++;
1115                                 cb = (long)*input++;
1116                                 *bptr++ = yuv_to_rgb( y0, cr, cb );
1117                                 *bptr++ = yuv_to_rgb( y2, cr, cb );
1118                         }
1119
1120                         cptr = (unsigned short *)vq4;
1121                         dptr = (unsigned short *)vq8;
1122         
1123                         for(i=0;i<four;i++) {
1124                                 aptr = (unsigned short *)vq2 + (*input++)*2;
1125                                 bptr = (unsigned short *)vq2 + (*input++)*2;
1126                                 for(j=0;j<2;j++) { 
1127                                         VQ2TO2(aptr,bptr,cptr,dptr);
1128                                 }
1129                         }
1130                 } else if (samplesPerPixel == 4) {
1131                         ibptr = (unsigned int *) bptr;
1132                         for(i=0;i<two;i++) {
1133                                 y0 = (long)*input; input+=2;
1134                                 y2 = (long)*input; input+=2;
1135                                 cr = (long)*input++;
1136                                 cb = (long)*input++;
1137                                 *ibptr++ = yuv_to_rgb24( y0, cr, cb );
1138                                 *ibptr++ = yuv_to_rgb24( y2, cr, cb );
1139                         }
1140
1141                         icptr = (unsigned int *)vq4;
1142                         idptr = (unsigned int *)vq8;
1143         
1144                         for(i=0;i<four;i++) {
1145                                 iaptr = (unsigned int *)vq2 + (*input++)*2;
1146                                 ibptr = (unsigned int *)vq2 + (*input++)*2;
1147                                 for(j=0;j<2;j++) { 
1148                                         VQ2TO2(iaptr,ibptr,icptr,idptr);
1149                                 }
1150                         }
1151                 }
1152         }
1153 }
1154
1155 /*
1156 ==============
1157 idCinematicLocal::recurseQuad
1158 ==============
1159 */
1160 void idCinematicLocal::recurseQuad( long startX, long startY, long quadSize, long xOff, long yOff ) {
1161         byte *scroff;
1162         long bigx, bigy, lowx, lowy, useY;
1163         long offset;
1164
1165         offset = screenDelta;
1166         
1167         lowx = lowy = 0;
1168         bigx = xsize;
1169         bigy = ysize;
1170
1171         if (bigx > CIN_WIDTH) bigx = CIN_WIDTH;
1172         if (bigy > CIN_HEIGHT) bigy = CIN_HEIGHT;
1173
1174         if ( (startX >= lowx) && (startX+quadSize) <= (bigx) && (startY+quadSize) <= (bigy) && (startY >= lowy) && quadSize <= MAXSIZE) {
1175                 useY = startY;
1176                 scroff = image + (useY+((CIN_HEIGHT-bigy)>>1)+yOff)*(samplesPerLine) + (((startX+xOff))*samplesPerPixel);
1177
1178                 qStatus[0][onQuad  ] = scroff;
1179                 qStatus[1][onQuad++] = scroff+offset;
1180         }
1181
1182         if ( quadSize != MINSIZE ) {
1183                 quadSize >>= 1;
1184                 recurseQuad( startX,              startY                  , quadSize, xOff, yOff );
1185                 recurseQuad( startX+quadSize, startY              , quadSize, xOff, yOff );
1186                 recurseQuad( startX,              startY+quadSize , quadSize, xOff, yOff );
1187                 recurseQuad( startX+quadSize, startY+quadSize , quadSize, xOff, yOff );
1188         }
1189 }
1190
1191 /*
1192 ==============
1193 idCinematicLocal::setupQuad
1194 ==============
1195 */
1196 void idCinematicLocal::setupQuad( long xOff, long yOff ) {
1197         long numQuadCels, i,x,y;
1198         byte *temp;
1199
1200         numQuadCels  = (CIN_WIDTH*CIN_HEIGHT) / (16);
1201         numQuadCels += numQuadCels/4 + numQuadCels/16;
1202         numQuadCels += 64;                                                        // for overflow
1203
1204         numQuadCels  = (xsize*ysize) / (16);
1205         numQuadCels += numQuadCels/4;
1206         numQuadCels += 64;                                                        // for overflow
1207
1208         onQuad = 0;
1209
1210         for(y=0;y<(long)ysize;y+=16) 
1211                 for(x=0;x<(long)xsize;x+=16) 
1212                         recurseQuad( x, y, 16, xOff, yOff );
1213
1214         temp = NULL;
1215
1216         for(i=(numQuadCels-64);i<numQuadCels;i++) {
1217                 qStatus[0][i] = temp;                     // eoq
1218                 qStatus[1][i] = temp;                     // eoq
1219         }
1220 }
1221
1222 /*
1223 ==============
1224 idCinematicLocal::readQuadInfo
1225 ==============
1226 */
1227 void idCinematicLocal::readQuadInfo( byte *qData ) {
1228         xsize    = qData[0]+qData[1]*256;
1229         ysize    = qData[2]+qData[3]*256;
1230         maxsize  = qData[4]+qData[5]*256;
1231         minsize  = qData[6]+qData[7]*256;
1232         
1233         CIN_HEIGHT = ysize;
1234         CIN_WIDTH  = xsize;
1235
1236         samplesPerLine = CIN_WIDTH*samplesPerPixel;
1237         screenDelta = CIN_HEIGHT*samplesPerLine;
1238
1239         if (!image ) {
1240                 image = (byte *)Mem_Alloc( CIN_WIDTH*CIN_HEIGHT*samplesPerPixel*2 );
1241         }
1242
1243         half = false;
1244         smootheddouble = false;
1245         
1246         t[0] = (0 - (unsigned int)image)+(unsigned int)image+screenDelta;
1247         t[1] = (0 - ((unsigned int)image + screenDelta))+(unsigned int)image;
1248
1249         drawX = CIN_WIDTH;
1250         drawY = CIN_HEIGHT;
1251 }
1252
1253 /*
1254 ==============
1255 idCinematicLocal::RoQPrepMcomp
1256 ==============
1257 */
1258 void idCinematicLocal::RoQPrepMcomp( long xoff, long yoff ) {
1259         long i, j, x, y, temp, temp2;
1260
1261         i=samplesPerLine; j=samplesPerPixel;
1262         if ( xsize == (ysize*4) && !half ) { j = j+j; i = i+i; }
1263         
1264         for(y=0;y<16;y++) {
1265                 temp2 = (y+yoff-8)*i;
1266                 for(x=0;x<16;x++) {
1267                         temp = (x+xoff-8)*j;
1268                         mcomp[(x*16)+y] = normalBuffer0-(temp2+temp);
1269                 }
1270         }
1271 }
1272
1273 /*
1274 ==============
1275 idCinematicLocal::RoQReset
1276 ==============
1277 */
1278 void idCinematicLocal::RoQReset() {
1279         
1280         iFile->Seek( 0, FS_SEEK_SET );
1281         iFile->Read( file, 16 );
1282         RoQ_init();
1283         status = FMV_LOOPED;
1284 }
1285
1286
1287 typedef struct {
1288   struct jpeg_source_mgr pub;   /* public fields */
1289
1290   byte   *infile;               /* source stream */
1291   JOCTET * buffer;              /* start of buffer */
1292   boolean start_of_file;        /* have we gotten any data yet? */
1293   int   memsize;
1294 } my_source_mgr;
1295
1296 typedef my_source_mgr * my_src_ptr;
1297
1298 #define INPUT_BUF_SIZE  32768   /* choose an efficiently fread'able size */
1299
1300 /* jpeg error handling */
1301 struct jpeg_error_mgr jerr;
1302
1303 /*
1304  * Fill the input buffer --- called whenever buffer is emptied.
1305  *
1306  * In typical applications, this should read fresh data into the buffer
1307  * (ignoring the current state of next_input_byte & bytes_in_buffer),
1308  * reset the pointer & count to the start of the buffer, and return TRUE
1309  * indicating that the buffer has been reloaded.  It is not necessary to
1310  * fill the buffer entirely, only to obtain at least one more byte.
1311  *
1312  * There is no such thing as an EOF return.  If the end of the file has been
1313  * reached, the routine has a choice of ERREXIT() or inserting fake data into
1314  * the buffer.  In most cases, generating a warning message and inserting a
1315  * fake EOI marker is the best course of action --- this will allow the
1316  * decompressor to output however much of the image is there.  However,
1317  * the resulting error message is misleading if the real problem is an empty
1318  * input file, so we handle that case specially.
1319  *
1320  * In applications that need to be able to suspend compression due to input
1321  * not being available yet, a FALSE return indicates that no more data can be
1322  * obtained right now, but more may be forthcoming later.  In this situation,
1323  * the decompressor will return to its caller (with an indication of the
1324  * number of scanlines it has read, if any).  The application should resume
1325  * decompression after it has loaded more data into the input buffer.  Note
1326  * that there are substantial restrictions on the use of suspension --- see
1327  * the documentation.
1328  *
1329  * When suspending, the decompressor will back up to a convenient restart point
1330  * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
1331  * indicate where the restart point will be if the current call returns FALSE.
1332  * Data beyond this point must be rescanned after resumption, so move it to
1333  * the front of the buffer rather than discarding it.
1334  */
1335
1336
1337 METHODDEF boolean fill_input_buffer( j_decompress_ptr cinfo )
1338 {
1339   my_src_ptr src = (my_src_ptr) cinfo->src;
1340   int nbytes;
1341
1342   nbytes = INPUT_BUF_SIZE;
1343   if (nbytes > src->memsize) nbytes = src->memsize;
1344   if (nbytes == 0) {
1345     /* Insert a fake EOI marker */
1346     src->buffer[0] = (JOCTET) 0xFF;
1347     src->buffer[1] = (JOCTET) JPEG_EOI;
1348     nbytes = 2;
1349   } else {
1350           memcpy( src->buffer, src->infile, INPUT_BUF_SIZE );
1351           src->infile = src->infile + nbytes;
1352           src->memsize = src->memsize - INPUT_BUF_SIZE;
1353   }
1354   src->pub.next_input_byte = src->buffer;
1355   src->pub.bytes_in_buffer = nbytes;
1356   src->start_of_file = FALSE;
1357
1358   return TRUE;
1359 }
1360 /*
1361  * Initialize source --- called by jpeg_read_header
1362  * before any data is actually read.
1363  */
1364
1365
1366 METHODDEF void init_source (j_decompress_ptr cinfo)
1367 {
1368   my_src_ptr src = (my_src_ptr) cinfo->src;
1369
1370   /* We reset the empty-input-file flag for each image,
1371    * but we don't clear the input buffer.
1372    * This is correct behavior for reading a series of images from one source.
1373    */
1374   src->start_of_file = TRUE;
1375 }
1376
1377 /*
1378  * Skip data --- used to skip over a potentially large amount of
1379  * uninteresting data (such as an APPn marker).
1380  *
1381  * Writers of suspendable-input applications must note that skip_input_data
1382  * is not granted the right to give a suspension return.  If the skip extends
1383  * beyond the data currently in the buffer, the buffer can be marked empty so
1384  * that the next read will cause a fill_input_buffer call that can suspend.
1385  * Arranging for additional bytes to be discarded before reloading the input
1386  * buffer is the application writer's problem.
1387  */
1388
1389 METHODDEF void
1390 skip_input_data (j_decompress_ptr cinfo, long num_bytes)
1391 {
1392   my_src_ptr src = (my_src_ptr) cinfo->src;
1393
1394   /* Just a dumb implementation for now.  Could use fseek() except
1395    * it doesn't work on pipes.  Not clear that being smart is worth
1396    * any trouble anyway --- large skips are infrequent.
1397    */
1398   if (num_bytes > 0) {
1399         src->infile = src->infile + num_bytes;
1400     src->pub.next_input_byte += (size_t) num_bytes;
1401     src->pub.bytes_in_buffer -= (size_t) num_bytes;
1402   }
1403 }
1404
1405
1406 /*
1407  * An additional method that can be provided by data source modules is the
1408  * resync_to_restart method for error recovery in the presence of RST markers.
1409  * For the moment, this source module just uses the default resync method
1410  * provided by the JPEG library.  That method assumes that no backtracking
1411  * is possible.
1412  */
1413
1414
1415 /*
1416  * Terminate source --- called by jpeg_finish_decompress
1417  * after all data has been read.  Often a no-op.
1418  *
1419  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
1420  * application must deal with any cleanup that should happen even
1421  * for error exit.
1422  */
1423
1424 METHODDEF void
1425 term_source (j_decompress_ptr cinfo)
1426 {
1427         cinfo = cinfo;
1428   /* no work necessary here */
1429 }
1430
1431 GLOBAL void
1432 jpeg_memory_src (j_decompress_ptr cinfo, byte *infile, int size)
1433 {
1434   my_src_ptr src;
1435
1436   /* The source object and input buffer are made permanent so that a series
1437    * of JPEG images can be read from the same file by calling jpeg_stdio_src
1438    * only before the first one.  (If we discarded the buffer at the end of
1439    * one image, we'd likely lose the start of the next one.)
1440    * This makes it unsafe to use this manager and a different source
1441    * manager serially with the same JPEG object.  Caveat programmer.
1442    */
1443   if (cinfo->src == NULL) {     /* first time for this JPEG object? */
1444     cinfo->src = (struct jpeg_source_mgr *)
1445       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
1446                                   sizeof(my_source_mgr));
1447     src = (my_src_ptr) cinfo->src;
1448     src->buffer = (JOCTET *)
1449       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
1450                                   INPUT_BUF_SIZE * sizeof(JOCTET));
1451   }
1452
1453   src = (my_src_ptr) cinfo->src;
1454   src->pub.init_source = init_source;
1455   src->pub.fill_input_buffer = fill_input_buffer;
1456   src->pub.skip_input_data = skip_input_data;
1457   src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
1458   src->pub.term_source = term_source;
1459   src->infile = infile;
1460   src->memsize = size;
1461   src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
1462   src->pub.next_input_byte = NULL; /* until buffer loaded */
1463 }
1464
1465 int JPEGBlit( byte *wStatus, byte *data, int datasize )
1466 {
1467   /* This struct contains the JPEG decompression parameters and pointers to
1468    * working space (which is allocated as needed by the JPEG library).
1469    */
1470   struct jpeg_decompress_struct cinfo;
1471   /* We use our private extension JPEG error handler.
1472    * Note that this struct must live as long as the main JPEG parameter
1473    * struct, to avoid dangling-pointer problems.
1474    */
1475   /* More stuff */
1476   JSAMPARRAY buffer;            /* Output row buffer */
1477   int row_stride;               /* physical row width in output buffer */
1478
1479   /* Step 1: allocate and initialize JPEG decompression object */
1480
1481   /* We set up the normal JPEG error routines, then override error_exit. */
1482   cinfo.err = jpeg_std_error(&jerr);
1483
1484   /* Now we can initialize the JPEG decompression object. */
1485   jpeg_create_decompress(&cinfo);
1486
1487   /* Step 2: specify data source (eg, a file) */
1488
1489   jpeg_memory_src(&cinfo, data, datasize);
1490
1491   /* Step 3: read file parameters with jpeg_read_header() */
1492
1493   (void) jpeg_read_header(&cinfo, TRUE);
1494   /* We can ignore the return value from jpeg_read_header since
1495    *   (a) suspension is not possible with the stdio data source, and
1496    *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
1497    * See libjpeg.doc for more info.
1498    */
1499
1500   /* Step 4: set parameters for decompression */
1501
1502   /* In this example, we don't need to change any of the defaults set by
1503    * jpeg_read_header(), so we do nothing here.
1504    */
1505
1506   /* Step 5: Start decompressor */
1507
1508         cinfo.dct_method = JDCT_IFAST;
1509     cinfo.dct_method = JDCT_FASTEST;
1510         cinfo.dither_mode = JDITHER_NONE;
1511     cinfo.do_fancy_upsampling = FALSE;
1512 //      cinfo.out_color_space = JCS_GRAYSCALE;
1513         
1514   (void) jpeg_start_decompress(&cinfo);
1515   /* We can ignore the return value since suspension is not possible
1516    * with the stdio data source.
1517    */
1518
1519   /* We may need to do some setup of our own at this point before reading
1520    * the data.  After jpeg_start_decompress() we have the correct scaled
1521    * output image dimensions available, as well as the output colormap
1522    * if we asked for color quantization.
1523    * In this example, we need to make an output work buffer of the right size.
1524    */ 
1525   /* JSAMPLEs per row in output buffer */
1526   row_stride = cinfo.output_width * cinfo.output_components;
1527
1528   /* Make a one-row-high sample array that will go away when done with image */
1529   buffer = (*cinfo.mem->alloc_sarray)
1530                 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
1531
1532   /* Step 6: while (scan lines remain to be read) */
1533   /*           jpeg_read_scanlines(...); */
1534
1535   /* Here we use the library's state variable cinfo.output_scanline as the
1536    * loop counter, so that we don't have to keep track ourselves.
1537    */
1538    
1539   wStatus += (cinfo.output_height-1)*row_stride;
1540   while (cinfo.output_scanline < cinfo.output_height) {
1541     /* jpeg_read_scanlines expects an array of pointers to scanlines.
1542      * Here the array is only one element long, but you could ask for
1543      * more than one scanline at a time if that's more convenient.
1544      */
1545     (void) jpeg_read_scanlines(&cinfo, &buffer[0], 1);
1546
1547     /* Assume put_scanline_someplace wants a pointer and sample count. */
1548         memcpy( wStatus, &buffer[0][0], row_stride );
1549         /*
1550         int x;
1551         unsigned int *buf = (unsigned int *)&buffer[0][0];
1552         unsigned int *out = (unsigned int *)wStatus;
1553         for(x=0;x<cinfo.output_width;x++) {
1554                 unsigned int pixel = buf[x];
1555                 byte *roof = (byte *)&pixel;
1556                 byte temp = roof[0];
1557                 roof[0] = roof[2];
1558                 roof[2] = temp;
1559                 out[x] = pixel;
1560         }
1561         */
1562         wStatus -= row_stride;
1563   }
1564
1565   /* Step 7: Finish decompression */
1566
1567   (void) jpeg_finish_decompress(&cinfo);
1568   /* We can ignore the return value since suspension is not possible
1569    * with the stdio data source.
1570    */
1571
1572   /* Step 8: Release JPEG decompression object */
1573
1574   /* This is an important step since it will release a good deal of memory. */
1575   jpeg_destroy_decompress(&cinfo);
1576
1577   /* At this point you may want to check to see whether any corrupt-data
1578    * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
1579    */
1580
1581   /* And we're done! */
1582   return 1;
1583 }
1584
1585 /*
1586 ==============
1587 idCinematicLocal::RoQInterrupt
1588 ==============
1589 */
1590 void idCinematicLocal::RoQInterrupt(void) {
1591         byte                            *framedata;
1592
1593         iFile->Read( file, RoQFrameSize+8 );
1594         if ( RoQPlayed >= ROQSize ) { 
1595                 if (looping) {
1596                         RoQReset();
1597                 } else {
1598                         status = FMV_EOF;
1599                 }
1600                 return; 
1601         }
1602
1603         framedata = file;
1604 //
1605 // new frame is ready
1606 //
1607 redump:
1608         switch(roq_id) 
1609         {
1610                 case    ROQ_QUAD_VQ:
1611                         if ((numQuads&1)) {
1612                                 normalBuffer0 = t[1];
1613                                 RoQPrepMcomp( roqF0, roqF1 );
1614                                 blitVQQuad32fs( qStatus[1], framedata);
1615                                 buf =   image + screenDelta;
1616                         } else {
1617                                 normalBuffer0 = t[0];
1618                                 RoQPrepMcomp( roqF0, roqF1 );
1619                                 blitVQQuad32fs( qStatus[0], framedata );
1620                                 buf =   image;
1621                         }
1622                         if (numQuads == 0) {            // first frame
1623                                 memcpy(image+screenDelta, image, samplesPerLine*ysize);
1624                         }
1625                         numQuads++;
1626                         dirty = true;
1627                         break;
1628                 case    ROQ_CODEBOOK:
1629                         decodeCodeBook( framedata, (unsigned short)roq_flags );
1630                         break;
1631                 case    ZA_SOUND_MONO:
1632                         break;
1633                 case    ZA_SOUND_STEREO:
1634                         break;
1635                 case    ROQ_QUAD_INFO:
1636                         if (numQuads == -1) {
1637                                 readQuadInfo( framedata );
1638                                 setupQuad( 0, 0 );
1639                         }
1640                         if (numQuads != 1) numQuads = 0;
1641                         break;
1642                 case    ROQ_PACKET:
1643                         inMemory = ( roq_flags != 0 );
1644                         RoQFrameSize = 0;           // for header
1645                         break;
1646                 case    ROQ_QUAD_HANG:
1647                         RoQFrameSize = 0;
1648                         break;
1649                 case    ROQ_QUAD_JPEG:
1650                         if (!numQuads) { 
1651                                 normalBuffer0 = t[0];
1652                                 JPEGBlit( image, framedata, RoQFrameSize );
1653                                 memcpy(image+screenDelta, image, samplesPerLine*ysize);
1654                                 numQuads++;
1655                         }
1656                         break;
1657                 default:
1658                         status = FMV_EOF;
1659                         break;
1660         }       
1661 //
1662 // read in next frame data
1663 //
1664         if ( RoQPlayed >= ROQSize ) { 
1665                 if (looping) {
1666                         RoQReset();
1667                 } else {
1668                         status = FMV_EOF;
1669                 }
1670                 return; 
1671         }
1672         
1673         framedata                += RoQFrameSize;
1674         roq_id           = framedata[0] + framedata[1]*256;
1675         RoQFrameSize = framedata[2] + framedata[3]*256 + framedata[4]*65536;
1676         roq_flags        = framedata[6] + framedata[7]*256;
1677         roqF0            = (char)framedata[7];
1678         roqF1            = (char)framedata[6];
1679
1680         if (RoQFrameSize>65536||roq_id==0x1084) {
1681                 common->DPrintf("roq_size>65536||roq_id==0x1084\n");
1682                 status = FMV_EOF;
1683                 if (looping) {
1684                         RoQReset();
1685                 }
1686                 return;
1687         }
1688         if (inMemory && (status != FMV_EOF)) { 
1689                 inMemory = false; framedata += 8; goto redump; 
1690         }
1691 //
1692 // one more frame hits the dust
1693 //
1694 //      assert(RoQFrameSize <= 65536);
1695 //      r = Sys_StreamedRead( file, RoQFrameSize+8, 1, iFile );
1696         RoQPlayed       += RoQFrameSize+8;
1697 }
1698
1699 /*
1700 ==============
1701 idCinematicLocal::RoQ_init
1702 ==============
1703 */
1704 void idCinematicLocal::RoQ_init( void ) {
1705
1706         RoQPlayed = 24;
1707
1708         /*      get frame rate */
1709         roqFPS   = file[ 6] + file[ 7]*256;
1710         
1711         if (!roqFPS) roqFPS = 30;
1712
1713         numQuads = -1;
1714
1715         roq_id          = file[ 8] + file[ 9]*256;
1716         RoQFrameSize= file[10] + file[11]*256 + file[12]*65536;
1717         roq_flags       = file[14] + file[15]*256;
1718 }
1719
1720 /*
1721 ==============
1722 idCinematicLocal::RoQShutdown
1723 ==============
1724 */
1725 void idCinematicLocal::RoQShutdown( void ) {
1726         if ( status == FMV_IDLE ) {
1727                 return;
1728         }
1729         status = FMV_IDLE;
1730
1731         if ( iFile ) {
1732                 fileSystem->CloseFile( iFile );
1733                 iFile = NULL;
1734         }
1735
1736         fileName = "";
1737 }
1738
1739 //===========================================
1740
1741 /*
1742 ==============
1743 idSndWindow::InitFromFile
1744 ==============
1745 */
1746 bool idSndWindow::InitFromFile( const char *qpath, bool looping ) {
1747         idStr fname = qpath;
1748
1749         fname.ToLower();
1750         if ( !fname.Icmp( "waveform" ) ) {
1751                 showWaveform = true;
1752         } else {
1753                 showWaveform = false;
1754         }
1755         return true;
1756 }
1757
1758 /*
1759 ==============
1760 idSndWindow::ImageForTime
1761 ==============
1762 */
1763 cinData_t idSndWindow::ImageForTime( int milliseconds ) {
1764         return soundSystem->ImageForTime( milliseconds, showWaveform );
1765 }
1766
1767 /*
1768 ==============
1769 idSndWindow::AnimationLength
1770 ==============
1771 */
1772 int idSndWindow::AnimationLength() {
1773         return -1;
1774 }