diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/engine/kernel.h | 4 | ||||
-rw-r--r-- | engines/sci/engine/kernel_tables.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/kvideo.cpp | 12 | ||||
-rw-r--r-- | engines/sci/graphics/video32.cpp | 219 | ||||
-rw-r--r-- | engines/sci/graphics/video32.h | 206 |
5 files changed, 246 insertions, 197 deletions
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index d49f0649c1..845e63af79 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -447,9 +447,7 @@ reg_t kPlayVMDInit(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMDClose(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMDPlayUntilEvent(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMDShowCursor(EngineState *s, int argc, reg_t *argv); -reg_t kPlayVMDStartBlob(EngineState *s, int argc, reg_t *argv); -reg_t kPlayVMDStopBlobs(EngineState *s, int argc, reg_t *argv); -reg_t kPlayVMDBlack(EngineState *s, int argc, reg_t *argv); +reg_t kPlayVMDSetBlackoutArea(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMDRestrictPalette(EngineState *s, int argc, reg_t *argv); reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 6e5add15e2..31a9938514 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -423,7 +423,7 @@ static const SciKernelMapSubEntry kPlayVMD_subops[] = { { SIG_SINCE_SCI21, 16, MAP_CALL(PlayVMDShowCursor), "i", NULL }, { SIG_SINCE_SCI21, 17, MAP_DUMMY(PlayVMDStartBlob), "", NULL }, { SIG_SINCE_SCI21, 18, MAP_DUMMY(PlayVMDStopBlobs), "", NULL }, - { SIG_SINCE_SCI21, 21, MAP_CALL(PlayVMDBlack), "iiii", NULL }, + { SIG_SINCE_SCI21, 21, MAP_CALL(PlayVMDSetBlackoutArea), "iiii", NULL }, { SIG_SINCE_SCI21, 23, MAP_CALL(PlayVMDRestrictPalette), "ii", NULL }, SCI_SUBOPENTRY_TERMINATOR }; diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index aa37da6ea0..1096e78cca 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -342,17 +342,7 @@ reg_t kPlayVMDShowCursor(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -reg_t kPlayVMDStartBlob(EngineState *s, int argc, reg_t *argv) { - debug("kPlayVMDStartBlob"); - return s->r_acc; -} - -reg_t kPlayVMDStopBlobs(EngineState *s, int argc, reg_t *argv) { - debug("kPlayVMDStopBlobs"); - return s->r_acc; -} - -reg_t kPlayVMDBlack(EngineState *s, int argc, reg_t *argv) { +reg_t kPlayVMDSetBlackoutArea(EngineState *s, int argc, reg_t *argv) { const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; diff --git a/engines/sci/graphics/video32.cpp b/engines/sci/graphics/video32.cpp index 86ff82a8d0..dfddac1036 100644 --- a/engines/sci/graphics/video32.cpp +++ b/engines/sci/graphics/video32.cpp @@ -33,37 +33,49 @@ #include "video/coktel_decoder.h" namespace Sci { + +#pragma mark VMDPlayer + VMDPlayer::VMDPlayer(SegManager *segMan, EventManager *eventMan) : _segMan(segMan), _eventMan(eventMan), _decoder(new Video::AdvancedVMDDecoder(Audio::Mixer::kSFXSoundType)), + _isOpen(false), _isInitialized(false), + _yieldInterval(0), + _lastYieldedFrameNo(0), + + _plane(nullptr), + _screenItem(nullptr), + _planeIsOwned(true), + _priority(0), + _doublePixels(false), + _stretchVertical(false), + _blackLines(false), + _leaveScreenBlack(false), + _leaveLastFrame(false), + + _blackoutPlane(nullptr), + _startColor(0), - _planeSet(false), _endColor(255), - _blackLines(false), - _doublePixels(false), - _lastYieldedFrameNo(0), - _blackoutRect(), _blackPalette(false), + _boostPercent(100), _boostStartColor(0), _boostEndColor(255), - _leaveLastFrame(false), - _leaveScreenBlack(false), - _plane(nullptr), - _screenItem(nullptr), - _stretchVertical(false), - _priority(0), - _blackoutPlane(nullptr), - _yieldInterval(0) {} + + _showCursor(false) {} VMDPlayer::~VMDPlayer() { close(); delete _decoder; } +#pragma mark - +#pragma mark VMDPlayer - Playback + VMDPlayer::IOStatus VMDPlayer::open(const Common::String &fileName, const OpenFlags flags) { if (_isOpen) { error("Attempted to play %s, but another VMD was loaded", fileName.c_str()); @@ -83,20 +95,57 @@ VMDPlayer::IOStatus VMDPlayer::open(const Common::String &fileName, const OpenFl void VMDPlayer::init(const int16 x, const int16 y, const PlayFlags flags, const int16 boostPercent, const int16 boostStartColor, const int16 boostEndColor) { _x = getSciVersion() >= SCI_VERSION_3 ? x : (x & ~1); _y = y; - _leaveScreenBlack = flags & kPlayFlagLeaveScreenBlack; - _leaveLastFrame = flags & kPlayFlagLeaveLastFrame; _doublePixels = flags & kPlayFlagDoublePixels; _blackLines = ConfMan.getBool("enable_black_lined_video") && (flags & kPlayFlagBlackLines); _boostPercent = 100 + (flags & kPlayFlagBoost ? boostPercent : 0); - _blackPalette = flags & kPlayFlagBlackPalette; - _stretchVertical = flags & kPlayFlagStretchVertical; _boostStartColor = CLIP<int16>(boostStartColor, 0, 255); _boostEndColor = CLIP<int16>(boostEndColor, 0, 255); + _leaveScreenBlack = flags & kPlayFlagLeaveScreenBlack; + _leaveLastFrame = flags & kPlayFlagLeaveLastFrame; + _blackPalette = flags & kPlayFlagBlackPalette; + _stretchVertical = flags & kPlayFlagStretchVertical; } -void VMDPlayer::restrictPalette(const uint8 startColor, const uint8 endColor) { - _startColor = startColor; - _endColor = endColor; +VMDPlayer::IOStatus VMDPlayer::close() { + if (!_isOpen) { + return kIOSuccess; + } + + _decoder->close(); + _isOpen = false; + _isInitialized = false; + + if (!_planeIsOwned && _screenItem != nullptr) { + g_sci->_gfxFrameout->deleteScreenItem(*_screenItem); + _screenItem = nullptr; + } else if (_plane != nullptr) { + g_sci->_gfxFrameout->deletePlane(*_plane); + _plane = nullptr; + } + + if (!_leaveLastFrame && _leaveScreenBlack) { + // This call *actually* deletes the plane/screen item + g_sci->_gfxFrameout->frameOut(true); + } + + if (_blackoutPlane != nullptr) { + g_sci->_gfxFrameout->deletePlane(*_blackoutPlane); + _blackoutPlane = nullptr; + } + + if (!_leaveLastFrame && !_leaveScreenBlack) { + // This call *actually* deletes the blackout plane + g_sci->_gfxFrameout->frameOut(true); + } + + if (!_showCursor) { + g_sci->_gfxCursor->kernelShow(); + } + + _lastYieldedFrameNo = 0; + _planeIsOwned = true; + _priority = 0; + return kIOSuccess; } VMDPlayer::EventFlags VMDPlayer::kernelPlayUntilEvent(const EventFlags flags, const int16 lastFrameNo, const int16 yieldInterval) { @@ -154,20 +203,13 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { g_sci->_gfxCursor->kernelHide(); } - const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; - const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; - const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; - - Common::Rect vmdRect( - _x, - _y, - _x + _decoder->getWidth(), - _y + _decoder->getHeight() - ); + Common::Rect vmdRect(_x, + _y, + _x + _decoder->getWidth(), + _y + _decoder->getHeight()); ScaleInfo vmdScaleInfo; - if (!_blackoutRect.isEmpty() && !_planeSet) { + if (!_blackoutRect.isEmpty() && _planeIsOwned) { _blackoutPlane = new Plane(_blackoutRect); g_sci->_gfxFrameout->addPlane(*_blackoutPlane); } @@ -184,6 +226,11 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { vmdRect.bottom += vmdRect.height(); } + const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; + const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + BitmapResource vmdBitmap(_segMan, vmdRect.width(), vmdRect.height(), 255, 0, 0, screenWidth, screenHeight, 0, false); if (screenWidth != scriptWidth || screenHeight != scriptHeight) { @@ -194,7 +241,7 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { vmdCelInfo.bitmap = vmdBitmap.getObject(); _decoder->setSurfaceMemory(vmdBitmap.getPixels(), vmdBitmap.getWidth(), vmdBitmap.getHeight(), 1); - if (!_planeSet) { + if (_planeIsOwned) { _x = 0; _y = 0; _plane = new Plane(vmdRect, kPlanePicColored); @@ -237,8 +284,7 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { const int currentFrameNo = _decoder->getCurFrame(); - if ( - _yieldInterval > 0 && + if (_yieldInterval > 0 && currentFrameNo != _lastYieldedFrameNo && (currentFrameNo % _yieldInterval) == 0 ) { @@ -247,21 +293,35 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { break; } - if (flags & kEventFlagMouseDown && _eventMan->getSciEvent(SCI_EVENT_MOUSE_PRESS | SCI_EVENT_PEEK).type != SCI_EVENT_NONE) { + SciEvent event = _eventMan->getSciEvent(SCI_EVENT_MOUSE_PRESS | SCI_EVENT_PEEK); + if ((flags & kEventFlagMouseDown) && event.type == SCI_EVENT_MOUSE_PRESS) { stopFlag = kEventFlagMouseDown; break; } - if (flags & kEventFlagEscapeKey) { - const SciEvent event = _eventMan->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_PEEK); - if (event.type != SCI_EVENT_NONE && event.character == SCI_KEY_ESC) { + event = _eventMan->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_PEEK); + if ((flags & kEventFlagEscapeKey) && event.type == SCI_EVENT_KEYBOARD) { + bool stop = false; + if (getSciVersion() < SCI_VERSION_3) { + while ((event = _eventMan->getSciEvent(SCI_EVENT_KEYBOARD)), + event.type != SCI_EVENT_NONE) { + if (event.character == SCI_KEY_ESC) { + stop = true; + break; + } + } + } else { + stop = (event.character == SCI_KEY_ESC); + } + + if (stop) { stopFlag = kEventFlagEscapeKey; break; } } - if (flags & kEventFlagHotRectangle) { - // TODO: Hot rectangles + // TODO: Hot rectangles + if ((flags & kEventFlagHotRectangle) /* && event.type == SCI_EVENT_HOT_RECTANGLE */) { warning("Hot rectangles not implemented in VMD player"); stopFlag = kEventFlagHotRectangle; break; @@ -272,25 +332,8 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { return stopFlag; } -void VMDPlayer::fillPalette(Palette &palette) const { - const byte *vmdPalette = _decoder->getPalette() + _startColor * 3; - for (uint16 i = _startColor; i <= _endColor; ++i) { - int16 r = *vmdPalette++; - int16 g = *vmdPalette++; - int16 b = *vmdPalette++; - - if (_boostPercent != 100 && i >= _boostStartColor && i <= _boostEndColor) { - r = CLIP<int16>(r * _boostPercent / 100, 0, 255); - g = CLIP<int16>(g * _boostPercent / 100, 0, 255); - b = CLIP<int16>(b * _boostPercent / 100, 0, 255); - } - - palette.colors[i].r = r; - palette.colors[i].g = g; - palette.colors[i].b = b; - palette.colors[i].used = true; - } -} +#pragma mark - +#pragma mark VMDPlayer - Rendering void VMDPlayer::renderFrame() const { // This writes directly to the CelObjMem we already created, @@ -304,6 +347,7 @@ void VMDPlayer::renderFrame() const { const bool dirtyPalette = _decoder->hasDirtyPalette(); if (dirtyPalette) { Palette palette; + palette.timestamp = g_sci->getTickCount(); if (_blackPalette) { for (uint16 i = _startColor; i <= _endColor; ++i) { palette.colors[i].r = palette.colors[i].g = palette.colors[i].b = 0; @@ -331,45 +375,32 @@ void VMDPlayer::renderFrame() const { } } -VMDPlayer::IOStatus VMDPlayer::close() { - if (!_isOpen) { - return kIOSuccess; - } - - _decoder->close(); - _isOpen = false; - _isInitialized = false; - - if (_planeSet && _screenItem != nullptr) { - g_sci->_gfxFrameout->deleteScreenItem(*_screenItem); - _screenItem = nullptr; - } else if (_plane != nullptr) { - g_sci->_gfxFrameout->deletePlane(*_plane); - _plane = nullptr; - } - - if (!_leaveLastFrame && _leaveScreenBlack) { - // This call *actually* deletes the plane/screen item - g_sci->_gfxFrameout->frameOut(true); - } +void VMDPlayer::fillPalette(Palette &palette) const { + const byte *vmdPalette = _decoder->getPalette() + _startColor * 3; + for (uint16 i = _startColor; i <= _endColor; ++i) { + int16 r = *vmdPalette++; + int16 g = *vmdPalette++; + int16 b = *vmdPalette++; - if (_blackoutPlane != nullptr) { - g_sci->_gfxFrameout->deletePlane(*_blackoutPlane); - _blackoutPlane = nullptr; - } + if (_boostPercent != 100 && i >= _boostStartColor && i <= _boostEndColor) { + r = CLIP<int16>(r * _boostPercent / 100, 0, 255); + g = CLIP<int16>(g * _boostPercent / 100, 0, 255); + b = CLIP<int16>(b * _boostPercent / 100, 0, 255); + } - if (!_leaveLastFrame && !_leaveScreenBlack) { - // This call *actually* deletes the blackout plane - g_sci->_gfxFrameout->frameOut(true); + palette.colors[i].r = r; + palette.colors[i].g = g; + palette.colors[i].b = b; + palette.colors[i].used = true; } +} - if (!_showCursor) { - g_sci->_gfxCursor->kernelShow(); - } +#pragma mark - +#pragma mark VMDPlayer - Palette - _planeSet = false; - _priority = 0; - return kIOSuccess; +void VMDPlayer::restrictPalette(const uint8 startColor, const uint8 endColor) { + _startColor = startColor; + _endColor = endColor; } } // End of namespace Sci diff --git a/engines/sci/graphics/video32.h b/engines/sci/graphics/video32.h index d51316bfbd..cf863ba41d 100644 --- a/engines/sci/graphics/video32.h +++ b/engines/sci/graphics/video32.h @@ -29,6 +29,11 @@ class Plane; class ScreenItem; class SegManager; +#pragma mark VMDPlayer + +/** + * VMDPlayer is used to play VMD videos. + */ class VMDPlayer { public: enum OpenFlags { @@ -44,7 +49,6 @@ public: enum PlayFlags { kPlayFlagNone = 0, kPlayFlagDoublePixels = 1, - kPlayFlagNoFrameskip = 2, // NOTE: the current VMD decoder does not allow this kPlayFlagBlackLines = 4, kPlayFlagBoost = 0x10, kPlayFlagLeaveScreenBlack = 0x20, @@ -67,6 +71,14 @@ public: VMDPlayer(SegManager *segMan, EventManager *eventMan); ~VMDPlayer(); +private: + SegManager *_segMan; + EventManager *_eventMan; + Video::AdvancedVMDDecoder *_decoder; + +#pragma mark - +#pragma mark VMDPlayer - Playback +public: /** * Opens a stream to a VMD resource. */ @@ -83,33 +95,35 @@ public: */ IOStatus close(); - /** - * Restricts use of the system palette by VMD playback to - * the given range of palette indexes. - */ - void restrictPalette(const uint8 startColor, const uint8 endColor); - // NOTE: Was WaitForEvent in SSCI EventFlags kernelPlayUntilEvent(const EventFlags flags, const int16 lastFrameNo, const int16 yieldInterval); +private: /** - * Sets the area of the screen that should be blacked out - * during VMD playback. + * Whether or not a VMD stream has been opened with + * `open`. */ - void setBlackoutArea(const Common::Rect &rect) { _blackoutRect = rect; } + bool _isOpen; /** - * Sets whether or not the mouse cursor should be drawn. - * This does not have any effect during playback, but can - * be used to prevent the mouse cursor from being shown - * after the video has finished. + * Whether or not a VMD player has been initialised + * with `init`. */ - void setShowCursor(const bool shouldShow) { _showCursor = shouldShow; } + bool _isInitialized; -private: - SegManager *_segMan; - EventManager *_eventMan; - Video::AdvancedVMDDecoder *_decoder; + /** + * For VMDs played with the `kEventFlagYieldToVM` flag, + * the number of frames that should be rendered until + * yielding back to the SCI VM. + */ + int32 _yieldInterval; + + /** + * For VMDs played with the `kEventFlagYieldToVM` flag, + * the last frame when control of the main thread was + * yielded back to the SCI VM. + */ + int _lastYieldedFrameNo; /** * Plays the VMD until an event occurs (e.g. user @@ -117,41 +131,38 @@ private: */ EventFlags playUntilEvent(const EventFlags flags); +#pragma mark - +#pragma mark VMDPlayer - Rendering +private: /** - * Renders a frame of video to the output bitmap. + * The location of the VMD plane, in game script + * coordinates. */ - void renderFrame() const; + int16 _x, _y; /** - * Fills the given palette with RGB values from - * the VMD palette, applying brightness boost if - * it is enabled. + * The plane where the VMD will be drawn. */ - void fillPalette(Palette &palette) const; + Plane *_plane; /** - * Whether or not a VMD stream has been opened with - * `open`. + * The screen item representing the VMD surface. */ - bool _isOpen; + ScreenItem *_screenItem; - /** - * Whether or not a VMD player has been initialised - * with `init`. - */ - bool _isInitialized; + // TODO: planeIsOwned and priority are used in SCI3+ only /** - * Whether or not the playback area of the VMD - * should be left black at the end of playback. + * If true, the plane for this VMD was set + * externally and is not owned by this VMDPlayer. */ - bool _leaveScreenBlack; + bool _planeIsOwned; /** - * Whether or not the area of the VMD should be left - * displaying the final frame of the video. + * The screen priority of the video. + * @see ScreenItem::_priority */ - bool _leaveLastFrame; + int _priority; /** * Whether or not the video should be pixel doubled. @@ -171,24 +182,60 @@ private: bool _blackLines; /** - * The amount of brightness boost for the video. - * Values above 100 increase brightness; values below - * 100 reduce it. + * Whether or not the playback area of the VMD + * should be left black at the end of playback. */ - int16 _boostPercent; + bool _leaveScreenBlack; /** - * The first color in the palette that should be - * brightness boosted. + * Whether or not the area of the VMD should be left + * displaying the final frame of the video. */ - uint8 _boostStartColor; + bool _leaveLastFrame; /** - * The last color in the palette that should be - * brightness boosted. + * Renders a frame of video to the output bitmap. */ - uint8 _boostEndColor; + void renderFrame() const; + + /** + * Fills the given palette with RGB values from + * the VMD palette, applying brightness boost if + * it is enabled. + */ + void fillPalette(Palette &palette) const; + +#pragma mark - +#pragma mark VMDPlayer - Blackout +public: + /** + * Sets the area of the screen that should be blacked out + * during VMD playback. + */ + void setBlackoutArea(const Common::Rect &rect) { _blackoutRect = rect; } + +private: + /** + * The dimensions of the blackout plane. + */ + Common::Rect _blackoutRect; + + /** + * An optional plane that will be used to black out + * areas of the screen outside of the VMD surface. + */ + Plane *_blackoutPlane; + +#pragma mark - +#pragma mark VMDPlayer - Palette +public: + /** + * Restricts use of the system palette by VMD playback to + * the given range of palette indexes. + */ + void restrictPalette(const uint8 startColor, const uint8 endColor); +private: /** * The first color in the system palette that the VMD * can write to. @@ -209,62 +256,45 @@ private: */ bool _blackPalette; - // TODO: planeSet and priority are used in SCI3+ only - bool _planeSet; - - /** - * The screen priority of the video. - * @see ScreenItem::_priority - */ - int _priority; - +#pragma mark - +#pragma mark VMDPlayer - Brightness boost +private: /** - * The plane where the VMD will be drawn. + * The amount of brightness boost for the video. + * Values above 100 increase brightness; values below + * 100 reduce it. */ - Plane *_plane; + int16 _boostPercent; /** - * The screen item representing the VMD surface. + * The first color in the palette that should be + * brightness boosted. */ - ScreenItem *_screenItem; + uint8 _boostStartColor; /** - * An optional plane that will be used to black out - * areas of the screen outside the area of the VMD - * surface. + * The last color in the palette that should be + * brightness boosted. */ - Plane *_blackoutPlane; + uint8 _boostEndColor; +#pragma mark - +#pragma mark VMDPlayer - Mouse cursor +public: /** - * The dimensions of the blackout plane. + * Sets whether or not the mouse cursor should be drawn. + * This does not have any effect during playback, but can + * be used to prevent the mouse cursor from being shown + * again after the video has finished. */ - Common::Rect _blackoutRect; + void setShowCursor(const bool shouldShow) { _showCursor = shouldShow; } +private: /** * Whether or not the mouse cursor should be shown * during playback. */ bool _showCursor; - - /** - * The location of the VMD plane, in game script - * coordinates. - */ - int16 _x, _y; - - /** - * For VMDs played with the `kEventFlagYieldToVM` flag, - * the number of frames that should be drawn until - * yielding back to the SCI VM. - */ - int32 _yieldInterval; - - /** - * For VMDs played with the `kEventFlagYieldToVM` flag, - * the last frame when control of the main thread was - * yielded back to the SCI VM. - */ - int _lastYieldedFrameNo; }; class Video32 { |