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
This commit is contained in:
Filippos Karapetis 2010-12-22 13:51:35 +00:00
parent 5a3ed29a4b
commit 430dc10c49
4 changed files with 82 additions and 49 deletions

View File

@ -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

View File

@ -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:

View File

@ -116,6 +116,9 @@ void EngineState::reset(bool isRestoring) {
scriptStepCounter = 0;
scriptGCInterval = GC_INTERVAL;
_videoState.reset();
_syncedAudioOptions = false;
}
void EngineState::speedThrottler(uint32 neededSleep) {

View File

@ -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.
*/