Ticket #8948: sword_smk_latest.patch

File sword_smk_latest.patch, 52.8 KB (added by bluegr, 16 years ago)

Patch against the latest SVN

  • engines/sword1/animation.cpp

     
    2727#include "common/file.h"
    2828#include "sword1/sword1.h"
    2929#include "sword1/animation.h"
    30 #include "sword1/credits.h"
    3130#include "sword1/text.h"
    3231#include "sound/vorbis.h"
    3332
     
    3635#include "common/str.h"
    3736#include "common/events.h"
    3837#include "common/system.h"
     38#include "common/list.h"
    3939#include "graphics/surface.h"
    4040
     41#include "gui/message.h"
     42
    4143namespace Sword1 {
    4244
    4345static const char *sequenceList[20] = {
     
    6769// Basic movie player
    6870///////////////////////////////////////////////////////////////////////////////
    6971
    70 MoviePlayer::MoviePlayer(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system)
    71         : _vm(vm), _screen(screen), _textMan(textMan), _snd(snd), _system(system) {
     72MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Graphics::VideoDecoder *decoder, DecoderType decoderType)
     73        : _vm(vm), _textMan(textMan), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system), VideoPlayer(decoder) {
    7274        _bgSoundStream = NULL;
    73         _ticks = 0;
    74         _black = 1;
    75         _white = 255;
    76         _currentFrame = 0;
    77         _forceFrame = false;
    78         _framesSkipped = 0;
     75        _decoderType = decoderType;
    7976}
    8077
    8178MoviePlayer::~MoviePlayer(void) {
     79        delete(_decoder);
    8280}
    8381
    84 void MoviePlayer::updatePalette(byte *pal, bool packed) {
    85         byte palette[4 * 256];
    86         byte *p = palette;
    87 
    88         uint32 maxWeight = 0;
    89         uint32 minWeight = 0xFFFFFFFF;
    90 
    91         for (int i = 0; i < 256; i++) {
    92                 int r = *pal++;
    93                 int g = *pal++;
    94                 int b = *pal++;
    95 
    96                 if (!packed)
    97                         pal++;
    98 
    99                 uint32 weight = 3 * r * r + 6 * g * g + 2 * b * b;
    100 
    101                 if (weight >= maxWeight) {
    102                         _white = i;
    103                         maxWeight = weight;
    104                 }
    105 
    106                 if (weight <= minWeight) {
    107                         _black = i;
    108                         minWeight = i;
    109                 }
    110 
    111                 *p++ = r;
    112                 *p++ = g;
    113                 *p++ = b;
    114                 *p++ = 0;
    115         }
    116 
    117         _system->setPalette(palette, 0, 256);
    118         _forceFrame = true;
    119 }
    120 
    121 void MoviePlayer::handleScreenChanged(void) {
    122 }
    123 
    124 bool MoviePlayer::initOverlays(uint32 id) {
    125         return true;
    126 }
    127 
    128 bool MoviePlayer::checkSkipFrame(void) {
    129         if (_forceFrame) {
    130                 _forceFrame = false;
    131                 return false;
    132         }
    133         if (_framesSkipped > 10) {
    134                 warning("Forced frame %d to be displayed", _currentFrame);
    135                 _framesSkipped = 0;
    136                 return false;
    137         }
    138         if (_bgSoundStream) {
    139                 if ((_snd->getSoundElapsedTime(_bgSoundHandle) * 12) / 1000 < _currentFrame + 1)
    140                         return false;
    141         } else {
    142                 if (_system->getMillis() <= _ticks)
    143                         return false;
    144         }
    145         _framesSkipped++;
    146         return true;
    147 }
    148 
    149 bool MoviePlayer::syncFrame(void) {
    150         _ticks += 83;
    151         if (checkSkipFrame()) {
    152                 warning("Skipped frame %d", _currentFrame);
    153                 return false;
    154         }
    155         if (_bgSoundStream) {
    156                 while (_snd->isSoundHandleActive(_bgSoundHandle) && (_snd->getSoundElapsedTime(_bgSoundHandle) * 12) / 1000 < _currentFrame) {
    157                         _system->delayMillis(10);
    158                 }
    159 
    160                 // In case the background sound ends prematurely, update _ticks
    161                 // so that we can still fall back on the no-sound sync case for
    162                 // the subsequent frames.
    163 
    164                 _ticks = _system->getMillis();
    165         } else {
    166                 while (_system->getMillis() < _ticks) {
    167                         _system->delayMillis(10);
    168                 }
    169         }
    170         return true;
    171 }
    172 
    17382/**
    17483 * Plays an animated cutscene.
    17584 * @param id the id of the file
     
    17887        Common::File f;
    17988        char fileName[20];
    18089
    181         _id = id;
    182         _bgSoundStream = NULL;
     90        if (_decoderType == kVideoDecoderDXA) {
     91                _bgSoundStream = Audio::AudioStream::openStreamFile(sequenceList[id]);
     92        } else {
     93                _bgSoundStream = NULL;
     94        }
    18395
    18496        if (SwordEngine::_systemVars.showText) {
    18597                sprintf(fileName, "%s.txt", sequenceList[id]);
     
    221133                }
    222134        }
    223135
    224         if (SwordEngine::_systemVars.cutscenePackVersion == 1) {
    225                 if ((id == SEQ_INTRO) || (id == SEQ_FINALE) || (id == SEQ_HISTORY) || (id == SEQ_FERRARI)) {
    226 #ifdef USE_VORBIS
    227                         // these sequences are language specific
    228                         sprintf(fileName, "%s.snd", sequenceList[id]);
    229                         Common::File *oggSource = new Common::File();
    230                         if (oggSource->open(fileName)) {
    231                                 SplittedAudioStream *sStream = new SplittedAudioStream();
    232                                 uint32 numSegs = oggSource->readUint32LE(); // number of audio segments, either 1 or 2.
    233                                 // for each segment and each of the 7 languages, we've got fileoffset and size
    234                                 uint32 *header = (uint32*)malloc(numSegs * 7 * 2 * 4);
    235                                 for (uint32 cnt = 0; cnt < numSegs * 7 * 2; cnt++)
    236                                         header[cnt] = oggSource->readUint32LE();
    237                                 for (uint32 segCnt = 0; segCnt < numSegs; segCnt++) {
    238                                         oggSource->seek( header[SwordEngine::_systemVars.language * 2 + 0 + segCnt * 14]);
    239                                         uint32 segSize = header[SwordEngine::_systemVars.language * 2 + 1 + segCnt * 14];
    240                                         Common::MemoryReadStream *stream = oggSource->readStream(segSize);
    241                                         Audio::AudioStream *apStream = Audio::makeVorbisStream(stream, true);
    242                                         if (!apStream)
    243                                                 error("Can't create Vorbis Stream from file %s", fileName);
    244                                         sStream->appendStream(apStream);
    245                                 }
    246                                 free(header);
    247                                 _bgSoundStream = sStream;
    248                         } else
    249                                 warning("Sound file \"%s\" not found", fileName);
    250                         delete oggSource;
     136        char filename[20];
     137        switch (_decoderType) {
     138        case kVideoDecoderDXA:
     139                snprintf(filename, sizeof(filename), "%s.dxa", sequenceList[id]);
     140                break;
     141#ifdef USE_SWORD_SMACKS
     142        case kVideoDecoderSMK:
     143                snprintf(filename, sizeof(filename), "%s.smk", sequenceList[id]);
     144                break;
    251145#endif
    252                         initOverlays(id);
    253                 }
    254146        }
     147
     148        if (_decoder->loadFile(filename)) {
     149                // The Broken Sword games always use external audio tracks.
     150                if (_decoder->readSoundHeader() != MKID_BE('NULL'))
     151                        return false;
     152        } else {
     153                return false;
     154        }
     155
    255156        return true;
    256157}
    257158
    258159void MoviePlayer::play(void) {
    259         _screen->clearScreen();
    260         _framesSkipped = 0;
    261         _ticks = _system->getMillis();
    262         _bgSoundStream = Audio::AudioStream::openStreamFile(sequenceList[_id]);
    263160        if (_bgSoundStream) {
    264                 _snd->playInputStream(Audio::Mixer::kSFXSoundType, &_bgSoundHandle, _bgSoundStream);
     161                _snd->playInputStream(Audio::Mixer::kSFXSoundType, _bgSoundHandle, _bgSoundStream);
    265162        }
    266         _currentFrame = 0;
    267163        bool terminated = false;
    268         Common::EventManager *eventMan = _system->getEventManager();
    269         while (!terminated && decodeFrame()) {
    270                 if (!_movieTexts.empty()) {
    271                         if (_currentFrame == _movieTexts[0]->_startFrame) {
    272                                 _textMan->makeTextSprite(2, (uint8 *)_movieTexts[0]->_text, 600, LETTER_COL);
    273164
    274                                 FrameHeader *frame = _textMan->giveSpriteData(2);
    275                                 _textWidth = frame->width;
    276                                 _textHeight = frame->height;
    277                                 _textX = 320 - _textWidth / 2;
    278                                 _textY = 420 - _textHeight;
    279                         }
    280                         if (_currentFrame == _movieTexts[0]->_endFrame) {
    281                                 _textMan->releaseText(2, false);
    282                                 delete _movieTexts.remove_at(0);
    283                         }
    284                 }
    285                 processFrame();
    286                 if (syncFrame())
    287                         updateScreen();
    288                 _currentFrame++;
    289                 Common::Event event;
    290                 while (eventMan->pollEvent(event)) {
    291                         switch (event.type) {
    292                         case Common::EVENT_SCREEN_CHANGED:
    293                                 handleScreenChanged();
    294                                 break;
    295                         case Common::EVENT_KEYDOWN:
    296                                 if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
    297                                         terminated = true;
    298                                 break;
    299                         default:
    300                                 break;
    301                         }
    302                 }
    303                 if (_vm->shouldQuit())
    304                         terminated = true;
    305         }
     165        Common::List<Common::Event> stopEvents;
     166        Common::Event stopEvent;
     167        stopEvents.clear();
     168        stopEvent.type = Common::EVENT_KEYDOWN;
     169        stopEvent.kbd = Common::KEYCODE_ESCAPE;
     170        stopEvents.push_back(stopEvent);
    306171
     172        terminated = !playVideo(&stopEvents);
     173
    307174        if (terminated)
    308                 _snd->stopHandle(_bgSoundHandle);
     175                _snd->stopHandle(*_bgSoundHandle);
    309176
    310177        _textMan->releaseText(2, false);
    311178
    312179        while (!_movieTexts.empty())
    313180                delete _movieTexts.remove_at(_movieTexts.size() - 1);
    314181
    315         while (_snd->isSoundHandleActive(_bgSoundHandle))
     182        while (_snd->isSoundHandleActive(*_bgSoundHandle))
    316183                _system->delayMillis(100);
    317184
    318185        // It's tempting to call _screen->fullRefresh() here to restore the old
     
    322189
    323190        byte pal[3 * 256];
    324191        memset(pal, 0, sizeof(pal));
    325         updatePalette(pal, true);
     192        _system->setPalette(pal, 0, 255);
    326193}
    327194
    328 SplittedAudioStream::SplittedAudioStream(void) {
    329         _queue = NULL;
    330 }
     195void MoviePlayer::performPostProcessing(byte *screen) {
     196        if (!_movieTexts.empty()) {
     197                if (_decoder->getCurFrame() == _movieTexts[0]->_startFrame) {
     198                        _textMan->makeTextSprite(2, (uint8 *)_movieTexts[0]->_text, 600, LETTER_COL);
    331199
    332 SplittedAudioStream::~SplittedAudioStream(void) {
    333         while (_queue) {
    334                 delete _queue->stream;
    335                 FileQueue *que = _queue->next;
    336                 delete _queue;
    337                 _queue = que;
    338         }
    339 }
    340 
    341 int SplittedAudioStream::getRate(void) const {
    342         if (_queue)
    343                 return _queue->stream->getRate();
    344         else
    345                 return 22050;
    346 }
    347 
    348 void SplittedAudioStream::appendStream(Audio::AudioStream *stream) {
    349         FileQueue **que = &_queue;
    350         while (*que)
    351                 que = &((*que)->next);
    352         *que = new FileQueue;
    353         (*que)->stream = stream;
    354         (*que)->next = NULL;
    355 }
    356 
    357 bool SplittedAudioStream::endOfData(void) const {
    358         if (_queue)
    359                 return _queue->stream->endOfData();
    360         else
    361                 return true;
    362 }
    363 
    364 bool SplittedAudioStream::isStereo(void) const {
    365         if (_queue)
    366                 return _queue->stream->isStereo();
    367         else
    368                 return false; // all the BS1 files are mono, anyways.
    369 }
    370 
    371 int SplittedAudioStream::readBuffer(int16 *buffer, const int numSamples) {
    372         int retVal = 0;
    373         int needSamples = numSamples;
    374         while (needSamples && _queue) {
    375                 int retSmp = _queue->stream->readBuffer(buffer, needSamples);
    376                 needSamples -= retSmp;
    377                 retVal += retSmp;
    378                 buffer += retSmp;
    379                 if (_queue->stream->endOfData()) {
    380                         delete _queue->stream;
    381                         FileQueue *que = _queue->next;
    382                         delete _queue;
    383                         _queue = que;
     200                        FrameHeader *frame = _textMan->giveSpriteData(2);
     201                        _textWidth = frame->width;
     202                        _textHeight = frame->height;
     203                        _textX = 320 - _textWidth / 2;
     204                        _textY = 420 - _textHeight;
    384205                }
     206                if (_decoder->getCurFrame() == _movieTexts[0]->_endFrame) {
     207                        _textMan->releaseText(2, false);
     208                        delete _movieTexts.remove_at(0);
     209                }
    385210        }
    386         return retVal;
    387 }
    388211
    389 #ifdef USE_ZLIB
    390 
    391 ///////////////////////////////////////////////////////////////////////////////
    392 // Movie player for the new DXA movies
    393 ///////////////////////////////////////////////////////////////////////////////
    394 
    395 MoviePlayerDXA::MoviePlayerDXA(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system)
    396         : MoviePlayer(vm, screen, textMan, snd, system) {
    397         debug(0, "Creating DXA cutscene player");
    398 }
    399 
    400 MoviePlayerDXA::~MoviePlayerDXA(void) {
    401         closeFile();
    402 }
    403 
    404 bool MoviePlayerDXA::load(uint32 id) {
    405         if (!MoviePlayer::load(id))
    406                 return false;
    407 
    408         char filename[20];
    409         snprintf(filename, sizeof(filename), "%s.dxa", sequenceList[id]);
    410         if (loadFile(filename)) {
    411                 // The Broken Sword games always use external audio tracks.
    412                 if (_fileStream->readUint32BE() != MKID_BE('NULL'))
    413                         return false;
    414                 _frameWidth = getWidth();
    415                 _frameHeight = getHeight();
    416                 _frameX = (640 - _frameWidth) / 2;
    417                 _frameY = (480 - _frameHeight) / 2;
    418                 return true;
    419         }
    420         return false;
    421 }
    422 
    423 bool MoviePlayerDXA::initOverlays(uint32 id) {
    424         // TODO
    425         return true;
    426 }
    427 
    428 void MoviePlayerDXA::setPalette(byte *pal) {
    429         updatePalette(pal, true);
    430 }
    431 
    432 bool MoviePlayerDXA::decodeFrame(void) {
    433         if ((uint32)_currentFrame < (uint32)getFrameCount()) {
    434                 decodeNextFrame();
    435                 return true;
    436         }
    437         return false;
    438 }
    439 
    440 void MoviePlayerDXA::processFrame(void) {
    441 }
    442 
    443 void MoviePlayerDXA::updateScreen(void) {
    444         Graphics::Surface *frameBuffer = _system->lockScreen();
    445         copyFrameToBuffer((byte *)frameBuffer->pixels, _frameX, _frameY, 640);
    446 
    447         // TODO: Handle the advanced cutscene packs. Do they really exist?
    448 
    449         // We cannot draw the text to _drawBuffer, since that's one of the
    450         // decoder's internal buffers, and besides it may be much smaller than
    451         // the screen, so it's possible that the subtitles don't fit on it.
    452         // Instead, we get the frame buffer from the backend, after copying the
    453         // frame to it, and draw on that.
    454 
    455212        if (_textMan->giveSpriteData(2)) {
    456213                byte *src = (byte *)_textMan->giveSpriteData(2) + sizeof(FrameHeader);
    457                 byte *dst = (byte *)frameBuffer->getBasePtr(_textX, _textY);
     214                byte *dst = screen + _textY * _decoder->getWidth() + _textX * 1;
    458215
    459216                for (int y = 0; y < _textHeight; y++) {
    460217                        for (int x = 0; x < _textWidth; x++) {
    461218                                switch (src[x]) {
    462219                                case BORDER_COL:
    463                                         dst[x] = _black;
     220                                        dst[x] = _decoder->getBlack();
    464221                                        break;
    465222                                case LETTER_COL:
    466                                         dst[x] = _white;
     223                                        dst[x] = _decoder->getWhite();
    467224                                        break;
    468225                                }
    469226                        }
    470227                        src += _textWidth;
    471                         dst += frameBuffer->pitch;
     228                        dst += _decoder->getWidth();
    472229                }
    473 
    474230        }
    475 
    476         _system->unlockScreen();
    477 
    478         _system->updateScreen();
    479231}
    480232
    481 #endif
    482 
    483 #ifdef USE_MPEG2
    484 
    485 ///////////////////////////////////////////////////////////////////////////////
    486 // Movie player for the old MPEG movies
    487 ///////////////////////////////////////////////////////////////////////////////
    488 
    489 MoviePlayerMPEG::MoviePlayerMPEG(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system)
    490         : MoviePlayer(vm, screen, textMan, snd, system) {
    491 #ifdef BACKEND_8BIT
    492         debug(0, "Creating MPEG cutscene player (8-bit)");
    493 #else
    494         debug(0, "Creating MPEG cutscene player (16-bit)");
    495 #endif
    496         for (uint8 cnt = 0; cnt < INTRO_LOGO_OVLS; cnt++)
    497                 _logoOvls[cnt] = NULL;
    498         _introPal = NULL;
    499         _anim = NULL;
     233DXAPlayerWithSound::DXAPlayerWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)
     234        : _mixer(mixer), _bgSoundHandle(bgSoundHandle)  {
    500235}
    501236
    502 MoviePlayerMPEG::~MoviePlayerMPEG(void) {
    503         free(_introPal);
    504         for (uint8 cnt = 0; cnt < INTRO_LOGO_OVLS; cnt++)
    505                 free(_logoOvls[cnt]);
    506         delete _anim;
    507 }
     237int32 DXAPlayerWithSound::getAudioLag() {
     238        if (!_fileStream)
     239                return 0;
    508240
    509 void MoviePlayerMPEG::handleScreenChanged(void) {
    510         _anim->handleScreenChanged();
    511 }
     241        int32 frameDelay = getFrameDelay();
     242        int32 videoTime = _videoInfo.currentFrame * frameDelay;
     243        int32 audioTime;
    512244
    513 void MoviePlayerMPEG::insertOverlay(OverlayColor *buf, uint8 *ovl, OverlayColor *pal) {
    514         if (ovl != NULL)
    515                 for (uint32 cnt = 0; cnt < 640 * 400; cnt++)
    516                         if (ovl[cnt])
    517                                 buf[cnt] = pal[ovl[cnt]];
    518 }
     245        audioTime = (((int32) _mixer->getSoundElapsedTime(*_bgSoundHandle)) * 100);
    519246
    520 bool MoviePlayerMPEG::load(uint32 id) {
    521         if (MoviePlayer::load(id)) {
    522                 _anim = new AnimationState(this, _screen, _system);
    523                 return _anim->init(sequenceList[id]);
    524         }
    525         return false;
     247        return videoTime - audioTime;
    526248}
    527249
    528 bool MoviePlayerMPEG::initOverlays(uint32 id) {
    529         if (id == SEQ_INTRO) {
    530                 ArcFile ovlFile;
    531                 if (!ovlFile.open("intro.dat")) {
    532                         warning("\"intro.dat\" not found");
    533                         return false;
    534                 }
    535                 ovlFile.enterPath(SwordEngine::_systemVars.language);
    536                 for (uint8 fcnt = 0; fcnt < 12; fcnt++) {
    537                         _logoOvls[fcnt] = ovlFile.decompressFile(fcnt);
    538                         if (fcnt > 0)
    539                                 for (uint32 cnt = 0; cnt < 640 * 400; cnt++)
    540                                         if (_logoOvls[fcnt - 1][cnt] && !_logoOvls[fcnt][cnt])
    541                                                 _logoOvls[fcnt][cnt] = _logoOvls[fcnt - 1][cnt];
    542                 }
    543                 uint8 *pal = ovlFile.fetchFile(12);
    544                 _introPal = (OverlayColor *)malloc(256 * sizeof(OverlayColor));
    545                 Graphics::PixelFormat format = _system->getOverlayFormat();
    546                 for (uint16 cnt = 0; cnt < 256; cnt++)
    547                         _introPal[cnt] = format.RGBToColor(pal[cnt * 3 + 0], pal[cnt * 3 + 1], pal[cnt * 3 + 2]);
    548         }
    549 
    550         return true;
    551 }
    552 
    553 bool MoviePlayerMPEG::decodeFrame(void) {
    554         return _anim->decodeFrame();
    555 }
    556 
    557 void MoviePlayerMPEG::updateScreen(void) {
    558         _anim->updateScreen();
    559 }
    560 
    561 void MoviePlayerMPEG::processFrame(void) {
    562 #ifndef BACKEND_8BIT
    563         if ((_id != 4) || (SwordEngine::_systemVars.cutscenePackVersion == 0))
    564                 return;
    565         OverlayColor *buf = _anim->giveRgbBuffer();
    566         if ((_currentFrame > 397) && (_currentFrame < 444)) { // Broken Sword Logo
    567                 if (_currentFrame <= 403)
    568                         insertOverlay(buf, _logoOvls[_currentFrame - 398], _introPal); // fade up
    569                 else if (_currentFrame <= 437)
    570                         insertOverlay(buf, _logoOvls[(_currentFrame - 404) % 6 + 6], _introPal); // animation
    571                 else {
    572                         insertOverlay(buf, _logoOvls[5 - (_currentFrame - 438)], _introPal); // fade down
    573                 }
    574         }
    575 #endif
    576 }
    577 
    578 AnimationState::AnimationState(MoviePlayer *player, Screen *screen, OSystem *system)
    579         : BaseAnimationState(system, 640, 400), _player(player), _screen(screen) {
    580 }
    581 
    582 AnimationState::~AnimationState(void) {
    583 }
    584 
    585 #ifdef BACKEND_8BIT
    586 void AnimationState::setPalette(byte *pal) {
    587         _player->updatePalette(pal, false);
    588 }
    589 #endif
    590 
    591 void AnimationState::drawYUV(int width, int height, byte *const *dat) {
    592         _frameWidth = width;
    593         _frameHeight = height;
    594 
    595 #ifdef BACKEND_8BIT
    596         _screen->plotYUV(_lut, width, height, dat);
    597 #else
    598         plotYUV(width, height, dat);
    599 #endif
    600 }
    601 
    602 OverlayColor *AnimationState::giveRgbBuffer(void) {
    603 #ifdef BACKEND_8BIT
    604         return NULL;
    605 #else
    606         return _overlay;
    607 #endif
    608 }
    609 
    610 Audio::AudioStream *AnimationState::createAudioStream(const char *name, void *arg) {
    611         if (arg)
    612                 return (Audio::AudioStream*)arg;
    613         else
    614                 return Audio::AudioStream::openStreamFile(name);
    615 }
    616 
    617 #endif
    618 
    619250///////////////////////////////////////////////////////////////////////////////
    620251// Factory function for creating the appropriate cutscene player
    621252///////////////////////////////////////////////////////////////////////////////
    622253
    623 MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system) {
    624 #if defined(USE_ZLIB) || defined(USE_MPEG2)
     254MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system) {
    625255        char filename[20];
     256        char buf[60];
     257        Audio::SoundHandle bgSoundHandle;
     258
     259#ifdef USE_SWORD_SMACKS
     260        snprintf(filename, sizeof(filename), "%s.smk", sequenceList[id]);
     261
     262        if (Common::File::exists(filename)) {
     263                Graphics::SMKPlayer *smkDecoder = new Graphics::SMKPlayer(snd);
     264                return new MoviePlayer(vm, textMan, snd, system, &bgSoundHandle, smkDecoder, kVideoDecoderSMK);
     265        }
    626266#endif
    627267
    628 #ifdef USE_ZLIB
    629268        snprintf(filename, sizeof(filename), "%s.dxa", sequenceList[id]);
    630269
    631270        if (Common::File::exists(filename)) {
    632                 return new MoviePlayerDXA(vm, screen, textMan, snd, system);
    633         }
     271#ifdef USE_ZLIB
     272                DXAPlayerWithSound *dxaDecoder = new DXAPlayerWithSound(snd, &bgSoundHandle);
     273                return new MoviePlayer(vm, textMan, snd, system, &bgSoundHandle, dxaDecoder, kVideoDecoderDXA);
     274#else
     275                GUI::MessageDialog dialog("DXA cutscenes found but ScummVM has been built without zlib support", "OK");
     276                dialog.runModal();
     277                return NULL;
    634278#endif
     279        }
    635280
    636 #ifdef USE_MPEG2
     281        // Old MPEG2 cutscenes
    637282        snprintf(filename, sizeof(filename), "%s.mp2", sequenceList[id]);
    638283
    639284        if (Common::File::exists(filename)) {
    640                 return new MoviePlayerMPEG(vm, screen, textMan, snd, system);
     285                GUI::MessageDialog dialog("MPEG2 cutscenes are no longer supported", "OK");
     286                dialog.runModal();
     287                return NULL;
    641288        }
    642 #endif
    643289
     290        sprintf(buf, "Cutscene '%s' not found", sequenceList[id]);
     291        GUI::MessageDialog dialog(buf, "OK");
     292        dialog.runModal();
     293
    644294        return NULL;
    645295}
    646296
  • engines/sword1/animation.h

     
    2727#define SWORD1_ANIMATION_H
    2828
    2929#include "graphics/video/dxa_player.h"
    30 #include "graphics/video/mpeg_player.h"
     30#ifdef USE_SWORD_SMACKS
     31#include "graphics/video/smk_player.h"
     32#endif
     33#include "graphics/video/video_player.h"
    3134
    3235#include "sword1/screen.h"
    3336#include "sword1/sound.h"
     
    3538
    3639namespace Sword1 {
    3740
    38 enum {
    39         SEQ_FERRARI = 0,
    40         SEQ_LADDER,
    41         SEQ_STEPS,
    42         SEQ_SEWER,
    43         SEQ_INTRO,
    44         SEQ_RIVER,
    45         SEQ_TRUCK,
    46         SEQ_GRAVE,
    47         SEQ_MONTFCON,
    48         SEQ_TAPESTRY,
    49         SEQ_IRELAND,
    50         SEQ_FINALE,
    51         SEQ_HISTORY,
    52         SEQ_SPANISH,
    53         SEQ_WELL,
    54         SEQ_CANDLE,
    55         SEQ_GEODROP,
    56         SEQ_VULTURE,
    57         SEQ_ENDDEMO,
    58         SEQ_CREDITS
     41enum DecoderType {
     42        kVideoDecoderDXA = 0,
     43        kVideoDecoderSMK = 1
    5944};
    6045
    61 #define INTRO_LOGO_OVLS 12
    62 #define INTRO_TEXT_OVLS 8
    63 
    6446class MovieText {
    6547public:
    6648        uint16 _startFrame;
     
    7658        }
    7759};
    7860
    79 class MoviePlayer {
     61class DXAPlayerWithSound : public Graphics::DXAPlayer {
    8062public:
    81         MoviePlayer(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system);
     63        DXAPlayerWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle);
     64        ~DXAPlayerWithSound() {}
     65
     66        int32 getAudioLag();
     67private:
     68        Audio::Mixer *_mixer;
     69        Audio::SoundHandle *_bgSoundHandle;
     70};
     71
     72class MoviePlayer : public Graphics::VideoPlayer {
     73public:
     74        MoviePlayer(SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Graphics::VideoDecoder *decoder, DecoderType decoderType);
    8275        virtual ~MoviePlayer(void);
    83         virtual bool load(uint32 id);
     76        bool load(uint32 id);
    8477        void play(void);
    85         void updatePalette(byte *pal, bool packed = true);
    86 private:
    87         bool checkSkipFrame(void);
    8878protected:
    8979        SwordEngine *_vm;
    90         Screen *_screen;
    9180        Text *_textMan;
    9281        Audio::Mixer *_snd;
    9382        OSystem *_system;
    9483        Common::Array<MovieText *> _movieTexts;
    9584        int _textX, _textY, _textWidth, _textHeight;
    96         byte _black, _white;
     85        DecoderType _decoderType;
    9786
    98         uint32 _id;
    99 
    100         uint _currentFrame;
    101         int _framesSkipped;
    102         bool _forceFrame;
    103 
    104         int _frameWidth, _frameHeight;
    105         int _frameX, _frameY;
    106 
    107         Audio::SoundHandle _bgSoundHandle;
     87        Audio::SoundHandle *_bgSoundHandle;
    10888        Audio::AudioStream *_bgSoundStream;
    109         uint32 _ticks;
    11089
    111         virtual void handleScreenChanged(void);
    112         virtual bool initOverlays(uint32 id);
    113         virtual bool decodeFrame(void) = 0;
    114         virtual void processFrame(void) = 0;
    115         virtual bool syncFrame(void);
    116         virtual void updateScreen(void) = 0;
     90        void performPostProcessing(byte *screen);
    11791};
    11892
    119 #ifdef USE_ZLIB
     93MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system);
    12094
    121 class MoviePlayerDXA : public MoviePlayer, ::Graphics::DXAPlayer {
    122 protected:
    123         virtual void setPalette(byte *pal);
    124 public:
    125         MoviePlayerDXA(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system);
    126         virtual ~MoviePlayerDXA(void);
    127         bool load(uint32 id);
    128 protected:
    129         bool initOverlays(uint32 id);
    130         bool decodeFrame(void);
    131         void processFrame(void);
    132         void updateScreen(void);
    133 };
    134 
    135 #endif
    136 
    137 #ifdef USE_MPEG2
    138 
    139 class AnimationState : public Graphics::BaseAnimationState {
    140 private:
    141         MoviePlayer *_player;
    142         Screen *_screen;
    143 
    144 public:
    145         AnimationState(MoviePlayer *player, Screen *screen, OSystem *system);
    146         ~AnimationState(void);
    147         OverlayColor *giveRgbBuffer(void);
    148 
    149 private:
    150         void drawYUV(int width, int height, byte *const *dat);
    151 
    152 #ifdef BACKEND_8BIT
    153         void setPalette(byte *pal);
    154 #endif
    155 
    156 protected:
    157         virtual Audio::AudioStream *createAudioStream(const char *name, void *arg);
    158 };
    159 
    160 class MoviePlayerMPEG : public MoviePlayer {
    161 public:
    162         MoviePlayerMPEG(SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system);
    163         virtual ~MoviePlayerMPEG(void);
    164         bool load(uint32 id);
    165 protected:
    166         void insertOverlay(OverlayColor *buf, uint8 *ovl, OverlayColor *pal);
    167         AnimationState *_anim;
    168         OverlayColor *_introPal;
    169         uint8 *_logoOvls[INTRO_LOGO_OVLS];
    170 
    171         bool initOverlays(uint32 id);
    172         bool decodeFrame(void);
    173         void processFrame(void);
    174         void updateScreen(void);
    175         void handleScreenChanged(void);
    176 };
    177 
    178 #endif
    179 
    180 struct FileQueue {
    181         Audio::AudioStream *stream;
    182         FileQueue *next;
    183 };
    184 
    185 class SplittedAudioStream : public Audio::AudioStream {
    186 public:
    187         SplittedAudioStream(void);
    188         ~SplittedAudioStream(void);
    189         void appendStream(Audio::AudioStream *stream);
    190         virtual int readBuffer(int16 *buffer, const int numSamples);
    191         virtual bool isStereo(void) const;
    192         virtual bool endOfData(void) const;
    193         virtual int getRate(void) const;
    194 private:
    195         FileQueue *_queue;
    196 };
    197 
    198 MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Screen *screen, Text *textMan, Audio::Mixer *snd, OSystem *system);
    199 
    20095} // End of namespace Sword1
    20196
    20297#endif
  • engines/sword1/credits.cpp

     
    1 /* ScummVM - Graphic Adventure Engine
    2  *
    3  * ScummVM is the legal property of its developers, whose names
    4  * are too numerous to list here. Please refer to the COPYRIGHT
    5  * file distributed with this source distribution.
    6  *
    7  * This program is free software; you can redistribute it and/or
    8  * modify it under the terms of the GNU General Public License
    9  * as published by the Free Software Foundation; either version 2
    10  * of the License, or (at your option) any later version.
    11 
    12  * This program is distributed in the hope that it will be useful,
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15  * GNU General Public License for more details.
    16 
    17  * You should have received a copy of the GNU General Public License
    18  * along with this program; if not, write to the Free Software
    19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    20  *
    21  * $URL$
    22  * $Id$
    23  *
    24  */
    25 
    26 
    27 #include "common/endian.h"
    28 
    29 #include "sword1/credits.h"
    30 #include "sword1/screen.h"
    31 #include "sword1/sword1.h"
    32 
    33 #include "sound/audiostream.h"
    34 #include "sound/mixer.h"
    35 
    36 #include "common/file.h"
    37 #include "common/util.h"
    38 #include "common/events.h"
    39 #include "common/system.h"
    40 
    41 
    42 #define CREDITS_X 480
    43 #define CREDITS_Y 300
    44 #define BUFSIZE_Y 640
    45 
    46 #define START_X ((640 - CREDITS_X) / 2)
    47 #define START_Y ((480 - CREDITS_Y) / 2)
    48 
    49 #define SCROLL_TIMING (2000 / 59) // 29.5 frames per second
    50 
    51 #define LOGO_FADEUP_TIME (133 * 1000)
    52 #define LOGO_FADEDOWN_TIME (163 * 1000)
    53 
    54 namespace Sword1 {
    55 
    56 enum {
    57         FONT_PAL = 0,
    58         FONT,
    59         TEXT,
    60         REVO_PAL,
    61         REVO_LOGO,
    62         F_EOF
    63 };
    64 
    65 enum {
    66         FNT_LFT = 0,   // left column
    67         FNT_RGT,           // right column
    68         FNT_CEN,           // centered
    69         FNT_BIG = 64,  // big font
    70         FNT_EOL = 128, // linebreak
    71         FNT_EOB = 255  // end of textblock
    72 };
    73 
    74 
    75 CreditsPlayer::CreditsPlayer(OSystem *pSystem, Audio::Mixer *pMixer) {
    76         _system = pSystem;
    77         _mixer = pMixer;
    78         _smlFont = _bigFont = NULL;
    79 }
    80 
    81 bool spaceInBuf(uint16 blitSta, uint16 blitEnd, uint16 renderDest) {
    82         if (blitEnd > blitSta) {
    83                 if ((renderDest > blitEnd) || (renderDest + 15 < blitSta))
    84                         return true;
    85         } else {
    86                 if ((renderDest > blitEnd) && (renderDest + 15 < blitSta))
    87                         return true;
    88         }
    89         return false;
    90 }
    91 
    92 void CreditsPlayer::play(void) {
    93         Audio::AudioStream *bgSoundStream = Audio::AudioStream::openStreamFile("credits");
    94         if (bgSoundStream == NULL) {
    95                 warning("\"credits.ogg\" not found, skipping credits sequence");
    96                 return;
    97         }
    98         ArcFile credFile;
    99         if (!credFile.open("credits.dat")) {
    100                 warning("\"credits.dat\" not found, skipping credits sequence");
    101                 return;
    102         }
    103 
    104         uint8 *palSrc = credFile.fetchFile(FONT_PAL, &_palLen);
    105         for (uint32 cnt = 0; cnt < _palLen; cnt++)
    106                 _palette[(cnt / 3) * 4 + cnt % 3] = palSrc[cnt];
    107         _palLen /= 3;
    108 
    109         generateFonts(&credFile);
    110 
    111         uint8 *textData = credFile.fetchFile(TEXT);
    112         textData += READ_LE_UINT32(textData + SwordEngine::_systemVars.language * 4);
    113 
    114         uint8 *screenBuf = (uint8*)malloc(CREDITS_X * BUFSIZE_Y);
    115         memset(screenBuf, 0, CREDITS_X * BUFSIZE_Y);
    116         _system->copyRectToScreen(screenBuf, 640, 0, 0, 640, 480);
    117         _system->setPalette(_palette, 0, _palLen);
    118 
    119         // everything's initialized, time to render and show the credits.
    120         Audio::SoundHandle bgSound;
    121         _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &bgSound, bgSoundStream, 0);
    122 
    123         int relDelay = 0;
    124         uint16 scrollY = 0;
    125         uint16 renderY = BUFSIZE_Y / 2;
    126         uint16 clearY = 0xFFFF;
    127         bool clearLine = false;
    128         while (((*textData != FNT_EOB) || (scrollY != renderY)) && !Engine::shouldQuit()) {
    129                 if ((int32)_mixer->getSoundElapsedTime(bgSound) - relDelay < (SCROLL_TIMING * 2)) { // sync to audio
    130                         if (scrollY < BUFSIZE_Y - CREDITS_Y)
    131                                 _system->copyRectToScreen(screenBuf + scrollY * CREDITS_X, CREDITS_X, START_X, START_Y, CREDITS_X, CREDITS_Y);
    132                         else {
    133                                 _system->copyRectToScreen(screenBuf + scrollY * CREDITS_X, CREDITS_X, START_X, START_Y, CREDITS_X, BUFSIZE_Y - scrollY);
    134                                 _system->copyRectToScreen(screenBuf, CREDITS_X, START_X, START_Y + BUFSIZE_Y - scrollY, CREDITS_X, CREDITS_Y - (BUFSIZE_Y - scrollY));
    135                         }
    136                         _system->updateScreen();
    137                 } else
    138                         warning("frame skipped");
    139 
    140                 while (spaceInBuf(scrollY, (scrollY + CREDITS_Y) % BUFSIZE_Y, renderY) && (*textData != FNT_EOB)) {
    141                         if (*textData & FNT_EOL) {
    142                                 renderY = (renderY + 16) % BUFSIZE_Y; // linebreak
    143                                 clearLine = true;
    144                                 *textData &= ~FNT_EOL;
    145                         }
    146                         if (spaceInBuf(scrollY, (scrollY + CREDITS_Y) % BUFSIZE_Y, renderY)) {
    147                                 if (clearLine)
    148                                         memset(screenBuf + renderY * CREDITS_X, 0, 16 * CREDITS_X);
    149                                 clearLine = false;
    150                                 renderLine(screenBuf, textData + 1, renderY, *textData);
    151                                 if (*textData & FNT_BIG)
    152                                         renderY += 16;
    153                                 while (*++textData != 0) // search for the start of next string
    154                                         ;
    155                                 textData++;
    156                         }
    157                         if (*textData == FNT_EOB)
    158                                 clearY = renderY;
    159                 }
    160                 if ((*textData == FNT_EOB) && spaceInBuf(scrollY, (scrollY + CREDITS_Y) % BUFSIZE_Y, clearY)) {
    161                         memset(screenBuf + clearY * CREDITS_X, 0, 16 * CREDITS_X);
    162                         clearY = (clearY + 16) % BUFSIZE_Y;
    163                 }
    164 
    165                 relDelay += SCROLL_TIMING;
    166                 delay(relDelay - (int32)_mixer->getSoundElapsedTime(bgSound));
    167                 scrollY = (scrollY + 1) % BUFSIZE_Y;
    168         }
    169         free(_smlFont);
    170         free(_bigFont);
    171         _smlFont = _bigFont = NULL;
    172         free(screenBuf);
    173 
    174         // credits done, now show the revolution logo
    175         uint8 *revoBuf = credFile.decompressFile(REVO_LOGO);
    176         uint8 *revoPal = credFile.fetchFile(REVO_PAL, &_palLen);
    177         _palLen /= 3;
    178         while ((_mixer->getSoundElapsedTime(bgSound) < LOGO_FADEUP_TIME) && !Engine::shouldQuit()) {
    179                 delay(100);
    180         }
    181         memset(_palette, 0, 256 * 4);
    182         _system->setPalette(_palette, 0, 256);
    183         _system->copyRectToScreen(revoBuf, 480, START_X, START_Y, CREDITS_X, CREDITS_Y);
    184         _system->updateScreen();
    185 
    186         fadePalette(revoPal, true, _palLen);
    187         while ((_mixer->getSoundElapsedTime(bgSound) < LOGO_FADEDOWN_TIME) && !Engine::shouldQuit()) {
    188                 delay(100);
    189         }
    190         fadePalette(revoPal, false, _palLen);
    191         delay(3000);
    192 
    193         if (Engine::shouldQuit())
    194                 _mixer->stopAll();
    195         free(revoBuf);
    196 }
    197 
    198 void CreditsPlayer::fadePalette(uint8 *srcPal, bool fadeup, uint16 len) {
    199         int8 fadeDir = fadeup ? 1 : -1;
    200         int fadeStart = fadeup ? 0 : 12;
    201 
    202         int relDelay = _system->getMillis();
    203         for (int fadeStep = fadeStart; (fadeStep >= 0) && (fadeStep <= 12) && !Engine::shouldQuit(); fadeStep += fadeDir) {
    204                 for (uint16 cnt = 0; cnt < len * 3; cnt++)
    205                         _palette[(cnt / 3) * 4 + (cnt % 3)] = (srcPal[cnt] * fadeStep) / 12;
    206                 _system->setPalette(_palette, 0, 256);
    207                 relDelay += 1000 / 12;
    208                 delay(relDelay - _system->getMillis());
    209         }
    210 }
    211 
    212 void CreditsPlayer::renderLine(uint8 *screenBuf, uint8 *line, uint16 yBufPos, uint8 flags) {
    213         uint8 *font;
    214         uint16 fntSize = 16;
    215         if (flags & FNT_BIG) {
    216                 font = _bigFont;
    217                 fntSize = 32;
    218                 flags &= ~FNT_BIG;
    219         } else
    220                 font = _smlFont;
    221 
    222         uint16 width = getWidth(font, line);
    223         uint16 xBufPos = (flags == FNT_CEN) ? (CREDITS_X - width) / 2 : ((flags == FNT_LFT) ? (234 - width) : 255);
    224         uint8 *bufDest = screenBuf + yBufPos * CREDITS_X + xBufPos;
    225         while (*line) {
    226                 uint8 *chrSrc = font + _numChars + (*line - 1) * fntSize * fntSize;
    227                 for (uint16 cnty = 0; cnty < fntSize; cnty++) {
    228                         for (uint16 cntx = 0; cntx < fntSize; cntx++)
    229                                 bufDest[cnty * CREDITS_X + cntx] = chrSrc[cntx];
    230                         chrSrc += fntSize;
    231                 }
    232                 bufDest += font[*line++ - 1];
    233         }
    234 }
    235 
    236 uint16 CreditsPlayer::getWidth(uint8 *font, uint8 *line) {
    237         uint16 width = 0;
    238         while (*line)
    239                 width += font[*line++ - 1];
    240         return width;
    241 }
    242 
    243 void CreditsPlayer::generateFonts(ArcFile *arcFile) {
    244         _bigFont = arcFile->decompressFile(FONT);
    245         _numChars = *_bigFont;
    246         memmove(_bigFont, _bigFont + 1, _numChars * (32 * 32 + 1));
    247         _smlFont = (uint8*)malloc(_numChars * (32 * 32 + 1));
    248         uint8 *src = _bigFont + _numChars;
    249         uint8 *dst = _smlFont + _numChars;
    250         for (uint16 cnt = 0; cnt < _numChars; cnt++) {
    251                 _smlFont[cnt] = (_bigFont[cnt]++ + 1) / 2; // width table
    252                 for (uint16 cnty = 0; cnty < 16; cnty++) {
    253                         for (uint16 cntx = 0; cntx < 16; cntx++) {
    254                                 uint8 resR = (uint8)((_palette[src[0] * 4 + 0] + _palette[src[1] * 4 + 0] + _palette[src[32] * 4 + 0] + _palette[src[33] * 4 + 0]) >> 2);
    255                                 uint8 resG = (uint8)((_palette[src[0] * 4 + 1] + _palette[src[1] * 4 + 1] + _palette[src[32] * 4 + 1] + _palette[src[33] * 4 + 1]) >> 2);
    256                                 uint8 resB = (uint8)((_palette[src[0] * 4 + 2] + _palette[src[1] * 4 + 2] + _palette[src[32] * 4 + 2] + _palette[src[33] * 4 + 2]) >> 2);
    257                                 *dst++ = getPalIdx(resR, resG, resB);
    258                                 src += 2;
    259                         }
    260                         src += 32;
    261                 }
    262         }
    263 }
    264 
    265 uint8 CreditsPlayer::getPalIdx(uint8 r, uint8 g, uint8 b) {
    266         for (uint16 cnt = 0; cnt < _palLen; cnt++)
    267                 if ((_palette[cnt * 4 + 0] == r) && (_palette[cnt * 4 + 1] == g) && (_palette[cnt * 4 + 2] == b))
    268                         return (uint8)cnt;
    269         assert(_palLen < 256);
    270         _palette[_palLen * 4 + 0] = r;
    271         _palette[_palLen * 4 + 1] = g;
    272         _palette[_palLen * 4 + 2] = b;
    273         return (uint8)_palLen++;
    274 }
    275 
    276 void CreditsPlayer::delay(int msecs) {
    277 
    278         Common::Event event;
    279         uint32 start = _system->getMillis();
    280         do {
    281                 Common::EventManager *eventMan = _system->getEventManager();
    282                 while (eventMan->pollEvent(event)) {
    283 #if 0
    284                         switch (event.type) {
    285                         default:
    286                                 break;
    287                         }
    288 #endif
    289                 }
    290 
    291                 _system->updateScreen();
    292 
    293                 if (msecs > 0)
    294                         _system->delayMillis(10);
    295 
    296         } while ((_system->getMillis() < start + msecs) && !Engine::shouldQuit());
    297 }
    298 
    299 ArcFile::ArcFile(void) {
    300         _buf = NULL;
    301 }
    302 
    303 ArcFile::~ArcFile(void) {
    304         if (_buf)
    305                 free(_buf);
    306 }
    307 
    308 bool ArcFile::open(const char *name) {
    309         Common::File arc;
    310         if (!arc.open(name))
    311                 return false;
    312         _bufPos = _buf = (uint8*)malloc(arc.size());
    313         arc.read(_buf, arc.size());
    314         arc.close();
    315         return true;
    316 }
    317 
    318 void ArcFile::enterPath(uint32 id) {
    319         _bufPos += READ_LE_UINT32(_bufPos + id * 4);
    320 }
    321 
    322 uint8 *ArcFile::fetchFile(uint32 fileId, uint32 *size) {
    323         if (size)
    324                 *size = READ_LE_UINT32(_bufPos + (fileId + 1) * 4) - READ_LE_UINT32(_bufPos + fileId * 4);
    325         return _bufPos + READ_LE_UINT32(_bufPos + fileId * 4);
    326 }
    327 
    328 uint8 *ArcFile::decompressFile(uint32 fileId) {
    329         uint32 size;
    330         uint8 *srcBuf = fetchFile(fileId, &size);
    331         uint8 *dstBuf = (uint8*)malloc(READ_LE_UINT32(srcBuf));
    332         uint8 *srcPos = srcBuf + 4;
    333         uint8 *dstPos = dstBuf;
    334         while (srcPos < srcBuf + size) {
    335                 uint16 len = READ_LE_UINT16(srcPos);
    336                 memset(dstPos, 0, len);
    337                 dstPos += len;
    338                 srcPos += 2;
    339                 if (srcPos < srcBuf + size) {
    340                         len = *srcPos++;
    341                         memcpy(dstPos, srcPos, len);
    342                         dstPos += len;
    343                         srcPos += len;
    344                 }
    345         }
    346         return dstBuf;
    347 }
    348 
    349 } // end of namespace Sword1
  • engines/sword1/credits.h

     
    1 /* ScummVM - Graphic Adventure Engine
    2  *
    3  * ScummVM is the legal property of its developers, whose names
    4  * are too numerous to list here. Please refer to the COPYRIGHT
    5  * file distributed with this source distribution.
    6  *
    7  * This program is free software; you can redistribute it and/or
    8  * modify it under the terms of the GNU General Public License
    9  * as published by the Free Software Foundation; either version 2
    10  * of the License, or (at your option) any later version.
    11 
    12  * This program is distributed in the hope that it will be useful,
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15  * GNU General Public License for more details.
    16 
    17  * You should have received a copy of the GNU General Public License
    18  * along with this program; if not, write to the Free Software
    19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    20  *
    21  * $URL$
    22  * $Id$
    23  *
    24  */
    25 
    26 #ifndef SWORD1_CREDITS_H
    27 #define SWORD1_CREDITS_H
    28 
    29 #include "common/util.h"
    30 
    31 namespace Audio {
    32         class Mixer;
    33 }
    34 class OSystem;
    35 
    36 namespace Sword1 {
    37 
    38 class ArcFile {
    39 public:
    40         ArcFile(void);
    41         ~ArcFile(void);
    42         bool open(const char *name);
    43         uint8 *fetchFile(uint32 fileId, uint32 *size = NULL);
    44         uint8 *decompressFile(uint32 fileId);
    45         void enterPath(uint32 id);
    46         void backToRoot(void) { _bufPos = _buf; }
    47 private:
    48         uint8 *_bufPos;
    49         uint8 *_buf;
    50 };
    51 
    52 class CreditsPlayer {
    53 public:
    54         CreditsPlayer(OSystem *pSystem, Audio::Mixer *pMixer);
    55         void play(void);
    56 private:
    57         void generateFonts(ArcFile *arcFile);
    58         void renderLine(uint8 *screenBuf, uint8 *line, uint16 yBufPos, uint8 flags);
    59         void fadePalette(uint8 *srcPal, bool fadeup, uint16 len);
    60         void delay(int msecs);
    61         uint16 getWidth(uint8 *font, uint8 *line);
    62         uint8 getPalIdx(uint8 r, uint8 g, uint8 b);
    63         uint8 _palette[256 * 4];
    64         uint32 _palLen;
    65         uint8 _numChars;
    66 
    67         OSystem *_system;
    68         Audio::Mixer *_mixer;
    69 
    70         uint8 *_smlFont, *_bigFont;
    71 };
    72 
    73 } // end of namespace Sword1
    74 
    75 #endif // BS1CREDITS_H
  • engines/sword1/logic.cpp

     
    4141#include "sword1/music.h"
    4242#include "sword1/swordres.h"
    4343#include "sword1/animation.h"
    44 #include "sword1/credits.h"
    4544
    4645#include "sword1/debug.h"
    4746
     
    960959        // meantime, we don't want any looping sound effects still playing.
    961960        _sound->quitScreen();
    962961
    963         if ((SwordEngine::_systemVars.cutscenePackVersion == 1) && (sequenceId == SEQ_CREDITS)) {
    964                 CreditsPlayer player(_system, _mixer);
    965                 player.play();
    966         } else {
    967                 MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _screen, _textMan, _mixer, _system);
    968                 if (player) {
    969                         if (player->load(sequenceId))
    970                                 player->play();
    971                         delete player;
    972                 }
     962        MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _mixer, _system);
     963        if (player) {
     964                _screen->clearScreen();
     965                if (player->load(sequenceId))
     966                        player->play();
     967                delete player;
    973968        }
    974969        return SCRIPT_CONT;
    975970}
  • engines/sword1/module.mk

     
    33MODULE_OBJS := \
    44        animation.o \
    55        control.o \
    6         credits.o \
    76        debug.o \
    87        detection.o \
    98        eventman.o \
  • engines/sword1/sword1.cpp

     
    5858        Common::File::addDefaultDirectory(_gameDataDir.getChild("MUSIC"));
    5959        Common::File::addDefaultDirectory(_gameDataDir.getChild("SPEECH"));
    6060        Common::File::addDefaultDirectory(_gameDataDir.getChild("VIDEO"));
     61        Common::File::addDefaultDirectory(_gameDataDir.getChild("SMACKSHI"));
    6162        Common::File::addDefaultDirectory(_gameDataDir.getChild("clusters"));
    6263        Common::File::addDefaultDirectory(_gameDataDir.getChild("music"));
    6364        Common::File::addDefaultDirectory(_gameDataDir.getChild("speech"));
    6465        Common::File::addDefaultDirectory(_gameDataDir.getChild("video"));
     66        Common::File::addDefaultDirectory(_gameDataDir.getChild("smackshi"));
    6567}
    6668
    6769SwordEngine::~SwordEngine() {
     
    475477        */
    476478        // make the demo flag depend on the Gamesettings for now, and not on what the datafiles look like
    477479        _systemVars.isDemo = (_features & GF_DEMO) != 0;
    478         _systemVars.cutscenePackVersion = 0;
    479 #ifdef USE_MPEG2
    480         if (Common::File::exists("intro.snd")) {
    481                 _systemVars.cutscenePackVersion = 1;
    482         }
    483 #endif
    484480}
    485481
    486482Common::Error SwordEngine::go() {
  • engines/sword1/sword1.h

     
    6767        uint8   language;
    6868        bool    isDemo;
    6969        bool    isMac;
    70 
    71         uint8   cutscenePackVersion;
    7270};
    7371
    7472class SwordEngine : public Engine {
  • engines/sword2/animation.cpp

     
    4242#include "sword2/sound.h"
    4343#include "sword2/animation.h"
    4444
     45#include "gui/message.h"
     46
    4547namespace Sword2 {
    4648
    4749///////////////////////////////////////////////////////////////////////////////
     
    9193        _leadOutFrame = (uint)-1;
    9294        _seamless = false;
    9395        _framesSkipped = 0;
    94         _forceFrame = false;
    9596        _currentText = 0;
    9697}
    9798
     
    103104        return _system->getMillis() - _pauseTicks;
    104105}
    105106
    106 void MoviePlayer::updatePalette(byte *pal, bool packed) {
    107         byte palette[4 * 256];
    108         byte *p = palette;
    109 
    110         uint32 maxWeight = 0;
    111         uint32 minWeight = 0xFFFFFFFF;
    112 
    113         for (int i = 0; i < 256; i++) {
    114                 int r = *pal++;
    115                 int g = *pal++;
    116                 int b = *pal++;
    117 
    118                 if (!packed)
    119                         pal++;
    120 
    121                 uint32 weight = 3 * r * r + 6 * g * g + 2 * b * b;
    122 
    123                 if (weight >= maxWeight) {
    124                         _white = i;
    125                         maxWeight = weight;
    126                 }
    127 
    128                 if (weight <= minWeight) {
    129                         _black = i;
    130                         minWeight = i;
    131                 }
    132 
    133                 *p++ = r;
    134                 *p++ = g;
    135                 *p++ = b;
    136                 *p++ = 0;
    137         }
    138 
    139         _vm->_screen->setPalette(0, 256, palette, RDPAL_INSTANT);
    140         _forceFrame = true;
    141 }
    142 
    143107void MoviePlayer::savePalette() {
    144108        memcpy(_originalPalette, _vm->_screen->getPalette(), sizeof(_originalPalette));
    145109}
     
    157121}
    158122
    159123bool MoviePlayer::checkSkipFrame() {
    160         if (_forceFrame) {
    161                 _forceFrame = false;
    162                 return false;
    163         }
    164 
    165124        if (_framesSkipped > 10) {
    166125                warning("Forced frame %d to be displayed", _currentFrame);
    167126                _framesSkipped = 0;
     
    512471        }
    513472}
    514473
    515 #ifdef USE_ZLIB
     474#ifdef USE_SWORD_SMACKS
    516475
    517476///////////////////////////////////////////////////////////////////////////////
    518 // Movie player for the new DXA movies
     477// Movie player for the original SMK movies
    519478///////////////////////////////////////////////////////////////////////////////
    520479
    521 MoviePlayerDXA::MoviePlayerDXA(Sword2Engine *vm, const char *name)
    522         : MoviePlayer(vm, name) {
    523         debug(0, "Creating DXA cutscene player");
     480MoviePlayerSMK::MoviePlayerSMK(Sword2Engine *vm, const char *name)
     481        : MoviePlayer(vm, name), SMKPlayer(vm->_mixer) {
     482        debug(0, "Creating SMK cutscene player");
    524483}
    525484
    526 MoviePlayerDXA::~MoviePlayerDXA() {
     485MoviePlayerSMK::~MoviePlayerSMK() {
    527486        closeFile();
    528487}
    529488
    530 void MoviePlayerDXA::setPalette(byte *pal) {
    531         updatePalette(pal);
    532 }
    533 
    534 bool MoviePlayerDXA::decodeFrame() {
     489bool MoviePlayerSMK::decodeFrame() {
    535490        decodeNextFrame();
    536491        copyFrameToBuffer(_frameBuffer, _frameX, _frameY, _vm->_screen->getScreenWide());
    537492        return true;
    538493}
    539494
    540 bool MoviePlayerDXA::load() {
     495bool MoviePlayerSMK::load() {
    541496        if (!MoviePlayer::load())
    542497                return false;
    543498
    544499        char filename[20];
    545500
    546         snprintf(filename, sizeof(filename), "%s.dxa", _name);
     501        snprintf(filename, sizeof(filename), "%s.smk", _name);
    547502
    548503        if (loadFile(filename)) {
    549                 // The Broken Sword games always use external audio tracks.
    550                 if (_fileStream->readUint32BE() != MKID_BE('NULL'))
    551                         return false;
    552 
    553504                _frameBuffer = _vm->_screen->getScreen();
    554505
    555506                _frameWidth = getWidth();
     
    566517
    567518#endif
    568519
    569 #ifdef USE_MPEG2
     520#ifdef USE_ZLIB
    570521
    571522///////////////////////////////////////////////////////////////////////////////
    572 // Movie player for the old MPEG movies
     523// Movie player for the new DXA movies
    573524///////////////////////////////////////////////////////////////////////////////
    574525
    575 MoviePlayerMPEG::MoviePlayerMPEG(Sword2Engine *vm, const char *name)
     526MoviePlayerDXA::MoviePlayerDXA(Sword2Engine *vm, const char *name)
    576527        : MoviePlayer(vm, name) {
    577 #ifdef BACKEND_8BIT
    578         debug(0, "Creating MPEG cutscene player (8-bit)");
    579 #else
    580         debug(0, "Creating MPEG cutscene player (16-bit)");
    581 #endif
     528        debug(0, "Creating DXA cutscene player");
    582529}
    583530
    584 MoviePlayerMPEG::~MoviePlayerMPEG() {
    585         delete _anim;
    586         _anim = NULL;
     531MoviePlayerDXA::~MoviePlayerDXA() {
     532        closeFile();
    587533}
    588534
    589 bool MoviePlayerMPEG::load() {
    590         if (!MoviePlayer::load())
    591                 return false;
    592 
    593         _anim = new AnimationState(_vm, this);
    594 
    595         if (!_anim->init(_name)) {
    596                 delete _anim;
    597                 _anim = NULL;
    598                 return false;
    599         }
    600 
    601 #ifdef BACKEND_8BIT
    602         _frameBuffer = _vm->_screen->getScreen();
    603 #endif
    604 
     535bool MoviePlayerDXA::decodeFrame() {
     536        decodeNextFrame();
     537        copyFrameToBuffer(_frameBuffer, _frameX, _frameY, _vm->_screen->getScreenWide());
    605538        return true;
    606539}
    607540
    608 bool MoviePlayerMPEG::decodeFrame() {
    609         bool result = _anim->decodeFrame();
     541bool MoviePlayerDXA::load() {
     542        if (!MoviePlayer::load())
     543                return false;
    610544
    611 #ifdef BACKEND_8BIT
    612         _frameWidth = _anim->getFrameWidth();
    613         _frameHeight = _anim->getFrameHeight();
     545        char filename[20];
    614546
    615         _frameX = (_vm->_screen->getScreenWide() - _frameWidth) / 2;
    616         _frameY = (_vm->_screen->getScreenDeep() - _frameHeight) / 2;
    617 #endif
     547        snprintf(filename, sizeof(filename), "%s.dxa", _name);
    618548
    619         return result;
    620 }
     549        if (loadFile(filename)) {
     550                // The Broken Sword games always use external audio tracks.
     551                if (_fileStream->readUint32BE() != MKID_BE('NULL'))
     552                        return false;
    621553
    622 AnimationState::AnimationState(Sword2Engine *vm, MoviePlayer *player)
    623         : BaseAnimationState(vm->_system, 640, 480) {
    624         _vm = vm;
    625         _player = player;
    626 }
     554                _frameBuffer = _vm->_screen->getScreen();
    627555
    628 AnimationState::~AnimationState() {
    629 }
     556                _frameWidth = getWidth();
     557                _frameHeight = getHeight();
    630558
    631 #ifdef BACKEND_8BIT
     559                _frameX = (_vm->_screen->getScreenWide() - _frameWidth) / 2;
     560                _frameY = (_vm->_screen->getScreenDeep() - _frameHeight) / 2;
    632561
    633 void AnimationState::setPalette(byte *pal) {
    634         _player->updatePalette(pal, false);
    635 }
    636 
    637 #else
    638 
    639 void MoviePlayerMPEG::handleScreenChanged() {
    640         _anim->handleScreenChanged();
    641 }
    642 
    643 void MoviePlayerMPEG::clearFrame() {
    644         _anim->clearFrame();
    645 }
    646 
    647 void MoviePlayerMPEG::drawFrame() {
    648 }
    649 
    650 void MoviePlayerMPEG::updateScreen() {
    651         _anim->updateScreen();
    652 }
    653 
    654 void MoviePlayerMPEG::drawTextObject() {
    655         if (_textObject.textMem && _textSurface) {
    656                 _anim->drawTextObject(&_textObject.textSprite, _textSurface);
     562                return true;
    657563        }
    658 }
    659564
    660 void MoviePlayerMPEG::undrawTextObject() {
    661         // As long as we only have subtitles for full-sized cutscenes, we don't
    662         // really need to implement this function.
     565        return false;
    663566}
    664567
    665 void AnimationState::drawTextObject(SpriteInfo *s, byte *src) {
    666         int moviePitch = _movieScale * _movieWidth;
    667         int textX = _movieScale * s->x;
    668         int textY = _movieScale * (_frameHeight - s->h - 12);
    669 
    670         OverlayColor *dst = _overlay + textY * moviePitch + textX;
    671 
    672         Graphics::PixelFormat format = _sys->getOverlayFormat();
    673         OverlayColor pen = format.RGBToColor(255, 255, 255);
    674         OverlayColor border = format.RGBToColor(0, 0, 0);
    675 
    676         // TODO: Use the AdvMame scalers for the text? Pre-scale it?
    677 
    678         for (int y = 0; y < s->h; y++) {
    679                 OverlayColor *ptr = dst;
    680 
    681                 for (int x = 0; x < s->w; x++) {
    682                         switch (src[x]) {
    683                         case 1:
    684                                 *ptr++ = border;
    685                                 if (_movieScale > 1) {
    686                                         *ptr++ = border;
    687                                         if (_movieScale > 2)
    688                                                 *ptr++ = border;
    689                                 }
    690                                 break;
    691                         case 255:
    692                                 *ptr++ = pen;
    693                                 if (_movieScale > 1) {
    694                                         *ptr++ = pen;
    695                                         if (_movieScale > 2)
    696                                                 *ptr++ = pen;
    697                                 }
    698                                 break;
    699                         default:
    700                                 ptr += _movieScale;
    701                                 break;
    702                         }
    703                 }
    704 
    705                 if (_movieScale > 1) {
    706                         memcpy(dst + moviePitch, dst, _movieScale * s->w * sizeof(OverlayColor));
    707                         if (_movieScale > 2)
    708                                 memcpy(dst + 2 * moviePitch, dst, _movieScale * s->w * sizeof(OverlayColor));
    709                 }
    710 
    711                 dst += _movieScale * moviePitch;
    712                 src += s->w;
    713         }
    714 }
    715568#endif
    716569
    717 void AnimationState::clearFrame() {
    718 #ifdef BACKEND_8BIT
    719         memset(_vm->_screen->getScreen(), 0, _movieWidth * _movieHeight);
    720 #else
    721         Graphics::PixelFormat format = _sys->getOverlayFormat();
    722         OverlayColor black = format.RGBToColor(0, 0, 0);
    723 
    724         for (int i = 0; i < _movieScale * _movieWidth * _movieScale * _movieHeight; i++)
    725                 _overlay[i] = black;
    726 #endif
    727 }
    728 
    729 void AnimationState::drawYUV(int width, int height, byte *const *dat) {
    730         _frameWidth = width;
    731         _frameHeight = height;
    732 
    733 #ifdef BACKEND_8BIT
    734         byte *buf = _vm->_screen->getScreen() + ((480 - height) / 2) * RENDERWIDE + (640 - width) / 2;
    735 
    736         int x, y;
    737 
    738         int ypos = 0;
    739         int cpos = 0;
    740         int linepos = 0;
    741 
    742         for (y = 0; y < height; y += 2) {
    743                 for (x = 0; x < width; x += 2) {
    744                         int i = ((((dat[2][cpos] + ROUNDADD) >> SHIFT) * (BITDEPTH + 1)) + ((dat[1][cpos] + ROUNDADD) >> SHIFT)) * (BITDEPTH + 1);
    745                         cpos++;
    746 
    747                         buf[linepos               ] = _lut[i + ((dat[0][        ypos  ] + ROUNDADD) >> SHIFT)];
    748                         buf[RENDERWIDE + linepos++] = _lut[i + ((dat[0][width + ypos++] + ROUNDADD) >> SHIFT)];
    749                         buf[linepos               ] = _lut[i + ((dat[0][        ypos  ] + ROUNDADD) >> SHIFT)];
    750                         buf[RENDERWIDE + linepos++] = _lut[i + ((dat[0][width + ypos++] + ROUNDADD) >> SHIFT)];
    751                 }
    752                 linepos += (2 * RENDERWIDE - width);
    753                 ypos += width;
    754         }
    755 #else
    756         plotYUV(width, height, dat);
    757 #endif
    758 }
    759 
    760 #endif
    761 
    762570///////////////////////////////////////////////////////////////////////////////
    763571// Dummy player for subtitled speech only
    764572///////////////////////////////////////////////////////////////////////////////
     
    802610
    803611                byte msgNoCutscenesRU[] = "Po\344uk - to\344\345ko pev\345: hagmute k\344abuwy Ucke\343n, u\344u nocetute ca\343t npoekta u ckava\343te budeo po\344uku";
    804612
    805 #if defined(USE_MPEG2) || defined(USE_ZLIB)
     613#if defined(USE_ZLIB)
    806614                byte msgNoCutscenes[] = "Cutscene - Narration Only: Press ESC to exit, or visit www.scummvm.org to download cutscene videos";
    807615#else
    808                 byte msgNoCutscenes[] = "Cutscene - Narration Only: Press ESC to exit, or recompile ScummVM with MPEG2 or ZLib support";
     616                byte msgNoCutscenes[] = "Cutscene - Narration Only: Press ESC to exit, or recompile ScummVM with ZLib support";
    809617#endif
    810618
    811619                byte *msg;
     
    885693MoviePlayer *makeMoviePlayer(Sword2Engine *vm, const char *name) {
    886694        static char filename[20];
    887695
     696#ifdef USE_SWORD_SMACKS
     697        snprintf(filename, sizeof(filename), "%s.smk", name);
     698
     699        if (Common::File::exists(filename)) {
     700                return new MoviePlayerSMK(vm, name);
     701        }
     702#endif
     703
    888704#ifdef USE_ZLIB
    889705        snprintf(filename, sizeof(filename), "%s.dxa", name);
    890706
     
    893709        }
    894710#endif
    895711
    896 #ifdef USE_MPEG2
    897712        snprintf(filename, sizeof(filename), "%s.mp2", name);
    898713
    899714        if (Common::File::exists(filename)) {
    900                 return new MoviePlayerMPEG(vm, name);
     715                GUI::MessageDialog dialog("MPEG2 cutscenes are no longer supported", "OK");
     716                dialog.runModal();
    901717        }
    902 #endif
    903718
    904719        return new MoviePlayerDummy(vm, name);
    905720}
  • engines/sword2/animation.h

     
    2929#define SWORD2_ANIMATION_H
    3030
    3131#include "graphics/video/dxa_player.h"
    32 #include "graphics/video/mpeg_player.h"
     32#ifdef USE_SWORD_SMACKS
     33#include "graphics/video/smk_player.h"
     34#endif
    3335#include "sound/mixer.h"
    3436
    3537#include "sword2/screen.h"
     
    9799        bool _seamless;
    98100
    99101        int _framesSkipped;
    100         bool _forceFrame;
    101102
    102103        static const MovieInfo _movies[];
    103104
     
    126127        MoviePlayer(Sword2Engine *vm, const char *name);
    127128        virtual ~MoviePlayer();
    128129
    129         void updatePalette(byte *pal, bool packed = true);
    130130        virtual bool load();
    131131        bool userInterrupt();
    132132        void play(SequenceTextInfo *textList, uint32 numLines, int32 leadIn, int32 leadOut);
     
    148148        bool load();
    149149};
    150150
    151 #ifdef USE_MPEG2
    152 class AnimationState : public ::Graphics::BaseAnimationState {
    153 private:
    154         Sword2Engine *_vm;
    155         MoviePlayer *_player;
    156 
    157 public:
    158         AnimationState(Sword2Engine *vm, MoviePlayer *player);
    159         ~AnimationState();
    160 
    161 #ifndef BACKEND_8BIT
    162         void drawTextObject(SpriteInfo *s, byte *src);
    163 #endif
    164 
    165         void clearFrame();
    166 
    167 private:
    168         void drawYUV(int width, int height, byte *const *dat);
    169 
    170 #ifdef BACKEND_8BIT
    171         void setPalette(byte *pal);
    172 #endif
    173 };
    174 
    175 class MoviePlayerMPEG : public MoviePlayer {
     151#ifdef USE_SWORD_SMACKS
     152class MoviePlayerSMK : public MoviePlayer, ::Graphics::SMKPlayer {
    176153protected:
    177         AnimationState *_anim;
     154        bool decodeFrame();
    178155
    179         virtual bool decodeFrame();
    180 
    181 #ifndef BACKEND_8BIT
    182         void handleScreenChanged();
    183         void clearFrame();
    184         void drawFrame();
    185         void updateScreen();
    186         void drawTextObject();
    187         void undrawTextObject();
    188 #endif
    189 
    190156public:
    191         MoviePlayerMPEG(Sword2Engine *vm, const char *name);
    192         ~MoviePlayerMPEG();
     157        MoviePlayerSMK(Sword2Engine *vm, const char *name);
     158        ~MoviePlayerSMK();
    193159
    194160        bool load();
    195161};
     
    198164#ifdef USE_ZLIB
    199165class MoviePlayerDXA : public MoviePlayer, ::Graphics::DXAPlayer {
    200166protected:
    201         void setPalette(byte *pal);
    202167        bool decodeFrame();
    203168
    204169public:
  • engines/sword2/sword2.cpp

     
    252252        Common::File::addDefaultDirectory(_gameDataDir.getChild("CLUSTERS"));
    253253        Common::File::addDefaultDirectory(_gameDataDir.getChild("SWORD2"));
    254254        Common::File::addDefaultDirectory(_gameDataDir.getChild("VIDEO"));
     255        Common::File::addDefaultDirectory(_gameDataDir.getChild("SMACKS"));
    255256        Common::File::addDefaultDirectory(_gameDataDir.getChild("clusters"));
    256257        Common::File::addDefaultDirectory(_gameDataDir.getChild("sword2"));
    257258        Common::File::addDefaultDirectory(_gameDataDir.getChild("video"));
     259        Common::File::addDefaultDirectory(_gameDataDir.getChild("smacks"));
    258260
    259261        if (0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword2demo"))
    260262                _features = GF_DEMO;
  • graphics/video/video_player.h

     
    141141         */
    142142        virtual bool decodeNextFrame() = 0;
    143143
     144        /**
     145         * Used to read the sound header from DXA files. It's not pretty,
     146         * but it's slightly better than exposing _fileStream
     147         */
     148        uint32 readSoundHeader() { return _fileStream->readUint32BE(); }
     149
    144150protected:
    145151        struct {
    146152                uint32 width;