From 76624fc69c28bc422076740521e77f2ba83a2320 Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Sun, 21 Dec 2008 04:36:11 +0000 Subject: Add initial Smacker support for The Feeble Files. svn-id: r35457 --- engines/agos/animation.cpp | 553 +++++++++++++++++++++++++++------------------ 1 file changed, 329 insertions(+), 224 deletions(-) (limited to 'engines/agos/animation.cpp') diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp index 328aa75acc..d6e5a1f414 100644 --- a/engines/agos/animation.cpp +++ b/engines/agos/animation.cpp @@ -41,120 +41,41 @@ namespace AGOS { -MoviePlayer::MoviePlayer(AGOSEngine *vm, Audio::Mixer *mixer) - : DXAPlayer(), _vm(vm), _mixer(mixer) { - _omniTV = false; - - _omniTVFile = 0; +MoviePlayer::MoviePlayer(AGOSEngine *vm) + : _vm(vm) { + _mixer = _vm->_mixer; _leftButtonDown = false; _rightButtonDown = false; + _skipMovie = false; memset(baseName, 0, sizeof(baseName)); - _sequenceNum = 0; _ticks = 0; } -bool MoviePlayer::load(const char *filename) { - char videoName[20]; - uint i; - - int baseLen = strlen(filename) - 4; - memset(baseName, 0, sizeof(baseName)); - memcpy(baseName, filename, baseLen); - - // Change file extension to dxa - sprintf(videoName, "%s.dxa", baseName); - - if (!loadFile(videoName)) { - // Check short filename to work around - // bug in a German Windows 2CD version. - if (baseLen >= 8) { - char shortName[20]; - memset(shortName, 0, sizeof(shortName)); - memcpy(shortName, filename, 6); - - sprintf(shortName, "%s~1.dxa", shortName); - - if (!loadFile(shortName)) - error("Failed to load video file %s or %s", videoName, shortName); - - memset(baseName, 0, sizeof(baseName)); - memcpy(baseName, shortName, 8); - debug(0, "Playing video %s", shortName); - } else { - error("Failed to load video file %s", videoName); - } - } else { - debug(0, "Playing video %s", videoName); - } - - CursorMan.showMouse(false); - - if ((_vm->getPlatform() == Common::kPlatformAmiga || _vm->getPlatform() == Common::kPlatformMacintosh) && - _vm->_language != Common::EN_ANY) { - _sequenceNum = 0; - for (i = 0; i < 90; i++) { - if (!scumm_stricmp(baseName, _sequenceList[i])) - _sequenceNum = i; - } - } - - return true; -} - -void MoviePlayer::playOmniTV() { - // Load OmniTV video - if (_fileStream) { - _vm->setBitFlag(42, false); - _omniTV = true; - startSound(); - } else { - if (_omniTVFile) { - // Restore state - _fileStream = _omniTVFile; - _mixer->pauseHandle(_omniTVSound, false); - - _vm->setBitFlag(42, false); - _omniTV = true; - } else { - _vm->_variableArray[254] = 6747; - } - } +MoviePlayer::~MoviePlayer() { } void MoviePlayer::play() { if (_vm->getBitFlag(40)) { - playOmniTV(); + _vm->setBitFlag(42, false); + startSound(); return; } - if (_omniTVFile) { - // Clear any paused OmniTV video - _mixer->stopHandle(_omniTVSound); - delete _omniTVFile; - _omniTVFile = 0; - } - _leftButtonDown = false; _rightButtonDown = false; + _skipMovie = false; - _mixer->stopAll(); - - // Resolution is smaller in Amiga verison so always clear screen - if (_width == 384 && _height == 280) { - _vm->clearSurfaces(); - } + _vm->_mixer->stopAll(); _ticks = _vm->_system->getMillis(); startSound(); - while (_frameNum < _framesCount && !_vm->shouldQuit()) - handleNextFrame(); - - closeFile(); + playVideo(); + stopVideo(); _vm->o_killAnimate(); @@ -171,92 +92,7 @@ void MoviePlayer::play() { _vm->_fastFadeOutFlag = true; } -void MoviePlayer::startSound() { - byte *buffer; - uint32 offset, size, tag; - - tag = _fileStream->readUint32BE(); - if (tag == MKID_BE('WAVE')) { - size = _fileStream->readUint32BE(); - - if (_sequenceNum) { - Common::File in; - - _fileStream->seek(size, SEEK_CUR); - - in.open((const char *)"audio.wav"); - if (!in.isOpen()) { - error("Can't read offset file 'audio.wav'"); - } - - in.seek(_sequenceNum * 8, SEEK_SET); - offset = in.readUint32LE(); - size = in.readUint32LE(); - - buffer = (byte *)malloc(size); - in.seek(offset, SEEK_SET); - in.read(buffer, size); - in.close(); - } else { - buffer = (byte *)malloc(size); - _fileStream->read(buffer, size); - } - - Common::MemoryReadStream stream(buffer, size); - _bgSoundStream = Audio::makeWAVStream(stream); - free(buffer); - } else { - _bgSoundStream = Audio::AudioStream::openStreamFile(baseName); - } - - if (_bgSoundStream != NULL) { - if (_omniTV) { - _mixer->stopHandle(_omniTVSound); - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_omniTVSound, _bgSoundStream); - } else { - _mixer->stopHandle(_bgSound); - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_bgSound, _bgSoundStream); - } - } -} - -void MoviePlayer::nextFrame() { - if (!_omniTV) - return; - - if (_vm->getBitFlag(42)) { - // Save state - _omniTVFile = _fileStream; - _mixer->pauseHandle(_omniTVSound, true); - - _fileStream = 0; - _omniTV = false; - return; - } - - if (_mixer->isSoundHandleActive(_bgSound) && (_mixer->getSoundElapsedTime(_bgSound) * _framesPerSec) / 1000 < _frameNum) { - copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth); - return; - } - - if (_frameNum < _framesCount) { - decodeNextFrame(); - copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth); - _frameNum++; - } else { - _omniTV = false; - _omniTVFile = 0; - closeFile(); - _vm->_variableArray[254] = 6747; - } -} - void MoviePlayer::handleNextFrame() { - decodeNextFrame(); - if (processFrame()) - _vm->_system->updateScreen(); - _frameNum++; - Common::Event event; Common::EventManager *eventMan = _vm->_system->getEventManager(); while (eventMan->pollEvent(event)) { @@ -285,60 +121,16 @@ void MoviePlayer::handleNextFrame() { } if (_leftButtonDown && _rightButtonDown && !_vm->getBitFlag(41)) { - _frameNum = _framesCount; + _skipMovie = true; _mixer->stopHandle(_bgSound); } } -void MoviePlayer::setPalette(byte *pal) { - byte palette[1024]; - byte *p = palette; +/////////////////////////////////////////////////////////////////////////////// +// Movie player for DXA movies +/////////////////////////////////////////////////////////////////////////////// - for (int i = 0; i < 256; i++) { - *p++ = *pal++; - *p++ = *pal++; - *p++ = *pal++; - *p++ = 0; - } - - _vm->_system->setPalette(palette, 0, 256); -} - -bool MoviePlayer::processFrame() { - Graphics::Surface *screen = _vm->_system->lockScreen(); - copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - _width) / 2, (_vm->_screenHeight - _height) / 2, _vm->_screenWidth); - _vm->_system->unlockScreen(); - - if ((_bgSoundStream == NULL) || ((int)(_mixer->getSoundElapsedTime(_bgSound) * _framesPerSec) / 1000 < _frameNum + 1) || - _frameSkipped > _framesPerSec) { - if (_frameSkipped > _framesPerSec) { - warning("force frame %i redraw", _frameNum); - _frameSkipped = 0; - } - - if (_bgSoundStream && _mixer->isSoundHandleActive(_bgSound)) { - while (_mixer->isSoundHandleActive(_bgSound) && (_mixer->getSoundElapsedTime(_bgSound) * _framesPerSec) / 1000 < _frameNum) { - _vm->_system->delayMillis(10); - } - // In case the background sound ends prematurely, update - // _ticks so that we can still fall back on the no-sound - // sync case for the subsequent frames. - _ticks = _vm->_system->getMillis(); - } else { - _ticks += _frameTicks; - while (_vm->_system->getMillis() < _ticks) - _vm->_system->delayMillis(10); - } - - return true; - } - - warning("dropped frame %i", _frameNum); - _frameSkipped++; - return false; -} - -const char * MoviePlayer::_sequenceList[90] = { +const char * MoviePlayerDXA::_sequenceList[90] = { "agent32", "Airlock", "Badluck", @@ -431,4 +223,317 @@ const char * MoviePlayer::_sequenceList[90] = { "wurbatak" }; +MoviePlayerDXA::MoviePlayerDXA(AGOSEngine *vm, const char *name) + : MoviePlayer(vm) { + debug(0, "Creating DXA cutscene player"); + + memset(baseName, 0, sizeof(baseName)); + memcpy(baseName, name, strlen(name)); + + _sequenceNum = 0; +} + +bool MoviePlayerDXA::load() { + char videoName[20]; + uint i; + + if ((_vm->getPlatform() == Common::kPlatformAmiga || _vm->getPlatform() == Common::kPlatformMacintosh) && + _vm->_language != Common::EN_ANY) { + _sequenceNum = 0; + for (i = 0; i < 90; i++) { + if (!scumm_stricmp(baseName, _sequenceList[i])) + _sequenceNum = i; + } + } + + sprintf(videoName, "%s.dxa", baseName); + if (!loadFile(videoName)) + error("Failed to load video file %s", videoName); + + debug(0, "Playing video %s", videoName); + + CursorMan.showMouse(false); + + return true; +} + +void MoviePlayerDXA::playVideo() { + while (_frameNum < _framesCount && !_skipMovie && !_vm->shouldQuit()) + handleNextFrame(); +} + +void MoviePlayerDXA::stopVideo() { + closeFile(); + _mixer->stopHandle(_bgSound); +} + +void MoviePlayerDXA::startSound() { + byte *buffer; + uint32 offset, size, tag; + + tag = _fileStream->readUint32BE(); + if (tag == MKID_BE('WAVE')) { + size = _fileStream->readUint32BE(); + + if (_sequenceNum) { + Common::File in; + + _fileStream->seek(size, SEEK_CUR); + + in.open((const char *)"audio.wav"); + if (!in.isOpen()) { + error("Can't read offset file 'audio.wav'"); + } + + in.seek(_sequenceNum * 8, SEEK_SET); + offset = in.readUint32LE(); + size = in.readUint32LE(); + + buffer = (byte *)malloc(size); + in.seek(offset, SEEK_SET); + in.read(buffer, size); + in.close(); + } else { + buffer = (byte *)malloc(size); + _fileStream->read(buffer, size); + } + + Common::MemoryReadStream stream(buffer, size); + _bgSoundStream = Audio::makeWAVStream(stream); + free(buffer); + } else { + _bgSoundStream = Audio::AudioStream::openStreamFile(baseName); + } + + if (_bgSoundStream != NULL) { + _vm->_mixer->stopHandle(_bgSound); + _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_bgSound, _bgSoundStream); + } +} + +void MoviePlayerDXA::nextFrame() { + if (_vm->_mixer->isSoundHandleActive(_bgSound) && (_vm->_mixer->getSoundElapsedTime(_bgSound) * _framesPerSec) / 1000 < _frameNum) { + copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth); + return; + } + + if (_frameNum < _framesCount) { + decodeNextFrame(); + copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth); + } else { + closeFile(); + _vm->_variableArray[254] = 6747; + } +} + +void MoviePlayerDXA::handleNextFrame() { + decodeNextFrame(); + if (processFrame()) + _vm->_system->updateScreen(); + + MoviePlayer::handleNextFrame(); +} + +void MoviePlayerDXA::setPalette(byte *pal) { + byte palette[1024]; + byte *p = palette; + + for (int i = 0; i < 256; i++) { + *p++ = *pal++; + *p++ = *pal++; + *p++ = *pal++; + *p++ = 0; + } + + _vm->_system->setPalette(palette, 0, 256); +} + +bool MoviePlayerDXA::processFrame() { + Graphics::Surface *screen = _vm->_system->lockScreen(); + copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - _width) / 2, (_vm->_screenHeight - _height) / 2, _vm->_screenWidth); + _vm->_system->unlockScreen(); + + if ((_bgSoundStream == NULL) || ((int)(_mixer->getSoundElapsedTime(_bgSound) * _framesPerSec) / 1000 < _frameNum + 1) || + _frameSkipped > _framesPerSec) { + if (_frameSkipped > _framesPerSec) { + warning("force frame %i redraw", _frameNum); + _frameSkipped = 0; + } + + if (_bgSoundStream && _mixer->isSoundHandleActive(_bgSound)) { + while (_mixer->isSoundHandleActive(_bgSound) && (_mixer->getSoundElapsedTime(_bgSound) * _framesPerSec) / 1000 < _frameNum) { + _vm->_system->delayMillis(10); + } + // In case the background sound ends prematurely, update + // _ticks so that we can still fall back on the no-sound + // sync case for the subsequent frames. + _ticks = _vm->_system->getMillis(); + } else { + _ticks += _frameTicks; + while (_vm->_system->getMillis() < _ticks) + _vm->_system->delayMillis(10); + } + + return true; + } + + warning("dropped frame %i", _frameNum); + _frameSkipped++; + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// Movie player for Smacker movies +/////////////////////////////////////////////////////////////////////////////// + + +MoviePlayerSMK::MoviePlayerSMK(AGOSEngine *vm, const char *name) + : MoviePlayer(vm), SMKPlayer(vm->_mixer) { + debug(0, "Creating SMK cutscene player"); + + memset(baseName, 0, sizeof(baseName)); + memcpy(baseName, name, strlen(name)); +} + +bool MoviePlayerSMK::load() { + char videoName[20]; + + sprintf(videoName, "%s.smk", baseName); + if (!loadFile(videoName)) + error("Failed to load video file %s", videoName); + + debug(0, "Playing video %s", videoName); + + CursorMan.showMouse(false); + + return true; +} + +void MoviePlayerSMK::playVideo() { + while (getCurFrame() < getFrameCount() && !_skipMovie && !_vm->shouldQuit()) + handleNextFrame(); +} + +void MoviePlayerSMK::stopVideo() { + closeFile(); +} + +void MoviePlayerSMK::startSound() { +} + +void MoviePlayerSMK::handleNextFrame() { + decodeNextFrame(); + if (processFrame()) + _vm->_system->updateScreen(); + + MoviePlayer::handleNextFrame(); +} + +void MoviePlayerSMK::nextFrame() { + if (_vm->getBitFlag(42)) { + closeFile(); + return; + } + + if (getCurFrame() < getFrameCount()) { + decodeNextFrame(); + copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth); + } else { + closeFile(); + _vm->_variableArray[254] = 6747; + } +} + +void MoviePlayerSMK::setPalette(byte *pal) { + byte palette[1024]; + byte *p = palette; + + for (int i = 0; i < 256; i++) { + *p++ = *pal++; + *p++ = *pal++; + *p++ = *pal++; + *p++ = 0; + } + + _vm->_system->setPalette(palette, 0, 256); +} + +bool MoviePlayerSMK::processFrame() { + Graphics::Surface *screen = _vm->_system->lockScreen(); + copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth); + _vm->_system->unlockScreen(); + + if (!getAudioLag() || getAudioLag() > 0 || _frameSkipped > getFrameRate()) { + if (_frameSkipped > getFrameRate()) { + warning("force frame %i redraw", getCurFrame()); + _frameSkipped = 0; + } + + if (getAudioLag() > 0) { + while (getAudioLag() > 0) { + _vm->_system->delayMillis(10); + } + // In case the background sound ends prematurely, update + // _ticks so that we can still fall back on the no-sound + // sync case for the subsequent frames. + _ticks = _vm->_system->getMillis(); + } else { + _ticks += getFrameDelay(); + while (_vm->_system->getMillis() < _ticks) + _vm->_system->delayMillis(10); + } + + return true; + } + + warning("dropped frame %i", getCurFrame()); + _frameSkipped++; + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// Factory function for creating the appropriate cutscene player +/////////////////////////////////////////////////////////////////////////////// + +MoviePlayer *makeMoviePlayer(AGOSEngine *vm, const char *name) { + char baseName[40]; + char filename[20]; + + int baseLen = strlen(name) - 4; + memset(baseName, 0, sizeof(baseName)); + memcpy(baseName, name, baseLen); + + if (vm->getLanguage() == Common::DE_DEU && baseLen >= 8) { + // Check short filename to work around + // bug in a German Windows 2CD version. + char shortName[20]; + memset(shortName, 0, sizeof(shortName)); + memcpy(shortName, filename, 6); + + sprintf(filename, "%s~1.dxa", shortName); + if (Common::File::exists(filename)) { + memset(baseName, 0, sizeof(baseName)); + memcpy(baseName, shortName, 8); + } + + sprintf(filename, "%s~1.smk", shortName); + if (Common::File::exists(filename)) { + memset(baseName, 0, sizeof(baseName)); + memcpy(baseName, shortName, 8); + } + } + + sprintf(filename, "%s.dxa", baseName); + if (Common::File::exists(filename)) { + return new MoviePlayerDXA(vm, baseName); + } + + sprintf(filename, "%s.smk", baseName); + if (Common::File::exists(filename)) { + return new MoviePlayerSMK(vm, baseName); + } + + return NULL; +} + } // End of namespace AGOS -- cgit v1.2.3