aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrichiesams2013-08-04 23:10:27 -0500
committerrichiesams2013-08-04 23:52:31 -0500
commit7b9858d6b45ad4c02729445975518a48292c3658 (patch)
treebf16bfbb81d4614ff10d4fd6ec2ce5a4e0211d69
parenta86a0832e08c777ef23f2ce97004963b301dd598 (diff)
downloadscummvm-rg350-7b9858d6b45ad4c02729445975518a48292c3658.tar.gz
scummvm-rg350-7b9858d6b45ad4c02729445975518a48292c3658.tar.bz2
scummvm-rg350-7b9858d6b45ad4c02729445975518a48292c3658.zip
ZVISION: Make video code blocking.
The script system requires that all ResultAction::execute() block until they finish. The video system *was* 'asyncronous' in that you would just start a video and then run() would finish processing it. This code forces the video to complely finish before playVideo returns. The Clock object is used to keep track of deltaTime while the video is playing.
-rw-r--r--engines/zvision/console.cpp6
-rw-r--r--engines/zvision/events.cpp5
-rw-r--r--engines/zvision/render_manager.cpp13
-rw-r--r--engines/zvision/render_manager.h24
-rw-r--r--engines/zvision/video.cpp87
-rw-r--r--engines/zvision/zvision.cpp31
-rw-r--r--engines/zvision/zvision.h22
7 files changed, 93 insertions, 95 deletions
diff --git a/engines/zvision/console.cpp b/engines/zvision/console.cpp
index 9c7d79a8f1..6634e0bef4 100644
--- a/engines/zvision/console.cpp
+++ b/engines/zvision/console.cpp
@@ -69,9 +69,9 @@ bool Console::cmdLoadVideo(int argc, const char **argv) {
return true;
}
- Video::VideoDecoder *videoDecoder = new ZorkAVIDecoder();
- if (videoDecoder && videoDecoder->loadFile(argv[1])) {
- _engine->getRenderManager()->startVideo(videoDecoder);
+ ZorkAVIDecoder videoDecoder;
+ if (videoDecoder.loadFile(argv[1])) {
+ _engine->playVideo(videoDecoder);
}
return true;
diff --git a/engines/zvision/events.cpp b/engines/zvision/events.cpp
index e392d3c78a..508d2610aa 100644
--- a/engines/zvision/events.cpp
+++ b/engines/zvision/events.cpp
@@ -61,11 +61,6 @@ void ZVision::processEvents() {
if (_event.kbd.hasFlags(Common::KBD_CTRL))
quitGame();
break;
- case Common::KEYCODE_ESCAPE:
- if (_renderManager->isVideoPlaying())
- _renderManager->cancelVideo();
-
- break;
default:
break;
}
diff --git a/engines/zvision/render_manager.cpp b/engines/zvision/render_manager.cpp
index b6163c83c1..604c310689 100644
--- a/engines/zvision/render_manager.cpp
+++ b/engines/zvision/render_manager.cpp
@@ -38,25 +38,12 @@ RenderManager::RenderManager(OSystem *system, const int width, const int height)
: _system(system),
_width(width),
_height(height),
- _pixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), // RGB555
- _currentVideo(0),
_currentBackground(0),
- _scaledVideoFrameBuffer(0),
_needsScreenUpdate(false),
_renderTable(width, height) {
}
-/**
- * Initialize graphics
- */
-void RenderManager::initialize() {
- initGraphics(_width, _height, true, &_pixelFormat);
-}
-
void RenderManager::updateScreen(bool isConsoleActive) {
- if (_currentVideo != 0)
- continueVideo();
-
if (_needsScreenUpdate || isConsoleActive) {
_system->updateScreen();
_needsScreenUpdate = false;
diff --git a/engines/zvision/render_manager.h b/engines/zvision/render_manager.h
index fc2598ecf9..9554e888d9 100644
--- a/engines/zvision/render_manager.h
+++ b/engines/zvision/render_manager.h
@@ -26,8 +26,6 @@
#include "common/types.h"
#include "common/rect.h"
-#include "graphics/pixelformat.h"
-
#include "zvision/render_table.h"
class OSystem;
@@ -51,7 +49,6 @@ private:
OSystem *_system;
const int _width;
const int _height;
- const Graphics::PixelFormat _pixelFormat;
RenderTable _renderTable;
Common::SeekableReadStream *_currentBackground;
@@ -66,22 +63,6 @@ public:
void updateScreen(bool isConsoleActive);
/**
- * Start a video playing. It will also load the first frame of the video.
- *
- * @param videoDecoder The video to play
- */
- void startVideo(Video::VideoDecoder *videoDecoder);
- /**
- * @return Is a video currently being played
- */
- bool isVideoPlaying() { return _currentVideo == 0; }
- /**
- * Cancels a video prematurely. Any sound remaining in the queue will continue to play.
- * The last frame of the video will remain on the screen until something else overwrites it
- */
- void cancelVideo();
-
- /**
* Blits the image or a portion of the image to the screen. Actual screen updates won't happen until the end of the frame.
* The image will be clipped to fit inside the window.
*
@@ -116,11 +97,6 @@ public:
bool needsScreenUpdate() { return _needsScreenUpdate; };
private:
- /**
- * Checks the time since the last video frame, and blits the next frame to the screen
- */
- void continueVideo();
-
void renderSubRectToScreen(uint16 *buffer, uint32 imageWidth, uint32 imageHeight, uint32 horizontalPitch, uint32 destinationX, uint32 destinationY, Common::Rect subRectangle);
};
diff --git a/engines/zvision/video.cpp b/engines/zvision/video.cpp
index 1ccf736970..8550a6cfca 100644
--- a/engines/zvision/video.cpp
+++ b/engines/zvision/video.cpp
@@ -27,7 +27,9 @@
#include "engines/util.h"
#include "graphics/surface.h"
+#include "zvision/clock.h"
#include "zvision/render_manager.h"
+#include "zvision/zvision.h"
namespace ZVision {
@@ -71,62 +73,77 @@ void scale2x(const byte *src, byte *dst, uint32 srcWidth, uint32 srcHeight, byte
}
}
-void RenderManager::startVideo(Video::VideoDecoder *videoDecoder) {
- if (!videoDecoder)
- return;
-
- _currentVideo = videoDecoder;
-
+void ZVision::playVideo(Video::VideoDecoder &videoDecoder) {
+ // Videos use a different pixel format
Common::List<Graphics::PixelFormat> formats;
- formats.push_back(videoDecoder->getPixelFormat());
+ formats.push_back(videoDecoder.getPixelFormat());
initGraphics(_width, _height, true, formats);
-
- _scaledVideoFrameBuffer = new byte[_currentVideo->getWidth() * _currentVideo->getHeight() * _currentVideo->getPixelFormat().bytesPerPixel * 4];
-
- _currentVideo->start();
- // Load the first frame
- continueVideo();
-}
-
-void RenderManager::continueVideo() {
- byte bytesPerPixel = _currentVideo->getPixelFormat().bytesPerPixel;
- uint16 origWidth = _currentVideo->getWidth();
- uint16 origHeight = _currentVideo->getHeight();
+ byte bytesPerPixel = videoDecoder.getPixelFormat().bytesPerPixel;
+ uint16 origWidth = videoDecoder.getWidth();
+ uint16 origHeight = videoDecoder.getHeight();
uint16 pitch = origWidth * bytesPerPixel;
+
+ // Most videos are very small. Therefore we do a simple 2x scale
bool shouldBeScaled = (origWidth * 2 <= 640 && origHeight * 2 <= 480);
uint16 finalWidth = shouldBeScaled ? origWidth * 2 : origWidth;
uint16 finalHeight = shouldBeScaled ? origHeight * 2 : origHeight;
- uint16 x = (_system->getWidth() - finalWidth) / 2;
- uint16 y = (_system->getHeight() - finalHeight) / 2;
+ byte *scaledVideoFrameBuffer = new byte[origHeight * pitch * 4];
+
+ uint16 x = (_width - finalWidth) / 2;
+ uint16 y = (_height - finalHeight) / 2;
+
+ _clock->stop();
+ videoDecoder.start();
+
+ // Only continue while the video is still playing
+ while (videoDecoder.isPlaying()) {
+ _clock->update();
+ uint32 currentTime = _clock->getLastMeasuredTime();
+
+ // Check for engine quit and video stop key presses
+ while (_eventMan->pollEvent(_event)) {
+ switch (_event.type) {
+ case Common::EVENT_KEYDOWN:
+ switch (_event.kbd.keycode) {
+ case Common::KEYCODE_q:
+ if (_event.kbd.hasFlags(Common::KBD_CTRL))
+ quitGame();
+ break;
+ case Common::KEYCODE_SPACE:
+ videoDecoder.stop();
+ break;
+ }
+ }
+ }
- if (!_currentVideo->endOfVideo()) {
- if (_currentVideo->needsUpdate()) {
- const Graphics::Surface *frame = _currentVideo->decodeNextFrame();
+ if (videoDecoder.needsUpdate()) {
+ const Graphics::Surface *frame = videoDecoder.decodeNextFrame();
if (frame) {
if (shouldBeScaled) {
- scale2x((byte *)frame->pixels, _scaledVideoFrameBuffer, origWidth, origHeight, bytesPerPixel);
- _system->copyRectToScreen(_scaledVideoFrameBuffer, pitch * 2, x, y, finalWidth, finalHeight);
+ scale2x((byte *)frame->pixels, scaledVideoFrameBuffer, origWidth, origHeight, bytesPerPixel);
+ _system->copyRectToScreen(scaledVideoFrameBuffer, pitch * 2, x, y, finalWidth, finalHeight);
} else {
_system->copyRectToScreen((byte *)frame->pixels, pitch, x, y, finalWidth, finalHeight);
}
- _needsScreenUpdate = true;
+ _system->updateScreen();
}
}
- } else {
- cancelVideo();
+
+ // Calculate the frame delay based off a desired frame time
+ int delay = _desiredFrameTime - (currentTime - _system->getMillis());
+ // Ensure non-negative
+ delay = delay < 0 ? 0 : delay;
+ _system->delayMillis(delay);
}
-}
-void RenderManager::cancelVideo() {
+ _clock->stop();
+
+ // Reset the pixel format to the original state
initGraphics(_width, _height, true, &_pixelFormat);
- delete _currentVideo;
- _currentVideo = 0;
- delete[] _scaledVideoFrameBuffer;
- _scaledVideoFrameBuffer = 0;
}
} // End of namespace ZVision
diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp
index ca43549f50..0015c41499 100644
--- a/engines/zvision/zvision.cpp
+++ b/engines/zvision/zvision.cpp
@@ -31,11 +31,14 @@
#include "common/file.h"
#include "engines/util.h"
+
+#include "audio/mixer.h"
#include "zvision/zvision.h"
#include "zvision/console.h"
#include "zvision/script_manager.h"
#include "zvision/render_manager.h"
+#include "zvision/clock.h"
#include "zvision/zfs_archive.h"
#include "zvision/detection.h"
@@ -47,7 +50,9 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc)
: Engine(syst),
_gameDescription(gameDesc),
_width(640),
- _height(480) {
+ _height(480),
+ _pixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), /*RGB 555*/
+ _desiredFrameTime(33) /* ~30 fps */ {
// Put your engine in a sane state, but do nothing big yet;
// in particular, do not load data from files; rather, if you
// need to do such things, do them from run().
@@ -75,14 +80,19 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc)
_scriptManager = new ScriptManager(this);
_renderManager = new RenderManager(_system, _width, _height);
+ // Create clock
+ _clock = new Clock(_system);
+
debug("ZVision::ZVision");
}
-
+
ZVision::~ZVision() {
debug("ZVision::~ZVision");
// Dispose of resources
delete _console;
+ delete _clock;
+ delete _renderManager;
delete _scriptManager;
delete _rnd;
@@ -103,7 +113,7 @@ void ZVision::initialize() {
SearchMan.add(name, archive);
}
- _renderManager->initialize();
+ initGraphics(_width, _height, true, &_pixelFormat);
_scriptManager->initialize();
@@ -115,25 +125,20 @@ Common::Error ZVision::run() {
initialize();
// Main loop
- uint32 currentTime = _system->getMillis();
- uint32 lastTime = currentTime;
- const uint desiredFrameTime = 33; // ~30 fps
-
while (!shouldQuit()) {
- processEvents();
+ _clock->update();
+ uint32 currentTime = _clock->getLastMeasuredTime();
- currentTime = _system->getMillis();
- uint32 deltaTime = currentTime - lastTime;
- lastTime = currentTime;
+ processEvents();
- _scriptManager->updateNodes(deltaTime);
+ _scriptManager->updateNodes(_clock->getDeltaTime());
_scriptManager->checkPuzzleCriteria();
// Render a frame
_renderManager->updateScreen(_console->isActive());
// Calculate the frame delay based off a desired frame time
- int delay = desiredFrameTime - (currentTime - _system->getMillis());
+ int delay = _desiredFrameTime - (currentTime - _system->getMillis());
// Ensure non-negative
delay = delay < 0 ? 0 : delay;
_system->delayMillis(delay);
diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h
index 9588623f56..459096a03b 100644
--- a/engines/zvision/zvision.h
+++ b/engines/zvision/zvision.h
@@ -29,16 +29,24 @@
#include "engines/engine.h"
+#include "graphics/pixelformat.h"
+
#include "zvision/detection.h"
#include "gui/debugger.h"
-
+
+
+namespace Video {
+class VideoDecoder;
+}
+
namespace ZVision {
struct ZVisionGameDescription;
class Console;
class ScriptManager;
class RenderManager;
+class Clock;
// our engine debug channels
enum {
@@ -58,25 +66,35 @@ private:
const ZVisionGameDescription *_gameDescription;
const int _width;
const int _height;
+ const Graphics::PixelFormat _pixelFormat;
+
+ const uint _desiredFrameTime;
// We need random numbers
Common::RandomSource *_rnd;
+
// Managers
ScriptManager *_scriptManager;
RenderManager *_renderManager;
+ // Clock
+ Clock *_clock;
+
// To prevent allocation every time we process events
Common::Event _event;
public:
uint32 getFeatures() const;
Common::Language getLanguage() const;
- virtual Common::Error run();
+ Common::Error run();
+
ScriptManager *getScriptManager() const;
RenderManager *getRenderManager() const;
Common::RandomSource *getRandomSource() const;
ZVisionGameId getGameId() const;
+ void playVideo(Video::VideoDecoder &videoDecoder);
+
private:
void initialize();