/*
===========================================================================
IceTech GPL Source Code
Copyright (C) 2026 Justin Marshall
This file is part of the IceTech GPL Source Code (?IceTech Source Code?).
IceTech Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IceTech Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with IceTech Source Code. If not, see .
In addition, the IceTech 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 IceTech Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Justin Marshall, justinmarshall20@gmail.com
===========================================================================
*/
#include "precompiled.h"
#pragma hdrstop
#include "tr_local.h"
#define LittleInt(x) x
#define CIN_system 1
#define CIN_loop 2
#define CIN_hold 4
#define CIN_silent 8
#define CIN_shader 16
class idCinematicLocal : public idCinematic {
public:
idCinematicLocal();
virtual ~idCinematicLocal();
virtual bool InitFromFile(const char* qpath, bool looping);
virtual cinData_t ImageForTime(int milliseconds);
virtual int AnimationLength();
virtual void Close();
virtual void ResetTime(int time);
private:
size_t mcomp[256];
byte** qStatus[2];
idStr fileName;
int CIN_WIDTH, CIN_HEIGHT;
idFile* iFile;
cinStatus_t status;
int tfps;
int RoQPlayed;
int ROQSize;
unsigned int RoQFrameSize;
int onQuad;
int numQuads;
int samplesPerLine;
unsigned int roq_id;
int screenDelta;
byte* buf;
int samplesPerPixel; // defaults to 2
unsigned int xsize, ysize, maxsize, minsize;
int normalBuffer0;
int roq_flags;
int roqF0;
int roqF1;
int t[2];
int roqFPS;
int drawX, drawY;
int animationLength;
int startTime;
float frameRate;
byte* image;
bool looping;
bool dirty;
bool half;
bool smootheddouble;
bool inMemory;
void RoQ_init(void);
void blitVQQuad32fs(byte** status, unsigned char* data);
void RoQShutdown(void);
void RoQInterrupt(void);
void move8_32(byte* src, byte* dst, int spl);
void move4_32(byte* src, byte* dst, int spl);
void blit8_32(byte* src, byte* dst, int spl);
void blit4_32(byte* src, byte* dst, int spl);
void blit2_32(byte* src, byte* dst, int spl);
unsigned short yuv_to_rgb(int y, int u, int v);
unsigned int yuv_to_rgb24(int y, int u, int v);
void decodeCodeBook(byte* input, unsigned short roq_flags);
void recurseQuad(int startX, int startY, int quadSize, int xOff, int yOff);
void setupQuad(int xOff, int yOff);
void readQuadInfo(byte* qData);
void RoQPrepMcomp(int xoff, int yoff);
void RoQReset();
};
const int DEFAULT_CIN_WIDTH = 512;
const int DEFAULT_CIN_HEIGHT = 512;
const int MAXSIZE = 8;
const int MINSIZE = 4;
const int ROQ_FILE = 0x1084;
const int ROQ_QUAD = 0x1000;
const int ROQ_QUAD_INFO = 0x1001;
const int ROQ_CODEBOOK = 0x1002;
const int ROQ_QUAD_VQ = 0x1011;
const int ROQ_QUAD_JPEG = 0x1012;
const int ROQ_QUAD_HANG = 0x1013;
const int ROQ_PACKET = 0x1030;
const int ZA_SOUND_MONO = 0x1020;
const int ZA_SOUND_STEREO = 0x1021;
// temporary buffers used by all cinematics
static int ROQ_YY_tab[256];
static int ROQ_UB_tab[256];
static int ROQ_UG_tab[256];
static int ROQ_VG_tab[256];
static int ROQ_VR_tab[256];
static byte* file = NULL;
static unsigned short* vq2 = NULL;
static unsigned short* vq4 = NULL;
static unsigned short* vq8 = NULL;
//===========================================
/*
==============
idCinematicLocal::InitCinematic
==============
*/
void idCinematic::InitCinematic(void) {
float t_ub, t_vr, t_ug, t_vg;
int i;
// generate YUV tables
t_ub = (1.77200f / 2.0f) * (float)(1 << 6) + 0.5f;
t_vr = (1.40200f / 2.0f) * (float)(1 << 6) + 0.5f;
t_ug = (0.34414f / 2.0f) * (float)(1 << 6) + 0.5f;
t_vg = (0.71414f / 2.0f) * (float)(1 << 6) + 0.5f;
for (i = 0; i < 256; i++) {
float x = (float)(2 * i - 255);
ROQ_UB_tab[i] = (int)((t_ub * x) + (1 << 5));
ROQ_VR_tab[i] = (int)((t_vr * x) + (1 << 5));
ROQ_UG_tab[i] = (int)((-t_ug * x));
ROQ_VG_tab[i] = (int)((-t_vg * x) + (1 << 5));
ROQ_YY_tab[i] = (int)((i << 6) | (i >> 2));
}
file = (byte*)Mem_Alloc(65536);
vq2 = (word*)Mem_Alloc(256 * 16 * 4 * sizeof(word));
vq4 = (word*)Mem_Alloc(256 * 64 * 4 * sizeof(word));
vq8 = (word*)Mem_Alloc(256 * 256 * 4 * sizeof(word));
}
/*
==============
idCinematicLocal::ShutdownCinematic
==============
*/
void idCinematic::ShutdownCinematic(void) {
Mem_Free(file);
file = NULL;
Mem_Free(vq2);
vq2 = NULL;
Mem_Free(vq4);
vq4 = NULL;
Mem_Free(vq8);
vq8 = NULL;
}
/*
==============
idCinematicLocal::Alloc
==============
*/
idCinematic* idCinematic::Alloc() {
return new idCinematicLocal;
}
/*
==============
idCinematicLocal::~idCinematic
==============
*/
idCinematic::~idCinematic() {
Close();
}
/*
==============
idCinematicLocal::InitFromFile
==============
*/
bool idCinematic::InitFromFile(const char* qpath, bool looping) {
return false;
}
/*
==============
idCinematicLocal::AnimationLength
==============
*/
int idCinematic::AnimationLength() {
return 0;
}
/*
==============
idCinematicLocal::ResetTime
==============
*/
void idCinematic::ResetTime(int milliseconds) {
}
/*
==============
idCinematicLocal::ImageForTime
==============
*/
cinData_t idCinematic::ImageForTime(int milliseconds) {
cinData_t c;
memset(&c, 0, sizeof(c));
return c;
}
/*
==============
idCinematicLocal::Close
==============
*/
void idCinematic::Close() {
}
//===========================================
/*
==============
idCinematicLocal::idCinematicLocal
==============
*/
idCinematicLocal::idCinematicLocal() {
image = NULL;
status = FMV_EOF;
buf = NULL;
iFile = NULL;
qStatus[0] = (byte**)Mem_Alloc(32768 * sizeof(byte*));
qStatus[1] = (byte**)Mem_Alloc(32768 * sizeof(byte*));
}
/*
==============
idCinematicLocal::~idCinematicLocal
==============
*/
idCinematicLocal::~idCinematicLocal() {
Close();
Mem_Free(qStatus[0]);
qStatus[0] = NULL;
Mem_Free(qStatus[1]);
qStatus[1] = NULL;
}
/*
==============
idCinematicLocal::InitFromFile
==============
*/
bool idCinematicLocal::InitFromFile(const char* qpath, bool amilooping) {
unsigned short RoQID;
Close();
inMemory = 0;
animationLength = 100000;
if (strstr(qpath, "/") == NULL && strstr(qpath, "\\") == NULL) {
sprintf(fileName, "video/%s", qpath);
}
else {
sprintf(fileName, "%s", qpath);
}
iFile = fileSystem->OpenFileRead(fileName);
if (!iFile) {
return false;
}
ROQSize = iFile->Length();
looping = amilooping;
CIN_HEIGHT = DEFAULT_CIN_HEIGHT;
CIN_WIDTH = DEFAULT_CIN_WIDTH;
samplesPerPixel = 4;
startTime = 0; //Sys_Milliseconds();
buf = NULL;
iFile->Read(file, 16);
RoQID = (unsigned short)(file[0]) + (unsigned short)(file[1]) * 256;
frameRate = file[6];
if (frameRate == 32.0f) {
frameRate = 1000.0f / 32.0f;
}
if (RoQID == ROQ_FILE) {
RoQ_init();
status = FMV_PLAY;
ImageForTime(0);
status = (looping) ? FMV_PLAY : FMV_IDLE;
return true;
}
RoQShutdown();
return false;
}
/*
==============
idCinematicLocal::Close
==============
*/
void idCinematicLocal::Close() {
if (image) {
Mem_Free((void*)image);
image = NULL;
buf = NULL;
status = FMV_EOF;
}
RoQShutdown();
}
/*
==============
idCinematicLocal::AnimationLength
==============
*/
int idCinematicLocal::AnimationLength() {
return animationLength;
}
/*
==============
idCinematicLocal::ResetTime
==============
*/
void idCinematicLocal::ResetTime(int time) {
startTime = (backEnd.viewDef) ? 1000 * backEnd.viewDef->floatTime : -1;
status = FMV_PLAY;
}
/*
==============
idCinematicLocal::ImageForTime
==============
*/
cinData_t idCinematicLocal::ImageForTime(int thisTime) {
cinData_t cinData;
if (thisTime < 0) {
thisTime = 0;
}
memset(&cinData, 0, sizeof(cinData));
if (r_skipROQ.GetBool()) {
return cinData;
}
if (status == FMV_EOF || status == FMV_IDLE) {
return cinData;
}
if (buf == NULL || startTime == -1) {
if (startTime == -1) {
RoQReset();
}
startTime = thisTime;
}
tfps = ((thisTime - startTime) * frameRate) / 1000;
if (tfps < 0) {
tfps = 0;
}
if (tfps < numQuads) {
RoQReset();
buf = NULL;
status = FMV_PLAY;
}
if (buf == NULL) {
while (buf == NULL) {
RoQInterrupt();
}
}
else {
while ((tfps != numQuads && status == FMV_PLAY)) {
RoQInterrupt();
}
}
if (status == FMV_LOOPED) {
status = FMV_PLAY;
while (buf == NULL && status == FMV_PLAY) {
RoQInterrupt();
}
startTime = thisTime;
}
if (status == FMV_EOF) {
if (looping) {
RoQReset();
buf = NULL;
if (status == FMV_LOOPED) {
status = FMV_PLAY;
}
while (buf == NULL && status == FMV_PLAY) {
RoQInterrupt();
}
startTime = thisTime;
}
else {
status = FMV_IDLE;
RoQShutdown();
}
}
cinData.imageWidth = CIN_WIDTH;
cinData.imageHeight = CIN_HEIGHT;
cinData.status = status;
cinData.image = buf;
return cinData;
}
/*
==============
idCinematicLocal::move8_32
==============
*/
void idCinematicLocal::move8_32(byte* src, byte* dst, int spl) {
#if 1
int* dsrc, * ddst;
int dspl;
dsrc = (int*)src;
ddst = (int*)dst;
dspl = spl >> 2;
ddst[0 * dspl + 0] = dsrc[0 * dspl + 0];
ddst[0 * dspl + 1] = dsrc[0 * dspl + 1];
ddst[0 * dspl + 2] = dsrc[0 * dspl + 2];
ddst[0 * dspl + 3] = dsrc[0 * dspl + 3];
ddst[0 * dspl + 4] = dsrc[0 * dspl + 4];
ddst[0 * dspl + 5] = dsrc[0 * dspl + 5];
ddst[0 * dspl + 6] = dsrc[0 * dspl + 6];
ddst[0 * dspl + 7] = dsrc[0 * dspl + 7];
ddst[1 * dspl + 0] = dsrc[1 * dspl + 0];
ddst[1 * dspl + 1] = dsrc[1 * dspl + 1];
ddst[1 * dspl + 2] = dsrc[1 * dspl + 2];
ddst[1 * dspl + 3] = dsrc[1 * dspl + 3];
ddst[1 * dspl + 4] = dsrc[1 * dspl + 4];
ddst[1 * dspl + 5] = dsrc[1 * dspl + 5];
ddst[1 * dspl + 6] = dsrc[1 * dspl + 6];
ddst[1 * dspl + 7] = dsrc[1 * dspl + 7];
ddst[2 * dspl + 0] = dsrc[2 * dspl + 0];
ddst[2 * dspl + 1] = dsrc[2 * dspl + 1];
ddst[2 * dspl + 2] = dsrc[2 * dspl + 2];
ddst[2 * dspl + 3] = dsrc[2 * dspl + 3];
ddst[2 * dspl + 4] = dsrc[2 * dspl + 4];
ddst[2 * dspl + 5] = dsrc[2 * dspl + 5];
ddst[2 * dspl + 6] = dsrc[2 * dspl + 6];
ddst[2 * dspl + 7] = dsrc[2 * dspl + 7];
ddst[3 * dspl + 0] = dsrc[3 * dspl + 0];
ddst[3 * dspl + 1] = dsrc[3 * dspl + 1];
ddst[3 * dspl + 2] = dsrc[3 * dspl + 2];
ddst[3 * dspl + 3] = dsrc[3 * dspl + 3];
ddst[3 * dspl + 4] = dsrc[3 * dspl + 4];
ddst[3 * dspl + 5] = dsrc[3 * dspl + 5];
ddst[3 * dspl + 6] = dsrc[3 * dspl + 6];
ddst[3 * dspl + 7] = dsrc[3 * dspl + 7];
ddst[4 * dspl + 0] = dsrc[4 * dspl + 0];
ddst[4 * dspl + 1] = dsrc[4 * dspl + 1];
ddst[4 * dspl + 2] = dsrc[4 * dspl + 2];
ddst[4 * dspl + 3] = dsrc[4 * dspl + 3];
ddst[4 * dspl + 4] = dsrc[4 * dspl + 4];
ddst[4 * dspl + 5] = dsrc[4 * dspl + 5];
ddst[4 * dspl + 6] = dsrc[4 * dspl + 6];
ddst[4 * dspl + 7] = dsrc[4 * dspl + 7];
ddst[5 * dspl + 0] = dsrc[5 * dspl + 0];
ddst[5 * dspl + 1] = dsrc[5 * dspl + 1];
ddst[5 * dspl + 2] = dsrc[5 * dspl + 2];
ddst[5 * dspl + 3] = dsrc[5 * dspl + 3];
ddst[5 * dspl + 4] = dsrc[5 * dspl + 4];
ddst[5 * dspl + 5] = dsrc[5 * dspl + 5];
ddst[5 * dspl + 6] = dsrc[5 * dspl + 6];
ddst[5 * dspl + 7] = dsrc[5 * dspl + 7];
ddst[6 * dspl + 0] = dsrc[6 * dspl + 0];
ddst[6 * dspl + 1] = dsrc[6 * dspl + 1];
ddst[6 * dspl + 2] = dsrc[6 * dspl + 2];
ddst[6 * dspl + 3] = dsrc[6 * dspl + 3];
ddst[6 * dspl + 4] = dsrc[6 * dspl + 4];
ddst[6 * dspl + 5] = dsrc[6 * dspl + 5];
ddst[6 * dspl + 6] = dsrc[6 * dspl + 6];
ddst[6 * dspl + 7] = dsrc[6 * dspl + 7];
ddst[7 * dspl + 0] = dsrc[7 * dspl + 0];
ddst[7 * dspl + 1] = dsrc[7 * dspl + 1];
ddst[7 * dspl + 2] = dsrc[7 * dspl + 2];
ddst[7 * dspl + 3] = dsrc[7 * dspl + 3];
ddst[7 * dspl + 4] = dsrc[7 * dspl + 4];
ddst[7 * dspl + 5] = dsrc[7 * dspl + 5];
ddst[7 * dspl + 6] = dsrc[7 * dspl + 6];
ddst[7 * dspl + 7] = dsrc[7 * dspl + 7];
#else
double* dsrc, * ddst;
int dspl;
dsrc = (double*)src;
ddst = (double*)dst;
dspl = spl >> 3;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += dspl; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += dspl; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += dspl; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += dspl; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += dspl; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += dspl; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += dspl; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
#endif
}
/*
==============
idCinematicLocal::move4_32
==============
*/
void idCinematicLocal::move4_32(byte* src, byte* dst, int spl) {
#if 1
int* dsrc, * ddst;
int dspl;
dsrc = (int*)src;
ddst = (int*)dst;
dspl = spl >> 2;
ddst[0 * dspl + 0] = dsrc[0 * dspl + 0];
ddst[0 * dspl + 1] = dsrc[0 * dspl + 1];
ddst[0 * dspl + 2] = dsrc[0 * dspl + 2];
ddst[0 * dspl + 3] = dsrc[0 * dspl + 3];
ddst[1 * dspl + 0] = dsrc[1 * dspl + 0];
ddst[1 * dspl + 1] = dsrc[1 * dspl + 1];
ddst[1 * dspl + 2] = dsrc[1 * dspl + 2];
ddst[1 * dspl + 3] = dsrc[1 * dspl + 3];
ddst[2 * dspl + 0] = dsrc[2 * dspl + 0];
ddst[2 * dspl + 1] = dsrc[2 * dspl + 1];
ddst[2 * dspl + 2] = dsrc[2 * dspl + 2];
ddst[2 * dspl + 3] = dsrc[2 * dspl + 3];
ddst[3 * dspl + 0] = dsrc[3 * dspl + 0];
ddst[3 * dspl + 1] = dsrc[3 * dspl + 1];
ddst[3 * dspl + 2] = dsrc[3 * dspl + 2];
ddst[3 * dspl + 3] = dsrc[3 * dspl + 3];
#else
double* dsrc, * ddst;
int dspl;
dsrc = (double*)src;
ddst = (double*)dst;
dspl = spl >> 3;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
dsrc += dspl; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
dsrc += dspl; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
dsrc += dspl; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
#endif
}
/*
==============
idCinematicLocal::blit8_32
==============
*/
void idCinematicLocal::blit8_32(byte* src, byte* dst, int spl) {
#if 1
int* dsrc, * ddst;
int dspl;
dsrc = (int*)src;
ddst = (int*)dst;
dspl = spl >> 2;
ddst[0 * dspl + 0] = dsrc[0];
ddst[0 * dspl + 1] = dsrc[1];
ddst[0 * dspl + 2] = dsrc[2];
ddst[0 * dspl + 3] = dsrc[3];
ddst[0 * dspl + 4] = dsrc[4];
ddst[0 * dspl + 5] = dsrc[5];
ddst[0 * dspl + 6] = dsrc[6];
ddst[0 * dspl + 7] = dsrc[7];
ddst[1 * dspl + 0] = dsrc[8];
ddst[1 * dspl + 1] = dsrc[9];
ddst[1 * dspl + 2] = dsrc[10];
ddst[1 * dspl + 3] = dsrc[11];
ddst[1 * dspl + 4] = dsrc[12];
ddst[1 * dspl + 5] = dsrc[13];
ddst[1 * dspl + 6] = dsrc[14];
ddst[1 * dspl + 7] = dsrc[15];
ddst[2 * dspl + 0] = dsrc[16];
ddst[2 * dspl + 1] = dsrc[17];
ddst[2 * dspl + 2] = dsrc[18];
ddst[2 * dspl + 3] = dsrc[19];
ddst[2 * dspl + 4] = dsrc[20];
ddst[2 * dspl + 5] = dsrc[21];
ddst[2 * dspl + 6] = dsrc[22];
ddst[2 * dspl + 7] = dsrc[23];
ddst[3 * dspl + 0] = dsrc[24];
ddst[3 * dspl + 1] = dsrc[25];
ddst[3 * dspl + 2] = dsrc[26];
ddst[3 * dspl + 3] = dsrc[27];
ddst[3 * dspl + 4] = dsrc[28];
ddst[3 * dspl + 5] = dsrc[29];
ddst[3 * dspl + 6] = dsrc[30];
ddst[3 * dspl + 7] = dsrc[31];
ddst[4 * dspl + 0] = dsrc[32];
ddst[4 * dspl + 1] = dsrc[33];
ddst[4 * dspl + 2] = dsrc[34];
ddst[4 * dspl + 3] = dsrc[35];
ddst[4 * dspl + 4] = dsrc[36];
ddst[4 * dspl + 5] = dsrc[37];
ddst[4 * dspl + 6] = dsrc[38];
ddst[4 * dspl + 7] = dsrc[39];
ddst[5 * dspl + 0] = dsrc[40];
ddst[5 * dspl + 1] = dsrc[41];
ddst[5 * dspl + 2] = dsrc[42];
ddst[5 * dspl + 3] = dsrc[43];
ddst[5 * dspl + 4] = dsrc[44];
ddst[5 * dspl + 5] = dsrc[45];
ddst[5 * dspl + 6] = dsrc[46];
ddst[5 * dspl + 7] = dsrc[47];
ddst[6 * dspl + 0] = dsrc[48];
ddst[6 * dspl + 1] = dsrc[49];
ddst[6 * dspl + 2] = dsrc[50];
ddst[6 * dspl + 3] = dsrc[51];
ddst[6 * dspl + 4] = dsrc[52];
ddst[6 * dspl + 5] = dsrc[53];
ddst[6 * dspl + 6] = dsrc[54];
ddst[6 * dspl + 7] = dsrc[55];
ddst[7 * dspl + 0] = dsrc[56];
ddst[7 * dspl + 1] = dsrc[57];
ddst[7 * dspl + 2] = dsrc[58];
ddst[7 * dspl + 3] = dsrc[59];
ddst[7 * dspl + 4] = dsrc[60];
ddst[7 * dspl + 5] = dsrc[61];
ddst[7 * dspl + 6] = dsrc[62];
ddst[7 * dspl + 7] = dsrc[63];
#else
double* dsrc, * ddst;
int dspl;
dsrc = (double*)src;
ddst = (double*)dst;
dspl = spl >> 3;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += 4; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += 4; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += 4; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += 4; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += 4; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += 4; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
dsrc += 4; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1]; ddst[2] = dsrc[2]; ddst[3] = dsrc[3];
#endif
}
/*
==============
idCinematicLocal::blit4_32
==============
*/
void idCinematicLocal::blit4_32(byte* src, byte* dst, int spl) {
#if 1
int* dsrc, * ddst;
int dspl;
dsrc = (int*)src;
ddst = (int*)dst;
dspl = spl >> 2;
ddst[0 * dspl + 0] = dsrc[0];
ddst[0 * dspl + 1] = dsrc[1];
ddst[0 * dspl + 2] = dsrc[2];
ddst[0 * dspl + 3] = dsrc[3];
ddst[1 * dspl + 0] = dsrc[4];
ddst[1 * dspl + 1] = dsrc[5];
ddst[1 * dspl + 2] = dsrc[6];
ddst[1 * dspl + 3] = dsrc[7];
ddst[2 * dspl + 0] = dsrc[8];
ddst[2 * dspl + 1] = dsrc[9];
ddst[2 * dspl + 2] = dsrc[10];
ddst[2 * dspl + 3] = dsrc[11];
ddst[3 * dspl + 0] = dsrc[12];
ddst[3 * dspl + 1] = dsrc[13];
ddst[3 * dspl + 2] = dsrc[14];
ddst[3 * dspl + 3] = dsrc[15];
#else
double* dsrc, * ddst;
int dspl;
dsrc = (double*)src;
ddst = (double*)dst;
dspl = spl >> 3;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
dsrc += 2; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
dsrc += 2; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
dsrc += 2; ddst += dspl;
ddst[0] = dsrc[0]; ddst[1] = dsrc[1];
#endif
}
/*
==============
idCinematicLocal::blit2_32
==============
*/
void idCinematicLocal::blit2_32(byte* src, byte* dst, int spl) {
#if 1
int* dsrc, * ddst;
int dspl;
dsrc = (int*)src;
ddst = (int*)dst;
dspl = spl >> 2;
ddst[0 * dspl + 0] = dsrc[0];
ddst[0 * dspl + 1] = dsrc[1];
ddst[1 * dspl + 0] = dsrc[2];
ddst[1 * dspl + 1] = dsrc[3];
#else
double* dsrc, * ddst;
int dspl;
dsrc = (double*)src;
ddst = (double*)dst;
dspl = spl >> 3;
ddst[0] = dsrc[0];
ddst[dspl] = dsrc[1];
#endif
}
/*
==============
idCinematicLocal::blitVQQuad32fs
==============
*/
void idCinematicLocal::blitVQQuad32fs(byte** status, unsigned char* data) {
unsigned short newd, celdata, code;
unsigned int index, i;
newd = 0;
celdata = 0;
index = 0;
do {
if (!newd) {
newd = 7;
celdata = data[0] + data[1] * 256;
data += 2;
}
else {
newd--;
}
code = (unsigned short)(celdata & 0xc000);
celdata <<= 2;
switch (code) {
case 0x8000: // vq code
blit8_32((byte*)&vq8[(*data) * 128], status[index], samplesPerLine);
data++;
index += 5;
break;
case 0xc000: // drop
index++; // skip 8x8
for (i = 0; i < 4; i++) {
if (!newd) {
newd = 7;
celdata = data[0] + data[1] * 256;
data += 2;
}
else {
newd--;
}
code = (unsigned short)(celdata & 0xc000); celdata <<= 2;
switch (code) { // code in top two bits of code
case 0x8000: // 4x4 vq code
blit4_32((byte*)&vq4[(*data) * 32], status[index], samplesPerLine);
data++;
break;
case 0xc000: // 2x2 vq code
blit2_32((byte*)&vq2[(*data) * 8], status[index], samplesPerLine);
data++;
blit2_32((byte*)&vq2[(*data) * 8], status[index] + 8, samplesPerLine);
data++;
blit2_32((byte*)&vq2[(*data) * 8], status[index] + samplesPerLine * 2, samplesPerLine);
data++;
blit2_32((byte*)&vq2[(*data) * 8], status[index] + samplesPerLine * 2 + 8, samplesPerLine);
data++;
break;
case 0x4000: // motion compensation
move4_32(status[index] + mcomp[(*data)], status[index], samplesPerLine);
data++;
break;
}
index++;
}
break;
case 0x4000: // motion compensation
move8_32(status[index] + mcomp[(*data)], status[index], samplesPerLine);
data++;
index += 5;
break;
case 0x0000:
index += 5;
break;
}
} while (status[index] != NULL);
}
#define VQ2TO4(a,b,c,d) { \
*c++ = a[0]; \
*d++ = a[0]; \
*d++ = a[0]; \
*c++ = a[1]; \
*d++ = a[1]; \
*d++ = a[1]; \
*c++ = b[0]; \
*d++ = b[0]; \
*d++ = b[0]; \
*c++ = b[1]; \
*d++ = b[1]; \
*d++ = b[1]; \
*d++ = a[0]; \
*d++ = a[0]; \
*d++ = a[1]; \
*d++ = a[1]; \
*d++ = b[0]; \
*d++ = b[0]; \
*d++ = b[1]; \
*d++ = b[1]; \
a += 2; b += 2; }
#define VQ2TO2(a,b,c,d) { \
*c++ = *a; \
*d++ = *a; \
*d++ = *a; \
*c++ = *b; \
*d++ = *b; \
*d++ = *b; \
*d++ = *a; \
*d++ = *a; \
*d++ = *b; \
*d++ = *b; \
a++; b++; }
/*
==============
idCinematicLocal::yuv_to_rgb
==============
*/
unsigned short idCinematicLocal::yuv_to_rgb(int y, int u, int v) {
int r, g, b, YY = (int)(ROQ_YY_tab[(y)]);
r = (YY + ROQ_VR_tab[v]) >> 9;
g = (YY + ROQ_UG_tab[u] + ROQ_VG_tab[v]) >> 8;
b = (YY + ROQ_UB_tab[u]) >> 9;
if (r < 0) { r = 0; } if (g < 0) { g = 0; } if (b < 0) { b = 0; }
if (r > 31) { r = 31; } if (g > 63) { g = 63; } if (b > 31) { b = 31; }
return (unsigned short)((r << 11) + (g << 5) + (b));
}
/*
==============
idCinematicLocal::yuv_to_rgb24
==============
*/
unsigned int idCinematicLocal::yuv_to_rgb24(int y, int u, int v) {
int r, g, b, YY = (int)(ROQ_YY_tab[(y)]);
r = (YY + ROQ_VR_tab[v]) >> 6;
g = (YY + ROQ_UG_tab[u] + ROQ_VG_tab[v]) >> 6;
b = (YY + ROQ_UB_tab[u]) >> 6;
if (r < 0) { r = 0; } if (g < 0) { g = 0; } if (b < 0) { b = 0; }
if (r > 255) { r = 255; } if (g > 255) { g = 255; } if (b > 255) { b = 255; }
return LittleInt((r)+(g << 8) + (b << 16));
}
/*
==============
idCinematicLocal::decodeCodeBook
==============
*/
void idCinematicLocal::decodeCodeBook(byte* input, unsigned short roq_flags) {
int i, j, two, four;
unsigned short* aptr, * bptr, * cptr, * dptr;
int y0, y1, y2, y3, cr, cb;
unsigned int* iaptr, * ibptr, * icptr, * idptr;
if (!roq_flags) {
two = four = 256;
}
else {
two = roq_flags >> 8;
if (!two) two = 256;
four = roq_flags & 0xff;
}
four *= 2;
bptr = (unsigned short*)vq2;
if (!half) {
if (!smootheddouble) {
//
// normal height
//
if (samplesPerPixel == 2) {
for (i = 0; i < two; i++) {
y0 = (int)*input++;
y1 = (int)*input++;
y2 = (int)*input++;
y3 = (int)*input++;
cr = (int)*input++;
cb = (int)*input++;
*bptr++ = yuv_to_rgb(y0, cr, cb);
*bptr++ = yuv_to_rgb(y1, cr, cb);
*bptr++ = yuv_to_rgb(y2, cr, cb);
*bptr++ = yuv_to_rgb(y3, cr, cb);
}
cptr = (unsigned short*)vq4;
dptr = (unsigned short*)vq8;
for (i = 0; i < four; i++) {
aptr = (unsigned short*)vq2 + (*input++) * 4;
bptr = (unsigned short*)vq2 + (*input++) * 4;
for (j = 0; j < 2; j++)
VQ2TO4(aptr, bptr, cptr, dptr);
}
}
else if (samplesPerPixel == 4) {
ibptr = (unsigned int*)bptr;
for (i = 0; i < two; i++) {
y0 = (int)*input++;
y1 = (int)*input++;
y2 = (int)*input++;
y3 = (int)*input++;
cr = (int)*input++;
cb = (int)*input++;
*ibptr++ = yuv_to_rgb24(y0, cr, cb);
*ibptr++ = yuv_to_rgb24(y1, cr, cb);
*ibptr++ = yuv_to_rgb24(y2, cr, cb);
*ibptr++ = yuv_to_rgb24(y3, cr, cb);
}
icptr = (unsigned int*)vq4;
idptr = (unsigned int*)vq8;
for (i = 0; i < four; i++) {
iaptr = (unsigned int*)vq2 + (*input++) * 4;
ibptr = (unsigned int*)vq2 + (*input++) * 4;
for (j = 0; j < 2; j++)
VQ2TO4(iaptr, ibptr, icptr, idptr);
}
}
}
else {
//
// double height, smoothed
//
if (samplesPerPixel == 2) {
for (i = 0; i < two; i++) {
y0 = (int)*input++;
y1 = (int)*input++;
y2 = (int)*input++;
y3 = (int)*input++;
cr = (int)*input++;
cb = (int)*input++;
*bptr++ = yuv_to_rgb(y0, cr, cb);
*bptr++ = yuv_to_rgb(y1, cr, cb);
*bptr++ = yuv_to_rgb(((y0 * 3) + y2) / 4, cr, cb);
*bptr++ = yuv_to_rgb(((y1 * 3) + y3) / 4, cr, cb);
*bptr++ = yuv_to_rgb((y0 + (y2 * 3)) / 4, cr, cb);
*bptr++ = yuv_to_rgb((y1 + (y3 * 3)) / 4, cr, cb);
*bptr++ = yuv_to_rgb(y2, cr, cb);
*bptr++ = yuv_to_rgb(y3, cr, cb);
}
cptr = (unsigned short*)vq4;
dptr = (unsigned short*)vq8;
for (i = 0; i < four; i++) {
aptr = (unsigned short*)vq2 + (*input++) * 8;
bptr = (unsigned short*)vq2 + (*input++) * 8;
for (j = 0; j < 2; j++) {
VQ2TO4(aptr, bptr, cptr, dptr);
VQ2TO4(aptr, bptr, cptr, dptr);
}
}
}
else if (samplesPerPixel == 4) {
ibptr = (unsigned int*)bptr;
for (i = 0; i < two; i++) {
y0 = (int)*input++;
y1 = (int)*input++;
y2 = (int)*input++;
y3 = (int)*input++;
cr = (int)*input++;
cb = (int)*input++;
*ibptr++ = yuv_to_rgb24(y0, cr, cb);
*ibptr++ = yuv_to_rgb24(y1, cr, cb);
*ibptr++ = yuv_to_rgb24(((y0 * 3) + y2) / 4, cr, cb);
*ibptr++ = yuv_to_rgb24(((y1 * 3) + y3) / 4, cr, cb);
*ibptr++ = yuv_to_rgb24((y0 + (y2 * 3)) / 4, cr, cb);
*ibptr++ = yuv_to_rgb24((y1 + (y3 * 3)) / 4, cr, cb);
*ibptr++ = yuv_to_rgb24(y2, cr, cb);
*ibptr++ = yuv_to_rgb24(y3, cr, cb);
}
icptr = (unsigned int*)vq4;
idptr = (unsigned int*)vq8;
for (i = 0; i < four; i++) {
iaptr = (unsigned int*)vq2 + (*input++) * 8;
ibptr = (unsigned int*)vq2 + (*input++) * 8;
for (j = 0; j < 2; j++) {
VQ2TO4(iaptr, ibptr, icptr, idptr);
VQ2TO4(iaptr, ibptr, icptr, idptr);
}
}
}
}
}
else {
//
// 1/4 screen
//
if (samplesPerPixel == 2) {
for (i = 0; i < two; i++) {
y0 = (int)*input; input += 2;
y2 = (int)*input; input += 2;
cr = (int)*input++;
cb = (int)*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 (samplesPerPixel == 4) {
ibptr = (unsigned int*)bptr;
for (i = 0; i < two; i++) {
y0 = (int)*input; input += 2;
y2 = (int)*input; input += 2;
cr = (int)*input++;
cb = (int)*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);
}
}
}
}
}
/*
==============
idCinematicLocal::recurseQuad
==============
*/
void idCinematicLocal::recurseQuad(int startX, int startY, int quadSize, int xOff, int yOff) {
byte* scroff;
int bigx, bigy, lowx, lowy, useY;
int offset;
offset = screenDelta;
lowx = lowy = 0;
bigx = xsize;
bigy = ysize;
if (bigx > CIN_WIDTH) bigx = CIN_WIDTH;
if (bigy > CIN_HEIGHT) bigy = CIN_HEIGHT;
if ((startX >= lowx) && (startX + quadSize) <= (bigx) && (startY + quadSize) <= (bigy) && (startY >= lowy) && quadSize <= MAXSIZE) {
useY = startY;
scroff = image + (useY + ((CIN_HEIGHT - bigy) >> 1) + yOff) * (samplesPerLine)+(((startX + xOff)) * samplesPerPixel);
qStatus[0][onQuad] = scroff;
qStatus[1][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);
}
}
/*
==============
idCinematicLocal::setupQuad
==============
*/
void idCinematicLocal::setupQuad(int xOff, int yOff) {
int numQuadCels, i, x, y;
byte* temp;
numQuadCels = (CIN_WIDTH * CIN_HEIGHT) / (16);
numQuadCels += numQuadCels / 4 + numQuadCels / 16;
numQuadCels += 64; // for overflow
numQuadCels = (xsize * ysize) / (16);
numQuadCels += numQuadCels / 4;
numQuadCels += 64; // for overflow
onQuad = 0;
for (y = 0; y < (int)ysize; y += 16)
for (x = 0; x < (int)xsize; x += 16)
recurseQuad(x, y, 16, xOff, yOff);
temp = NULL;
for (i = (numQuadCels - 64); i < numQuadCels; i++) {
qStatus[0][i] = temp; // eoq
qStatus[1][i] = temp; // eoq
}
}
/*
==============
idCinematicLocal::readQuadInfo
==============
*/
void idCinematicLocal::readQuadInfo(byte* qData) {
xsize = qData[0] + qData[1] * 256;
ysize = qData[2] + qData[3] * 256;
maxsize = qData[4] + qData[5] * 256;
minsize = qData[6] + qData[7] * 256;
CIN_HEIGHT = ysize;
CIN_WIDTH = xsize;
samplesPerLine = CIN_WIDTH * samplesPerPixel;
screenDelta = CIN_HEIGHT * samplesPerLine;
if (!image) {
image = (byte*)Mem_Alloc(CIN_WIDTH * CIN_HEIGHT * samplesPerPixel * 2);
}
half = false;
smootheddouble = false;
t[0] = (0 - (ptrdiff_t)image) + (ptrdiff_t)image + screenDelta;
t[1] = (0 - ((ptrdiff_t)image + screenDelta)) + (ptrdiff_t)image;
drawX = CIN_WIDTH;
drawY = CIN_HEIGHT;
}
/*
==============
idCinematicLocal::RoQPrepMcomp
==============
*/
void idCinematicLocal::RoQPrepMcomp(int xoff, int yoff) {
int i, j, x, y, temp, temp2;
i = samplesPerLine; j = samplesPerPixel;
if (xsize == (ysize * 4) && !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;
mcomp[(x * 16) + y] = normalBuffer0 - (temp2 + temp);
}
}
}
/*
==============
idCinematicLocal::RoQReset
==============
*/
void idCinematicLocal::RoQReset() {
iFile->Seek(0, FS_SEEK_SET);
iFile->Read(file, 16);
RoQ_init();
status = FMV_LOOPED;
}
#ifdef ID_USE_LIBJPEG
/* jpeg error handling */
struct jpeg_error_mgr jerr;
#endif
int JPEGBlit(byte* wStatus, byte* data, int datasize)
{
#ifndef ID_USE_LIBJPEG
// I don't think this code is actually used, because
// * the jpeg encoder parts in the roq encoder are disabled with #if 0
// * ffmpeg doesn't support ROQ_QUAD_JPEG and can decode all doom3 roqs anyway
common->Warning("Contrary to Daniel's assumption, JPEGBlit() is actually called! Please report that as a dhewm3 bug!\n");
#else
/* This struct contains the JPEG decompression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
*/
struct jpeg_decompress_struct cinfo;
/* We use our private extension JPEG error handler.
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
/* More stuff */
JSAMPARRAY buffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
/* Step 1: allocate and initialize JPEG decompression object */
/* We set up the normal JPEG error routines, then override error_exit. */
cinfo.err = jpeg_std_error(&jerr);
/* Now we can initialize the JPEG decompression object. */
jpeg_create_decompress(&cinfo);
/* Step 2: specify data source (eg, a file) */
jpeg_mem_src(&cinfo, data, datasize);
/* Step 3: read file parameters with jpeg_read_header() */
(void)jpeg_read_header(&cinfo, TRUE);
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
* See libjpeg.doc for more info.
*/
/* Step 4: set parameters for decompression */
/* In this example, we don't need to change any of the defaults set by
* jpeg_read_header(), so we do nothing here.
*/
/* Step 5: Start decompressor */
cinfo.dct_method = JDCT_IFAST;
cinfo.dct_method = JDCT_FASTEST;
cinfo.dither_mode = JDITHER_NONE;
cinfo.do_fancy_upsampling = FALSE;
// cinfo.out_color_space = JCS_GRAYSCALE;
(void)jpeg_start_decompress(&cinfo);
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
*/
/* We may need to do some setup of our own at this point before reading
* the data. After jpeg_start_decompress() we have the correct scaled
* output image dimensions available, as well as the output colormap
* if we asked for color quantization.
* In this example, we need to make an output work buffer of the right size.
*/
/* JSAMPLEs per row in output buffer */
row_stride = cinfo.output_width * cinfo.output_components;
/* Make a one-row-high sample array that will go away when done with image */
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);
/* Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
/* Here we use the library's state variable cinfo.output_scanline as the
* loop counter, so that we don't have to keep track ourselves.
*/
wStatus += (cinfo.output_height - 1) * row_stride;
while (cinfo.output_scanline < cinfo.output_height) {
/* jpeg_read_scanlines expects an array of pointers to scanlines.
* Here the array is only one element long, but you could ask for
* more than one scanline at a time if that's more convenient.
*/
(void)jpeg_read_scanlines(&cinfo, &buffer[0], 1);
/* Assume put_scanline_someplace wants a pointer and sample count. */
memcpy(wStatus, &buffer[0][0], row_stride);
/*
int x;
unsigned int *buf = (unsigned int *)&buffer[0][0];
unsigned int *out = (unsigned int *)wStatus;
for(x=0;xRead(file, RoQFrameSize + 8);
if (RoQPlayed >= ROQSize) {
if (looping) {
RoQReset();
}
else {
status = FMV_EOF;
}
return;
}
framedata = file;
//
// new frame is ready
//
redump:
switch (roq_id)
{
case ROQ_QUAD_VQ:
if ((numQuads & 1)) {
normalBuffer0 = t[1];
RoQPrepMcomp(roqF0, roqF1);
blitVQQuad32fs(qStatus[1], framedata);
buf = image + screenDelta;
}
else {
normalBuffer0 = t[0];
RoQPrepMcomp(roqF0, roqF1);
blitVQQuad32fs(qStatus[0], framedata);
buf = image;
}
if (numQuads == 0) { // first frame
memcpy(image + screenDelta, image, samplesPerLine * ysize);
}
numQuads++;
dirty = true;
break;
case ROQ_CODEBOOK:
decodeCodeBook(framedata, (unsigned short)roq_flags);
break;
case ZA_SOUND_MONO:
break;
case ZA_SOUND_STEREO:
break;
case ROQ_QUAD_INFO:
if (numQuads == -1) {
readQuadInfo(framedata);
setupQuad(0, 0);
}
if (numQuads != 1) numQuads = 0;
break;
case ROQ_PACKET:
inMemory = (roq_flags != 0);
RoQFrameSize = 0; // for header
break;
case ROQ_QUAD_HANG:
RoQFrameSize = 0;
break;
case ROQ_QUAD_JPEG:
if (!numQuads) {
normalBuffer0 = t[0];
JPEGBlit(image, framedata, RoQFrameSize);
memcpy(image + screenDelta, image, samplesPerLine * ysize);
numQuads++;
}
break;
default:
status = FMV_EOF;
break;
}
//
// read in next frame data
//
if (RoQPlayed >= ROQSize) {
if (looping) {
RoQReset();
}
else {
status = FMV_EOF;
}
return;
}
framedata += RoQFrameSize;
roq_id = framedata[0] + framedata[1] * 256;
RoQFrameSize = framedata[2] + framedata[3] * 256 + framedata[4] * 65536;
roq_flags = framedata[6] + framedata[7] * 256;
roqF0 = (signed char)framedata[7];
roqF1 = (signed char)framedata[6];
if (RoQFrameSize > 65536 || roq_id == 0x1084) {
common->DPrintf("roq_size>65536||roq_id==0x1084\n");
status = FMV_EOF;
if (looping) {
RoQReset();
}
return;
}
if (inMemory && (status != FMV_EOF)) {
inMemory = false; framedata += 8; goto redump;
}
//
// one more frame hits the dust
//
// assert(RoQFrameSize <= 65536);
// r = Sys_StreamedRead( file, RoQFrameSize+8, 1, iFile );
RoQPlayed += RoQFrameSize + 8;
}
/*
==============
idCinematicLocal::RoQ_init
==============
*/
void idCinematicLocal::RoQ_init(void) {
RoQPlayed = 24;
/* get frame rate */
roqFPS = file[6] + file[7] * 256;
if (!roqFPS) roqFPS = 30;
numQuads = -1;
roq_id = file[8] + file[9] * 256;
RoQFrameSize = file[10] + file[11] * 256 + file[12] * 65536;
roq_flags = file[14] + file[15] * 256;
}
/*
==============
idCinematicLocal::RoQShutdown
==============
*/
void idCinematicLocal::RoQShutdown(void) {
if (status == FMV_IDLE) {
return;
}
status = FMV_IDLE;
if (iFile) {
fileSystem->CloseFile(iFile);
iFile = NULL;
}
fileName = "";
}
//===========================================
/*
==============
idSndWindow::InitFromFile
==============
*/
bool idSndWindow::InitFromFile(const char* qpath, bool looping) {
idStr fname = qpath;
fname.ToLower();
if (!fname.Icmp("waveform")) {
showWaveform = true;
}
else {
showWaveform = false;
}
return true;
}
/*
==============
idSndWindow::ImageForTime
==============
*/
cinData_t idSndWindow::ImageForTime(int milliseconds) {
return soundSystem->ImageForTime(milliseconds, showWaveform);
}
/*
==============
idSndWindow::AnimationLength
==============
*/
int idSndWindow::AnimationLength() {
return -1;
}