~ubuntu-branches/ubuntu/precise/openarena/precise

« back to all changes in this revision

Viewing changes to code/client/cl_cin.c

  • Committer: Bazaar Package Importer
  • Author(s): Bruno "Fuddl" Kleinert
  • Date: 2007-01-20 12:28:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070120122809-2yza5ojt7nqiyiam
Tags: upstream-0.6.0
ImportĀ upstreamĀ versionĀ 0.6.0

Show diffs side-by-side

added added

removed removed

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