aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/console.cpp7
-rw-r--r--engines/sci/engine/kvideo.cpp92
-rw-r--r--engines/sci/engine/state.cpp3
-rw-r--r--engines/sci/engine/state.h29
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.
*/