aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/bladerunner/overlays.cpp44
-rw-r--r--engines/bladerunner/overlays.h1
-rw-r--r--engines/bladerunner/script/scene/bb06.cpp15
-rw-r--r--engines/bladerunner/script/scene/bb51.cpp2
-rw-r--r--engines/bladerunner/vqa_player.cpp23
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;