UFO: Alien Invasion
Loading...
Searching...
No Matches
cl_cinematic_roq.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26
27#include "cl_cinematic_roq.h"
28#include "cl_cinematic.h"
29#include "../client.h" /* needed by r_draw.h */
30#include "../renderer/r_draw.h"
31#include "../sound/s_main.h"
32#include "../sound/s_music.h"
33
34typedef struct {
35 int vr[256];
36 int ug[256];
37 int vg[256];
38 int ub[256];
40
41#define ROQ_IDENT 0x1084
42
43#define ROQ_QUAD_INFO 0x1001
44#define ROQ_QUAD_CODEBOOK 0x1002
45#define ROQ_QUAD_VQ 0x1011
46#define ROQ_SOUND_MONO 0x1020
47#define ROQ_SOUND_STEREO 0x1021
48
49#define ROQ_CHUNK_HEADER_SIZE 8 /* Size of a RoQ chunk header */
50
51#define ROQ_MAX_CHUNK_SIZE 65536 /* Max size of a RoQ chunk */
52
53#define ROQ_SOUND_RATE 22050
54
55#define ROQ_ID_FCC 0x4000
56#define ROQ_ID_SLD 0x8000
57#define ROQ_ID_CCC 0xC000
58
59typedef struct {
60 uint16_t id;
61 uint32_t size;
62 uint16_t flags;
64
65typedef struct {
66 uint32_t pixel[4];
68
69typedef struct {
70 byte index[4];
72
95
96static short roqCin_sqrTable[256];
98
99static int roqCin_quadOffsets2[2][4];
100static int roqCin_quadOffsets4[2][4];
101
102#define ROQCIN (*((roqCinematic_t*)cin->codecData))
103
107static inline byte CIN_ROQ_ClampByte (int value)
108{
109 if (value < 0)
110 return 0;
111
112 if (value > 255)
113 return 255;
114
115 return value;
116}
117
121static void CIN_ROQ_ApplyVector2x2 (cinematic_t* cin, int x, int y, const byte* indices)
122{
123 for (int i = 0; i < 4; i++) {
124 const int xp = x + roqCin_quadOffsets2[0][i];
125 const int yp = y + roqCin_quadOffsets2[1][i];
126 const unsigned int* src = (const unsigned int*)ROQCIN.quadVectors + (indices[i] * 4);
127 unsigned* dst = ROQCIN.frameBuffer[0] + (yp * ROQCIN.frameWidth + xp);
128
129 dst[0] = src[0];
130 dst[1] = src[1];
131
132 dst += ROQCIN.frameWidth;
133
134 dst[0] = src[2];
135 dst[1] = src[3];
136 }
137}
138
142static void CIN_ROQ_ApplyVector4x4 (cinematic_t* cin, int x, int y, const byte* indices)
143{
144 for (int i = 0; i < 4; i++) {
145 const int xp = x + roqCin_quadOffsets4[0][i];
146 const int yp = y + roqCin_quadOffsets4[1][i];
147 const unsigned int* src = (const unsigned int*)ROQCIN.quadVectors + (indices[i] * 4);
148 unsigned* dst = ROQCIN.frameBuffer[0] + (yp * ROQCIN.frameWidth + xp);
149
150 dst[0] = src[0];
151 dst[1] = src[0];
152 dst[2] = src[1];
153 dst[3] = src[1];
154
155 dst += ROQCIN.frameWidth;
156
157 dst[0] = src[0];
158 dst[1] = src[0];
159 dst[2] = src[1];
160 dst[3] = src[1];
161
162 dst += ROQCIN.frameWidth;
163
164 dst[0] = src[2];
165 dst[1] = src[2];
166 dst[2] = src[3];
167 dst[3] = src[3];
168
169 dst += ROQCIN.frameWidth;
170
171 dst[0] = src[2];
172 dst[1] = src[2];
173 dst[2] = src[3];
174 dst[3] = src[3];
175 }
176}
177
181static void CIN_ROQ_ApplyMotion4x4 (cinematic_t* cin, int x, int y, int mx, int my, int mv)
182{
183 const int xp = x + 8 - (mv >> 4) - mx;
184 const int yp = y + 8 - (mv & 15) - my;
185 unsigned const* src = ROQCIN.frameBuffer[1] + (yp * ROQCIN.frameWidth + xp);
186 unsigned* dst = ROQCIN.frameBuffer[0] + (y * ROQCIN.frameWidth + x);
187
188 for (int i = 0; i < 4; i++, src += ROQCIN.frameWidth, dst += ROQCIN.frameWidth) {
189 dst[0] = src[0];
190 dst[1] = src[1];
191 dst[2] = src[2];
192 dst[3] = src[3];
193 }
194}
195
199static void CIN_ROQ_ApplyMotion8x8 (cinematic_t* cin, int x, int y, int mx, int my, int mv)
200{
201 const int xp = x + 8 - (mv >> 4) - mx;
202 const int yp = y + 8 - (mv & 15) - my;
203 unsigned const* src = ROQCIN.frameBuffer[1] + (yp * ROQCIN.frameWidth + xp);
204 unsigned* dst = ROQCIN.frameBuffer[0] + (y * ROQCIN.frameWidth + x);
205
206 for (int i = 0; i < 8; i++, src += ROQCIN.frameWidth, dst += ROQCIN.frameWidth) {
207 dst[0] = src[0];
208 dst[1] = src[1];
209 dst[2] = src[2];
210 dst[3] = src[3];
211 dst[4] = src[4];
212 dst[5] = src[5];
213 dst[6] = src[6];
214 dst[7] = src[7];
215 }
216}
217
221static void CIN_ROQ_DecodeInfo (cinematic_t* cin, const byte* data)
222{
223 if (ROQCIN.frameBuffer[0] && ROQCIN.frameBuffer[1])
224 return; /* Already allocated */
225
226 /* Allocate the frame buffer */
227 ROQCIN.frameWidth = data[0] | (data[1] << 8);
228 ROQCIN.frameHeight = data[2] | (data[3] << 8);
229
230 ROQCIN.frameWidth = LittleShort(ROQCIN.frameWidth);
231 ROQCIN.frameHeight = LittleShort(ROQCIN.frameHeight);
232
233 if (!Q_IsPowerOfTwo(ROQCIN.frameWidth) || !Q_IsPowerOfTwo(ROQCIN.frameHeight))
234 Com_Error(ERR_DROP, "CIN_DecodeInfo: size is not a power of two (%i x %i)", ROQCIN.frameWidth, ROQCIN.frameHeight);
235
236 ROQCIN.frameBuffer[0] = Mem_PoolAllocTypeN(unsigned, ROQCIN.frameWidth * ROQCIN.frameHeight, cl_genericPool);
237 ROQCIN.frameBuffer[1] = Mem_PoolAllocTypeN(unsigned, ROQCIN.frameWidth * ROQCIN.frameHeight, cl_genericPool);
238}
239
243static void CIN_ROQ_DecodeCodeBook (cinematic_t* cin, const byte* data)
244{
245 int numQuadVectors, numQuadCells;
246
247 if (ROQCIN.chunk.flags) {
248 numQuadVectors = (ROQCIN.chunk.flags >> 8) & 0xFF;
249 numQuadCells = (ROQCIN.chunk.flags >> 0) & 0xFF;
250
251 if (!numQuadVectors)
252 numQuadVectors = 256;
253 } else {
254 numQuadVectors = 256;
255 numQuadCells = 256;
256 }
257
258 /* Decode YUV quad vectors to RGB */
259 for (int i = 0; i < numQuadVectors; i++) {
260 const int r = roqCin_yuvTable.vr[data[5]];
261 const int g = roqCin_yuvTable.ug[data[4]] + roqCin_yuvTable.vg[data[5]];
262 const int b = roqCin_yuvTable.ub[data[4]];
263
264 ((byte*)&ROQCIN.quadVectors[i].pixel[0])[0] = CIN_ROQ_ClampByte(data[0] + r);
265 ((byte*)&ROQCIN.quadVectors[i].pixel[0])[1] = CIN_ROQ_ClampByte(data[0] - g);
266 ((byte*)&ROQCIN.quadVectors[i].pixel[0])[2] = CIN_ROQ_ClampByte(data[0] + b);
267 ((byte*)&ROQCIN.quadVectors[i].pixel[0])[3] = 255;
268
269 ((byte*)&ROQCIN.quadVectors[i].pixel[1])[0] = CIN_ROQ_ClampByte(data[1] + r);
270 ((byte*)&ROQCIN.quadVectors[i].pixel[1])[1] = CIN_ROQ_ClampByte(data[1] - g);
271 ((byte*)&ROQCIN.quadVectors[i].pixel[1])[2] = CIN_ROQ_ClampByte(data[1] + b);
272 ((byte*)&ROQCIN.quadVectors[i].pixel[1])[3] = 255;
273
274 ((byte*)&ROQCIN.quadVectors[i].pixel[2])[0] = CIN_ROQ_ClampByte(data[2] + r);
275 ((byte*)&ROQCIN.quadVectors[i].pixel[2])[1] = CIN_ROQ_ClampByte(data[2] - g);
276 ((byte*)&ROQCIN.quadVectors[i].pixel[2])[2] = CIN_ROQ_ClampByte(data[2] + b);
277 ((byte*)&ROQCIN.quadVectors[i].pixel[2])[3] = 255;
278
279 ((byte*)&ROQCIN.quadVectors[i].pixel[3])[0] = CIN_ROQ_ClampByte(data[3] + r);
280 ((byte*)&ROQCIN.quadVectors[i].pixel[3])[1] = CIN_ROQ_ClampByte(data[3] - g);
281 ((byte*)&ROQCIN.quadVectors[i].pixel[3])[2] = CIN_ROQ_ClampByte(data[3] + b);
282 ((byte*)&ROQCIN.quadVectors[i].pixel[3])[3] = 255;
283
284 data += 6;
285 }
286
287 /* Copy quad cells */
288 for (int i = 0; i < numQuadCells; i++) {
289 ROQCIN.quadCells[i].index[0] = data[0];
290 ROQCIN.quadCells[i].index[1] = data[1];
291 ROQCIN.quadCells[i].index[2] = data[2];
292 ROQCIN.quadCells[i].index[3] = data[3];
293
294 data += 4;
295 }
296}
297
301static void CIN_ROQ_DecodeVideo (cinematic_t* cin, const byte* data)
302{
303 if (!ROQCIN.frameBuffer[0] || !ROQCIN.frameBuffer[1])
304 return; /* No frame buffer */
305
306 int vqFlag = 0;
307 int vqFlagPos = 0;
308
309 int xPos = 0;
310 int yPos = 0;
311
312 const int xMot = (char)((ROQCIN.chunk.flags >> 8) & 0xFF);
313 const int yMot = (char)((ROQCIN.chunk.flags >> 0) & 0xFF);
314
315 int index = 0;
316
317 while (1) {
318 for (int y = yPos; y < yPos + 16; y += 8) {
319 for (int x = xPos; x < xPos + 16; x += 8) {
320 if (!vqFlagPos) {
321 vqFlagPos = 7;
322 vqFlag = data[index + 0] | (data[index + 1] << 8);
323 vqFlag = LittleShort(vqFlag);
324 index += 2;
325 } else
326 vqFlagPos--;
327
328 int vqCode = vqFlag & ROQ_ID_CCC;
329 vqFlag <<= 2;
330
331 switch (vqCode) {
332 case ROQ_ID_FCC:
333 CIN_ROQ_ApplyMotion8x8(cin, x, y, xMot, yMot, data[index]);
334 index += 1;
335 break;
336 case ROQ_ID_SLD:
337 CIN_ROQ_ApplyVector4x4(cin, x, y, ROQCIN.quadCells[data[index]].index);
338 index += 1;
339 break;
340 case ROQ_ID_CCC:
341 for (int i = 0; i < 4; i++) {
342 const int xp = x + roqCin_quadOffsets4[0][i];
343 const int yp = y + roqCin_quadOffsets4[1][i];
344
345 if (!vqFlagPos) {
346 vqFlagPos = 7;
347 vqFlag = data[index + 0] | (data[index + 1] << 8);
348 vqFlag = LittleShort(vqFlag);
349
350 index += 2;
351 } else
352 vqFlagPos--;
353
354 vqCode = vqFlag & ROQ_ID_CCC;
355 vqFlag <<= 2;
356
357 switch (vqCode) {
358 case ROQ_ID_FCC:
359 CIN_ROQ_ApplyMotion4x4(cin, xp, yp, xMot, yMot, data[index]);
360 index += 1;
361 break;
362 case ROQ_ID_SLD:
363 CIN_ROQ_ApplyVector2x2(cin, xp, yp, ROQCIN.quadCells[data[index]].index);
364 index += 1;
365 break;
366 case ROQ_ID_CCC:
367 CIN_ROQ_ApplyVector2x2(cin, xp, yp, &data[index]);
368 index += 4;
369 break;
370 }
371 }
372 break;
373 }
374 }
375 }
376
377 xPos += 16;
378 if (xPos >= ROQCIN.frameWidth) {
379 xPos -= ROQCIN.frameWidth;
380
381 yPos += 16;
382 if (yPos >= ROQCIN.frameHeight)
383 break;
384 }
385 }
386
387 /* Copy or swap the buffers */
388 if (!ROQCIN.currentFrame)
389 memcpy(ROQCIN.frameBuffer[1], ROQCIN.frameBuffer[0], sizeof(*ROQCIN.frameBuffer[1]) * ROQCIN.frameWidth * ROQCIN.frameHeight);
390 else {
391 unsigned* const buffer = ROQCIN.frameBuffer[0];
392 ROQCIN.frameBuffer[0] = ROQCIN.frameBuffer[1];
393 ROQCIN.frameBuffer[1] = buffer;
394 }
395
396 ROQCIN.currentFrame++;
397}
398
403static void CIN_ROQ_DecodeSoundMono (cinematic_t* cin, const byte* data)
404{
405 short samples[ROQ_MAX_CHUNK_SIZE * 2];
406 int prev = 0;
407 int i = 0;
408
409 for (int j = 0; i < ROQCIN.chunk.size; i++, j += 2) {
410 prev = (short)(prev + roqCin_sqrTable[data[i]]);
411 samples[j] = (short)prev;
412 samples[j + 1] = (short)prev;
413 }
414
415 M_AddToSampleBuffer(&ROQCIN.musicStream, ROQ_SOUND_RATE, i, (const byte*)samples);
416}
417
422static void CIN_ROQ_DecodeSoundStereo (cinematic_t* cin, const byte* data)
423{
424 short samples[ROQ_MAX_CHUNK_SIZE];
425 int i;
426 short prevL = (ROQCIN.chunk.flags & 0xFF00) << 0;
427 short prevR = (ROQCIN.chunk.flags & 0x00FF) << 8;
428
429 for (i = 0; i < ROQCIN.chunk.size; i += 2) {
430 prevL = prevL + roqCin_sqrTable[data[i + 0]];
431 prevR = prevR + roqCin_sqrTable[data[i + 1]];
432
433 samples[i + 0] = prevL;
434 samples[i + 1] = prevR;
435 }
436
437 M_AddToSampleBuffer(&ROQCIN.musicStream, ROQ_SOUND_RATE, i / 2, (const byte*)samples);
438}
439
445{
446 if (ROQCIN.startTime + ((1000 / ROQCIN.frameRate) * ROQCIN.currentFrame) > CL_Milliseconds())
447 return true;
448
449 const int frame = ROQCIN.currentFrame;
450
451 do {
452 if (ROQCIN.offset >= ROQCIN.size)
453 return false; /* Finished */
454
455 /* Parse the chunk header */
456 ROQCIN.chunk.id = LittleShort(*(short*)&ROQCIN.header[0]);
457 ROQCIN.chunk.size = LittleLong(*(int*)&ROQCIN.header[2]);
458 ROQCIN.chunk.flags = LittleShort(*(short*)&ROQCIN.header[6]);
459
460 if (ROQCIN.chunk.id == ROQ_IDENT || ROQCIN.chunk.size > ROQ_MAX_CHUNK_SIZE) {
461 Com_Printf("Invalid chunk id during decode: %i\n", ROQCIN.chunk.id);
462 cin->replay = false;
463 return false; /* Invalid chunk */
464 }
465
466 /* Read the chunk data and the next chunk header */
467 FS_Read(ROQCIN.data, ROQCIN.chunk.size + ROQ_CHUNK_HEADER_SIZE, &ROQCIN.file);
468 ROQCIN.offset += ROQCIN.chunk.size + ROQ_CHUNK_HEADER_SIZE;
469
470 ROQCIN.header = ROQCIN.data + ROQCIN.chunk.size;
471
472 /* Decode the chunk data */
473 switch (ROQCIN.chunk.id) {
474 case ROQ_QUAD_INFO:
475 CIN_ROQ_DecodeInfo(cin, ROQCIN.data);
476 break;
479 break;
480 case ROQ_QUAD_VQ:
481 CIN_ROQ_DecodeVideo(cin, ROQCIN.data);
482 break;
483 case ROQ_SOUND_MONO:
484 if (!cin->noSound)
486 break;
487 case ROQ_SOUND_STEREO:
488 if (!cin->noSound)
490 break;
491 default:
492 Com_Printf("Invalid chunk id: %i\n", ROQCIN.chunk.id);
493 break;
494 }
495 /* loop until we finally got a new frame */
496 } while (frame == ROQCIN.currentFrame && cin->status);
497
498 return true;
499}
500
505{
506 assert(cin->status != CIN_STATUS_NONE);
507
508 if (!ROQCIN.frameBuffer[1])
509 return;
510 const int texnum = R_UploadData("***cinematic***", ROQCIN.frameBuffer[1], ROQCIN.frameWidth, ROQCIN.frameHeight);
511 R_DrawTexture(texnum, cin->x, cin->y, cin->w, cin->h);
512}
513
518{
519 const bool runState = CIN_ROQ_DecodeChunk(cin);
520 if (runState)
522 return runState;
523}
524
526{
527 if (ROQCIN.file.f || ROQCIN.file.z)
528 FS_CloseFile(&ROQCIN.file);
529 else
530 Com_Printf("CIN_ROQ_StopCinematic: Warning no opened file\n");
531
532 Mem_Free(ROQCIN.frameBuffer[0]);
533 Mem_Free(ROQCIN.frameBuffer[1]);
534
535 M_StopMusicStream(&ROQCIN.musicStream);
536
537 Mem_Free(cin->codecData);
538 cin->codecData = nullptr;
539}
540
541int CIN_ROQ_OpenCinematic (cinematic_t* cin, const char* fileName)
542{
543 roqChunk_t chunk;
544 byte header[ROQ_CHUNK_HEADER_SIZE];
545
546 if (cin->codecData && (ROQCIN.file.f || ROQCIN.file.z)) {
547 Com_Printf("WARNING: it seams there was already a roq running, it will be killed to start %s\n", fileName);
549 }
550
551 assert(cin->codecData == nullptr);
554
555 /* Open the file */
556 const int size = FS_OpenFile(fileName, &ROQCIN.file, FILE_READ);
557 if (!ROQCIN.file.f && !ROQCIN.file.z) {
558 Com_Printf("Cinematic %s not found\n", fileName);
559 return 1;
560 }
561
562 /* Parse the header */
563 FS_Read(header, sizeof(header), &ROQCIN.file);
564
565 /* first 8 bytes are the header */
566 chunk.id = LittleShort(*(short*)&header[0]);
567 chunk.size = LittleLong(*(int*)&header[2]);
568 chunk.flags = LittleShort(*(short*)&header[6]);
569
570 if (chunk.id != ROQ_IDENT) {
571 FS_CloseFile(&ROQCIN.file);
572 Com_Printf("CIN_PlayCinematic: invalid RoQ header\n");
573 return 1;
574 }
575
577
578 /* Fill it in */
579 Q_strncpyz(cin->name, fileName, sizeof(cin->name));
580
581 ROQCIN.size = size;
582 ROQCIN.offset = sizeof(header);
583
584 ROQCIN.frameWidth = 0;
585 ROQCIN.frameHeight = 0;
586 ROQCIN.startTime = CL_Milliseconds();
587 ROQCIN.frameRate = (chunk.flags != 0) ? chunk.flags : 30;
588 Mem_Free(ROQCIN.frameBuffer[0]);
589 ROQCIN.frameBuffer[0] = nullptr;
590 Mem_Free(ROQCIN.frameBuffer[1]);
591 ROQCIN.frameBuffer[1] = nullptr;
592
593 ROQCIN.currentFrame = 0;
594
595 /* Read the first chunk header */
598
599 ROQCIN.header = ROQCIN.data;
600
601 return 0;
602}
603
604void CIN_ROQ_Init (void)
605{
606 /* Build square table */
607 for (int i = 0; i < 128; i++) {
608 const short s = (short)(i * i);
609 roqCin_sqrTable[i] = s;
610 roqCin_sqrTable[i + 128] = -s;
611 }
612
613 /* Set up quad offsets */
614 for (int i = 0; i < 4; i++) {
615 roqCin_quadOffsets2[0][i] = 2 * (i & 1);
616 roqCin_quadOffsets2[1][i] = 2 * (i >> 1);
617 roqCin_quadOffsets4[0][i] = 4 * (i & 1);
618 roqCin_quadOffsets4[1][i] = 4 * (i >> 1);
619 }
620
621 /* Build YUV table */
622 for (int i = 0; i < 256; i++) {
623 const float f = (float)(i - 128);
624 roqCin_yuvTable.vr[i] = Q_ftol(f * 1.40200f);
625 roqCin_yuvTable.ug[i] = Q_ftol(f * 0.34414f);
626 roqCin_yuvTable.vg[i] = Q_ftol(f * 0.71414f);
627 roqCin_yuvTable.ub[i] = Q_ftol(f * 1.77200f);
628 }
629}
#define LittleLong(X)
Definition byte.h:37
#define LittleShort(X)
Definition byte.h:35
Header file for cinematics.
@ CINEMATIC_TYPE_ROQ
@ CIN_STATUS_NONE
static void CIN_ROQ_DecodeVideo(cinematic_t *cin, const byte *data)
static void CIN_ROQ_ApplyMotion4x4(cinematic_t *cin, int x, int y, int mx, int my, int mv)
static void CIN_ROQ_DrawCinematic(cinematic_t *cin)
#define ROQ_QUAD_CODEBOOK
#define ROQ_IDENT
int CIN_ROQ_OpenCinematic(cinematic_t *cin, const char *fileName)
void CIN_ROQ_CloseCinematic(cinematic_t *cin)
#define ROQ_MAX_CHUNK_SIZE
static void CIN_ROQ_ApplyVector4x4(cinematic_t *cin, int x, int y, const byte *indices)
static bool CIN_ROQ_DecodeChunk(cinematic_t *cin)
#define ROQ_QUAD_VQ
static byte CIN_ROQ_ClampByte(int value)
Clamps integer value into byte.
void CIN_ROQ_Init(void)
#define ROQ_ID_FCC
#define ROQ_SOUND_RATE
static short roqCin_sqrTable[256]
static void CIN_ROQ_ApplyVector2x2(cinematic_t *cin, int x, int y, const byte *indices)
static void CIN_ROQ_DecodeCodeBook(cinematic_t *cin, const byte *data)
static int roqCin_quadOffsets4[2][4]
static void CIN_ROQ_DecodeSoundMono(cinematic_t *cin, const byte *data)
#define ROQ_CHUNK_HEADER_SIZE
static void CIN_ROQ_DecodeInfo(cinematic_t *cin, const byte *data)
static void CIN_ROQ_ApplyMotion8x8(cinematic_t *cin, int x, int y, int mx, int my, int mv)
#define ROQCIN
#define ROQ_SOUND_MONO
static yuvTable_t roqCin_yuvTable
#define ROQ_SOUND_STEREO
#define ROQ_ID_CCC
#define ROQ_QUAD_INFO
bool CIN_ROQ_RunCinematic(cinematic_t *cin)
static int roqCin_quadOffsets2[2][4]
static void CIN_ROQ_DecodeSoundStereo(cinematic_t *cin, const byte *data)
#define ROQ_ID_SLD
Header file for ROQ cinematics.
void FS_CloseFile(qFILE *f)
memPool_t * vid_genericPool
Definition cl_main.cpp:87
memPool_t * cl_genericPool
Definition cl_main.cpp:86
int CL_Milliseconds(void)
Definition cl_main.cpp:1207
Primary header for client.
void Com_Error(int code, const char *fmt,...)
Definition common.cpp:459
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define ERR_DROP
Definition common.h:211
int FS_Read(void *buffer, int len, qFILE *f)
Definition files.cpp:371
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
Definition files.cpp:162
@ FILE_READ
Definition filesys.h:111
voidpf void uLong size
Definition ioapi.h:42
bool Q_IsPowerOfTwo(int i)
Checks whether i is power of two value.
Definition mathlib.cpp:972
#define Q_ftol(f)
Definition mathlib.h:48
#define Mem_PoolAllocTypeN(type, n, pool)
Definition mem.h:42
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_PoolAllocType(type, pool)
Definition mem.h:43
void R_DrawTexture(int texnum, int x, int y, int w, int h)
Bind and draw a texture.
Definition r_draw.cpp:328
int R_UploadData(const char *name, unsigned *frame, int width, int height)
Uploads image data.
Definition r_draw.cpp:270
QGL_EXTERN GLsizei const GLvoid * data
Definition r_gl.h:89
QGL_EXTERN GLuint index
Definition r_gl.h:110
QGL_EXTERN GLfloat f
Definition r_gl.h:114
QGL_EXTERN GLint i
Definition r_gl.h:113
Specifies sound API?
void M_StopMusicStream(musicStream_t *userdata)
Definition s_music.cpp:462
void M_AddToSampleBuffer(musicStream_t *userdata, int rate, int samples, const byte *data)
Add stereo samples with a 16 byte width to the stream buffer.
Definition s_music.cpp:428
Specifies music API.
#define OBJZERO(obj)
Definition shared.h:178
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition shared.cpp:457
void * codecData
char name[MAX_QPATH]
unsigned * frameBuffer[2]
byte data[ROQ_MAX_CHUNK_SIZE+ROQ_CHUNK_HEADER_SIZE]
roqQuadVector_t quadVectors[256]
musicStream_t musicStream
roqQuadCell_t quadCells[256]