aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/kyra/vqa.cpp470
-rw-r--r--engines/kyra/vqa.h86
2 files changed, 280 insertions, 276 deletions
diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp
index 975a763715..ab106d40f8 100644
--- a/engines/kyra/vqa.cpp
+++ b/engines/kyra/vqa.cpp
@@ -60,32 +60,32 @@ static uint32 readTag(Common::SeekableReadStream *stream) {
}
VQADecoder::VQADecoder() {
+ memset(&_header, 0, sizeof(_header));
}
VQADecoder::~VQADecoder() {
close();
+ delete[] _frameInfo;
}
bool VQADecoder::loadStream(Common::SeekableReadStream *stream) {
close();
+ _fileStream = stream;
- if (stream->readUint32BE() != MKTAG('F','O','R','M')) {
+ if (_fileStream->readUint32BE() != MKTAG('F','O','R','M')) {
warning("VQADecoder::loadStream(): Cannot find `FORM' tag");
return false;
}
// Ignore the size of the FORM chunk. We're only interested in its
// children.
- stream->readUint32BE();
+ _fileStream->readUint32BE();
- if (stream->readUint32BE() != MKTAG('W','V','Q','A')) {
+ if (_fileStream->readUint32BE() != MKTAG('W','V','Q','A')) {
warning("VQADecoder::loadStream(): Cannot find `WVQA' tag");
return false;
}
- VQAVideoTrack *videoTrack = new VQADecoder::VQAVideoTrack(stream);
- addTrack(videoTrack);
-
// We want to find both a VQHD chunk containing the header, and a FINF
// chunk containing the frame offsets.
@@ -99,14 +99,13 @@ bool VQADecoder::loadStream(Common::SeekableReadStream *stream) {
while (!foundVQHD || !foundFINF) {
uint32 tag = readTag(stream);
- uint32 size = stream->readUint32BE();
+ uint32 size = _fileStream->readUint32BE();
switch (tag) {
case MKTAG('V','Q','H','D'):
- videoTrack->handleVQHD();
- if (videoTrack->hasSound()) {
- audioTrack = new VQAAudioTrack(stream, videoTrack->getAudioFreq());
- videoTrack->setAudioTrack(audioTrack);
+ handleVQHD(_fileStream);
+ if (_header.flags & 1) {
+ audioTrack = new VQAAudioTrack(&_header);
addTrack(audioTrack);
}
foundVQHD = true;
@@ -120,12 +119,12 @@ bool VQADecoder::loadStream(Common::SeekableReadStream *stream) {
warning("VQADecoder::loadStream(): Expected size %d for `FINF' chunk, but got %u", 4 * getFrameCount(), size);
return false;
}
- videoTrack->handleFINF();
+ handleFINF(_fileStream);
foundFINF = true;
break;
default:
warning("VQADecoder::loadStream(): Unknown tag `%s'", tag2str(tag));
- stream->seek(size, SEEK_CUR);
+ _fileStream->seek(size, SEEK_CUR);
break;
}
}
@@ -133,11 +132,158 @@ bool VQADecoder::loadStream(Common::SeekableReadStream *stream) {
return true;
}
+void VQADecoder::handleVQHD(Common::SeekableReadStream *stream) {
+ _header.version = stream->readUint16LE();
+ _header.flags = stream->readUint16LE();
+ _header.numFrames = stream->readUint16LE();
+ _header.width = stream->readUint16LE();
+ _header.height = stream->readUint16LE();
+ _header.blockW = stream->readByte();
+ _header.blockH = stream->readByte();
+ _header.frameRate = stream->readByte();
+ _header.cbParts = stream->readByte();
+ _header.colors = stream->readUint16LE();
+ _header.maxBlocks = stream->readUint16LE();
+ _header.unk1 = stream->readUint32LE();
+ _header.unk2 = stream->readUint16LE();
+ _header.freq = stream->readUint16LE();
+ _header.channels = stream->readByte();
+ _header.bits = stream->readByte();
+ _header.unk3 = stream->readUint32LE();
+ _header.unk4 = stream->readUint16LE();
+ _header.maxCBFZSize = stream->readUint32LE();
+ _header.unk5 = stream->readUint32LE();
+
+ _frameInfo = new uint32[_header.numFrames + 1];
+
+ VQAVideoTrack *videoTrack = new VQAVideoTrack(&_header);
+ addTrack(videoTrack);
+
+ // Kyrandia 3 uses version 1 VQA files, and is the only known game to
+ // do so. This version of the format has some implicit default values.
+
+ if (_header.version == 1) {
+ if (_header.freq == 0)
+ _header.freq = 22050;
+ if (_header.channels == 0)
+ _header.channels = 1;
+ if (_header.bits == 0)
+ _header.bits = 8;
+ }
+
+ if (_header.flags & 1) {
+ // Kyrandia 3 uses 8-bit sound, and so far testing indicates
+ // that it's all mono.
+ //
+ // This is good, because it means we won't have to worry about
+ // the confusing parts of the VQA spec, where 8- and 16-bit
+ // data have different signedness and stereo sample layout
+ // varies between different games.
+
+ assert(_header.bits == 8);
+ assert(_header.channels == 1);
+ }
+}
+
+void VQADecoder::handleFINF(Common::SeekableReadStream *stream) {
+ for (int i = 0; i < _header.numFrames; i++) {
+ _frameInfo[i] = 2 * stream->readUint32LE();
+ }
+
+ // HACK: This flag is set in jung2.vqa, and its purpose - if it has
+ // one - is currently unknown. It can't be a general purpose flag,
+ // because in large movies the frame offset can be large enough to
+ // set this flag, though of course never for the first frame.
+ //
+ // At least in my copy of Kyrandia 3, _frameInfo[0] is 0x81000098, and
+ // the desired index is 0x4716. So the value should be 0x80004716, but
+ // I don't want to hard-code it. Instead, scan the file for the offset
+ // to the first VQFR chunk.
+
+ if (_frameInfo[0] & 0x01000000) {
+ uint32 oldPos = stream->pos();
+
+ while (1) {
+ uint32 scanTag = readTag(stream);
+ uint32 scanSize = stream->readUint32BE();
+
+ if (stream->eos())
+ break;
+
+ if (scanTag == MKTAG('V','Q','F','R')) {
+ _frameInfo[0] = (stream->pos() - 8) | 0x80000000;
+ break;
+ }
+
+ stream->seek(scanSize, SEEK_CUR);
+ }
+
+ stream->seek(oldPos);
+ }
+
+ _frameInfo[_header.numFrames] = 0x7FFFFFFF;
+}
+
+void VQADecoder::readNextPacket() {
+ VQAVideoTrack *videoTrack = (VQAVideoTrack *)getTrack(0);
+ VQAAudioTrack *audioTrack = (VQAAudioTrack *)getTrack(1);
+
+ assert(videoTrack);
+
+ int curFrame = videoTrack->getCurFrame();
+
+ // Stop if reading the tag is enough to put us ahead of the next frame
+ int32 end = (_frameInfo[curFrame + 1] & 0x7FFFFFFF) - 7;
+
+ // At this point, we probably only need to adjust for the offset in the
+ // stream to be even. But we may as well do this to really make sure
+ // we have the correct offset.
+ if (curFrame >= 0) {
+ _fileStream->seek(_frameInfo[curFrame] & 0x7FFFFFFF);
+ if (_frameInfo[curFrame] & 0x80000000) {
+ videoTrack->setHasDirtyPalette();
+ }
+ }
+
+ while (!_fileStream->eos() && _fileStream->pos() < end) {
+ uint32 tag = readTag(_fileStream);
+ uint32 size;
+
+ switch (tag) {
+ case MKTAG('S','N','D','0'): // Uncompressed sound
+ assert(audioTrack);
+ audioTrack->handleSND0(_fileStream);
+ break;
+ case MKTAG('S','N','D','1'): // Compressed sound, almost like AUD
+ assert(audioTrack);
+ audioTrack->handleSND1(_fileStream);
+ break;
+ case MKTAG('S','N','D','2'): // Compressed sound
+ assert(audioTrack);
+ audioTrack->handleSND2(_fileStream);
+ break;
+ case MKTAG('V','Q','F','R'):
+ videoTrack->handleVQFR(_fileStream);
+ break;
+ case MKTAG('C','M','D','S'):
+ // The purpose of this is unknown, but it's known to
+ // exist so don't warn about it.
+ size = _fileStream->readUint32BE();
+ _fileStream->seek(size, SEEK_CUR);
+ break;
+ default:
+ warning("VQADecoder::readNextPacket(): Unknown tag `%s'", tag2str(tag));
+ size = _fileStream->readUint32BE();
+ _fileStream->seek(size, SEEK_CUR);
+ break;
+ }
+ }
+}
+
// -----------------------------------------------------------------------
-VQADecoder::VQAAudioTrack::VQAAudioTrack(Common::SeekableReadStream *stream, int freq) {
- _fileStream = stream;
- _audioStream = Audio::makeQueuingAudioStream(freq, false);
+VQADecoder::VQAAudioTrack::VQAAudioTrack(VQAHeader *header) {
+ _audioStream = Audio::makeQueuingAudioStream(header->freq, false);
}
VQADecoder::VQAAudioTrack::~VQAAudioTrack() {
@@ -148,20 +294,20 @@ Audio::AudioStream *VQADecoder::VQAAudioTrack::getAudioStream() const {
return _audioStream;
}
-void VQADecoder::VQAAudioTrack::handleSND0() {
- uint32 size = _fileStream->readUint32BE();
+void VQADecoder::VQAAudioTrack::handleSND0(Common::SeekableReadStream *stream) {
+ uint32 size = stream->readUint32BE();
byte *buf = (byte *)malloc(size);
- _fileStream->read(buf, size);
+ stream->read(buf, size);
_audioStream->queueBuffer(buf, size, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
}
-void VQADecoder::VQAAudioTrack::handleSND1() {
- _fileStream->readUint32BE();
- uint16 outsize = _fileStream->readUint16LE();
- uint16 insize = _fileStream->readUint16LE();
+void VQADecoder::VQAAudioTrack::handleSND1(Common::SeekableReadStream *stream) {
+ stream->readUint32BE();
+ uint16 outsize = stream->readUint16LE();
+ uint16 insize = stream->readUint16LE();
byte *inbuf = (byte *)malloc(insize);
- _fileStream->read(inbuf, insize);
+ stream->read(inbuf, insize);
if (insize == outsize) {
_audioStream->queueBuffer(inbuf, insize, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
@@ -241,50 +387,61 @@ void VQADecoder::VQAAudioTrack::handleSND1() {
}
}
-void VQADecoder::VQAAudioTrack::handleSND2() {
- uint32 size = _fileStream->readUint32BE();
+void VQADecoder::VQAAudioTrack::handleSND2(Common::SeekableReadStream *stream) {
+ uint32 size = stream->readUint32BE();
warning("VQADecoder::VQAAudioTrack::handleSND2(): `SND2' is not implemented");
- _fileStream->seek(size, SEEK_CUR);
+ stream->seek(size, SEEK_CUR);
}
// -----------------------------------------------------------------------
-VQADecoder::VQAVideoTrack::VQAVideoTrack(Common::SeekableReadStream *stream) {
- _fileStream = stream;
- _surface = new Graphics::Surface();
+VQADecoder::VQAVideoTrack::VQAVideoTrack(VQAHeader *header) {
memset(_palette, 0, sizeof(_palette));
_dirtyPalette = false;
- _audioTrack = NULL;
+
+ _width = header->width;
+ _height = header->height;
+ _blockW = header->blockW;
+ _blockH = header->blockH;
+ _cbParts = header->cbParts;
+
+ _newFrame = false;
_curFrame = -1;
+ _frameCount = header->numFrames;
+ _frameRate = header->frameRate;
- memset(&_header, 0, sizeof(_header));
- _frameInfo = NULL;
- _codeBookSize = 0;
+ _codeBookSize = 0xF00 * header->blockW * header->blockH;
_compressedCodeBook = false;
- _codeBook = NULL;
+ _codeBook = new byte[_codeBookSize];
_partialCodeBookSize = 0;
_numPartialCodeBooks = 0;
- _partialCodeBook = NULL;
- _numVectorPointers = 0;
- _vectorPointers = NULL;
+ _partialCodeBook = new byte[_codeBookSize];
+ _numVectorPointers = (header->width / header->blockW) * (header->height * header->blockH);
+ _vectorPointers = new uint16[_numVectorPointers];
+
+ memset(_codeBook, 0, _codeBookSize);
+ memset(_partialCodeBook, 0, _codeBookSize);
+ memset(_vectorPointers, 0, _numVectorPointers);
+
+ _surface = new Graphics::Surface();
+ _surface->create(header->width, header->height, Graphics::PixelFormat::createFormatCLUT8());
}
VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
+ _surface->free();
delete _surface;
- delete[] _frameInfo;
delete[] _codeBook;
delete[] _partialCodeBook;
delete[] _vectorPointers;
- // The audio track gets deleted by VQADecoder.
}
uint16 VQADecoder::VQAVideoTrack::getWidth() const {
- return _header.width;
+ return _width;
}
uint16 VQADecoder::VQAVideoTrack::getHeight() const {
- return _header.height;
+ return _height;
}
Graphics::PixelFormat VQADecoder::VQAVideoTrack::getPixelFormat() const {
@@ -296,19 +453,15 @@ int VQADecoder::VQAVideoTrack::getCurFrame() const {
}
int VQADecoder::VQAVideoTrack::getFrameCount() const {
- return _header.numFrames;
+ return _frameCount;
}
Common::Rational VQADecoder::VQAVideoTrack::getFrameRate() const {
- return _header.frameRate;
-}
-
-bool VQADecoder::VQAVideoTrack::hasSound() const {
- return (_header.flags & 1) != 0;
+ return _frameRate;
}
-int VQADecoder::VQAVideoTrack::getAudioFreq() const {
- return _header.freq;
+void VQADecoder::VQAVideoTrack::setHasDirtyPalette() {
+ _dirtyPalette = true;
}
bool VQADecoder::VQAVideoTrack::hasDirtyPalette() const {
@@ -320,93 +473,40 @@ const byte *VQADecoder::VQAVideoTrack::getPalette() const {
return _palette;
}
-void VQADecoder::VQAVideoTrack::setAudioTrack(VQAAudioTrack *audioTrack) {
- _audioTrack = audioTrack;
-}
-
const Graphics::Surface *VQADecoder::VQAVideoTrack::decodeNextFrame() {
- // Stop if reading the tag is enough to put us ahead of the next frame
- int32 end = (_frameInfo[_curFrame + 1] & 0x7FFFFFFF) - 7;
-
- // At this point, we probably only need to adjust for the offset in the
- // stream to be even. But we may as well do this to really make sure
- // we have the correct offset.
- if (_curFrame >= 0) {
- _fileStream->seek(_frameInfo[_curFrame] & 0x7FFFFFFF);
- }
-
- bool hasFrame = false;
+ if (_newFrame) {
+ _newFrame = false;
- while (!_fileStream->eos() && _fileStream->pos() < end) {
- uint32 tag = readTag(_fileStream);
- uint32 size;
+ int blockPitch = _width / _blockW;
- switch (tag) {
- case MKTAG('S','N','D','0'): // Uncompressed sound
- assert(_audioTrack);
- _audioTrack->handleSND0();
- break;
- case MKTAG('S','N','D','1'): // Compressed sound, almost like AUD
- assert(_audioTrack);
- _audioTrack->handleSND1();
- break;
- case MKTAG('S','N','D','2'): // Compressed sound
- assert(_audioTrack);
- _audioTrack->handleSND2();
- break;
- case MKTAG('V','Q','F','R'):
- handleVQFR();
- hasFrame = true;
- break;
- case MKTAG('C','M','D','S'):
- // The purpose of this is unknown, but it's known to
- // exist so don't warn about it.
- size = _fileStream->readUint32BE();
- _fileStream->seek(size, SEEK_CUR);
- break;
- default:
- warning("VQADecoder::VQAVideoTrack::decodeNextFrame(): Unknown tag `%s'", tag2str(tag));
- size = _fileStream->readUint32BE();
- _fileStream->seek(size, SEEK_CUR);
- break;
- }
- }
-
- if (hasFrame) {
- if (_frameInfo[_curFrame] & 0x80000000) {
- _dirtyPalette = true;
- }
-
- int blockPitch = _header.width / _header.blockW;
-
- for (int by = 0; by < _header.height / _header.blockH; by++) {
+ for (int by = 0; by < _height / _blockH; by++) {
for (int bx = 0; bx < blockPitch; bx++) {
- byte *dst = (byte *)_surface->getBasePtr(bx * _header.blockW, by * _header.blockH);
+ byte *dst = (byte *)_surface->getBasePtr(bx * _blockW, by * _blockH);
int val = _vectorPointers[by * blockPitch + bx];
int i;
if ((val & 0xFF00) == 0xFF00) {
// Solid color
- for (i = 0; i < _header.blockH; i++) {
- memset(dst, 255 - (val & 0xFF), _header.blockW);
- dst += _header.width;
+ for (i = 0; i < _blockH; i++) {
+ memset(dst, 255 - (val & 0xFF), _blockW);
+ dst += _width;
}
} else {
// Copy data from _vectorPointers. I'm not sure
// why we don't use the three least significant
// bits of 'val'.
- byte *src = &_codeBook[(val >> 3) * _header.blockW * _header.blockH];
+ byte *src = &_codeBook[(val >> 3) * _blockW * _blockH];
- for (i = 0; i < _header.blockH; i++) {
- memcpy(dst, src, _header.blockW);
- src += _header.blockW;
- dst += _header.width;
+ for (i = 0; i < _blockH; i++) {
+ memcpy(dst, src, _blockW);
+ src += _blockW;
+ dst += _width;
}
}
}
}
- if (_numPartialCodeBooks == _header.cbParts) {
+ if (_numPartialCodeBooks == _cbParts) {
if (_compressedCodeBook) {
Screen::decodeFrame4(_partialCodeBook, _codeBook, _codeBookSize);
} else {
@@ -421,160 +521,58 @@ const Graphics::Surface *VQADecoder::VQAVideoTrack::decodeNextFrame() {
return _surface;
}
-void VQADecoder::VQAVideoTrack::handleVQHD() {
- _header.version = _fileStream->readUint16LE();
- _header.flags = _fileStream->readUint16LE();
- _header.numFrames = _fileStream->readUint16LE();
- _header.width = _fileStream->readUint16LE();
- _header.height = _fileStream->readUint16LE();
- _header.blockW = _fileStream->readByte();
- _header.blockH = _fileStream->readByte();
- _header.frameRate = _fileStream->readByte();
- _header.cbParts = _fileStream->readByte();
- _header.colors = _fileStream->readUint16LE();
- _header.maxBlocks = _fileStream->readUint16LE();
- _header.unk1 = _fileStream->readUint32LE();
- _header.unk2 = _fileStream->readUint16LE();
- _header.freq = _fileStream->readUint16LE();
- _header.channels = _fileStream->readByte();
- _header.bits = _fileStream->readByte();
- _header.unk3 = _fileStream->readUint32LE();
- _header.unk4 = _fileStream->readUint16LE();
- _header.maxCBFZSize = _fileStream->readUint32LE();
- _header.unk5 = _fileStream->readUint32LE();
-
- _surface->create(_header.width, _header.height, Graphics::PixelFormat::createFormatCLUT8());
-
- // Kyrandia 3 uses version 1 VQA files, and is the only known game to
- // do so. This version of the format has some implicit default values.
-
- if (_header.version == 1) {
- if (_header.freq == 0)
- _header.freq = 22050;
- if (_header.channels == 0)
- _header.channels = 1;
- if (_header.bits == 0)
- _header.bits = 8;
- }
-
- _frameInfo = new uint32[_header.numFrames + 1];
-
- _codeBookSize = 0xF00 * _header.blockW * _header.blockH;
- _codeBook = new byte[_codeBookSize];
- _partialCodeBook = new byte[_codeBookSize];
- memset(_codeBook, 0, _codeBookSize);
- memset(_partialCodeBook, 0, _codeBookSize);
-
- _numVectorPointers = (_header.width / _header.blockW) * (_header.height * _header.blockH);
- _vectorPointers = new uint16[_numVectorPointers];
- memset(_vectorPointers, 0, _numVectorPointers * sizeof(uint16));
-
- _partialCodeBookSize = 0;
- _numPartialCodeBooks = 0;
-
- if (hasSound()) {
- // Kyrandia 3 uses 8-bit sound, and so far testing indicates
- // that it's all mono.
- //
- // This is good, because it means we won't have to worry about
- // the confusing parts of the VQA spec, where 8- and 16-bit
- // data have different signedness and stereo sample layout
- // varies between different games.
-
- assert(_header.bits == 8);
- assert(_header.channels == 1);
- }
-}
-
-void VQADecoder::VQAVideoTrack::handleFINF() {
- for (int i = 0; i < _header.numFrames; i++) {
- _frameInfo[i] = 2 * _fileStream->readUint32LE();
- }
-
- // HACK: This flag is set in jung2.vqa, and its purpose - if it has
- // one - is currently unknown. It can't be a general purpose flag,
- // because in large movies the frame offset can be large enough to
- // set this flag, though of course never for the first frame.
- //
- // At least in my copy of Kyrandia 3, _frameInfo[0] is 0x81000098, and
- // the desired index is 0x4716. So the value should be 0x80004716, but
- // I don't want to hard-code it. Instead, scan the file for the offset
- // to the first VQFR chunk.
-
- if (_frameInfo[0] & 0x01000000) {
- uint32 oldPos = _fileStream->pos();
-
- while (1) {
- uint32 scanTag = readTag(_fileStream);
- uint32 scanSize = _fileStream->readUint32BE();
-
- if (_fileStream->eos())
- break;
-
- if (scanTag == MKTAG('V','Q','F','R')) {
- _frameInfo[0] = (_fileStream->pos() - 8) | 0x80000000;
- break;
- }
-
- _fileStream->seek(scanSize, SEEK_CUR);
- }
-
- _fileStream->seek(oldPos);
- }
-
- _frameInfo[_header.numFrames] = 0x7FFFFFFF;
-}
-
-void VQADecoder::VQAVideoTrack::handleVQFR() {
- uint32 size = _fileStream->readUint32BE();
- int32 end = _fileStream->pos() + size - 8;
+void VQADecoder::VQAVideoTrack::handleVQFR(Common::SeekableReadStream *stream) {
+ uint32 size = stream->readUint32BE();
+ int32 end = stream->pos() + size - 8;
byte *inbuf;
- while (_fileStream->pos() < end) {
- uint32 tag = readTag(_fileStream);
+ _newFrame = true;
+
+ while (stream->pos() < end) {
+ uint32 tag = readTag(stream);
uint32 i;
- size = _fileStream->readUint32BE();
+ size = stream->readUint32BE();
switch (tag) {
case MKTAG('C','B','F','0'): // Full codebook
- _fileStream->read(_codeBook, size);
+ stream->read(_codeBook, size);
break;
case MKTAG('C','B','F','Z'): // Full codebook
inbuf = (byte *)malloc(size);
- _fileStream->read(inbuf, size);
+ stream->read(inbuf, size);
Screen::decodeFrame4(inbuf, _codeBook, _codeBookSize);
free(inbuf);
break;
case MKTAG('C','B','P','0'): // Partial codebook
_compressedCodeBook = false;
- _fileStream->read(_partialCodeBook + _partialCodeBookSize, size);
+ stream->read(_partialCodeBook + _partialCodeBookSize, size);
_partialCodeBookSize += size;
_numPartialCodeBooks++;
break;
case MKTAG('C','B','P','Z'): // Partial codebook
_compressedCodeBook = true;
- _fileStream->read(_partialCodeBook + _partialCodeBookSize, size);
+ stream->read(_partialCodeBook + _partialCodeBookSize, size);
_partialCodeBookSize += size;
_numPartialCodeBooks++;
break;
case MKTAG('C','P','L','0'): // Palette
assert(size <= 3 * 256);
- _fileStream->read(_palette, size);
+ stream->read(_palette, size);
break;
case MKTAG('C','P','L','Z'): // Palette
inbuf = (byte *)malloc(size);
- _fileStream->read(inbuf, size);
+ stream->read(inbuf, size);
Screen::decodeFrame4(inbuf, _palette, 3 * 256);
free(inbuf);
break;
case MKTAG('V','P','T','0'): // Frame data
assert(size / 2 <= _numVectorPointers);
for (i = 0; i < size / 2; i++)
- _vectorPointers[i] = _fileStream->readUint16LE();
+ _vectorPointers[i] = stream->readUint16LE();
break;
case MKTAG('V','P','T','Z'): // Frame data
inbuf = (byte *)malloc(size);
- _fileStream->read(inbuf, size);
+ stream->read(inbuf, size);
size = Screen::decodeFrame4(inbuf, (uint8 *)_vectorPointers, 2 * _numVectorPointers);
for (i = 0; i < size / 2; i++)
_vectorPointers[i] = TO_LE_16(_vectorPointers[i]);
@@ -582,7 +580,7 @@ void VQADecoder::VQAVideoTrack::handleVQFR() {
break;
default:
warning("VQADecoder::VQAVideoTrack::handleVQFR(): Unknown `VQFR' sub-tag `%s'", tag2str(tag));
- _fileStream->seek(size, SEEK_CUR);
+ stream->seek(size, SEEK_CUR);
break;
}
}
diff --git a/engines/kyra/vqa.h b/engines/kyra/vqa.h
index 44d1354f3d..02414819db 100644
--- a/engines/kyra/vqa.h
+++ b/engines/kyra/vqa.h
@@ -44,28 +44,59 @@ public:
virtual ~VQADecoder();
bool loadStream(Common::SeekableReadStream *stream);
+ void readNextPacket();
private:
+ Common::SeekableReadStream *_fileStream;
+
+ void handleVQHD(Common::SeekableReadStream *stream);
+ void handleFINF(Common::SeekableReadStream *stream);
+
+ struct VQAHeader {
+ uint16 version;
+ uint16 flags;
+ uint16 numFrames;
+ uint16 width;
+ uint16 height;
+ uint8 blockW;
+ uint8 blockH;
+ uint8 frameRate;
+ uint8 cbParts;
+ uint16 colors;
+ uint16 maxBlocks;
+ uint32 unk1;
+ uint16 unk2;
+ uint16 freq;
+ uint8 channels;
+ uint8 bits;
+ uint32 unk3;
+ uint16 unk4;
+ uint32 maxCBFZSize;
+ uint32 unk5;
+ };
+
+ VQAHeader _header;
+ uint32 *_frameInfo;
+
class VQAAudioTrack : public AudioTrack {
public:
- VQAAudioTrack(Common::SeekableReadStream *stream, int freq);
+ VQAAudioTrack(VQAHeader *header);
~VQAAudioTrack();
- void handleSND0();
- void handleSND1();
- void handleSND2();
+ void handleSND0(Common::SeekableReadStream *stream);
+ void handleSND1(Common::SeekableReadStream *stream);
+ void handleSND2(Common::SeekableReadStream *stream);
protected:
Audio::AudioStream *getAudioStream() const;
private:
Audio::QueuingAudioStream *_audioStream;
- Common::SeekableReadStream *_fileStream;
};
class VQAVideoTrack : public FixedRateVideoTrack {
public:
- VQAVideoTrack(Common::SeekableReadStream *stream);
+ VQAVideoTrack(VQAHeader *header);
~VQAVideoTrack();
uint16 getWidth() const;
@@ -75,54 +106,29 @@ private:
int getFrameCount() const;
const Graphics::Surface *decodeNextFrame();
- bool hasSound() const;
- int getAudioFreq() const;
+ void setHasDirtyPalette();
bool hasDirtyPalette() const;
const byte *getPalette() const;
- void setAudioTrack(VQAAudioTrack *audioTrack);
-
- void handleVQHD();
- void handleFINF();
- void handleVQFR();
+ void handleVQFR(Common::SeekableReadStream *stream);
protected:
Common::Rational getFrameRate() const;
private:
- Common::SeekableReadStream *_fileStream;
Graphics::Surface *_surface;
byte _palette[3 * 256];
mutable bool _dirtyPalette;
- VQAAudioTrack *_audioTrack;
+ bool _newFrame;
+
+ uint16 _width, _height;
+ uint8 _blockW, _blockH;
+ uint8 _cbParts;
+ int _frameCount;
int _curFrame;
+ byte _frameRate;
- struct VQAHeader {
- uint16 version;
- uint16 flags;
- uint16 numFrames;
- uint16 width;
- uint16 height;
- uint8 blockW;
- uint8 blockH;
- uint8 frameRate;
- uint8 cbParts;
- uint16 colors;
- uint16 maxBlocks;
- uint32 unk1;
- uint16 unk2;
- uint16 freq;
- uint8 channels;
- uint8 bits;
- uint32 unk3;
- uint16 unk4;
- uint32 maxCBFZSize;
- uint32 unk5;
- };
-
- VQAHeader _header;
- uint32 *_frameInfo;
uint32 _codeBookSize;
bool _compressedCodeBook;
byte *_codeBook;