mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-15 22:38:09 +00:00
b6017da9e2
it won't necessarily be played at the same position every time. For instance, in Lost in Time you can look at the captain's chair several times. The position of the video seems to depend on exactly where on the screen you clicked. svn-id: r28668
346 lines
8.2 KiB
C++
346 lines
8.2 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "gob/videoplayer.h"
|
|
#include "gob/global.h"
|
|
#include "gob/util.h"
|
|
#include "gob/dataio.h"
|
|
#include "gob/video.h"
|
|
#include "gob/draw.h"
|
|
#include "gob/game.h"
|
|
#include "gob/palanim.h"
|
|
#include "gob/inter.h"
|
|
|
|
namespace Gob {
|
|
|
|
const char *VideoPlayer::_extensions[] = { "IMD", "VMD" };
|
|
|
|
VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm) {
|
|
_curFile[0] = 0;
|
|
_stream = 0;
|
|
_video = 0;
|
|
_backSurf = false;
|
|
}
|
|
|
|
VideoPlayer::~VideoPlayer() {
|
|
closeVideo();
|
|
}
|
|
|
|
bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Type which) {
|
|
char fileName[256];
|
|
|
|
strncpy0(fileName, video, 250);
|
|
|
|
char *extStart = strrchr(fileName, '.');
|
|
// There's no empty extension
|
|
if (extStart == (fileName + strlen(fileName) - 1)) {
|
|
*extStart = 0;
|
|
extStart = 0;
|
|
}
|
|
|
|
if (extStart) {
|
|
// The requested file already has an extension. Verifying.
|
|
|
|
int i;
|
|
for (i = 0; i < ARRAYSIZE(_extensions); i++) {
|
|
if (!scumm_stricmp(extStart + 1, _extensions[i])) {
|
|
if ((which != kVideoTypeTry) && (which == ((Type) i))) {
|
|
warning("Attempted to open video \"%s\", "
|
|
"but requested a different type", fileName);
|
|
return false;
|
|
}
|
|
which = (Type) i;
|
|
break;
|
|
}
|
|
}
|
|
if (i >= ARRAYSIZE(_extensions))
|
|
extStart = 0;
|
|
|
|
}
|
|
|
|
if (!extStart) {
|
|
// No or unrecognized extension. Probing.
|
|
|
|
int len = strlen(fileName);
|
|
|
|
int i;
|
|
for (i = 0; i < ARRAYSIZE(_extensions); i++) {
|
|
if ((which == kVideoTypeTry) || (which == ((Type) i))) {
|
|
int16 handle;
|
|
|
|
fileName[len] = '.';
|
|
fileName[len + 1] = 0;
|
|
strcat(fileName, _extensions[i]);
|
|
|
|
handle = _vm->_dataIO->openData(fileName);
|
|
if (handle >= 0) {
|
|
_vm->_dataIO->closeData(handle);
|
|
which = (Type) i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ((i >= ARRAYSIZE(_extensions)) || (which == kVideoTypeTry)) {
|
|
fileName[len] = 0;
|
|
warning("Couldn't open video \"%s\"", fileName);
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
if (scumm_strnicmp(_curFile, fileName, strlen(fileName))) {
|
|
closeVideo();
|
|
|
|
int16 handle = _vm->_dataIO->openData(fileName);
|
|
|
|
if (handle < 0) {
|
|
warning("Couldn't open video \"%s\": No such file", fileName);
|
|
return false;
|
|
}
|
|
|
|
_stream = _vm->_dataIO->openAsStream(handle, true);
|
|
|
|
if (which == kVideoTypeIMD) {
|
|
_video = new Imd();
|
|
} else if (which == kVideoTypeVMD) {
|
|
_video = new Vmd();
|
|
} else {
|
|
warning("Couldn't open video \"%s\": Invalid video Type", fileName);
|
|
closeVideo();
|
|
return false;
|
|
}
|
|
|
|
if (!_video->load(*_stream)) {
|
|
warning("While loading video \"%s\"", fileName);
|
|
closeVideo();
|
|
return false;
|
|
}
|
|
|
|
strcpy(_curFile, fileName);
|
|
|
|
if (!(flags & kFlagNoVideo)) {
|
|
_backSurf = ((flags & kFlagFrontSurface) == 0);
|
|
SurfaceDesc::Ptr surf = _vm->_draw->_spritesArray[_backSurf ? 21 : 20];
|
|
_video->setVideoMemory(surf->getVidMem(), surf->getWidth(), surf->getHeight());
|
|
} else
|
|
_video->setVideoMemory();
|
|
|
|
_video->enableSound(*_vm->_mixer);
|
|
}
|
|
|
|
if (!_video)
|
|
return false;
|
|
|
|
_video->setXY(x, y);
|
|
WRITE_VAR(7, _video->getFramesCount());
|
|
|
|
return true;
|
|
}
|
|
|
|
void VideoPlayer::play(int16 startFrame, int16 lastFrame, int16 breakKey,
|
|
uint16 palCmd, int16 palStart, int16 palEnd,
|
|
int16 palFrame, int16 endFrame, bool fade, int16 reverseTo) {
|
|
|
|
if (!_video)
|
|
return;
|
|
|
|
breakKey = 27;
|
|
if (startFrame < 0)
|
|
startFrame = _video->getCurrentFrame();
|
|
if (lastFrame < 0)
|
|
lastFrame = _video->getFramesCount() - 1;
|
|
if (palFrame < 0)
|
|
palFrame = startFrame;
|
|
if (endFrame < 0)
|
|
endFrame = lastFrame;
|
|
palCmd &= 0x3F;
|
|
|
|
if (_video->getCurrentFrame() != startFrame) {
|
|
if (_video->getFeatures() & CoktelVideo::kFeaturesSound)
|
|
startFrame = _video->getCurrentFrame();
|
|
else
|
|
_video->seekFrame(startFrame);
|
|
}
|
|
|
|
_vm->_draw->_showCursor = 0;
|
|
_vm->_util->setFrameRate(12);
|
|
|
|
if (fade)
|
|
_vm->_palAnim->fade(0, -2, 0);
|
|
|
|
while (startFrame <= lastFrame) {
|
|
if (doPlay(startFrame, breakKey, palCmd, palStart, palEnd, palFrame, endFrame))
|
|
break;
|
|
|
|
if (fade) {
|
|
_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
|
|
fade = false;
|
|
}
|
|
|
|
_video->waitEndFrame();
|
|
startFrame++;
|
|
}
|
|
|
|
if (reverseTo >= 0) {
|
|
int16 toFrame = _video->getFramesCount() - reverseTo;
|
|
for (int i = _video->getCurrentFrame(); i >= toFrame; i--) {
|
|
_video->seekFrame(i, SEEK_SET, true);
|
|
if (doPlay(i, breakKey, 0, 0, 0, 0, 0)) {
|
|
_vm->_palAnim->fade(0, -2, 0);
|
|
memset((char *) _vm->_draw->_vgaPalette, 0, 768);
|
|
}
|
|
_video->waitEndFrame();
|
|
}
|
|
}
|
|
}
|
|
|
|
int16 VideoPlayer::getFramesCount() const {
|
|
if (!_video)
|
|
return 0;
|
|
|
|
return _video->getFramesCount();
|
|
}
|
|
|
|
int16 VideoPlayer::getCurrentFrame() const {
|
|
if (!_video)
|
|
return 0;
|
|
|
|
return _video->getCurrentFrame();
|
|
}
|
|
|
|
bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
|
|
uint16 palCmd, int16 palStart, int16 palEnd,
|
|
int16 palFrame, int16 endFrame) {
|
|
|
|
bool modifiedPal = false;
|
|
|
|
if ((frame == palFrame) || ((frame == endFrame) && (palCmd == 8))) {
|
|
modifiedPal = true;
|
|
_vm->_draw->_applyPal = true;
|
|
|
|
if (palCmd >= 4)
|
|
copyPalette(palStart, palEnd);
|
|
}
|
|
|
|
if (modifiedPal && (palCmd == 8) && !_backSurf)
|
|
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
|
|
|
|
|
|
CoktelVideo::State state = _video->nextFrame();
|
|
WRITE_VAR(11, frame);
|
|
|
|
|
|
if (modifiedPal && (palCmd == 16)) {
|
|
if (_backSurf)
|
|
_vm->_draw->forceBlit();
|
|
_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
|
|
_vm->_draw->_noInvalidated = true;
|
|
}
|
|
|
|
if (state.flags & CoktelVideo::kStatePalette) {
|
|
copyPalette(palStart, palEnd);
|
|
|
|
if (!_backSurf)
|
|
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
|
|
else
|
|
_vm->_draw->_applyPal = true;
|
|
}
|
|
|
|
if (modifiedPal && (palCmd == 8) && _backSurf)
|
|
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
|
|
|
|
|
|
if (_backSurf) {
|
|
_vm->_draw->invalidateRect(state.left, state.top, state.right, state.bottom);
|
|
_vm->_draw->blitInvalidated();
|
|
}
|
|
_vm->_video->retrace();
|
|
|
|
|
|
if (modifiedPal && ((palCmd == 2) || (palCmd == 4)))
|
|
_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
|
|
|
|
|
|
_vm->_util->processInput();
|
|
|
|
if (_vm->_quitRequested) {
|
|
_video->disableSound();
|
|
return true;
|
|
}
|
|
|
|
if (breakKey != 0) {
|
|
_vm->_util->getMouseState(&_vm->_global->_inter_mouseX,
|
|
&_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons);
|
|
|
|
_vm->_inter->storeKey(_vm->_util->checkKey());
|
|
if (VAR(0) == (unsigned) breakKey) {
|
|
_video->disableSound();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void VideoPlayer::copyPalette(int16 palStart, int16 palEnd) {
|
|
if ((palStart == -1) || (palEnd == -1))
|
|
memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
|
|
_video->getPalette(), 768);
|
|
else
|
|
memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) +
|
|
palStart * 3, _video->getPalette() + palStart * 3,
|
|
(palEnd - palStart + 1) * 3);
|
|
}
|
|
|
|
void VideoPlayer::writeVideoInfo(const char *video, int16 varX, int16 varY,
|
|
int16 varFrames, int16 varWidth, int16 varHeight) {
|
|
|
|
if (openVideo(video)) {
|
|
WRITE_VAR_OFFSET(varX, _video->getX());
|
|
WRITE_VAR_OFFSET(varY, _video->getY());
|
|
WRITE_VAR_OFFSET(varFrames, _video->getFramesCount());
|
|
WRITE_VAR_OFFSET(varWidth, _video->getWidth());
|
|
WRITE_VAR_OFFSET(varHeight, _video->getHeight());
|
|
closeVideo();
|
|
} else {
|
|
WRITE_VAR_OFFSET(varX, -1);
|
|
WRITE_VAR_OFFSET(varY, -1);
|
|
WRITE_VAR_OFFSET(varFrames, -1);
|
|
WRITE_VAR_OFFSET(varWidth, -1);
|
|
WRITE_VAR_OFFSET(varHeight, -1);
|
|
}
|
|
}
|
|
|
|
void VideoPlayer::closeVideo() {
|
|
delete _video;
|
|
delete _stream;
|
|
|
|
_video = 0;
|
|
_stream = 0;
|
|
*_curFile = 0;
|
|
}
|
|
|
|
} // End of namespace Gob
|