aboutsummaryrefslogtreecommitdiff
path: root/engines/bladerunner/vqa_decoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/bladerunner/vqa_decoder.cpp')
-rw-r--r--engines/bladerunner/vqa_decoder.cpp614
1 files changed, 330 insertions, 284 deletions
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index f4676d39d6..bd898bc171 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -22,9 +22,12 @@
#include "bladerunner/vqa_decoder.h"
+#include "bladerunner/bladerunner.h"
#include "bladerunner/decompress_lcw.h"
#include "bladerunner/decompress_lzo.h"
+#include "audio/decoders/raw.h"
+
#include "common/array.h"
#include "common/util.h"
@@ -63,23 +66,14 @@ namespace BladeRunner {
#define kWVQA 0x57565141
#define kZBUF 0x5A425546
-VQADecoder::VQADecoder()
- : _s(nullptr),
- _frame(0),
- _zbuf(0),
- _codebook(0),
- _cbfz(0),
- _vptr(0),
- _hasView(false),
- _audioFrame(0),
- _maxVIEWChunkSize(0),
- _maxZBUFChunkSize(0),
- _maxAESCChunkSize(0)
-{
-}
+int32 remain(Common::SeekableReadStream *s) {
+ int32 pos = s->pos();
+ if (pos == -1) return -1;
-VQADecoder::~VQADecoder()
-{
+ int32 size = s->size();
+ if (size == -1) return -1;
+
+ return size - pos;
}
struct IFFChunkHeader
@@ -92,23 +86,6 @@ struct IFFChunkHeader
uint32 size;
};
-static inline uint32 roundup(uint32 v)
-{
- return (v + 1) & ~1u;
-}
-
-const char *strTag(uint32 tag);
-
-int32 remain(Common::SeekableReadStream *s) {
- int32 pos = s->pos();
- if (pos == -1) return -1;
-
- int32 size = s->size();
- if (size == -1) return -1;
-
- return size - pos;
-}
-
static
bool readIFFChunkHeader(Common::SeekableReadStream *s, IFFChunkHeader *ts)
{
@@ -118,12 +95,14 @@ bool readIFFChunkHeader(Common::SeekableReadStream *s, IFFChunkHeader *ts)
ts->id = s->readUint32BE();
ts->size = s->readUint32BE();
- // if (ts->size != roundup(ts->size))
- // debug("%s: %d", strTag(ts->id), ts->size);
-
return true;
}
+static inline uint32 roundup(uint32 v)
+{
+ return (v + 1) & ~1u;
+}
+
const char *strTag(uint32 tag)
{
static char s[5];
@@ -137,8 +116,21 @@ const char *strTag(uint32 tag)
return s;
}
-bool VQADecoder::open(Common::SeekableReadStream *s)
+VQADecoder::VQADecoder()
+ : _s(nullptr),
+ _maxVIEWChunkSize(0),
+ _maxZBUFChunkSize(0),
+ _maxAESCChunkSize(0)
{
+}
+
+VQADecoder::~VQADecoder() {
+}
+
+bool VQADecoder::loadStream(Common::SeekableReadStream *s) {
+ close();
+ _s = s;
+
IFFChunkHeader chd;
uint32 type;
bool rc;
@@ -152,81 +144,124 @@ bool VQADecoder::open(Common::SeekableReadStream *s)
if (type != kWVQA)
return false;
- _s = s;
do {
if (!readIFFChunkHeader(_s, &chd))
return false;
- debug("\t%s : %x", strTag(chd.id), chd.size);
-
rc = false;
switch (chd.id)
{
- case kCINF: rc = readCINF(chd.size); break;
- case kCLIP: rc = readCLIP(chd.size); break;
- case kFINF: rc = readFINF(chd.size); break;
- case kLINF: rc = readLINF(chd.size); break;
- case kLNIN: rc = readLNIN(chd.size); break;
- case kMFCI: rc = readMFCI(chd.size); break;
- case kMSCI: rc = readMSCI(chd.size); break;
- case kVQHD: rc = readVQHD(chd.size); break;
+ case kCINF: rc = readCINF(s, chd.size); break;
+ case kCLIP: rc = readCLIP(s, chd.size); break;
+ case kFINF: rc = readFINF(s, chd.size); break;
+ case kLINF: rc = readLINF(s, chd.size); break;
+ case kLNIN: rc = readLNIN(s, chd.size); break;
+ case kMFCI: rc = readMFCI(s, chd.size); break;
+ case kMSCI: rc = readMSCI(s, chd.size); break;
+ case kVQHD: rc = readVQHD(s, chd.size); break;
default:
debug("Unhandled chunk '%s'", strTag(chd.id));
- _s->skip(roundup(chd.size));
+ s->skip(roundup(chd.size));
rc = true;
}
- if (!rc)
- {
+ if (!rc) {
debug("failed to handle chunk %s", strTag(chd.id));
- return -1;
+ return false;
}
-
} while (chd.id != kFINF);
+ _videoTrack = new VQAVideoTrack(this);
+ addTrack(_videoTrack);
+
+ _audioTrack = new VQAAudioTrack(this);
+ addTrack(_audioTrack);
+
+ /*
for (int i = 0; i != _loopInfo.loopCount; ++i) {
debug("LOOP %2d: %4d %4d %s", i,
_loopInfo.loops[i].begin,
_loopInfo.loops[i].end,
_loopInfo.loops[i].name.c_str());
}
+ */
return true;
}
-bool VQADecoder::readVQHD(uint32 size)
+void VQADecoder::readNextPacket() {
+ IFFChunkHeader chd;
+
+ if (remain(_s) < 8) {
+ warning("remain: %d", remain(_s));
+ assert(remain(_s) < 8);
+ }
+
+ do {
+ if (!readIFFChunkHeader(_s, &chd)) {
+ warning("Error reading chunk header");
+ return;
+ }
+
+ bool rc = false;
+ switch (chd.id) {
+ // Video track
+ case kAESC: rc = _videoTrack->readAESC(_s, chd.size); break;
+ case kLITE: rc = _videoTrack->readLITE(_s, chd.size); break;
+ case kVIEW: rc = _videoTrack->readVIEW(_s, chd.size); break;
+ case kVQFL: rc = _videoTrack->readVQFL(_s, chd.size); break;
+ case kVQFR: rc = _videoTrack->readVQFR(_s, chd.size); break;
+ case kZBUF: rc = _videoTrack->readZBUF(_s, chd.size); break;
+ // Sound track
+ case kSN2J: rc = _audioTrack->readSN2J(_s, chd.size); break;
+ case kSND2: rc = _audioTrack->readSND2(_s, chd.size); break;
+
+ default:
+ _s->skip(roundup(chd.size));
+ rc = false;
+ }
+
+ if (!rc) {
+ warning("Error handling chunk %s", strTag(chd.id));
+ return;
+ }
+ } while (chd.id != kVQFR);
+}
+
+bool VQADecoder::readVQHD(Common::SeekableReadStream *s, uint32 size)
{
if (size != 42)
return false;
- _header.version = _s->readUint16LE();
- _header.flags = _s->readUint16LE();
- _header.numFrames = _s->readUint16LE();
- _header.width = _s->readUint16LE();
- _header.height = _s->readUint16LE();
- _header.blockW = _s->readByte();
- _header.blockH = _s->readByte();
- _header.frameRate = _s->readByte();
- _header.cbParts = _s->readByte();
- _header.colors = _s->readUint16LE();
- _header.maxBlocks = _s->readUint16LE();
- _header.offset_x = _s->readUint16LE();
- _header.offset_y = _s->readUint16LE();
- _header.maxVPTRSize = _s->readUint16LE();
- _header.freq = _s->readUint16LE();
- _header.channels = _s->readByte();
- _header.bits = _s->readByte();
- _header.unk3 = _s->readUint32LE();
- _header.unk4 = _s->readUint16LE();
- _header.maxCBFZSize = _s->readUint32LE();
- _header.unk5 = _s->readUint32LE();
-
- if (_header.offset_x || _header.offset_y)
+ _header.version = s->readUint16LE();
+ _header.flags = s->readUint16LE();
+ _header.numFrames = s->readUint16LE();
+ _header.width = s->readUint16LE();
+ _header.height = s->readUint16LE();
+ _header.blockW = s->readByte();
+ _header.blockH = s->readByte();
+ _header.frameRate = s->readByte();
+ _header.cbParts = s->readByte();
+ _header.colors = s->readUint16LE();
+ _header.maxBlocks = s->readUint16LE();
+ _header.offsetX = s->readUint16LE();
+ _header.offsetY = s->readUint16LE();
+ _header.maxVPTRSize = s->readUint16LE();
+ _header.freq = s->readUint16LE();
+ _header.channels = s->readByte();
+ _header.bits = s->readByte();
+ _header.unk3 = s->readUint32LE();
+ _header.unk4 = s->readUint16LE();
+ _header.maxCBFZSize = s->readUint32LE();
+ _header.unk5 = s->readUint32LE();
+
+ if (_header.offsetX || _header.offsetY)
{
- debug("_header.offset_x, _header.offset_y: %d %d", _header.offset_x, _header.offset_y);
+ debug("_header.offsetX, _header.offsetY: %d %d", _header.offsetX, _header.offsetY);
}
// if (_header.unk3 || _header.unk4 != 4 || _header.unk5 || _header.flags != 0x0014)
+ if (false)
{
debug("_header.version %d", _header.version);
debug("_header.flags %04x", _header.flags);
@@ -239,8 +274,8 @@ bool VQADecoder::readVQHD(uint32 size)
debug("_header.cbParts %d", _header.cbParts);
debug("_header.colors %d", _header.colors);
debug("_header.maxBlocks %d", _header.maxBlocks);
- debug("_header.offsetX %d", _header.offset_x);
- debug("_header.offsetY %d", _header.offset_y);
+ debug("_header.offsetX %d", _header.offsetX);
+ debug("_header.offsetY %d", _header.offsetY);
debug("_header.maxVPTRSize %d", _header.maxVPTRSize);
debug("_header.freq %d", _header.freq);
debug("_header.channels %d", _header.channels);
@@ -251,12 +286,39 @@ bool VQADecoder::readVQHD(uint32 size)
debug("_header.unk5 %d", _header.unk5);
}
- // exit(-1);
+ return true;
+}
+
+bool VQADecoder::VQAVideoTrack::readVQFR(Common::SeekableReadStream *s, uint32 size)
+{
+ IFFChunkHeader chd;
+
+ while (size >= 8)
+ {
+ if (!readIFFChunkHeader(s, &chd))
+ return false;
+ size -= roundup(chd.size) + 8;
+
+ bool rc = false;
+ switch (chd.id)
+ {
+ case kCBFZ: rc = readCBFZ(s, chd.size); break;
+ case kVPTR: rc = readVPTR(s, chd.size); break;
+ default:
+ s->skip(roundup(chd.size));
+ }
+
+ if (!rc)
+ {
+ debug("VQFR: error handling chunk %s", strTag(chd.id));
+ return false;
+ }
+ }
return true;
}
-bool VQADecoder::readMSCI(uint32 size)
+bool VQADecoder::readMSCI(Common::SeekableReadStream *s, uint32 size)
{
IFFChunkHeader chd;
readIFFChunkHeader(_s, &chd);
@@ -265,8 +327,8 @@ bool VQADecoder::readMSCI(uint32 size)
return false;
uint32 count, unk0;
- count = _s->readUint32LE();
- unk0 = _s->readUint32LE();
+ count = s->readUint32LE();
+ unk0 = s->readUint32LE();
assert(unk0 == 0);
readIFFChunkHeader(_s, &chd);
@@ -276,8 +338,8 @@ bool VQADecoder::readMSCI(uint32 size)
for (uint32 i = 0; i < count; ++i)
{
uint32 tag, size;
- tag = _s->readUint32BE();
- size = _s->readUint32LE();
+ tag = s->readUint32BE();
+ size = s->readUint32LE();
switch (tag)
{
@@ -287,7 +349,6 @@ bool VQADecoder::readMSCI(uint32 size)
break;
case kZBUF:
_maxZBUFChunkSize = size;
- _zbufChunk = new uint8[roundup(_maxZBUFChunkSize)];
debug("max ZBUF size: %08x", _maxZBUFChunkSize);
break;
case kAESC:
@@ -299,14 +360,14 @@ bool VQADecoder::readMSCI(uint32 size)
}
uint32 zero;
- zero = _s->readUint32LE(); assert(zero == 0);
- zero = _s->readUint32LE(); assert(zero == 0);
+ zero = s->readUint32LE(); assert(zero == 0);
+ zero = s->readUint32LE(); assert(zero == 0);
}
return true;
}
-bool VQADecoder::readLINF(uint32 size)
+bool VQADecoder::readLINF(Common::SeekableReadStream *s, uint32 size)
{
IFFChunkHeader chd;
readIFFChunkHeader(_s, &chd);
@@ -314,8 +375,8 @@ bool VQADecoder::readLINF(uint32 size)
if (chd.id != kLINH || chd.size != 6)
return false;
- _loopInfo.loopCount = _s->readUint16LE();
- _loopInfo.flags = _s->readUint32LE();
+ _loopInfo.loopCount = s->readUint16LE();
+ _loopInfo.flags = s->readUint32LE();
if ((_loopInfo.flags & 3) == 0)
return false;
@@ -327,8 +388,8 @@ bool VQADecoder::readLINF(uint32 size)
_loopInfo.loops = new Loop[_loopInfo.loopCount];
for (int i = 0; i != _loopInfo.loopCount; ++i)
{
- _loopInfo.loops[i].begin = _s->readUint16LE();
- _loopInfo.loops[i].end = _s->readUint16LE();
+ _loopInfo.loops[i].begin = s->readUint16LE();
+ _loopInfo.loops[i].end = s->readUint16LE();
// debug("Loop %d: %04x %04x", i, _loopInfo.loops[i].begin, _loopInfo.loops[i].end);
}
@@ -336,7 +397,7 @@ bool VQADecoder::readLINF(uint32 size)
return true;
}
-bool VQADecoder::readCINF(uint32 size)
+bool VQADecoder::readCINF(Common::SeekableReadStream *s, uint32 size)
{
IFFChunkHeader chd;
@@ -344,8 +405,8 @@ bool VQADecoder::readCINF(uint32 size)
if (chd.id != kCINH || chd.size != 8u)
return false;
- _clipInfo.clipCount = _s->readUint16LE();
- _s->skip(6);
+ _clipInfo.clipCount = s->readUint16LE();
+ s->skip(6);
readIFFChunkHeader(_s, &chd);
if (chd.id != kCIND || chd.size != 6u * _clipInfo.clipCount)
@@ -355,15 +416,14 @@ bool VQADecoder::readCINF(uint32 size)
{
uint16 a;
uint32 b;
- a = _s->readUint16LE();
- b = _s->readUint32LE();
- debug("%4d %08x", a, b);
+ a = s->readUint16LE();
+ b = s->readUint32LE();
}
return true;
}
-bool VQADecoder::readFINF(uint32 size)
+bool VQADecoder::readFINF(Common::SeekableReadStream *s, uint32 size)
{
if (size != 4u * _header.numFrames)
return false;
@@ -371,7 +431,7 @@ bool VQADecoder::readFINF(uint32 size)
_frameInfo = new uint32[_header.numFrames];
for (uint32 i = 0; i != _header.numFrames; ++i)
- _frameInfo[i] = _s->readUint32LE();
+ _frameInfo[i] = s->readUint32LE();
if (false) {
uint32 last = 0;
@@ -386,7 +446,7 @@ bool VQADecoder::readFINF(uint32 size)
return true;
}
-bool VQADecoder::readLNIN(uint32 size)
+bool VQADecoder::readLNIN(Common::SeekableReadStream *s, uint32 size)
{
IFFChunkHeader chd;
@@ -396,11 +456,11 @@ bool VQADecoder::readLNIN(uint32 size)
uint16 loopNamesCount, loopUnk1, loopUnk2, loopUnk3, loopUnk4;
- loopNamesCount = _s->readUint16LE();
- loopUnk1 = _s->readUint16LE();
- loopUnk2 = _s->readUint16LE();
- loopUnk3 = _s->readUint16LE();
- loopUnk4 = _s->readUint16LE();
+ loopNamesCount = s->readUint16LE();
+ loopUnk1 = s->readUint16LE();
+ loopUnk2 = s->readUint16LE();
+ loopUnk3 = s->readUint16LE();
+ loopUnk4 = s->readUint16LE();
if (loopNamesCount != _loopInfo.loopCount)
return false;
@@ -411,7 +471,7 @@ bool VQADecoder::readLNIN(uint32 size)
uint32 *loopNameOffsets = (uint32*)alloca(loopNamesCount * sizeof(uint32));
for (int i = 0; i != loopNamesCount; ++i) {
- loopNameOffsets[i] = _s->readUint32LE();
+ loopNameOffsets[i] = s->readUint32LE();
}
readIFFChunkHeader(_s, &chd);
@@ -419,7 +479,7 @@ bool VQADecoder::readLNIN(uint32 size)
return false;
char *names = (char*)alloca(roundup(chd.size));
- _s->read(names, roundup(chd.size));
+ s->read(names, roundup(chd.size));
for (int i = 0; i != loopNamesCount; ++i) {
char *begin = names + loopNameOffsets[i];
@@ -431,157 +491,113 @@ bool VQADecoder::readLNIN(uint32 size)
return true;
}
-bool VQADecoder::readCLIP(uint32 size)
-{
- _s->skip(roundup(size));
+bool VQADecoder::readCLIP(Common::SeekableReadStream *s, uint32 size) {
+ s->skip(roundup(size));
return true;
}
-bool VQADecoder::readMFCI(uint32 size)
-{
- _s->skip(roundup(size));
+bool VQADecoder::readMFCI(Common::SeekableReadStream *s, uint32 size) {
+ s->skip(roundup(size));
return true;
}
-bool VQADecoder::readFrame()
-{
- IFFChunkHeader chd;
-
- if (!_s)
- return false;
-
- _hasView = false;
+VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
+ VQADecoder::Header *header = &vqaDecoder->_header;
- if (remain(_s) < 8) {
- debug("remain: %d", remain(_s));
- return false;
- }
+ _surface = nullptr;
+ _hasNewFrame = false;
- do {
- if (!readIFFChunkHeader(_s, &chd)) {
- debug("Error reading chunk header");
- return false;
- }
+ _numFrames = header->numFrames;
+ _width = header->width;
+ _height = header->height;
+ _blockW = header->blockW;
+ _blockH = header->blockH;
+ _frameRate = header->frameRate;
+ _maxBlocks = header->maxBlocks;
+ _offsetX = header->offsetX;
+ _offsetY = header->offsetY;
- // debug("%s ", strTag(chd.id));
+ _maxVPTRSize = header->maxVPTRSize;
+ _maxCBFZSize = header->maxCBFZSize;
+ _maxZBUFChunkSize = vqaDecoder->_maxZBUFChunkSize;
- bool rc = false;
- switch (chd.id)
- {
- case kAESC: rc = readAESC(chd.size); break;
- case kLITE: rc = readLITE(chd.size); break;
- case kSN2J: rc = readSN2J(chd.size); break;
- case kSND2: rc = readSND2(chd.size); break;
- case kVIEW: rc = readVIEW(chd.size); break;
- case kVQFL: rc = readVQFL(chd.size); break;
- case kVQFR: rc = readVQFR(chd.size); break;
- case kZBUF: rc = readZBUF(chd.size); break;
- default:
- _s->skip(roundup(chd.size));
- rc = true;
- }
+ _codebookSize = 0;
+ _codebook = nullptr;
+ _cbfz = nullptr;
+ _zbufChunk = nullptr;
- if (!rc)
- {
- debug("Error handling chunk %s", strTag(chd.id));
- return false;
- }
- } while (chd.id != kVQFR);
-
- return true;
-}
-
-
-bool VQADecoder::readSN2J(uint32 size)
-{
- if (size != 6)
- return false;
+ _vptrSize = 0;
+ _vptr = nullptr;
- uint16 step_index;
- uint32 predictor;
+ _curFrame = -1;
- step_index = _s->readUint16LE();
- predictor = _s->readUint32LE();
- // ima_adpcm_ws_decoder.set_parameters(step_index >> 5, predictor);
+ _zbufChunk = new uint8[roundup(_maxZBUFChunkSize)];
- return true;
+ _surface = new Graphics::Surface();
+ _surface->create(_width, _height, RGB555);
}
-bool VQADecoder::readSND2(uint32 size)
-{
- if (size != 735)
- {
- debug("audio frame size: %d", size);
- return false;
- }
-
- if (!_audioFrame)
- _audioFrame = new int16[2 * size];
- memset(_audioFrame, 0, 4 * size);
-
- uint8 *inFrame = new uint8[roundup(size)];
- _s->read(inFrame, roundup(size));
+VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
+ delete[] _codebook;
+ delete[] _cbfz;
+ delete[] _zbufChunk;
+ delete[] _vptr;
- // ima_adpcm_ws_decoder.decode(inFrame, size, _audioFrame);
+ delete _surface;
+}
- delete[] inFrame;
+uint16 VQADecoder::VQAVideoTrack::getWidth() const {
+ return _width;
+}
- return true;
+uint16 VQADecoder::VQAVideoTrack::getHeight() const {
+ return _height;
}
-bool VQADecoder::readVQFR(uint32 size)
-{
- IFFChunkHeader chd;
+Graphics::PixelFormat VQADecoder::VQAVideoTrack::getPixelFormat() const {
+ return _surface->format;
+}
- while (size >= 8)
- {
- if (!readIFFChunkHeader(_s, &chd))
- return false;
- size -= roundup(chd.size) + 8;
+int VQADecoder::VQAVideoTrack::getCurFrame() const {
+ return _curFrame;
+}
- // debug("(%s) ", strTag(chd.id)); fflush(0);
+int VQADecoder::VQAVideoTrack::getFrameCount() const {
+ return _numFrames;
+}
- bool rc = false;
- switch (chd.id)
- {
- case kCBFZ: rc = readCBFZ(chd.size); break;
- case kVPTR: rc = readVPTR(chd.size); break;
- default:
- _s->skip(roundup(chd.size));
- }
+Common::Rational VQADecoder::VQAVideoTrack::getFrameRate() const {
+ return _frameRate;
+}
- if (!rc)
- {
- debug("VQFR: error handling chunk %s", strTag(chd.id));
- return false;
- }
+const Graphics::Surface *VQADecoder::VQAVideoTrack::decodeNextFrame() {
+ debug("_curFrame: %d", _curFrame);
+ if (_hasNewFrame) {
+ decodeFrame((uint16*)_surface->getPixels());
+ _curFrame++;
+ _hasNewFrame = false;
}
-
- return true;
+ return _surface;
}
-bool VQADecoder::readVQFL(uint32 size)
-{
+bool VQADecoder::VQAVideoTrack::readVQFL(Common::SeekableReadStream *s, uint32 size) {
IFFChunkHeader chd;
- while (size >= 8)
- {
- if (!readIFFChunkHeader(_s, &chd))
+ while (size >= 8) {
+ if (!readIFFChunkHeader(s, &chd))
return false;
size -= roundup(chd.size) + 8;
bool rc = false;
- switch (chd.id)
- {
- case kCBFZ: rc = readCBFZ(chd.size); break;
+ switch (chd.id) {
+ case kCBFZ: rc = readCBFZ(s, chd.size); break;
default:
- _s->skip(roundup(chd.size));
+ s->skip(roundup(chd.size));
}
- if (!rc)
- {
- debug("VQFL: error handling chunk %s", strTag(chd.id));
+ if (!rc) {
+ warning("VQFL: error handling chunk %s", strTag(chd.id));
return false;
}
}
@@ -589,29 +605,27 @@ bool VQADecoder::readVQFL(uint32 size)
return true;
}
-bool VQADecoder::readCBFZ(uint32 size)
-{
- if (size > _header.maxCBFZSize)
- {
- debug("%d > %d", size, _header.maxCBFZSize);
+bool VQADecoder::VQAVideoTrack::readCBFZ(Common::SeekableReadStream *s, uint32 size) {
+ if (size > _maxCBFZSize) {
+ debug("%d > %d", size, _maxCBFZSize);
return false;
}
- if (!_codebook)
- {
- _codebookSize = 2 * _header.maxBlocks * _header.blockW * _header.blockH;
+ if (!_codebook) {
+ _codebookSize = 2 * _maxBlocks * _blockW * _blockH;
_codebook = new uint8[_codebookSize];
}
if (!_cbfz)
- _cbfz = new uint8[roundup(_header.maxCBFZSize)];
+ _cbfz = new uint8[roundup(_maxCBFZSize)];
- _s->read(_cbfz, roundup(size));
+ s->read(_cbfz, roundup(size));
decompress_lcw(_cbfz, size, _codebook, _codebookSize);
return true;
}
+#if 0
static
int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
{
@@ -655,52 +669,58 @@ int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
}
return dstSize - dstRemain;
}
+#endif
-bool VQADecoder::readZBUF(uint32 size)
+bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 size)
{
+ s->skip(roundup(size));
+ return true;
+#if 0
if (size > _maxZBUFChunkSize) {
debug("VQA ERROR: ZBUF chunk size: %08x > %08x", size, _maxZBUFChunkSize);
- _s->skip(roundup(size));
+ s->skip(roundup(size));
return false;
}
uint32 width, height, complete, unk0;
- width = _s->readUint32LE();
- height = _s->readUint32LE();
- complete = _s->readUint32LE();
- unk0 = _s->readUint32LE();
+ width = s->readUint32LE();
+ height = s->readUint32LE();
+ complete = s->readUint32LE();
+ unk0 = s->readUint32LE();
uint32 remain = size - 16;
- if (width != _header.width || height != _header.height)
+ if (width != width || height != height)
{
debug("%d, %d, %d, %d", width, height, complete, unk0);
- _s->skip(roundup(remain));
+ s->skip(roundup(remain));
return false;
}
+ s->read(_zbufChunk, roundup(remain));
+
if (!_zbuf)
{
if (!complete) {
- _s->skip(roundup(remain));
+ s->skip(roundup(remain));
return false;
}
_zbuf = new uint16[width * height];
}
- _s->read(_zbufChunk, roundup(remain));
-
if (complete) {
size_t zbufOutSize;
decompress_lzo1x(_zbufChunk, remain, (uint8*)_zbuf, &zbufOutSize);
} else {
decodeZBUF_partial(_zbufChunk, _zbuf, remain);
}
+#endif
return true;
}
-bool VQADecoder::getZBUF(uint16 *zbuf)
+#if 0
+bool VQADecoder::VQAVideoTrack::getZBUF(uint16 *zbuf)
{
if (!_zbuf)
return false;
@@ -708,50 +728,51 @@ bool VQADecoder::getZBUF(uint16 *zbuf)
memcpy(zbuf, _zbuf, 2 * _header.width * _header.height);
return true;
}
+#endif
-bool VQADecoder::readVIEW(uint32 size)
+bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 size)
{
if (size != 56)
return false;
- _s->skip(size);
- // _hasView = true;
-
+ s->skip(size);
return true;
}
-bool VQADecoder::readAESC(uint32 size)
+bool VQADecoder::VQAVideoTrack::readAESC(Common::SeekableReadStream *s, uint32 size)
{
- _s->skip(roundup(size));
+ s->skip(roundup(size));
return true;
}
-bool VQADecoder::readLITE(uint32 size)
+bool VQADecoder::VQAVideoTrack::readLITE(Common::SeekableReadStream *s, uint32 size)
{
- _s->skip(roundup(size));
+ s->skip(roundup(size));
return true;
}
-bool VQADecoder::readVPTR(uint32 size)
+bool VQADecoder::VQAVideoTrack::readVPTR(Common::SeekableReadStream *s, uint32 size)
{
- if (size > _header.maxVPTRSize)
+ if (size > _maxVPTRSize)
return false;
if (!_vptr)
- _vptr = new uint8[roundup(_header.maxVPTRSize)];
+ _vptr = new uint8[roundup(_maxVPTRSize)];
_vptrSize = size;
- _s->read(_vptr, roundup(size));
+ s->read(_vptr, roundup(size));
+
+ _hasNewFrame = true;
return true;
}
-void VQADecoder::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha) const
+void VQADecoder::VQAVideoTrack::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha)
{
- uint16 frame_width = _header.width;
+ uint16 frame_width = _width;
uint32 frame_stride = 640;
- uint16 block_width = _header.blockW;
- uint16 block_height = _header.blockH;
+ uint16 block_width = _blockW;
+ uint16 block_height = _blockH;
const uint8 *const block_src =
&_codebook[2 * srcBlock * block_width * block_height];
@@ -760,8 +781,8 @@ void VQADecoder::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned i
do
{
- uint32 frame_x = dstBlock % blocks_per_line * block_width + _header.offset_x / 2;
- uint32 frame_y = dstBlock / blocks_per_line * block_height + _header.offset_y;
+ uint32 frame_x = dstBlock % blocks_per_line * block_width + _offsetX / 2;
+ uint32 frame_y = dstBlock / blocks_per_line * block_height + _offsetY;
uint32 dst_offset = frame_x + frame_y * frame_stride;
@@ -789,23 +810,11 @@ void VQADecoder::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned i
while (--count);
}
-bool VQADecoder::seekToFrame(int frame)
-{
- if (frame < 0 || frame >= _header.numFrames)
- return false;
-
- _s->seek(2 * (_frameInfo[frame] & 0x0fffffff), SEEK_SET);
- return true;
-}
-
-bool VQADecoder::decodeFrame(uint16 *frame)
+bool VQADecoder::VQAVideoTrack::decodeFrame(uint16 *frame)
{
if (!_codebook || !_vptr)
return false;
- if (!_frame)
- _frame = new uint16[_header.width * _header.height];
-
uint8 *src = _vptr;
uint8 *end = _vptr + _vptrSize;
@@ -828,20 +837,20 @@ bool VQADecoder::decodeFrame(uint16 *frame)
count = 2 * (((command >> 8) & 0x1f) + 1);
srcBlock = command & 0x00ff;
- VPTRWriteBlock(_frame, dstBlock, srcBlock, count);
+ VPTRWriteBlock(frame, dstBlock, srcBlock, count);
dstBlock += count;
break;
case 2:
count = 2 * (((command >> 8) & 0x1f) + 1);
srcBlock = command & 0x00ff;
- VPTRWriteBlock(_frame, dstBlock, srcBlock, 1);
+ VPTRWriteBlock(frame, dstBlock, srcBlock, 1);
++dstBlock;
for (int i = 0; i < count; ++i)
{
srcBlock = *src++;
- VPTRWriteBlock(_frame, dstBlock, srcBlock, 1);
+ VPTRWriteBlock(frame, dstBlock, srcBlock, 1);
++dstBlock;
}
break;
@@ -850,7 +859,7 @@ bool VQADecoder::decodeFrame(uint16 *frame)
count = 1;
srcBlock = command & 0x1fff;
- VPTRWriteBlock(_frame, dstBlock, srcBlock, count, prefix == 4);
+ VPTRWriteBlock(frame, dstBlock, srcBlock, count, prefix == 4);
++dstBlock;
break;
case 5:
@@ -858,7 +867,7 @@ bool VQADecoder::decodeFrame(uint16 *frame)
count = *src++;
srcBlock = command & 0x1fff;
- VPTRWriteBlock(_frame, dstBlock, srcBlock, count, prefix == 6);
+ VPTRWriteBlock(frame, dstBlock, srcBlock, count, prefix == 6);
dstBlock += count;
break;
default:
@@ -866,14 +875,51 @@ bool VQADecoder::decodeFrame(uint16 *frame)
}
}
- memcpy(frame, _frame, 2 * 640 * 480);
+ return true;
+}
+
+VQADecoder::VQAAudioTrack::VQAAudioTrack(VQADecoder *vqaDecoder) {
+ _audioStream = Audio::makeQueuingAudioStream(vqaDecoder->_header.freq, false);
+}
+
+VQADecoder::VQAAudioTrack::~VQAAudioTrack() {
+ delete _audioStream;
+}
+
+Audio::AudioStream *VQADecoder::VQAAudioTrack::getAudioStream() const {
+ return _audioStream;
+}
+
+bool VQADecoder::VQAAudioTrack::readSND2(Common::SeekableReadStream *s, uint32 size)
+{
+ if (size != 735) {
+ error("audio frame size: %d", size);
+ return false;
+ }
+
+ s->read(_compressedAudioFrame, roundup(size));
+
+ int16 *audioFrame = (int16*)malloc(4 * size);
+ memset(audioFrame, 0, 4 * size);
+
+ _adpcmDecoder.decode(_compressedAudioFrame, size, audioFrame);
+
+ _audioStream->queueBuffer((byte*)audioFrame, 4 * size, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
return true;
}
-int16 *VQADecoder::getAudioFrame()
+bool VQADecoder::VQAAudioTrack::readSN2J(Common::SeekableReadStream *s, uint32 size)
{
- return _audioFrame;
+ if (size != 6)
+ return false;
+
+ uint16 stepIndex = s->readUint16LE();
+ uint32 predictor = s->readUint32LE();
+
+ _adpcmDecoder.setParameters(stepIndex >> 5, predictor);
+
+ return true;
}
}; // End of namespace BladeRunner