diff options
-rw-r--r-- | engines/bladerunner/overlays.cpp | 44 | ||||
-rw-r--r-- | engines/bladerunner/overlays.h | 1 | ||||
-rw-r--r-- | engines/bladerunner/script/scene/bb06.cpp | 15 | ||||
-rw-r--r-- | engines/bladerunner/script/scene/bb51.cpp | 2 | ||||
-rw-r--r-- | engines/bladerunner/vqa_player.cpp | 23 |
5 files changed, 71 insertions, 14 deletions
diff --git a/engines/bladerunner/overlays.cpp b/engines/bladerunner/overlays.cpp index 5bbac87c36..20e93b22e3 100644 --- a/engines/bladerunner/overlays.cpp +++ b/engines/bladerunner/overlays.cpp @@ -23,6 +23,7 @@ #include "bladerunner/overlays.h" #include "bladerunner/bladerunner.h" +#include "bladerunner/game_constants.h" #include "bladerunner/archive.h" #include "bladerunner/savefile.h" @@ -58,6 +59,10 @@ Overlays::~Overlays() { int Overlays::play(const Common::String &name, int loopId, bool loopForever, bool startNow, int a6) { assert(name.size() <= 12); + if (loopId < 0) { + warning("Overlays::play - loop id can't be a negative number!"); + return -1; + } int32 hash = MIXArchive::getHash(name); int index = findByHash(hash); @@ -70,20 +75,38 @@ int Overlays::play(const Common::String &name, int loopId, bool loopForever, boo _videos[index].name = name; _videos[index].hash = hash; _videos[index].loopId = loopId; + _videos[index].enqueuedLoopId = -1; _videos[index].loopForever = loopForever; _videos[index].vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront, Common::String::format("%s.VQA", name.c_str())); + if (!_videos[index].vqaPlayer) { + resetSingle(index); + return -1; + } + // TODO? Removed as redundant // repeat forever - _videos[index].vqaPlayer->setBeginAndEndFrame(0, 0, -1, kLoopSetModeJustStart, nullptr, nullptr); + //_videos[index].vqaPlayer->setBeginAndEndFrame(0, 0, -1, kLoopSetModeJustStart, nullptr, nullptr); } - _videos[index].vqaPlayer->open(); - _videos[index].vqaPlayer->setLoop( - loopId, - loopForever ? -1 : 0, - startNow ? kLoopSetModeImmediate : kLoopSetModeEnqueue, - nullptr, nullptr); + bool skipNewVQAPlayerOpen = false; + if (_videos[index].vqaPlayer + && !startNow + && _videos[index].vqaPlayer->getFrameCount() > 0 + ) { + skipNewVQAPlayerOpen = true; + _videos[index].enqueuedLoopId = loopId; + } + if (skipNewVQAPlayerOpen || _videos[index].vqaPlayer->open()) { + _videos[index].vqaPlayer->setLoop( + loopId, + loopForever ? -1 : 0, + startNow ? kLoopSetModeImmediate : kLoopSetModeEnqueue, + nullptr, nullptr); + } else { + resetSingle(index); + return -1; + } return index; } @@ -179,7 +202,12 @@ void Overlays::save(SaveFileWriteStream &f) { f.writeInt(0); // vqaPlayer pointer f.writeStringSz(ov.name, 13); f.writeSint32LE(ov.hash); - f.writeInt(ov.loopId); + if (ov.enqueuedLoopId != -1) { + // When there is an enqueued video, save that loop Id instead + f.writeInt(ov.enqueuedLoopId); + } else { + f.writeInt(ov.loopId); + } f.writeBool(ov.loopForever); f.writeInt(ov.frame); } diff --git a/engines/bladerunner/overlays.h b/engines/bladerunner/overlays.h index cbb01fa04b..3ba3a654c1 100644 --- a/engines/bladerunner/overlays.h +++ b/engines/bladerunner/overlays.h @@ -48,6 +48,7 @@ class Overlays { Common::String name; int32 hash; int loopId; + int enqueuedLoopId; bool loopForever; int frame; }; diff --git a/engines/bladerunner/script/scene/bb06.cpp b/engines/bladerunner/script/scene/bb06.cpp index 92fdefefd8..b2b185d630 100644 --- a/engines/bladerunner/script/scene/bb06.cpp +++ b/engines/bladerunner/script/scene/bb06.cpp @@ -67,7 +67,7 @@ void SceneScriptBB06::InitializeScene() { #else // bugfix: case of not transitioning from BB51: chess/ egg boiler sub-space if (Game_Flag_Query(kFlagBB06AndroidDestroyed)) { - Overlay_Play("BB06OVER", 1, false, false, 0); + Overlay_Play("BB06OVER", 1, true, true, 0); } #endif // BLADERUNNER_ORIGINAL_BUGS } @@ -111,8 +111,17 @@ bool SceneScriptBB06::ClickedOn3DObject(const char *objectName, bool a2) { } #else if (Player_Query_Combat_Mode()) { - Overlay_Play("BB06OVER", 0, false, true, 0); // explosion - don't loop + // Doll Explosion case: + // We need to use enqueued overlays for this. + // Note: Queuing only works on top of a video that is repeating itself. + // First we load the "exploding animation state" as a forever loop (even though it will only play once) + // Then we enqueue the final exploded state loop, also as a forever loop. + // This (along with some fixes in the Overlays class will ensure + // that the second overlay will play after the first has completed one loop + // and it will persist (across save games too). Game_Flag_Set(kFlagBB06AndroidDestroyed); + Overlay_Play("BB06OVER", 0, true, true, 0); + Overlay_Play("BB06OVER", 1, true, false, 0); Un_Combat_Target_Object("BOX31"); return true; } else { @@ -195,7 +204,7 @@ void SceneScriptBB06::SceneFrameAdvanced(int frame) { // last frame of transition is 15, try 13 for better transition - minimize weird effect if (frame == 13) { // executed once during transition FROM bb51 (chess sub space) if (Game_Flag_Query(kFlagBB06AndroidDestroyed)) { - Overlay_Play("BB06OVER", 1, false, false, 0); + Overlay_Play("BB06OVER", 1, true, true, 0); } } #endif // BLADERUNNER_ORIGINAL_BUGS diff --git a/engines/bladerunner/script/scene/bb51.cpp b/engines/bladerunner/script/scene/bb51.cpp index fd706c2bcf..d5d5630d36 100644 --- a/engines/bladerunner/script/scene/bb51.cpp +++ b/engines/bladerunner/script/scene/bb51.cpp @@ -51,7 +51,7 @@ void SceneScriptBB51::InitializeScene() { #if BLADERUNNER_ORIGINAL_BUGS // Sebastian's Doll Fix #else if (Game_Flag_Query(kFlagBB06AndroidDestroyed)) { - Overlay_Play("BB06OVER", 1, false, false, 0); + Overlay_Play("BB06OVER", 1, true, true, 0); } #endif // BLADERUNNER_ORIGINAL_BUGS diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp index 300740e028..65fab5f1cd 100644 --- a/engines/bladerunner/vqa_player.cpp +++ b/engines/bladerunner/vqa_player.cpp @@ -57,10 +57,12 @@ bool VQAPlayer::open() { _repeatsCountQueued = -1; if (_loopInitial >= 0) { + // TODO? When does this happen? _loopInitial seems to be unused setLoop(_loopInitial, _repeatsCountInitial, kLoopSetModeImmediate, nullptr, nullptr); } else { _frameNext = 0; - setBeginAndEndFrame(0, _frameEnd, 0, kLoopSetModeJustStart, nullptr, nullptr); + // TODO? Removed as redundant +// setBeginAndEndFrame(0, _frameEnd, 0, kLoopSetModeJustStart, nullptr, nullptr); } return true; @@ -107,6 +109,8 @@ int VQAPlayer::update(bool forceDraw, bool advanceFrame, bool useTime, Graphics: result = -1; } else if (_frameNext > _frameEnd) { result = -3; + // _repeatsCount == 0, so return here at the end of the video, to release the resource + return result; } else if (useTime && (now < _frameNextTime)) { result = -1; } else if (advanceFrame) { @@ -149,7 +153,9 @@ int VQAPlayer::update(bool forceDraw, bool advanceFrame, bool useTime, Graphics: _decoder.decodeVideoFrame(customSurface != nullptr ? customSurface : _surface, _frame, true); result = _frame; } - return result; + return result; // Note: result here could be negative. + // Negative valid value should only be -1, since there are various assertions + // assert(frame >= -1) in overlay modes (elevator, scores, spinner) } void VQAPlayer::updateZBuffer(ZBuffer *zbuffer) { @@ -187,11 +193,23 @@ bool VQAPlayer::setLoop(int loop, int repeatsCount, int loopSetMode, void (*call } bool VQAPlayer::setBeginAndEndFrame(int begin, int end, int repeatsCount, int loopSetMode, void (*callback)(void *, int, int), void *callbackData) { + if ( begin >= getFrameCount() + || end >= getFrameCount() + || begin >= end + || loopSetMode < 0 + || loopSetMode >= 3 + ) { + warning("VQAPlayer::setBeginAndEndFrame - Invalid arguments for video"); + return false; // VQA_DECODER_ERROR_BAD_INPUT case + } + if (repeatsCount < 0) { repeatsCount = -1; } if (_repeatsCount == 0 && loopSetMode == kLoopSetModeEnqueue) { + // if the member var _repeatsCount is 0 (which means "don't repeat existing loop") + // then execute set the enqueued loop for immediate execution loopSetMode = kLoopSetModeImmediate; } @@ -199,6 +217,7 @@ bool VQAPlayer::setBeginAndEndFrame(int begin, int end, int repeatsCount, int lo if (loopSetMode == kLoopSetModeJustStart) { _repeatsCount = repeatsCount; + _frameEnd = end; } else if (loopSetMode == kLoopSetModeEnqueue) { _repeatsCountQueued = repeatsCount; _frameEndQueued = end; |