From 430dc10c4944922894e32d1b29852794c9f27b7b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 22 Dec 2010 13:51:35 +0000 Subject: SCI: VMD video related changes - VMD videos are now properly started from the associated play subop of the kPlayVMD kernel call, and are now properly positioned on screen, and doubled only if the games require them to be - Added an enum for VMD video flags svn-id: r55003 --- engines/sci/console.cpp | 7 +++- engines/sci/engine/kvideo.cpp | 92 +++++++++++++++++++++---------------------- engines/sci/engine/state.cpp | 3 ++ engines/sci/engine/state.h | 29 +++++++++++++- 4 files changed, 82 insertions(+), 49 deletions(-) diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 21364319b8..cad6092cff 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -226,7 +226,7 @@ void Console::preEnter() { _engine->pauseEngine(true); } -extern void playVideo(Graphics::VideoDecoder *videoDecoder); +extern void playVideo(Graphics::VideoDecoder *videoDecoder, VideoState videoState); void Console::postEnter() { if (!_videoFile.empty()) { @@ -272,7 +272,10 @@ void Console::postEnter() { } #endif - playVideo(videoDecoder); + VideoState emptyState; + emptyState.fileName = _videoFile; + emptyState.flags = kDoubled; // always allow the videos to be double sized + playVideo(videoDecoder, emptyState); #ifdef ENABLE_SCI32 // Switch back to 8bpp if we played a duck video diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index b4c3c3bddf..fddfa3ba86 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -39,7 +39,7 @@ namespace Sci { -void playVideo(Graphics::VideoDecoder *videoDecoder) { +void playVideo(Graphics::VideoDecoder *videoDecoder, VideoState videoState) { if (!videoDecoder) return; @@ -50,16 +50,24 @@ void playVideo(Graphics::VideoDecoder *videoDecoder) { uint16 pitch = videoDecoder->getWidth() * bytesPerPixel; uint16 screenWidth = g_system->getWidth(); uint16 screenHeight = g_system->getHeight(); + bool isVMD = videoState.fileName.hasSuffix(".vmd"); - if (screenWidth == 640 && width <= 320 && height <= 240) { + if (screenWidth == 640 && width <= 320 && height <= 240 && ((videoState.flags & kDoubled) || !isVMD)) { width *= 2; height *= 2; pitch *= 2; scaleBuffer = new byte[width * height * bytesPerPixel]; } - uint16 x = (screenWidth - width) / 2; - uint16 y = (screenHeight - height) / 2; + uint16 x, y; + + if (videoState.x > 0 && videoState.y > 0 && isVMD) { + x = videoState.x; + y = videoState.y; + } else { + x = (screenWidth - width) / 2; + y = (screenHeight - height) / 2; + } bool skipVideo = false; if (videoDecoder->hasDirtyPalette()) @@ -172,7 +180,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { } if (videoDecoder) { - playVideo(videoDecoder); + playVideo(videoDecoder, s->_videoState); // HACK: Switch back to 8bpp if we played a QuickTime video. // We also won't be copying the screen to the SCI screen... @@ -196,32 +204,17 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { uint16 operation = argv[0].toUint16(); Graphics::VideoDecoder *videoDecoder = 0; bool reshowCursor = g_sci->_gfxCursor->isVisible(); - Common::String fileName, warningMsg; + Common::String warningMsg; switch (operation) { case 0: // init - // This is actually meant to init the video file, but we play it instead - fileName = s->_segMan->derefString(argv[1]); + s->_videoState.reset(); + s->_videoState.fileName = s->_segMan->derefString(argv[1]); // TODO: argv[2] (usually null). When it exists, it points to an "Event" object, // that holds no data initially (e.g. in the intro of Phantasmagoria 1 demo). // Perhaps it's meant for syncing if (argv[2] != NULL_REG) warning("kPlayVMD: third parameter isn't 0 (it's %04x:%04x - %s)", PRINT_REG(argv[2]), s->_segMan->getObjectName(argv[2])); - - videoDecoder = new Graphics::VMDDecoder(g_system->getMixer()); - - if (!videoDecoder->loadFile(fileName)) { - warning("Could not open VMD %s", fileName.c_str()); - break; - } - - if (reshowCursor) - g_sci->_gfxCursor->kernelHide(); - - playVideo(videoDecoder); - - if (reshowCursor) - g_sci->_gfxCursor->kernelShow(); break; case 1: { @@ -229,17 +222,6 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { // // x, y, flags, gammaBoost, gammaFirst, gammaLast // - // Flags are as follows: - // bit 0 doubled - // bit 1 "drop frames"? - // bit 2 insert black lines - // bit 3 unknown - // bit 4 gamma correction - // bit 5 hold black frame - // bit 6 hold last frame - // bit 7 unknown - // bit 8 stretch - // gammaBoost boosts palette colors in the range gammaFirst to // gammaLast, but only if bit 4 in flags is set. Percent value such that // 0% = no amplification These three parameters are optional if bit 4 is @@ -247,40 +229,58 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { // with subfx 21. The subtleness has to do with creation of temporary // planes and positioning relative to such planes. - int flags = argv[3].offset; + uint16 flags = argv[3].offset; Common::String flagspec; if (argc > 3) { - if (flags & 1) + if (flags & kDoubled) flagspec += "doubled "; - if (flags & 2) + if (flags & kDropFrames) flagspec += "dropframes "; - if (flags & 4) + if (flags & kBlackLines) flagspec += "blacklines "; - if (flags & 8) + if (flags & kUnkBit3) flagspec += "bit3 "; - if (flags & 16) + if (flags & kGammaBoost) flagspec += "gammaboost "; - if (flags & 32) + if (flags & kHoldBlackFrame) flagspec += "holdblack "; - if (flags & 64) + if (flags & kHoldLastFrame) flagspec += "holdlast "; - if (flags & 128) + if (flags & kUnkBit7) flagspec += "bit7 "; - if (flags & 256) + if (flags & kStretch) flagspec += "stretch"; warning("VMDFlags: %s", flagspec.c_str()); + + s->_videoState.flags = flags; } warning("x, y: %d, %d", argv[1].offset, argv[2].offset); + s->_videoState.x = argv[1].offset; + s->_videoState.y = argv[2].offset; if (argc > 4 && flags & 16) warning("gammaBoost: %d%% between palette entries %d and %d", argv[4].offset, argv[5].offset, argv[6].offset); break; } - case 6: - // Play, perhaps? Or stop? This is the last call made, and takes no extra parameters + case 6: // Play + videoDecoder = new Graphics::VMDDecoder(g_system->getMixer()); + + if (!videoDecoder->loadFile(s->_videoState.fileName)) { + warning("Could not open VMD %s", s->_videoState.fileName.c_str()); + break; + } + + if (reshowCursor) + g_sci->_gfxCursor->kernelHide(); + + playVideo(videoDecoder, s->_videoState); + + if (reshowCursor) + g_sci->_gfxCursor->kernelShow(); + break; case 14: // Takes an additional integer parameter (e.g. 3) case 16: diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 886b099a26..efcb826819 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -116,6 +116,9 @@ void EngineState::reset(bool isRestoring) { scriptStepCounter = 0; scriptGCInterval = GC_INTERVAL; + + _videoState.reset(); + _syncedAudioOptions = false; } void EngineState::speedThrottler(uint32 neededSleep) { diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index e5c9334315..fa79cc6930 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -113,6 +113,31 @@ public: bool isOpen() const; }; +enum VideoFlags { + kNone = 0, + kDoubled = 1 << 0, + kDropFrames = 1 << 1, + kBlackLines = 1 << 2, + kUnkBit3 = 1 << 3, + kGammaBoost = 1 << 4, + kHoldBlackFrame = 1 << 5, + kHoldLastFrame = 1 << 6, + kUnkBit7 = 1 << 7, + kStretch = 1 << 8 +}; + +struct VideoState { + Common::String fileName; + uint16 x; + uint16 y; + uint16 flags; + + void reset() { + fileName = ""; + x = y = 0; + } +}; + struct EngineState : public Common::Serializable { public: EngineState(SegManager *segMan); @@ -197,7 +222,6 @@ public: int gcCountDown; /**< Number of kernel calls until next gc */ -public: MessageState *_msgState; // MemorySegment provides access to a 256-byte block of memory that remains @@ -208,6 +232,9 @@ public: uint _memorySegmentSize; byte _memorySegment[kMemorySegmentMax]; + VideoState _videoState; + bool _syncedAudioOptions; + /** * Resets the engine state. */ -- cgit v1.2.3