Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

animation.cpp

/* 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-1/engines/agos/animation.cpp $
 * $Id: animation.cpp 30944 2008-02-23 22:50:18Z sev $
 *
 */



#include "common/endian.h"
#include "common/events.h"
#include "common/system.h"

#include "graphics/cursorman.h"
#include "graphics/surface.h"

#include "agos/animation.h"
#include "agos/intern.h"
#include "agos/agos.h"

#include "sound/audiostream.h"
#include "sound/wave.h"

namespace AGOS {

MoviePlayer::MoviePlayer(AGOSEngine *vm, Audio::Mixer *mixer)
      : DXAPlayer(), _vm(vm), _mixer(mixer) {
      _omniTV = false;

      _omniTVFile = 0;

      _leftButtonDown = false;
      _rightButtonDown = 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 (_fd) {
            _vm->setBitFlag(42, false);
            _omniTV = true;
            startSound();
      } else {
            if (_omniTVFile) {
                  // Restore state
                  _fd = _omniTVFile;
                  _mixer->pauseHandle(_omniTVSound, false);

                  _vm->setBitFlag(42, false);
                  _omniTV = true;
            } else {
                  _vm->_variableArray[254] = 6747;
            }
      }
}

void MoviePlayer::play() {
      if (_vm->getBitFlag(40)) {
            playOmniTV();
            return;
      }

      if (_omniTVFile) {
            // Clear any paused OmniTV video
            _mixer->stopHandle(_omniTVSound);
            delete _omniTVFile;
            _omniTVFile = 0;
      }

      _leftButtonDown = false;
      _rightButtonDown = false;

      _mixer->stopAll();

      // Resolution is smaller in Amiga verison so always clear screen
      if (_width == 384 && _height == 280) {
            _vm->clearSurfaces();
      }

      _ticks = _vm->_system->getMillis();

      startSound();

      while (_frameNum < _framesCount)
            handleNextFrame();

      closeFile();

      _vm->o_killAnimate();

      if (_vm->getBitFlag(41)) {
            _vm->fillBackFromFront();
      } else {
            uint8 palette[1024];
            memset(palette, 0, sizeof(palette));
            _vm->clearSurfaces();
            _vm->_system->setPalette(palette, 0, 256);
      }

       _vm->fillBackGroundFromBack();
      _vm->_fastFadeOutFlag = true;
}

void MoviePlayer::startSound() {
      byte *buffer;
      uint32 offset, size, tag;

      tag = _fd->readUint32BE();
      if (tag == MKID_BE('WAVE')) {
            size = _fd->readUint32BE();

            if (_sequenceNum) {
                  Common::File in;

                  _fd->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);
                  _fd->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 = _fd;
            _mixer->pauseHandle(_omniTVSound, true);

            _fd = 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)) {
            switch (event.type) {
            case Common::EVENT_KEYDOWN:
                  if (event.kbd.ascii == 27) {
                        _leftButtonDown = true;
                        _rightButtonDown = true;
                  }
                  break;
            case Common::EVENT_LBUTTONDOWN:
                  _leftButtonDown = true;
                  break;
            case Common::EVENT_RBUTTONDOWN:
                  _rightButtonDown = true;
                  break;
            case Common::EVENT_LBUTTONUP:
                  _leftButtonDown = false;
                  break;
            case Common::EVENT_RBUTTONUP:
                  _rightButtonDown = false;
                  break;
            case Common::EVENT_QUIT:
                  _vm->_system->quit();
                  break;
            default:
                  break;
            }
      }

      if (_leftButtonDown && _rightButtonDown && !_vm->getBitFlag(41)) {
            _frameNum = _framesCount;
            _mixer->stopHandle(_bgSound);
      }
}

void MoviePlayer::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 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] = {
      "agent32",
      "Airlock",
      "Badluck",
      "bentalk1",
      "bentalk2",
      "bentalk3",
      "BigFight",
      "BLOWLAB",
      "breakdown",
      "bridge",
      "button2",
      "cargo",
      "COACH",
      "Colatalk",
      "cygnus2",
      "dream",
      "escape2",
      "FASALL",
      "fbikewurb",
      "feebdel",
      "Feebohno",
      "feebpump",
      "feefone1",
      "feefone2",
      "founder2",
      "founder3",
      "founder4",
      "fxmadsam",
      "fxwakeup",
      "gate",
      "Get Car",
      "getaxe",
      "getlift",
      "icetrench",
      "intomb1",
      "intomb2",
      "Jackpot",
      "knockout",
      "labocto",
      "longfeeb",
      "Mainmin",
      "maznat",
      "meetsquid",
      "mflirt",
      "mfxHappy",
      "Mix_Feeb1",
      "Mix_Feeb2",
      "Mix_Feeb3",
      "Mix_Guardscn",
      "Mlights1",
      "MLights2",
      "MProtest",
      "mudman",
      "munlock",
      "MUS5P2",
      "MUSOSP1",
      "Omenter",
      "Omnicofe",
      "OUTMIN~1",
      "Readbook",
      "Rebelhq",
      "RebelHQ2",
      "Reedin",
      "rescue1",
      "rescue2",
      "samcar",
      "Samdead",
      "scanner",
      "Sleepy",
      "spitbrai",
      "statue1",
      "statue2",
      "sva1",
      "sva2",
      "Teeter",
      "Temple2",
      "Temple3",
      "Temple4",
      "Temple5",
      "Temple6",
      "Temple7",
      "Temple8",
      "Tic-tac2",
      "torture",
      "transmit",
      "Typey",
      "ventfall",
      "ventoff",
      "wasting",
      "wurbatak"
};

} // End of namespace AGOS

Generated by  Doxygen 1.6.0   Back to index