aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPeter Kohaut2017-03-26 22:09:29 +0200
committerPeter Kohaut2017-03-26 22:09:29 +0200
commitf5ebf4d6803feaf1e1ae914db1dad8ff4e39b445 (patch)
treed58ad62698a023100df42777aecc551eb4a5670b /engines
parent96b31ca5eb82af59f0032ecae7277fa36fb8eedf (diff)
downloadscummvm-rg350-f5ebf4d6803feaf1e1ae914db1dad8ff4e39b445.tar.gz
scummvm-rg350-f5ebf4d6803feaf1e1ae914db1dad8ff4e39b445.tar.bz2
scummvm-rg350-f5ebf4d6803feaf1e1ae914db1dad8ff4e39b445.zip
BLADERUNNER: Added correct video looping and loop switching
Diffstat (limited to 'engines')
-rw-r--r--engines/bladerunner/script/scene/rc01.cpp5
-rw-r--r--engines/bladerunner/vqa_player.cpp135
-rw-r--r--engines/bladerunner/vqa_player.h39
3 files changed, 129 insertions, 50 deletions
diff --git a/engines/bladerunner/script/scene/rc01.cpp b/engines/bladerunner/script/scene/rc01.cpp
index 8d8b604a89..1a5367b0fc 100644
--- a/engines/bladerunner/script/scene/rc01.cpp
+++ b/engines/bladerunner/script/scene/rc01.cpp
@@ -27,10 +27,7 @@ namespace BladeRunner {
void SceneScriptRC01::InitializeScene() {
#if _DEBUG
//TODO: not part of game, remove
- Game_Flag_Set(24); // force skip intro
- // Game_Flag_Set(9); // Force flag 9 so McCoy will be in view
-
- Footstep_Sound_Override_On(0);
+// Game_Flag_Set(24); // force skip intro
#endif
if (!Game_Flag_Query(24)) {
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index 4fb19cf561..e2b3833390 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -32,18 +32,26 @@ namespace BladeRunner {
bool VQAPlayer::open(const Common::String &name) {
_s = _vm->getResourceStream(name);
- if (!_s)
+ if (!_s) {
return false;
+ }
- if(!_decoder.loadStream(_s)) {
+ if (!_decoder.loadStream(_s)) {
delete _s;
_s = nullptr;
return false;
}
_hasAudio = _decoder.hasAudio();
- if (_hasAudio)
+ if (_hasAudio) {
_audioStream = Audio::makeQueuingAudioStream(_decoder.frequency(), false);
+ }
+
+ if (_loopInitial >= 0) {
+ setLoop(_loopInitial, _repeatsCountInitial, 2, nullptr, nullptr);
+ } else {
+ setBeginAndEndFrame(0, _decoder.numFrames() - 1, 0, 0, nullptr, nullptr);
+ }
return true;
}
@@ -57,19 +65,19 @@ void VQAPlayer::close() {
int VQAPlayer::update() {
uint32 now = 60 * _vm->_system->getMillis();
- if (_curFrame == -1) {
- _curFrame = 0;
- if (_curFrame >= 0) {
- _decoder.readPacket(_curFrame);
+ if (_frameCurrent == -1) {
+ _frameCurrent = 0;
+ if (_frameCurrent >= 0) {
+ _decoder.readPacket(_frameCurrent);
if (_hasAudio)
queueAudioFrame(_decoder.decodeAudioFrame());
_surface = _decoder.decodeVideoFrame();
_zBuffer = _decoder.decodeZBuffer();
}
- _decodedFrame = calcNextFrame(_curFrame);
- if (_decodedFrame >= 0) {
- _decoder.readPacket(_decodedFrame);
+ _frameDecoded = calcNextFrame(_frameCurrent);
+ if (_frameDecoded >= 0) {
+ _decoder.readPacket(_frameDecoded);
if (_hasAudio)
queueAudioFrame(_decoder.decodeAudioFrame());
}
@@ -80,25 +88,25 @@ int VQAPlayer::update() {
}
_nextFrameTime = now + 60000 / 15;
- return _curFrame;
+ return _frameCurrent;
}
if (now >= _nextFrameTime) {
- _curFrame = _decodedFrame;
- if (_curFrame >= 0) {
+ _frameCurrent = _frameDecoded;
+ if (_frameCurrent >= 0) {
_surface = _decoder.decodeVideoFrame();
_zBuffer = _decoder.decodeZBuffer();
}
- _decodedFrame = calcNextFrame(_curFrame);
- if (_decodedFrame >= 0) {
- _decoder.readPacket(_decodedFrame);
+ _frameDecoded = calcNextFrame(_frameCurrent);
+ if (_frameDecoded >= 0) {
+ _decoder.readPacket(_frameDecoded);
if (_hasAudio)
queueAudioFrame(_decoder.decodeAudioFrame());
}
_nextFrameTime += 60000 / 15;
- return _curFrame;
+ return _frameCurrent;
}
_surface = nullptr;
@@ -121,21 +129,58 @@ void VQAPlayer::updateLights(Lights *lights) {
_decoder.decodeLights(lights);
}
-bool VQAPlayer::setLoop(int loop, int unknown, int loopMode, void(*callback)(void*, int, int), void *callbackData) {
+bool VQAPlayer::setLoop(int loop, int repeatsCount, int loopMode, void (*callback)(void *, int, int), void *callbackData) {
+ debug("VQAPlayer::setBeginAndEndFrameFromLoop(%i, %i, %i, %p, %p), streamLoaded = %i", loop, repeatsCount, loopMode, (void*)callback, callbackData, _s != nullptr);
+ if (_s == nullptr) {
+ _loopInitial = loop;
+ _repeatsCountInitial = repeatsCount;
+ return true;
+ }
+
int begin, end;
if (!_decoder.getLoopBeginAndEndFrame(loop, &begin, &end)) {
return false;
}
+ if (setBeginAndEndFrame(begin, end, repeatsCount, loopMode, callback, callbackData)) {
+ _loop = loop;
+ return true;
+ }
+ return false;
+}
+
+bool VQAPlayer::setBeginAndEndFrame(int begin, int end, int repeatsCount, int loopMode, void (*callback)(void *, int, int), void *callbackData) {
+ debug("VQAPlayer::setBeginAndEndFrame(%i, %i, %i, %i, %p, %p), streamLoaded = %i", begin, end, repeatsCount, loopMode, (void*)callback, callbackData, _s != nullptr);
+
+ if (repeatsCount < 0) {
+ repeatsCount = -1;
+ }
- _curLoop = loop;
- _loopBegin = begin;
- _loopEnd = end;
+ if (_repeatsCount == 0 && loopMode == 1) {
+ loopMode = 2;
+ }
+
+ //TODO: there is code in original game which deals with changing loop at start of loop, is it nescesarry? loc_46EA04
+
+ _frameBegin = begin;
+
+ if (loopMode == 1) {
+ _repeatsCountQueued = repeatsCount;
+ _frameEndQueued = end;
+ } else if (loopMode == 2) {
+ _repeatsCount = repeatsCount;
+ _frameEnd = end;
+ _frameCurrent = begin;
+ //TODO: extract this to seek function
+ _decoder.readPacket(_frameCurrent);
+ _frameDecoded = _frameCurrent;
+ _nextFrameTime = 60 * _vm->_system->getMillis();
+ } else if (loopMode == 0) {
+ _repeatsCount = repeatsCount;
+ }
_callbackLoopEnded = callback;
_callbackData = callbackData;
- // warning("\t\t\tActive Loop: %d - %d\n", begin, end);
-
return true;
}
@@ -155,23 +200,45 @@ int VQAPlayer::getLoopEndFrame(int loop) {
return end;
}
-int VQAPlayer::calcNextFrame(int frame) const {
- if (frame < 0)
+int VQAPlayer::calcNextFrame(int frame) {
+ //TODO: needs a slight refactoring, because it is not only calculating the next frame
+ if (frame < 0) {
return -3;
+ }
+
+ int frameNext = frame + 1;
- if (_curLoop != -1 && frame >= _loopEnd) {
- frame = _loopBegin;
- if (_callbackLoopEnded != nullptr) {
- _callbackLoopEnded(_callbackData, 0, _curLoop);
+ if ((_repeatsCount > 0 || _repeatsCount == -1) && (frameNext > _frameEnd)) {
+ int loopEndQueued = _frameEndQueued;
+ if (_frameEndQueued != -1) {
+ _frameEnd = _frameEndQueued;
+ _frameEndQueued = -1;
+ }
+ if (frameNext != _frameBegin) {
+ frameNext = _frameBegin;
+ }
+
+ if (loopEndQueued == -1) {
+ if (_repeatsCount != -1) {
+ _repeatsCount--;
+ }
+ //callback for repeat, it is not used in the blade runner
+ } else {
+ _repeatsCount = _repeatsCountQueued;
+ _repeatsCountQueued = -1;
+
+ if (_callbackLoopEnded != nullptr) {
+ _callbackLoopEnded(_callbackData, 0, _loop);
+ }
}
- } else {
- frame++;
}
- if (frame == _decoder.numFrames())
- frame = -3;
+ //TODO: original game is using end of loop instead of count of frames
+ if (frameNext == _decoder.numFrames()) {
+ return -3;
+ }
- return frame;
+ return frameNext;
}
void VQAPlayer::queueAudioFrame(Audio::AudioStream *audioStream) {
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index 3a821a8323..941b3638ed 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -36,6 +36,8 @@ class BladeRunnerEngine;
class View;
class Lights;
+//TODO: split this into two components as it is in original game: universal vqa player, blade runner player functionality
+
class VQAPlayer {
BladeRunnerEngine *_vm;
Common::SeekableReadStream *_s;
@@ -44,11 +46,18 @@ class VQAPlayer {
const uint16 *_zBuffer;
Audio::QueuingAudioStream *_audioStream;
- int _curFrame;
- int _decodedFrame;
- int _curLoop;
- int _loopBegin;
- int _loopEnd;
+ int _frameCurrent;
+ int _frameDecoded;
+ int _frameBegin;
+ int _frameEnd;
+ int _loop;
+ int _repeatsCount;
+
+ int _repeatsCountQueued;
+ int _frameEndQueued;
+
+ int _loopInitial;
+ int _repeatsCountInitial;
uint32 _nextFrameTime;
bool _hasAudio;
@@ -65,11 +74,16 @@ public:
_s(nullptr),
_surface(nullptr),
_audioStream(nullptr),
- _curFrame(-1),
- _decodedFrame(-1),
- _curLoop(-1),
- _loopBegin(-1),
- _loopEnd(-1),
+ _frameCurrent(-1),
+ _frameDecoded(-1),
+ _frameBegin(-1),
+ _frameEnd(-1),
+ _loop(-1),
+ _repeatsCount(-1),
+ _repeatsCountQueued(-1),
+ _frameEndQueued(-1),
+ _loopInitial(-1),
+ _repeatsCountInitial(-1),
_nextFrameTime(0),
_hasAudio(false),
_audioStarted(false),
@@ -89,13 +103,14 @@ public:
void updateView(View *view);
void updateLights(Lights *lights);
- bool setLoop(int loop, int unknown, int loopMode, void(*callback)(void*, int, int), void* callbackData);
+ bool setBeginAndEndFrame(int begin, int end, int repeatsCount, int loopMode, void(*callback)(void *, int, int), void *callbackData);
+ bool setLoop(int loop, int repeatsCount, int loopMode, void(*callback)(void*, int, int), void* callbackData);
int getLoopBeginFrame(int loop);
int getLoopEndFrame(int loop);
private:
- int calcNextFrame(int frame) const;
+ int calcNextFrame(int frame);
void queueAudioFrame(Audio::AudioStream *audioStream);
};