1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * 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 this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "bladerunner/vqa_decoder.h"
24
25 #include "bladerunner/bladerunner.h"
26 #include "bladerunner/decompress_lcw.h"
27 #include "bladerunner/decompress_lzo.h"
28 #include "bladerunner/game_info.h"
29 #include "bladerunner/lights.h"
30 #include "bladerunner/screen_effects.h"
31 #include "bladerunner/view.h"
32 #include "bladerunner/zbuffer.h"
33
34 #include "audio/decoders/raw.h"
35
36 #include "common/array.h"
37 #include "common/util.h"
38 #include "common/memstream.h"
39
40 namespace BladeRunner {
41
42 #define kAESC 0x41455343
43 #define kCBFZ 0x4342465A
44 #define kCBPZ 0x4342505A
45 #define kCIND 0x43494E44
46 #define kCINF 0x43494E46
47 #define kCINH 0x43494E48
48 #define kCLIP 0x434C4950
49 #define kFINF 0x46494E46
50 #define kFORM 0x464f524d
51 #define kLIND 0x4C494E44
52 #define kLINF 0x4C494E46
53 #define kLINH 0x4C494E48
54 #define kLITE 0x4C495445
55 #define kLNID 0x4C4E4944
56 #define kLNIH 0x4C4E4948
57 #define kLNIN 0x4C4E494E
58 #define kLNIO 0x4C4E494F
59 #define kMFCD 0x4D464344
60 #define kMFCH 0x4D464348
61 #define kMFCI 0x4D464349
62 #define kMFCT 0x4D464354
63 #define kMSCH 0x4D534348
64 #define kMSCI 0x4D534349
65 #define kMSCT 0x4D534354
66 #define kSN2J 0x534e324a
67 #define kSND2 0x534e4432
68 #define kVIEW 0x56494557
69 #define kVPTR 0x56505452
70 #define kVQFL 0x5651464C
71 #define kVQFR 0x56514652
72 #define kVQHD 0x56514844
73 #define kWVQA 0x57565141
74 #define kZBUF 0x5A425546
75
remain(Common::SeekableReadStream * s)76 int32 remain(Common::SeekableReadStream *s) {
77 int32 pos = s->pos();
78 if (pos == -1) return -1;
79
80 int32 size = s->size();
81 if (size == -1) return -1;
82
83 return size - pos;
84 }
85
86 struct IFFChunkHeader {
IFFChunkHeaderBladeRunner::IFFChunkHeader87 IFFChunkHeader()
88 : id(0), size(0)
89 {}
90
91 uint32 id;
92 uint32 size;
93 };
94
readIFFChunkHeader(Common::SeekableReadStream * s,IFFChunkHeader * ts)95 static bool readIFFChunkHeader(Common::SeekableReadStream *s, IFFChunkHeader *ts) {
96 if (remain(s) < 8)
97 return false;
98
99 ts->id = s->readUint32BE();
100 ts->size = s->readUint32BE();
101
102 return true;
103 }
104
roundup(uint32 v)105 static inline uint32 roundup(uint32 v) {
106 return (v + 1) & ~1u;
107 }
108
VQADecoder()109 VQADecoder::VQADecoder() {
110 _s = nullptr;
111 _frameInfo = nullptr;
112 _videoTrack = nullptr;
113 _audioTrack = nullptr;
114 _maxVIEWChunkSize = 0;
115 _maxZBUFChunkSize = 0;
116 _maxAESCChunkSize = 0;
117 _header.version = 0;
118 _header.flags = 0;
119 _header.numFrames = 0;
120 _header.width = 0;
121 _header.height = 0;
122 _header.blockW = 0;
123 _header.blockH = 0;
124 _header.frameRate = 0;
125 _header.cbParts = 0;
126 _header.colors = 0;
127 _header.maxBlocks = 0;
128 _header.offsetX = 0;
129 _header.offsetY = 0;
130 _header.maxVPTRSize = 0;
131 _header.freq = 0;
132 _header.channels = 0;
133 _header.bits = 0;
134 _header.unk3 = 0;
135 _header.unk4 = 0;
136 _header.maxCBFZSize = 0;
137 _header.unk5 = 0;
138 _readingFrame = -1;
139 _decodingFrame = -1;
140 }
141
~VQADecoder()142 VQADecoder::~VQADecoder() {
143 for (uint i = _codebooks.size(); i != 0; --i) {
144 delete[] _codebooks[i - 1].data;
145 }
146 delete _audioTrack;
147 delete _videoTrack;
148 delete[] _frameInfo;
149 }
150
loadStream(Common::SeekableReadStream * s)151 bool VQADecoder::loadStream(Common::SeekableReadStream *s) {
152 // close();
153 _s = s;
154
155 IFFChunkHeader chd;
156 uint32 type;
157
158 readIFFChunkHeader(s, &chd);
159 if (chd.id != kFORM || !chd.size)
160 return false;
161
162 type = s->readUint32BE();
163
164 if (type != kWVQA)
165 return false;
166
167 do {
168 if (!readIFFChunkHeader(_s, &chd))
169 return false;
170
171 bool rc = false;
172 switch (chd.id) {
173 case kCINF: rc = readCINF(s, chd.size); break;
174 case kCLIP: rc = readCLIP(s, chd.size); break;
175 case kFINF: rc = readFINF(s, chd.size); break;
176 case kLINF: rc = readLINF(s, chd.size); break;
177 case kLNIN: rc = readLNIN(s, chd.size); break;
178 case kMFCI: rc = readMFCI(s, chd.size); break;
179 case kMSCI: rc = readMSCI(s, chd.size); break;
180 case kVQHD: rc = readVQHD(s, chd.size); break;
181 default:
182 warning("Unhandled chunk '%s'", tag2str(chd.id));
183 s->skip(roundup(chd.size));
184 rc = true;
185 }
186
187 if (!rc) {
188 warning("failed to handle chunk %s", tag2str(chd.id));
189 return false;
190 }
191 } while (chd.id != kFINF);
192
193 _videoTrack = new VQAVideoTrack(this);
194 _audioTrack = new VQAAudioTrack(this);
195
196 return true;
197 }
198
decodeVideoFrame(Graphics::Surface * surface,int frame,bool forceDraw)199 void VQADecoder::decodeVideoFrame(Graphics::Surface *surface, int frame, bool forceDraw) {
200 _decodingFrame = frame;
201 _videoTrack->decodeVideoFrame(surface, forceDraw);
202 }
203
decodeZBuffer(ZBuffer * zbuffer)204 void VQADecoder::decodeZBuffer(ZBuffer *zbuffer) {
205 _videoTrack->decodeZBuffer(zbuffer);
206 }
207
decodeAudioFrame()208 Audio::SeekableAudioStream *VQADecoder::decodeAudioFrame() {
209 return _audioTrack->decodeAudioFrame();
210 }
211
decodeView(View * view)212 void VQADecoder::decodeView(View *view) {
213 _videoTrack->decodeView(view);
214 }
215
decodeScreenEffects(ScreenEffects * screenEffects)216 void VQADecoder::decodeScreenEffects(ScreenEffects *screenEffects) {
217 _videoTrack->decodeScreenEffects(screenEffects);
218 }
219
decodeLights(Lights * lights)220 void VQADecoder::decodeLights(Lights *lights) {
221 _videoTrack->decodeLights(lights);
222 }
223
readPacket(uint readFlags)224 void VQADecoder::readPacket(uint readFlags) {
225 IFFChunkHeader chd;
226
227 if (remain(_s) < 8) {
228 warning("VQADecoder::readPacket(): remain: %d", remain(_s));
229 assert(remain(_s) < 8);
230 }
231
232 do {
233 if (!readIFFChunkHeader(_s, &chd)) {
234 error("VQADecoder::readPacket(): Error reading chunk header");
235 }
236
237 bool rc = false;
238 // Video track
239 switch (chd.id) {
240 case kAESC: rc = ((readFlags & kVQAReadCustom) == 0) ? _s->skip(roundup(chd.size)) : _videoTrack->readAESC(_s, chd.size); break;
241 case kLITE: rc = ((readFlags & kVQAReadCustom) == 0) ? _s->skip(roundup(chd.size)) : _videoTrack->readLITE(_s, chd.size); break;
242 case kVIEW: rc = ((readFlags & kVQAReadCustom) == 0) ? _s->skip(roundup(chd.size)) : _videoTrack->readVIEW(_s, chd.size); break;
243 case kVQFL: rc = ((readFlags & kVQAReadVideo ) == 0) ? _s->skip(roundup(chd.size)) : _videoTrack->readVQFL(_s, chd.size, readFlags); break;
244 case kVQFR: rc = ((readFlags & kVQAReadVideo ) == 0) ? _s->skip(roundup(chd.size)) : _videoTrack->readVQFR(_s, chd.size, readFlags); break;
245 case kZBUF: rc = ((readFlags & kVQAReadCustom) == 0) ? _s->skip(roundup(chd.size)) : _videoTrack->readZBUF(_s, chd.size); break;
246 // Sound track
247 case kSN2J: rc = ((readFlags & kVQAReadAudio) == 0) ? _s->skip(roundup(chd.size)) : _audioTrack->readSN2J(_s, chd.size); break;
248 case kSND2: rc = ((readFlags & kVQAReadAudio) == 0) ? _s->skip(roundup(chd.size)) : _audioTrack->readSND2(_s, chd.size); break;
249 default:
250 rc = false;
251 _s->skip(roundup(chd.size));
252 }
253
254 if (!rc) {
255 warning("VQADecoder::readPacket(): Error handling chunk %s", tag2str(chd.id));
256 return;
257 }
258 } while (chd.id != kVQFR);
259 }
260
readFrame(int frame,uint readFlags)261 void VQADecoder::readFrame(int frame, uint readFlags) {
262 if (frame < 0 || frame >= numFrames()) {
263 error("VQADecoder::readFrame(): frame %d out of bounds, frame count is %d", frame, numFrames());
264 }
265
266 uint32 frameOffset = 2 * (_frameInfo[frame] & 0x0FFFFFFF);
267 _s->seek(frameOffset);
268
269 _readingFrame = frame;
270 readPacket(readFlags);
271 }
272
readVQHD(Common::SeekableReadStream * s,uint32 size)273 bool VQADecoder::readVQHD(Common::SeekableReadStream *s, uint32 size) {
274 if (size != 42)
275 return false;
276
277 _header.version = s->readUint16LE();
278 _header.flags = s->readUint16LE();
279 _header.numFrames = s->readUint16LE();
280 _header.width = s->readUint16LE();
281 _header.height = s->readUint16LE();
282 _header.blockW = s->readByte();
283 _header.blockH = s->readByte();
284 _header.frameRate = s->readByte();
285 _header.cbParts = s->readByte();
286 _header.colors = s->readUint16LE();
287 _header.maxBlocks = s->readUint16LE();
288 _header.offsetX = s->readUint16LE();
289 _header.offsetY = s->readUint16LE();
290 _header.maxVPTRSize = s->readUint16LE();
291 _header.freq = s->readUint16LE();
292 _header.channels = s->readByte();
293 _header.bits = s->readByte();
294 _header.unk3 = s->readUint32LE();
295 _header.unk4 = s->readUint16LE();
296 _header.maxCBFZSize = s->readUint32LE();
297 _header.unk5 = s->readUint32LE();
298
299 // if (_header.unk3 || _header.unk4 != 4 || _header.unk5 || _header.flags != 0x0014) {
300 // debug("_header.version %d", _header.version);
301 // debug("_header.flags %04x", _header.flags);
302 // debug("_header.numFrames %d", _header.numFrames);
303 // debug("_header.width %d", _header.width);
304 // debug("_header.height %d", _header.height);
305 // debug("_header.blockW %d", _header.blockW);
306 // debug("_header.blockH %d", _header.blockH);
307 // debug("_header.frameRate %d", _header.frameRate);
308 // debug("_header.cbParts %d", _header.cbParts);
309 // debug("_header.colors %d", _header.colors);
310 // debug("_header.maxBlocks %d", _header.maxBlocks);
311 // debug("_header.offsetX %d", _header.offsetX);
312 // debug("_header.offsetY %d", _header.offsetY);
313 // debug("_header.maxVPTRSize %d", _header.maxVPTRSize);
314 // debug("_header.freq %d", _header.freq);
315 // debug("_header.channels %d", _header.channels);
316 // debug("_header.bits %d", _header.bits);
317 // debug("_header.unk3 %d", _header.unk3);
318 // debug("_header.unk4 %d", _header.unk4);
319 // debug("_header.maxCBFZSize %d", _header.maxCBFZSize);
320 // debug("_header.unk5 %d", _header.unk5);
321 // debug("\n");
322 // }
323
324 assert(_header.version == 2);
325 if (_header.channels != 0) {
326 assert(_header.freq == 22050);
327 assert(_header.channels == 1);
328 assert(_header.bits == 16);
329 }
330 assert(_header.colors == 0);
331
332 return true;
333 }
334
readVQFR(Common::SeekableReadStream * s,uint32 size,uint readFlags)335 bool VQADecoder::VQAVideoTrack::readVQFR(Common::SeekableReadStream *s, uint32 size, uint readFlags) {
336 IFFChunkHeader chd;
337
338 signed int sizeLeft = size; // we have to use signed int to avoid underflow
339
340 while (sizeLeft >= 8) {
341 if (!readIFFChunkHeader(s, &chd))
342 return false;
343 sizeLeft -= roundup(chd.size) + 8;
344
345 bool rc = false;
346 switch (chd.id) {
347 case kCBFZ: rc = ((readFlags & kVQAReadCodebook ) == 0) ? s->skip(roundup(chd.size)) : readCBFZ(s, chd.size); break;
348 case kCBPZ: rc = ((readFlags & kVQAReadCodebook ) == 0) ? s->skip(roundup(chd.size)) : readCBFZ(s, chd.size); break;
349 case kVPTR: rc = ((readFlags & kVQAReadVectorPointerTable) == 0) ? s->skip(roundup(chd.size)) : readVPTR(s, chd.size); break;
350 default:
351 s->skip(roundup(chd.size));
352 }
353
354 if (!rc) {
355 error("VQADecoder::VQAVideoTrack::readVQFR(): error handling chunk %s", tag2str(chd.id));
356 return false;
357 }
358 }
359
360 return true;
361 }
362
readMSCI(Common::SeekableReadStream * s,uint32 size)363 bool VQADecoder::readMSCI(Common::SeekableReadStream *s, uint32 size) {
364 IFFChunkHeader chd;
365 readIFFChunkHeader(_s, &chd);
366
367 if (chd.id != kMSCH)
368 return false;
369
370 uint32 count, unk0;
371 count = s->readUint32LE();
372 unk0 = s->readUint32LE();
373 assert(unk0 == 0);
374
375 readIFFChunkHeader(_s, &chd);
376 if (chd.id != kMSCT || chd.size != count * 0x10)
377 return false;
378
379 for (uint32 i = count; i != 0; --i) {
380 uint32 tag, max_size;
381 tag = s->readUint32BE();
382 max_size = s->readUint32LE();
383
384 switch (tag) {
385 case kVIEW:
386 _maxVIEWChunkSize = max_size;
387 break;
388 case kZBUF:
389 _maxZBUFChunkSize = max_size;
390 break;
391 case kAESC:
392 _maxAESCChunkSize = max_size;
393 break;
394 default:
395 warning("Unknown tag in MSCT: %s", tag2str(tag));
396 }
397
398 uint32 zero;
399 zero = s->readUint32LE(); assert(zero == 0);
400 zero = s->readUint32LE(); assert(zero == 0);
401 }
402
403 return true;
404 }
405
readLINF(Common::SeekableReadStream * s,uint32 size)406 bool VQADecoder::readLINF(Common::SeekableReadStream *s, uint32 size) {
407 IFFChunkHeader chd;
408 readIFFChunkHeader(_s, &chd);
409
410 if (chd.id != kLINH || chd.size != 6)
411 return false;
412
413 _loopInfo.loopCount = s->readUint16LE();
414 _loopInfo.flags = s->readUint32LE();
415
416 if ((_loopInfo.flags & 3) == 0)
417 return false;
418
419 readIFFChunkHeader(_s, &chd);
420 if (chd.id != kLIND || chd.size != 4u * _loopInfo.loopCount)
421 return false;
422
423 _loopInfo.loops = new Loop[_loopInfo.loopCount];
424 for (uint16 i = _loopInfo.loopCount; i != 0; --i) {
425 _loopInfo.loops[_loopInfo.loopCount - i].begin = s->readUint16LE();
426 _loopInfo.loops[_loopInfo.loopCount - i].end = s->readUint16LE();
427
428 // debug("Loop %d: %04x %04x", _loopInfo.loopCount - i, _loopInfo.loops[_loopInfo.loopCount - i].begin, _loopInfo.loops[_loopInfo.loopCount - i].end);
429 }
430
431 return true;
432 }
433
codebookInfoForFrame(int frame)434 VQADecoder::CodebookInfo &VQADecoder::codebookInfoForFrame(int frame) {
435 assert(frame < numFrames());
436 assert(!_codebooks.empty());
437
438 CodebookInfo *ci = nullptr;
439 uint count = _codebooks.size();
440
441 for (uint i = count; i != 0; --i) {
442 if (frame >= _codebooks[i - 1].frame) {
443 return _codebooks[i - 1];
444 }
445 }
446
447 assert(ci && "No codebook found");
448 return _codebooks[0];
449 }
450
readCINF(Common::SeekableReadStream * s,uint32 size)451 bool VQADecoder::readCINF(Common::SeekableReadStream *s, uint32 size) {
452 IFFChunkHeader chd;
453
454 readIFFChunkHeader(_s, &chd);
455 if (chd.id != kCINH || chd.size != 8u)
456 return false;
457
458 uint16 codebookCount = s->readUint16LE();
459 _codebooks.resize(codebookCount);
460
461 s->skip(6);
462
463 readIFFChunkHeader(_s, &chd);
464 if (chd.id != kCIND || chd.size != 6u * codebookCount)
465 return false;
466
467 for (uint16 i = codebookCount; i != 0; --i) {
468 _codebooks[codebookCount - i].frame = s->readUint16LE();
469 _codebooks[codebookCount - i].size = s->readUint32LE();
470 _codebooks[codebookCount - i].data = nullptr;
471
472 // debug("Codebook %2u: %4d %8d", codebookCount - i, _codebooks[codebookCount - i].frame, _codebooks[codebookCount - i].size);
473
474 assert(_codebooks[codebookCount - i].frame < numFrames());
475 }
476
477 return true;
478 }
479
readFINF(Common::SeekableReadStream * s,uint32 size)480 bool VQADecoder::readFINF(Common::SeekableReadStream *s, uint32 size) {
481 if (size != 4u * _header.numFrames)
482 return false;
483
484 _frameInfo = new uint32[_header.numFrames];
485
486 for (uint16 i = _header.numFrames; i != 0; --i)
487 _frameInfo[ _header.numFrames - i] = s->readUint32LE();
488
489 // if (false) {
490 // uint32 last = 0;
491 // for (uint32 i = 0; i != _header.numFrames; ++i) {
492 // uint32 diff = _frameInfo[i] - last;
493 // debug("_frameInfo[%4d] = 0x%08x - %08x", i, _frameInfo[i], diff);
494 // last = _frameInfo[i];
495 // }
496 // }
497
498 return true;
499 }
500
readLNIN(Common::SeekableReadStream * s,uint32 size)501 bool VQADecoder::readLNIN(Common::SeekableReadStream *s, uint32 size) {
502 IFFChunkHeader chd;
503
504 readIFFChunkHeader(_s, &chd);
505 if (chd.id != kLNIH || chd.size != 10)
506 return false;
507
508 uint16 loopNamesCount = s->readUint16LE();
509 uint16 loopUnk1 = s->readUint16LE();
510 uint16 loopUnk2 = s->readUint16LE();
511 uint16 loopUnk3 = s->readUint16LE();
512 uint16 loopUnk4 = s->readUint16LE();
513
514 #if BLADERUNNER_DEBUG_CONSOLE
515 debug("VQADecoder::readLNIN() Unknown Values: 0x%04x 0x%04x 0x%04x 0x%04x", loopUnk1, loopUnk2, loopUnk3, loopUnk4);
516 #else
517 (void)loopUnk1;
518 (void)loopUnk2;
519 (void)loopUnk3;
520 (void)loopUnk4;
521 #endif
522
523 if (loopNamesCount != _loopInfo.loopCount)
524 return false;
525
526 readIFFChunkHeader(_s, &chd);
527 if (chd.id != kLNIO || chd.size != 4u * loopNamesCount)
528 return false;
529
530 uint32 *loopNameOffsets = (uint32 *)malloc(loopNamesCount * sizeof(uint32));
531 for (uint16 i = loopNamesCount; i != 0; --i) {
532 loopNameOffsets[loopNamesCount - i] = s->readUint32LE();
533 }
534
535 readIFFChunkHeader(_s, &chd);
536 if (chd.id != kLNID) {
537 free(loopNameOffsets);
538 return false;
539 }
540
541 char *names = (char *)malloc(roundup(chd.size));
542 s->read(names, roundup(chd.size));
543
544 for (uint16 i = loopNamesCount; i != 0; --i) {
545 char *begin = names + loopNameOffsets[loopNamesCount - i];
546 uint32 len = ((i == 1) ? chd.size : loopNameOffsets[loopNamesCount - i + 1]) - loopNameOffsets[loopNamesCount - i];
547
548 _loopInfo.loops[loopNamesCount - i].name = Common::String(begin, len);
549
550 // debug("%2u: %s", loopNamesCount - i, _loopInfo.loops[loopNamesCount - i].name.c_str());
551 }
552
553 free(loopNameOffsets);
554 free(names);
555 return true;
556 }
557
getLoopBeginAndEndFrame(int loop,int * begin,int * end)558 bool VQADecoder::getLoopBeginAndEndFrame(int loop, int *begin, int *end) {
559 assert(begin && end);
560
561 if (loop < 0 || loop >= _loopInfo.loopCount)
562 return false;
563
564 *begin = _loopInfo.loops[loop].begin;
565 *end = _loopInfo.loops[loop].end;
566
567 return true;
568 }
569
getLoopIdFromFrame(int frame)570 int VQADecoder::getLoopIdFromFrame(int frame) {
571 if (frame >= 0) {
572 for (int loopId = 0; loopId < _loopInfo.loopCount; ++loopId) {
573 if (frame >= _loopInfo.loops[loopId].begin && frame <= _loopInfo.loops[loopId].end) {
574 return loopId;
575 }
576 }
577 }
578 return -1;
579 }
580
readCLIP(Common::SeekableReadStream * s,uint32 size)581 bool VQADecoder::readCLIP(Common::SeekableReadStream *s, uint32 size) {
582 s->skip(roundup(size));
583 return true;
584 }
585
readMFCI(Common::SeekableReadStream * s,uint32 size)586 bool VQADecoder::readMFCI(Common::SeekableReadStream *s, uint32 size) {
587 s->skip(roundup(size));
588 return true;
589 }
590
VQAVideoTrack(VQADecoder * vqaDecoder)591 VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
592 _vqaDecoder = vqaDecoder;
593 _hasNewFrame = false;
594
595 VQADecoder::Header *header = &vqaDecoder->_header;
596 _numFrames = header->numFrames;
597 _width = header->width;
598 _height = header->height;
599 _blockW = header->blockW;
600 _blockH = header->blockH;
601 _frameRate = header->frameRate;
602 _maxBlocks = header->maxBlocks;
603 _offsetX = header->offsetX;
604 _offsetY = header->offsetY;
605
606 _maxVPTRSize = header->maxVPTRSize;
607 _maxCBFZSize = header->maxCBFZSize;
608 _maxZBUFChunkSize = vqaDecoder->_maxZBUFChunkSize;
609
610 _codebook = nullptr;
611 _cbfz = nullptr;
612
613 _vpointerSize = 0;
614 _vpointer = nullptr;
615
616 _curFrame = -1;
617
618 _zbufChunkSize = 0;
619 _zbufChunk = new uint8[roundup(_maxZBUFChunkSize)];
620
621 _viewDataSize = 0;
622 _viewData = nullptr;
623
624 _screenEffectsDataSize = 0;
625 _screenEffectsData = nullptr;
626
627 _lightsDataSize = 0;
628 _lightsData = nullptr;
629 }
630
~VQAVideoTrack()631 VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
632 delete[] _cbfz;
633 delete[] _zbufChunk;
634 delete[] _vpointer;
635
636 delete[] _viewData;
637 delete[] _screenEffectsData;
638 delete[] _lightsData;
639 }
640
getWidth() const641 uint16 VQADecoder::VQAVideoTrack::getWidth() const {
642 return _width;
643 }
644
getHeight() const645 uint16 VQADecoder::VQAVideoTrack::getHeight() const {
646 return _height;
647 }
648
getFrameCount() const649 int VQADecoder::VQAVideoTrack::getFrameCount() const {
650 return _numFrames;
651 }
652
getFrameRate() const653 Common::Rational VQADecoder::VQAVideoTrack::getFrameRate() const {
654 return _frameRate;
655 }
656
decodeVideoFrame(Graphics::Surface * surface,bool forceDraw)657 void VQADecoder::VQAVideoTrack::decodeVideoFrame(Graphics::Surface *surface, bool forceDraw) {
658 if (_hasNewFrame || forceDraw) {
659 assert(surface);
660 decodeFrame(surface);
661 _hasNewFrame = false;
662 }
663 }
664
readVQFL(Common::SeekableReadStream * s,uint32 size,uint readFlags)665 bool VQADecoder::VQAVideoTrack::readVQFL(Common::SeekableReadStream *s, uint32 size, uint readFlags) {
666 IFFChunkHeader chd;
667
668 signed int sizeLeft = size; // we have to use signed int to avoid underflow
669
670 while (sizeLeft >= 8) {
671 if (!readIFFChunkHeader(s, &chd))
672 return false;
673 sizeLeft -= roundup(chd.size) + 8;
674
675 bool rc = false;
676 switch (chd.id) {
677 case kCBFZ: rc = readCBFZ(s, chd.size); break;
678 default:
679 s->skip(roundup(chd.size));
680 }
681
682 if (!rc) {
683 warning("VQFL: error handling chunk %s", tag2str(chd.id));
684 return false;
685 }
686 }
687
688 return true;
689 }
690
readCBFZ(Common::SeekableReadStream * s,uint32 size)691 bool VQADecoder::VQAVideoTrack::readCBFZ(Common::SeekableReadStream *s, uint32 size) {
692 if (size > _maxCBFZSize) {
693 warning("readCBFZ: chunk too large: %d > %d", size, _maxCBFZSize);
694 return false;
695 }
696
697 CodebookInfo &codebookInfo = _vqaDecoder->codebookInfoForFrame(_vqaDecoder->_readingFrame);
698 if (codebookInfo.data) {
699 s->skip(roundup(size));
700 return true;
701 }
702
703 uint32 codebookSize = 2 * _maxBlocks * _blockW * _blockH;
704 codebookInfo.data = new uint8[codebookSize];
705
706 if (!_cbfz) {
707 _cbfz = new uint8[roundup(_maxCBFZSize)];
708 }
709
710 s->read(_cbfz, roundup(size));
711
712 decompress_lcw(_cbfz, size, codebookInfo.data, codebookSize);
713
714 return true;
715 }
716
readZBUF(Common::SeekableReadStream * s,uint32 size)717 bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 size) {
718 if (size > _maxZBUFChunkSize) {
719 warning("VQA ERROR: ZBUF chunk size: %08x > %08x", size, _maxZBUFChunkSize);
720 s->skip(roundup(size));
721 return false;
722 }
723
724 _zbufChunkSize = size;
725 s->read(_zbufChunk, roundup(size));
726
727 return true;
728 }
729
decodeZBuffer(ZBuffer * zbuffer)730 void VQADecoder::VQAVideoTrack::decodeZBuffer(ZBuffer *zbuffer) {
731 if (_zbufChunkSize == 0) {
732 return;
733 }
734
735 zbuffer->decodeData(_zbufChunk, _zbufChunkSize);
736 }
737
readVIEW(Common::SeekableReadStream * s,uint32 size)738 bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 size) {
739 if (size != 56) {
740 return false;
741 }
742
743 if (_viewData) {
744 delete[] _viewData;
745 }
746
747 _viewDataSize = roundup(size);
748 _viewData = new uint8[_viewDataSize];
749 s->read(_viewData, _viewDataSize);
750
751 return true;
752 }
753
decodeView(View * view)754 void VQADecoder::VQAVideoTrack::decodeView(View *view) {
755 if (!view || !_viewData) {
756 return;
757 }
758
759 Common::MemoryReadStream s(_viewData, _viewDataSize);
760 view->readVqa(&s);
761
762 delete[] _viewData;
763 _viewData = nullptr;
764 }
765
readAESC(Common::SeekableReadStream * s,uint32 size)766 bool VQADecoder::VQAVideoTrack::readAESC(Common::SeekableReadStream *s, uint32 size) {
767 if (_screenEffectsData) {
768 delete[] _screenEffectsData;
769 }
770
771 _screenEffectsDataSize = roundup(size);
772 _screenEffectsData = new uint8[_screenEffectsDataSize];
773 s->read(_screenEffectsData, _screenEffectsDataSize);
774
775 return true;
776 }
777
decodeScreenEffects(ScreenEffects * aesc)778 void VQADecoder::VQAVideoTrack::decodeScreenEffects(ScreenEffects *aesc) {
779 if (!aesc || !_screenEffectsData) {
780 return;
781 }
782
783 Common::MemoryReadStream s(_screenEffectsData, _screenEffectsDataSize);
784 aesc->readVqa(&s);
785
786 delete[] _screenEffectsData;
787 _screenEffectsData = nullptr;
788 }
789
readLITE(Common::SeekableReadStream * s,uint32 size)790 bool VQADecoder::VQAVideoTrack::readLITE(Common::SeekableReadStream *s, uint32 size) {
791 if (_lightsData) {
792 delete[] _lightsData;
793 }
794
795 _lightsDataSize = roundup(size);
796 _lightsData = new uint8[_lightsDataSize];
797 s->read(_lightsData, _lightsDataSize);
798
799 return true;
800 }
801
802
decodeLights(Lights * lights)803 void VQADecoder::VQAVideoTrack::decodeLights(Lights *lights) {
804 if (!lights || !_lightsData) {
805 return;
806 }
807
808 Common::MemoryReadStream s(_lightsData, _lightsDataSize);
809 lights->readVqa(&s);
810
811 delete[] _lightsData;
812 _lightsData = nullptr;
813 }
814
815
readVPTR(Common::SeekableReadStream * s,uint32 size)816 bool VQADecoder::VQAVideoTrack::readVPTR(Common::SeekableReadStream *s, uint32 size) {
817 if (size > _maxVPTRSize)
818 return false;
819
820 if (!_vpointer) {
821 _vpointer = new uint8[roundup(_maxVPTRSize)];
822 }
823
824 _vpointerSize = size;
825 s->read(_vpointer, roundup(size));
826
827 _hasNewFrame = true;
828
829 return true;
830 }
831
VPTRWriteBlock(Graphics::Surface * surface,unsigned int dstBlock,unsigned int srcBlock,int count,bool alpha)832 void VQADecoder::VQAVideoTrack::VPTRWriteBlock(Graphics::Surface *surface, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha) {
833 const uint8 *const block_src = &_codebook[2 * srcBlock * _blockW * _blockH];
834
835 uint16 blocks_per_line = _width / _blockW;
836
837 uint32 intermDiv = 0;
838 uint32 dst_x = 0;
839 uint32 dst_y = 0;
840 uint16 vqaColor = 0;
841 uint8 a, r, g, b;
842
843 for (uint i = count; i != 0; --i) {
844 intermDiv = (dstBlock + count - i) / blocks_per_line;
845 dst_x = ((dstBlock + count - i) - intermDiv * blocks_per_line) * _blockW + _offsetX;
846 dst_y = intermDiv * _blockH + _offsetY;
847
848 const uint8 *src_p = block_src;
849
850 for (uint y = _blockH; y != 0; --y) {
851 for (uint x = _blockW; x != 0; --x) {
852 vqaColor = READ_LE_UINT16(src_p);
853 src_p += 2;
854
855 getGameDataColor(vqaColor, a, r, g, b);
856
857 if (!(alpha && a)) {
858 // clip is too slow and it is not needed
859 // void* dstPtr = surface->getBasePtr(CLIP(dst_x + x, (uint32)0, (uint32)(surface->w - 1)), CLIP(dst_y + y, (uint32)0, (uint32)(surface->h - 1)));
860 void* dstPtr = surface->getBasePtr(dst_x + _blockW - x, dst_y + _blockH - y);
861 // Ignore the alpha in the output as it is inversed in the input
862 drawPixel(*surface, dstPtr, surface->format.RGBToColor(r, g, b));
863 }
864 }
865 }
866 }
867 }
868
decodeFrame(Graphics::Surface * surface)869 bool VQADecoder::VQAVideoTrack::decodeFrame(Graphics::Surface *surface) {
870 CodebookInfo &codebookInfo = _vqaDecoder->codebookInfoForFrame(_vqaDecoder->_decodingFrame);
871
872 if (!codebookInfo.data) {
873 _vqaDecoder->readFrame(codebookInfo.frame, kVQAReadCodebook);
874 }
875
876 _codebook = codebookInfo.data;
877 if (!_codebook || !_vpointer)
878 return false;
879
880 uint8 *src = _vpointer;
881 uint8 *end = _vpointer + _vpointerSize;
882
883 uint16 count, srcBlock, dstBlock = 0;
884 (void)srcBlock;
885
886 while (end - src >= 2) {
887 uint16 command = src[0] | (src[1] << 8);
888 uint8 prefix = command >> 13;
889 src += 2;
890
891 switch (prefix) {
892 case 0:
893 count = command & 0x1fff;
894 dstBlock += count;
895 break;
896 case 1:
897 count = 2 * (((command >> 8) & 0x1f) + 1);
898 srcBlock = command & 0x00ff;
899
900 VPTRWriteBlock(surface, dstBlock, srcBlock, count);
901 dstBlock += count;
902 break;
903 case 2:
904 count = 2 * (((command >> 8) & 0x1f) + 1);
905 srcBlock = command & 0x00ff;
906
907 VPTRWriteBlock(surface, dstBlock, srcBlock, 1);
908 ++dstBlock;
909
910 for (uint16 i = count; i != 0; --i) {
911 srcBlock = *src++;
912 VPTRWriteBlock(surface, dstBlock, srcBlock, 1);
913 ++dstBlock;
914 }
915 break;
916 case 3:
917 case 4:
918 count = 1;
919 srcBlock = command & 0x1fff;
920
921 VPTRWriteBlock(surface, dstBlock, srcBlock, count, prefix == 4);
922 ++dstBlock;
923 break;
924 case 5:
925 case 6:
926 count = *src++;
927 srcBlock = command & 0x1fff;
928
929 VPTRWriteBlock(surface, dstBlock, srcBlock, count, prefix == 6);
930 dstBlock += count;
931 break;
932 default:
933 warning("VQAVideoTrack::decodeFrame: Undefined case %d", command >> 13);
934 }
935 }
936
937 return true;
938 }
939
VQAAudioTrack(VQADecoder * vqaDecoder)940 VQADecoder::VQAAudioTrack::VQAAudioTrack(VQADecoder *vqaDecoder) {
941 if (vqaDecoder != nullptr) {
942 _frequency = vqaDecoder->_header.freq;
943 } else {
944 warning("VQADecoder::VQAAudioTrack::VQAAudioTrack: null pointer for vqaDecoder parameter");
945 // TODO use some typical value?
946 _frequency = 0;
947 }
948 memset(_compressedAudioFrame, 0, sizeof(uint8));
949 }
950
~VQAAudioTrack()951 VQADecoder::VQAAudioTrack::~VQAAudioTrack() {
952 }
953
decodeAudioFrame()954 Audio::SeekableAudioStream *VQADecoder::VQAAudioTrack::decodeAudioFrame() {
955 int16 *audioFrame = (int16 *)malloc(kSizeInShortsAllocatedToAudioFrame);
956 if (audioFrame != nullptr) {
957 memset(audioFrame, 0, kSizeInShortsAllocatedToAudioFrame);
958
959 _adpcmDecoder.decode(_compressedAudioFrame, kSizeInBytesOfCompressedAudioFrame, audioFrame, true);
960
961 uint flags = Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
962
963 return Audio::makeRawStream((byte *)audioFrame, kSizeInShortsAllocatedToAudioFrame, _frequency, flags, DisposeAfterUse::YES);
964 } else {
965 warning("VQADecoder::VQAAudioTrack::decodeAudioFrame: Insufficient memory to allocate for audio frame");
966 return nullptr;
967 }
968 }
969
readSND2(Common::SeekableReadStream * s,uint32 size)970 bool VQADecoder::VQAAudioTrack::readSND2(Common::SeekableReadStream *s, uint32 size) {
971 if (size != kSizeInBytesOfCompressedAudioFrame) {
972 warning("audio frame size: %d", size);
973 return false;
974 }
975
976 s->read(_compressedAudioFrame, roundup(size));
977
978 return true;
979 }
980
readSN2J(Common::SeekableReadStream * s,uint32 size)981 bool VQADecoder::VQAAudioTrack::readSN2J(Common::SeekableReadStream *s, uint32 size) {
982 if (size != 6)
983 return false;
984
985 uint16 stepIndex = s->readUint16LE();
986 uint32 predictor = s->readUint32LE();
987
988 _adpcmDecoder.setParameters(stepIndex >> 5, predictor);
989
990 return true;
991 }
992
993 } // End of namespace BladeRunner
994