📄 cl_cin.c
字号:
//
// 1/4 screen
//
if (cinTable[currentHandle].samplesPerPixel==2) {
for(i=0;i<two;i++) {
y0 = (long)*input; input+=2;
y2 = (long)*input; input+=2;
cr = (long)*input++;
cb = (long)*input++;
*bptr++ = yuv_to_rgb( y0, cr, cb );
*bptr++ = yuv_to_rgb( y2, cr, cb );
}
cptr = (unsigned short *)vq4;
dptr = (unsigned short *)vq8;
for(i=0;i<four;i++) {
aptr = (unsigned short *)vq2 + (*input++)*2;
bptr = (unsigned short *)vq2 + (*input++)*2;
for(j=0;j<2;j++) {
VQ2TO2(aptr,bptr,cptr,dptr);
}
}
} else if (cinTable[currentHandle].samplesPerPixel == 1) {
bbptr = (byte *)bptr;
for(i=0;i<two;i++) {
*bbptr++ = cinTable[currentHandle].gray[*input]; input+=2;
*bbptr++ = cinTable[currentHandle].gray[*input]; input+=4;
}
bcptr = (byte *)vq4;
bdptr = (byte *)vq8;
for(i=0;i<four;i++) {
baptr = (byte *)vq2 + (*input++)*2;
bbptr = (byte *)vq2 + (*input++)*2;
for(j=0;j<2;j++) {
VQ2TO2(baptr,bbptr,bcptr,bdptr);
}
}
} else if (cinTable[currentHandle].samplesPerPixel == 4) {
ibptr = (unsigned int *) bptr;
for(i=0;i<two;i++) {
y0 = (long)*input; input+=2;
y2 = (long)*input; input+=2;
cr = (long)*input++;
cb = (long)*input++;
*ibptr++ = yuv_to_rgb24( y0, cr, cb );
*ibptr++ = yuv_to_rgb24( y2, cr, cb );
}
icptr = (unsigned int *)vq4;
idptr = (unsigned int *)vq8;
for(i=0;i<four;i++) {
iaptr = (unsigned int *)vq2 + (*input++)*2;
ibptr = (unsigned int *)vq2 + (*input++)*2;
for(j=0;j<2;j++) {
VQ2TO2(iaptr,ibptr,icptr,idptr);
}
}
}
}
}
/******************************************************************************
*
* Function:
*
* Description:
*
******************************************************************************/
static void recurseQuad( long startX, long startY, long quadSize, long xOff, long yOff )
{
byte *scroff;
long bigx, bigy, lowx, lowy, useY;
long offset;
offset = cinTable[currentHandle].screenDelta;
lowx = lowy = 0;
bigx = cinTable[currentHandle].xsize;
bigy = cinTable[currentHandle].ysize;
if (bigx > cinTable[currentHandle].CIN_WIDTH) bigx = cinTable[currentHandle].CIN_WIDTH;
if (bigy > cinTable[currentHandle].CIN_HEIGHT) bigy = cinTable[currentHandle].CIN_HEIGHT;
if ( (startX >= lowx) && (startX+quadSize) <= (bigx) && (startY+quadSize) <= (bigy) && (startY >= lowy) && quadSize <= MAXSIZE) {
useY = startY;
scroff = cin.linbuf + (useY+((cinTable[currentHandle].CIN_HEIGHT-bigy)>>1)+yOff)*(cinTable[currentHandle].samplesPerLine) + (((startX+xOff))*cinTable[currentHandle].samplesPerPixel);
cin.qStatus[0][cinTable[currentHandle].onQuad ] = scroff;
cin.qStatus[1][cinTable[currentHandle].onQuad++] = scroff+offset;
}
if ( quadSize != MINSIZE ) {
quadSize >>= 1;
recurseQuad( startX, startY , quadSize, xOff, yOff );
recurseQuad( startX+quadSize, startY , quadSize, xOff, yOff );
recurseQuad( startX, startY+quadSize , quadSize, xOff, yOff );
recurseQuad( startX+quadSize, startY+quadSize , quadSize, xOff, yOff );
}
}
/******************************************************************************
*
* Function:
*
* Description:
*
******************************************************************************/
static void setupQuad( long xOff, long yOff )
{
long numQuadCels, i,x,y;
byte *temp;
if (xOff == cin.oldXOff && yOff == cin.oldYOff && cinTable[currentHandle].ysize == cin.oldysize && cinTable[currentHandle].xsize == cin.oldxsize) {
return;
}
cin.oldXOff = xOff;
cin.oldYOff = yOff;
cin.oldysize = cinTable[currentHandle].ysize;
cin.oldxsize = cinTable[currentHandle].xsize;
numQuadCels = (cinTable[currentHandle].CIN_WIDTH*cinTable[currentHandle].CIN_HEIGHT) / (16);
numQuadCels += numQuadCels/4 + numQuadCels/16;
numQuadCels += 64; // for overflow
numQuadCels = (cinTable[currentHandle].xsize*cinTable[currentHandle].ysize) / (16);
numQuadCels += numQuadCels/4;
numQuadCels += 64; // for overflow
cinTable[currentHandle].onQuad = 0;
for(y=0;y<(long)cinTable[currentHandle].ysize;y+=16)
for(x=0;x<(long)cinTable[currentHandle].xsize;x+=16)
recurseQuad( x, y, 16, xOff, yOff );
temp = NULL;
for(i=(numQuadCels-64);i<numQuadCels;i++) {
cin.qStatus[0][i] = temp; // eoq
cin.qStatus[1][i] = temp; // eoq
}
}
/******************************************************************************
*
* Function:
*
* Description:
*
******************************************************************************/
static void readQuadInfo( byte *qData )
{
if (currentHandle < 0) return;
cinTable[currentHandle].xsize = qData[0]+qData[1]*256;
cinTable[currentHandle].ysize = qData[2]+qData[3]*256;
cinTable[currentHandle].maxsize = qData[4]+qData[5]*256;
cinTable[currentHandle].minsize = qData[6]+qData[7]*256;
cinTable[currentHandle].CIN_HEIGHT = cinTable[currentHandle].ysize;
cinTable[currentHandle].CIN_WIDTH = cinTable[currentHandle].xsize;
cinTable[currentHandle].samplesPerLine = cinTable[currentHandle].CIN_WIDTH*cinTable[currentHandle].samplesPerPixel;
cinTable[currentHandle].screenDelta = cinTable[currentHandle].CIN_HEIGHT*cinTable[currentHandle].samplesPerLine;
cinTable[currentHandle].half = qfalse;
cinTable[currentHandle].smootheddouble = qfalse;
cinTable[currentHandle].VQ0 = cinTable[currentHandle].VQNormal;
cinTable[currentHandle].VQ1 = cinTable[currentHandle].VQBuffer;
cinTable[currentHandle].t[0] = (0 - (unsigned int)cin.linbuf)+(unsigned int)cin.linbuf+cinTable[currentHandle].screenDelta;
cinTable[currentHandle].t[1] = (0 - ((unsigned int)cin.linbuf + cinTable[currentHandle].screenDelta))+(unsigned int)cin.linbuf;
cinTable[currentHandle].drawX = cinTable[currentHandle].CIN_WIDTH;
cinTable[currentHandle].drawY = cinTable[currentHandle].CIN_HEIGHT;
// rage pro is very slow at 512 wide textures, voodoo can't do it at all
if ( glConfig.hardwareType == GLHW_RAGEPRO || glConfig.maxTextureSize <= 256) {
if (cinTable[currentHandle].drawX>256) {
cinTable[currentHandle].drawX = 256;
}
if (cinTable[currentHandle].drawY>256) {
cinTable[currentHandle].drawY = 256;
}
if (cinTable[currentHandle].CIN_WIDTH != 256 || cinTable[currentHandle].CIN_HEIGHT != 256) {
Com_Printf("HACK: approxmimating cinematic for Rage Pro or Voodoo\n");
}
}
#if defined(MACOS_X)
cinTable[currentHandle].drawX = 256;
cinTable[currentHandle].drawX = 256;
#endif
}
/******************************************************************************
*
* Function:
*
* Description:
*
******************************************************************************/
static void RoQPrepMcomp( long xoff, long yoff )
{
long i, j, x, y, temp, temp2;
i=cinTable[currentHandle].samplesPerLine; j=cinTable[currentHandle].samplesPerPixel;
if ( cinTable[currentHandle].xsize == (cinTable[currentHandle].ysize*4) && !cinTable[currentHandle].half ) { j = j+j; i = i+i; }
for(y=0;y<16;y++) {
temp2 = (y+yoff-8)*i;
for(x=0;x<16;x++) {
temp = (x+xoff-8)*j;
cin.mcomp[(x*16)+y] = cinTable[currentHandle].normalBuffer0-(temp2+temp);
}
}
}
/******************************************************************************
*
* Function:
*
* Description:
*
******************************************************************************/
static void initRoQ()
{
if (currentHandle < 0) return;
cinTable[currentHandle].VQNormal = (void (*)(byte *, void *))blitVQQuad32fs;
cinTable[currentHandle].VQBuffer = (void (*)(byte *, void *))blitVQQuad32fs;
cinTable[currentHandle].samplesPerPixel = 4;
ROQ_GenYUVTables();
RllSetupTable();
}
/******************************************************************************
*
* Function:
*
* Description:
*
******************************************************************************/
/*
static byte* RoQFetchInterlaced( byte *source ) {
int x, *src, *dst;
if (currentHandle < 0) return NULL;
src = (int *)source;
dst = (int *)cinTable[currentHandle].buf2;
for(x=0;x<256*256;x++) {
*dst = *src;
dst++; src += 2;
}
return cinTable[currentHandle].buf2;
}
*/
static void RoQReset() {
if (currentHandle < 0) return;
Sys_EndStreamedFile(cinTable[currentHandle].iFile);
FS_FCloseFile( cinTable[currentHandle].iFile );
FS_FOpenFileRead (cinTable[currentHandle].fileName, &cinTable[currentHandle].iFile, qtrue);
// let the background thread start reading ahead
Sys_BeginStreamedFile( cinTable[currentHandle].iFile, 0x10000 );
Sys_StreamedRead (cin.file, 16, 1, cinTable[currentHandle].iFile);
RoQ_init();
cinTable[currentHandle].status = FMV_LOOPED;
}
/******************************************************************************
*
* Function:
*
* Description:
*
******************************************************************************/
static void RoQInterrupt(void)
{
byte *framedata;
short sbuf[32768];
int ssize;
if (currentHandle < 0) return;
Sys_StreamedRead( cin.file, cinTable[currentHandle].RoQFrameSize+8, 1, cinTable[currentHandle].iFile );
if ( cinTable[currentHandle].RoQPlayed >= cinTable[currentHandle].ROQSize ) {
if (cinTable[currentHandle].holdAtEnd==qfalse) {
if (cinTable[currentHandle].looping) {
RoQReset();
} else {
cinTable[currentHandle].status = FMV_EOF;
}
} else {
cinTable[currentHandle].status = FMV_IDLE;
}
return;
}
framedata = cin.file;
//
// new frame is ready
//
redump:
switch(cinTable[currentHandle].roq_id)
{
case ROQ_QUAD_VQ:
if ((cinTable[currentHandle].numQuads&1)) {
cinTable[currentHandle].normalBuffer0 = cinTable[currentHandle].t[1];
RoQPrepMcomp( cinTable[currentHandle].roqF0, cinTable[currentHandle].roqF1 );
cinTable[currentHandle].VQ1( (byte *)cin.qStatus[1], framedata);
cinTable[currentHandle].buf = cin.linbuf + cinTable[currentHandle].screenDelta;
} else {
cinTable[currentHandle].normalBuffer0 = cinTable[currentHandle].t[0];
RoQPrepMcomp( cinTable[currentHandle].roqF0, cinTable[currentHandle].roqF1 );
cinTable[currentHandle].VQ0( (byte *)cin.qStatus[0], framedata );
cinTable[currentHandle].buf = cin.linbuf;
}
if (cinTable[currentHandle].numQuads == 0) { // first frame
Com_Memcpy(cin.linbuf+cinTable[currentHandle].screenDelta, cin.linbuf, cinTable[currentHandle].samplesPerLine*cinTable[currentHandle].ysize);
}
cinTable[currentHandle].numQuads++;
cinTable[currentHandle].dirty = qtrue;
break;
case ROQ_CODEBOOK:
decodeCodeBook( framedata, (unsigned short)cinTable[currentHandle].roq_flags );
break;
case ZA_SOUND_MONO:
if (!cinTable[currentHandle].silent) {
ssize = RllDecodeMonoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
S_RawSamples( ssize, 22050, 2, 1, (byte *)sbuf, 1.0f );
}
break;
case ZA_SOUND_STEREO:
if (!cinTable[currentHandle].silent) {
if (cinTable[currentHandle].numQuads == -1) {
S_Update();
s_rawend = s_soundtime;
}
ssize = RllDecodeStereoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
S_RawSamples( ssize, 22050, 2, 2, (byte *)sbuf, 1.0f );
}
break;
case ROQ_QUAD_INFO:
if (cinTable[currentHandle].numQuads == -1) {
readQuadInfo( framedata );
setupQuad( 0, 0 );
// we need to use CL_ScaledMilliseconds because of the smp mode calls from the renderer
cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds()*com_timescale->value;
}
if (cinTable[currentHandle].numQuads != 1) cinTable[currentHandle].numQuads = 0;
break;
case ROQ_PACKET:
cinTable[currentHandle].inMemory = cinTable[currentHandle].roq_flags;
cinTable[currentHandle].RoQFrameSize = 0; // for header
break;
case ROQ_QUAD_HANG:
cinTable[currentHandle].RoQFrameSize = 0;
break;
case ROQ_QUAD_JPEG:
break;
default:
cinTable[currentHandle].status = FMV_EOF;
break;
}
//
// read in next frame data
//
if ( cinTable[currentHandle].RoQPlayed >= cinTable[currentHandle].ROQSize ) {
if (cinTable[currentHandle].holdAtEnd==qfalse) {
if (cinTable[currentHandle].looping) {
RoQReset();
} else {
cinTable[currentHandle].status = FMV_EOF;
}
} else {
cinTable[currentHandle].status = FMV_IDLE;
}
return;
}
framedata += cinTable[currentHandle].RoQFrameSize;
cinTable[currentHandle].roq_id = framedata[0] + framedata[1]*256;
cinTable[currentHandle].RoQFrameSize = framedata[2] + framedata[3]*256 + framedata[4]*65536;
cinTable[currentHandle].roq_flags = framedata[6] + framedata[7]*256;
cinTable[currentHandle].roqF0 = (char)framedata[7];
cinTable[currentHandle].roqF1 = (char)framedata[6];
if (cinTable[currentHandle].RoQFrameSize>65536||cinTable[currentHandle].roq_id==0x1084) {
Com_DPrintf("roq_size>65536||roq_id==0x1084\n");
cinTable[currentHandle].status = FMV_EOF;
if (cinTable[currentHandle].looping) {
RoQReset();
}
return;
}
if (cinTable[currentHandle].inMemory && (cinTable[currentHandle].status != FMV_EOF)) { cinTable[currentHandle].inMemory--; framedata += 8; goto redump; }
//
// one more frame hits the dust
//
// assert(cinTable[currentHandle].RoQFrameSize <= 65536);
// r = Sys_StreamedRead( cin.file, cinTable[currentHandle].RoQFrameSize+8, 1, cinTable[currentHandle].iFile );
cinTable[currentHandle].RoQPlayed += cinTable[currentHandle].RoQFrameSize+8;
}
/******************************************************************************
*
* Function:
*
* Description:
*
******************************************************************************/
static void RoQ_init( void )
{
// we need to use CL_ScaledMilliseconds because of the smp mode calls from the renderer
cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds()*com_timescale->value;
cinTable[currentHandle].RoQPlayed = 24;
/* get frame rate */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -