aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorThomas Fach-Pedersen2014-05-17 17:13:49 +0200
committerEugene Sandulenko2016-09-29 22:21:00 +0200
commitf0432bdf2568a0390e02ff18dd73ea5296a007e2 (patch)
tree855c77dc0ed4c14bf2012391ac863d51f33aab4c /engines
parent5c69ed59951c9436c5dd450396fc16dd5ab38f83 (diff)
downloadscummvm-rg350-f0432bdf2568a0390e02ff18dd73ea5296a007e2.tar.gz
scummvm-rg350-f0432bdf2568a0390e02ff18dd73ea5296a007e2.tar.bz2
scummvm-rg350-f0432bdf2568a0390e02ff18dd73ea5296a007e2.zip
BLADERUNNER: Split VQA decoder into player and decoder, add Outtake player
Diffstat (limited to 'engines')
-rw-r--r--engines/bladerunner/bladerunner.cpp51
-rw-r--r--engines/bladerunner/bladerunner.h6
-rw-r--r--engines/bladerunner/module.mk4
-rw-r--r--engines/bladerunner/outtake.cpp67
-rw-r--r--engines/bladerunner/outtake.h54
-rw-r--r--engines/bladerunner/vqa_decoder.cpp166
-rw-r--r--engines/bladerunner/vqa_decoder.h22
-rw-r--r--engines/bladerunner/vqa_player.cpp102
-rw-r--r--engines/bladerunner/vqa_player.h73
9 files changed, 374 insertions, 171 deletions
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 7e8466c14a..bcf8c090a8 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -25,6 +25,7 @@
#include "bladerunner/chapters.h"
#include "bladerunner/gameinfo.h"
#include "bladerunner/image.h"
+#include "bladerunner/outtake.h"
#include "bladerunner/settings.h"
#include "bladerunner/vqa_decoder.h"
@@ -206,56 +207,12 @@ void BladeRunnerEngine::handleEvents() {
}
}
-void BladeRunnerEngine::playOuttake(int id, bool no_localization) {
+void BladeRunnerEngine::outtakePlay(int id, bool noLocalization, int container) {
Common::String name = _gameInfo->getOuttake(id);
- if (no_localization)
- name += ".VQA";
- else
- name += "_E.VQA";
+ OuttakePlayer player(this);
- Common::SeekableReadStream *s = getResourceStream(name);
- if (!s)
- return;
-
- VQADecoder vqa_decoder(s);
-
- bool b = vqa_decoder.readHeader();
- if (!b) return;
-
- uint32 frame_count = 0;
- uint32 start_time = 0;
- uint32 next_frame_time = 0;
-
- for (;;)
- {
- handleEvents();
- // TODO: Handle skips
- if (shouldQuit())
- break;
-
- uint32 cur_time = next_frame_time + 1;
-
- if (next_frame_time <= cur_time)
- {
- int frame_number = vqa_decoder.readFrame();
- debug("frame_number: %d", frame_number);
-
- if (frame_number < 0)
- break;
-
- b = vqa_decoder.decodeFrame((uint16*)_surface1.getPixels());
-
- _system->copyRectToScreen(_surface1.getPixels(), _surface1.pitch, 0, 0, _surface1.w, _surface1.h);
- _system->updateScreen();
-
- ++frame_count;
-
- if (!next_frame_time)
- next_frame_time = cur_time;
- next_frame_time = next_frame_time + (60 * 1000) / 15;
- }
- }
+ player.play(name, noLocalization, -1);
}
bool BladeRunnerEngine::openArchive(const Common::String &name) {
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index c679b80f29..bf95ca7922 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -53,12 +53,12 @@ public:
int in_script_counter;
+ Graphics::Surface _surface1;
+
private:
static const int kArchiveCount = 10;
MIXArchive _archives[kArchiveCount];
- Graphics::Surface _surface1;
-
public:
BladeRunnerEngine(OSystem *syst);
@@ -77,7 +77,7 @@ public:
void gameTick();
void handleEvents();
- void playOuttake(int id, bool no_localization);
+ void outtakePlay(int id, bool no_localization, int container = -1);
bool openArchive(const Common::String &name);
bool closeArchive(const Common::String &name);
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index c0d6416ad6..44e681abf4 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -9,8 +9,10 @@ MODULE_OBJS = \
detection.o \
gameinfo.o \
image.o \
+ outtake.o \
settings.o \
- vqa_decoder.o
+ vqa_decoder.o \
+ vqa_player.o
# This module can be built as a plugin
ifeq ($(ENABLE_BLADERUNNER), DYNAMIC_PLUGIN)
diff --git a/engines/bladerunner/outtake.cpp b/engines/bladerunner/outtake.cpp
new file mode 100644
index 0000000000..01ceefad75
--- /dev/null
+++ b/engines/bladerunner/outtake.cpp
@@ -0,0 +1,67 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/outtake.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/vqa_player.h"
+
+#include "common/system.h"
+
+namespace BladeRunner {
+
+void OuttakePlayer::play(const Common::String &name, bool noLocalization, int container) {
+ if (container > 0) {
+ debug("OuttakePlayer::play TODO");
+ return;
+ }
+
+ Common::String resName;
+ if (noLocalization)
+ resName = name + ".VQA";
+ else
+ resName = name + "_E.VQA";
+
+ _vqaPlayer = new VQAPlayer(_vm, &_vm->_surface1);
+ _vqaPlayer->open(resName);
+
+ for (;;) {
+ _vm->handleEvents();
+ if (_vm->shouldQuit())
+ break;
+
+ int r = _vqaPlayer->update();
+ if (r == -3)
+ break;
+
+ if (r >= 0) {
+ _vm->_system->copyRectToScreen(_vm->_surface1.getPixels(), _vm->_surface1.pitch, 0, 0, _vm->_surface1.w, _vm->_surface1.h);
+ _vm->_system->updateScreen();
+ _vm->_system->delayMillis(10);
+ }
+ }
+
+ delete _vqaPlayer;
+ _vqaPlayer = nullptr;
+}
+
+}; // End of namespace BladeRunner
diff --git a/engines/bladerunner/outtake.h b/engines/bladerunner/outtake.h
new file mode 100644
index 0000000000..4e97b1b516
--- /dev/null
+++ b/engines/bladerunner/outtake.h
@@ -0,0 +1,54 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BLADERUNNER_OUTTAKE_H
+#define BLADERUNNER_OUTTAKE_H
+
+#include "common/str.h"
+
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class VQAPlayer;
+
+class OuttakePlayer {
+ BladeRunnerEngine *_vm;
+
+ bool _isVQAOpen;
+ VQAPlayer *_vqaPlayer;
+ Graphics::Surface *_surface;
+
+public:
+ OuttakePlayer(BladeRunnerEngine *vm) :
+ _vm(vm),
+ _isVQAOpen(false),
+ _vqaPlayer(nullptr)
+ {}
+
+ void play(const Common::String &name, bool noLocalization, int container);
+};
+
+}; // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index 46e45de1a7..c297935ab9 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -66,17 +66,13 @@ namespace BladeRunner {
#define kWVQA 0x57565141
#define kZBUF 0x5A425546
-VQADecoder::VQADecoder(Common::SeekableReadStream *s)
- : _s(s),
+VQADecoder::VQADecoder()
+ : _s(nullptr),
_frame(0),
_zbuf(0),
_codebook(0),
_cbfz(0),
_vptr(0),
- _curFrame(-1),
- _curLoop(-1),
- _loopSpecial(-1),
- _loopDefault(-1),
_hasView(false),
_audioFrame(0),
_maxVIEWChunkSize(0),
@@ -126,7 +122,7 @@ bool readIFFChunkHeader(Common::SeekableReadStream *s, IFFChunkHeader *ts)
ts->size = s->readUint32BE();
// if (ts->size != roundup(ts->size))
- // debug("%s: %d\n", strTag(ts->id), ts->size);
+ // debug("%s: %d", strTag(ts->id), ts->size);
return true;
}
@@ -144,26 +140,27 @@ const char *strTag(uint32 tag)
return s;
}
-bool VQADecoder::readHeader()
+bool VQADecoder::open(Common::SeekableReadStream *s)
{
IFFChunkHeader chd;
uint32 type;
bool rc;
- readIFFChunkHeader(_s, &chd);
+ readIFFChunkHeader(s, &chd);
if (chd.id != kFORM || !chd.size)
return false;
- type = _s->readUint32BE();
+ type = s->readUint32BE();
if (type != kWVQA)
return false;
+ _s = s;
do {
if (!readIFFChunkHeader(_s, &chd))
return false;
- debug("\t%s : %x\n", strTag(chd.id), chd.size);
+ debug("\t%s : %x", strTag(chd.id), chd.size);
rc = false;
switch (chd.id)
@@ -177,21 +174,21 @@ bool VQADecoder::readHeader()
case kMSCI: rc = readMSCI(chd.size); break;
case kVQHD: rc = readVQHD(chd.size); break;
default:
- debug("Unhandled chunk '%s'\n", strTag(chd.id));
+ debug("Unhandled chunk '%s'", strTag(chd.id));
_s->skip(roundup(chd.size));
rc = true;
}
if (!rc)
{
- debug("failed to handle chunk %s\n", strTag(chd.id));
- return false;
+ debug("failed to handle chunk %s", strTag(chd.id));
+ return -1;
}
} while (chd.id != kFINF);
for (int i = 0; i != _loopInfo.loopCount; ++i) {
- debug("LOOP %2d: %4d %4d %s\n", i,
+ debug("LOOP %2d: %4d %4d %s", i,
_loopInfo.loops[i].begin,
_loopInfo.loops[i].end,
_loopInfo.loops[i].name.c_str());
@@ -229,32 +226,32 @@ bool VQADecoder::readVQHD(uint32 size)
if (_header.offset_x || _header.offset_y)
{
- debug("_header.offset_x, _header.offset_y: %d %d\n", _header.offset_x, _header.offset_y);
+ debug("_header.offset_x, _header.offset_y: %d %d", _header.offset_x, _header.offset_y);
}
// if (_header.unk3 || _header.unk4 != 4 || _header.unk5 || _header.flags != 0x0014)
{
- debug("_header.version %d\n", _header.version);
- debug("_header.flags %04x\n", _header.flags);
- debug("_header.numFrames %d\n", _header.numFrames);
- debug("_header.width %d\n", _header.width);
- debug("_header.height %d\n", _header.height);
- debug("_header.blockW %d\n", _header.blockW);
- debug("_header.blockH %d\n", _header.blockH);
- debug("_header.frameRate %d\n", _header.frameRate);
- debug("_header.cbParts %d\n", _header.cbParts);
- debug("_header.colors %d\n", _header.colors);
- debug("_header.maxBlocks %d\n", _header.maxBlocks);
- debug("_header.offsetX %d\n", _header.offset_x);
- debug("_header.offsetY %d\n", _header.offset_y);
- debug("_header.maxVPTRSize %d\n", _header.maxVPTRSize);
- debug("_header.freq %d\n", _header.freq);
- debug("_header.channels %d\n", _header.channels);
- debug("_header.bits %d\n", _header.bits);
- debug("_header.unk3 %d\n", _header.unk3);
- debug("_header.unk4 %d\n", _header.unk4);
- debug("_header.maxCBFZSize %d\n", _header.maxCBFZSize);
- debug("_header.unk5 %d\n", _header.unk5);
+ debug("_header.version %d", _header.version);
+ debug("_header.flags %04x", _header.flags);
+ debug("_header.numFrames %d", _header.numFrames);
+ debug("_header.width %d", _header.width);
+ debug("_header.height %d", _header.height);
+ debug("_header.blockW %d", _header.blockW);
+ debug("_header.blockH %d", _header.blockH);
+ debug("_header.frameRate %d", _header.frameRate);
+ 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.maxVPTRSize %d", _header.maxVPTRSize);
+ debug("_header.freq %d", _header.freq);
+ debug("_header.channels %d", _header.channels);
+ debug("_header.bits %d", _header.bits);
+ debug("_header.unk3 %d", _header.unk3);
+ debug("_header.unk4 %d", _header.unk4);
+ debug("_header.maxCBFZSize %d", _header.maxCBFZSize);
+ debug("_header.unk5 %d", _header.unk5);
}
// exit(-1);
@@ -289,19 +286,19 @@ bool VQADecoder::readMSCI(uint32 size)
{
case kVIEW:
_maxVIEWChunkSize = size;
- debug("max VIEW size: %08x\n", _maxVIEWChunkSize);
+ debug("max VIEW size: %08x", _maxVIEWChunkSize);
break;
case kZBUF:
_maxZBUFChunkSize = size;
_zbufChunk = new uint8[roundup(_maxZBUFChunkSize)];
- debug("max ZBUF size: %08x\n", _maxZBUFChunkSize);
+ debug("max ZBUF size: %08x", _maxZBUFChunkSize);
break;
case kAESC:
_maxAESCChunkSize = size;
- debug("max AESC size: %08x\n", _maxAESCChunkSize);
+ debug("max AESC size: %08x", _maxAESCChunkSize);
break;
default:
- debug("Unknown tag in MSCT: %s\n", strTag(tag));
+ debug("Unknown tag in MSCT: %s", strTag(tag));
}
uint32 zero;
@@ -336,7 +333,7 @@ bool VQADecoder::readLINF(uint32 size)
_loopInfo.loops[i].begin = _s->readUint16LE();
_loopInfo.loops[i].end = _s->readUint16LE();
- // debug("Loop %d: %04x %04x\n", i, _loopInfo.loops[i].begin, _loopInfo.loops[i].end);
+ // debug("Loop %d: %04x %04x", i, _loopInfo.loops[i].begin, _loopInfo.loops[i].end);
}
return true;
@@ -363,7 +360,7 @@ bool VQADecoder::readCINF(uint32 size)
uint32 b;
a = _s->readUint16LE();
b = _s->readUint32LE();
- debug("%4d %08x\n", a, b);
+ debug("%4d %08x", a, b);
}
return true;
@@ -384,7 +381,7 @@ bool VQADecoder::readFINF(uint32 size)
for (uint32 i = 0; i != _header.numFrames; ++i)
{
uint32 diff = _frameInfo[i] - last;
- debug("_frameInfo[%4d] = 0x%08x - %08x\n", i, _frameInfo[i], diff);
+ debug("_frameInfo[%4d] = 0x%08x - %08x", i, _frameInfo[i], diff);
last = _frameInfo[i];
}
}
@@ -449,57 +446,24 @@ bool VQADecoder::readMFCI(uint32 size)
return true;
}
-int VQADecoder::readFrame()
+bool VQADecoder::readFrame()
{
- // debug("VQADecoder::readFrame(): %d, %d, %d, %d\n", _loopDefault, _loopSpecial, _curLoop, _curFrame);
-
- if (_loopInfo.loopCount)
- {
- if (_loopSpecial >= 0)
- {
- _curLoop = _loopSpecial;
- _loopSpecial = -1;
-
- _curFrame = _loopInfo.loops[_curLoop].begin;
- seekToFrame(_curFrame);
- }
- else if (_curLoop == -1 && _loopDefault >= 0)
- {
- _curLoop = _loopDefault;
- _curFrame = _loopInfo.loops[_curLoop].begin;
- seekToFrame(_curFrame);
- }
- else if (_curLoop >= -1 && _curFrame == _loopInfo.loops[_curLoop].end)
- {
- if (_loopDefault == -1)
- return -1;
-
- _curLoop = _loopDefault;
- _curFrame = _loopInfo.loops[_curLoop].begin;
- seekToFrame(_curFrame);
- }
- else
- ++_curFrame;
- }
- else
- ++_curFrame;
-
- if (_curFrame >= _header.numFrames)
- return -1;
-
IFFChunkHeader chd;
+ if (!_s)
+ return false;
+
_hasView = false;
if (remain(_s) < 8) {
- debug("remain: %d\n", remain(_s));
- return -1;
+ debug("remain: %d", remain(_s));
+ return false;
}
do {
if (!readIFFChunkHeader(_s, &chd)) {
- debug("Error reading chunk header\n");
- return -1;
+ debug("Error reading chunk header");
+ return false;
}
// debug("%s ", strTag(chd.id));
@@ -522,12 +486,12 @@ int VQADecoder::readFrame()
if (!rc)
{
- debug("Error handling chunk %s\n", strTag(chd.id));
- return -1;
+ debug("Error handling chunk %s", strTag(chd.id));
+ return false;
}
} while (chd.id != kVQFR);
- return _curFrame;
+ return true;
}
@@ -551,7 +515,7 @@ bool VQADecoder::readSND2(uint32 size)
{
if (size != 735)
{
- debug("audio frame size: %d\n", size);
+ debug("audio frame size: %d", size);
return false;
}
@@ -592,7 +556,7 @@ bool VQADecoder::readVQFR(uint32 size)
if (!rc)
{
- debug("VQFR: error handling chunk %s\n", strTag(chd.id));
+ debug("VQFR: error handling chunk %s", strTag(chd.id));
return false;
}
}
@@ -620,7 +584,7 @@ bool VQADecoder::readVQFL(uint32 size)
if (!rc)
{
- debug("VQFL: error handling chunk %s\n", strTag(chd.id));
+ debug("VQFL: error handling chunk %s", strTag(chd.id));
return false;
}
}
@@ -632,7 +596,7 @@ bool VQADecoder::readCBFZ(uint32 size)
{
if (size > _header.maxCBFZSize)
{
- debug("%d > %d\n", size, _header.maxCBFZSize);
+ debug("%d > %d", size, _header.maxCBFZSize);
return false;
}
@@ -698,7 +662,7 @@ int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
bool VQADecoder::readZBUF(uint32 size)
{
if (size > _maxZBUFChunkSize) {
- debug("VQA ERROR: ZBUF chunk size: %08x > %08x\n", size, _maxZBUFChunkSize);
+ debug("VQA ERROR: ZBUF chunk size: %08x > %08x", size, _maxZBUFChunkSize);
_s->skip(roundup(size));
return false;
}
@@ -713,7 +677,7 @@ bool VQADecoder::readZBUF(uint32 size)
if (width != _header.width || height != _header.height)
{
- debug("%d, %d, %d, %d\n", width, height, complete, unk0);
+ debug("%d, %d, %d, %d", width, height, complete, unk0);
_s->skip(roundup(remain));
return false;
}
@@ -828,18 +792,6 @@ void VQADecoder::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned i
while (--count);
}
-void VQADecoder::setLoopSpecial(int loop, bool wait)
-{
- _loopSpecial = loop;
- if (!wait)
- _curLoop = -1;
-}
-
-void VQADecoder::setLoopDefault(int loop)
-{
- _loopDefault = loop;
-}
-
bool VQADecoder::seekToFrame(int frame)
{
if (frame < 0 || frame >= _header.numFrames)
@@ -913,7 +865,7 @@ bool VQADecoder::decodeFrame(uint16 *frame)
dstBlock += count;
break;
default:
- debug("Undefined case %d\n", command >> 13);
+ debug("Undefined case %d", command >> 13);
}
}
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index cd0123e20a..ab1f9efe4d 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef BLADERUNNER_VQA_H
-#define BLADERUNNER_VQA_H
+#ifndef BLADERUNNER_VQA_DECODER_H
+#define BLADERUNNER_VQA_DECODER_H
#include "common/debug.h"
#include "common/str.h"
@@ -103,11 +103,6 @@ class VQADecoder
uint32 *_frameInfo;
- int _curFrame;
- int _curLoop;
- int _loopSpecial;
- int _loopDefault;
-
uint32 _maxVIEWChunkSize;
uint32 _maxZBUFChunkSize;
uint32 _maxAESCChunkSize;
@@ -140,16 +135,15 @@ class VQADecoder
bool readLITE(uint32 size);
public:
- VQADecoder(Common::SeekableReadStream *r);
+ VQADecoder();
~VQADecoder();
- bool readHeader();
- int readFrame();
+ bool open(Common::SeekableReadStream *s);
+ bool readFrame();
- void VPTRWriteBlock(uint16 *frame, unsigned int dst_block, unsigned int src_block, int count, bool alpha = false) const;
+ int getFrameTime() { return 1000 / _header.frameRate; }
- void setLoopSpecial(int loop, bool wait);
- void setLoopDefault(int loop);
+ void VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha = false) const;
bool seekToFrame(int frame);
bool decodeFrame(uint16 *frame);
@@ -158,6 +152,8 @@ public:
// bool get_view(view_t *view);
bool getZBUF(uint16 *zbuf);
+
+ friend class VQAPlayer;
};
}; // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
new file mode 100644
index 0000000000..8b614813a7
--- /dev/null
+++ b/engines/bladerunner/vqa_player.cpp
@@ -0,0 +1,102 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/vqa_player.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "common/system.h"
+
+namespace BladeRunner {
+
+bool VQAPlayer::open(const Common::String &name) {
+ _s = _vm->getResourceStream(name);
+ if (!_s)
+ return false;
+
+ if(!_decoder.open(_s)) {
+ delete _s;
+ _s = nullptr;
+ return false;
+ }
+
+ return true;
+}
+
+int VQAPlayer::update() {
+ uint32 now = _vm->_system->getMillis();
+
+ if (_nextFrameTime == 0)
+ _nextFrameTime = now;
+
+ if (now < _nextFrameTime)
+ return -1;
+
+ _nextFrameTime += 1000 / _decoder._header.frameRate;
+
+ if (_decoder._loopInfo.loopCount) {
+ if (_loopSpecial >= 0) {
+ _curLoop = _loopSpecial;
+ _loopSpecial = -3;
+
+ _curFrame = _decoder._loopInfo.loops[_curLoop].begin;
+ _decoder.seekToFrame(_curFrame);
+ } else if (_curLoop == -1 && _loopDefault >= 0) {
+ _curLoop = _loopDefault;
+ _curFrame = _decoder._loopInfo.loops[_curLoop].begin;
+ _decoder.seekToFrame(_curFrame);
+ } else if (_curLoop >= 0 && _curFrame == _decoder._loopInfo.loops[_curLoop].end) {
+ if (_loopDefault == -1)
+ return -3;
+
+ _curLoop = _loopDefault;
+ _curFrame = _decoder._loopInfo.loops[_curLoop].begin;
+ _decoder.seekToFrame(_curFrame);
+ }
+ else
+ ++_curFrame;
+ }
+ else
+ ++_curFrame;
+
+ if (_curFrame >= _decoder._header.numFrames)
+ return -3;
+
+ _decoder.readFrame();
+ _decoder.decodeFrame((uint16*)_surface->getPixels());
+
+ return _curFrame;
+}
+
+void VQAPlayer::setLoopSpecial(int loop, bool wait)
+{
+ _loopSpecial = loop;
+ if (!wait)
+ _curLoop = -1;
+}
+
+void VQAPlayer::setLoopDefault(int loop)
+{
+ _loopDefault = loop;
+}
+
+}; // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
new file mode 100644
index 0000000000..2d7d6822b3
--- /dev/null
+++ b/engines/bladerunner/vqa_player.h
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BLADERUNNER_VQA_PLAYER_H
+#define BLADERUNNER_VQA_PLAYER_H
+
+#include "bladerunner/vqa_decoder.h"
+
+#include "audio/audiostream.h"
+
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class VQAPlayer {
+ BladeRunnerEngine *_vm;
+ Common::SeekableReadStream *_s;
+ VQADecoder _decoder;
+ Graphics::Surface *_surface;
+ Audio::QueuingAudioStream *_audioStream;
+
+ int _curFrame;
+ int _curLoop;
+ int _loopSpecial;
+ int _loopDefault;
+
+ uint32 _nextFrameTime;
+
+public:
+
+ VQAPlayer(BladeRunnerEngine *vm, Graphics::Surface *surface)
+ : _vm(vm),
+ _s(nullptr),
+ _surface(surface),
+ _audioStream(nullptr),
+ _curFrame(-1),
+ _curLoop(-1),
+ _loopSpecial(-1),
+ _loopDefault(-1),
+ _nextFrameTime(0)
+ {}
+
+ bool open(const Common::String &name);
+ int update();
+
+ void setLoopSpecial(int loop, bool wait);
+ void setLoopDefault(int loop);
+};
+
+}; // End of namespace BladeRunner
+
+#endif