diff options
author | Filippos Karapetis | 2016-09-24 11:49:54 +0300 |
---|---|---|
committer | Filippos Karapetis | 2016-10-03 00:33:45 +0300 |
commit | 0152b7c47f0eef04bd01ae6e1cb808d25ccdd9a0 (patch) | |
tree | 5572e128ccaafb11c62c65b57128fc04a922d690 /engines/chewy | |
parent | f017940ca08e32a206982376df0bdc334acdea55 (diff) | |
download | scummvm-rg350-0152b7c47f0eef04bd01ae6e1cb808d25ccdd9a0.tar.gz scummvm-rg350-0152b7c47f0eef04bd01ae6e1cb808d25ccdd9a0.tar.bz2 scummvm-rg350-0152b7c47f0eef04bd01ae6e1cb808d25ccdd9a0.zip |
CHEWY: Add initial video (CFO) player
The game's videos are modified FLICs. There are some changes needed
to our FLIC decoder, which are included in a separate commit
Diffstat (limited to 'engines/chewy')
-rw-r--r-- | engines/chewy/chewy.cpp | 1 | ||||
-rw-r--r-- | engines/chewy/console.cpp | 9 | ||||
-rw-r--r-- | engines/chewy/graphics.cpp | 41 | ||||
-rw-r--r-- | engines/chewy/graphics.h | 1 | ||||
-rw-r--r-- | engines/chewy/module.mk | 3 | ||||
-rw-r--r-- | engines/chewy/resource.cpp | 8 | ||||
-rw-r--r-- | engines/chewy/resource.h | 7 | ||||
-rw-r--r-- | engines/chewy/video/cfo_decoder.cpp | 261 | ||||
-rw-r--r-- | engines/chewy/video/cfo_decoder.h | 59 |
9 files changed, 386 insertions, 4 deletions
diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp index b5271d5969..b2b8cd1b22 100644 --- a/engines/chewy/chewy.cpp +++ b/engines/chewy/chewy.cpp @@ -72,6 +72,7 @@ Common::Error ChewyEngine::run() { initialize(); + //_graphics->playVideo(0); _graphics->drawImage("episode1.tgp", 0); //_sound->playSpeech(1); //_sound->playSound(1); diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp index bf7e49c2d0..deaa1e3a62 100644 --- a/engines/chewy/console.cpp +++ b/engines/chewy/console.cpp @@ -157,11 +157,14 @@ bool Console::Cmd_PlayVideo(int argc, const char **argv) { return true; } + detach(); // close the console + int resNum = atoi(argv[1]); - debugPrintf("TODO: Play video %d", resNum); - // TODO + Graphics *g = new Graphics(); + g->playVideo(resNum); + delete g; - return true; + return false; } bool Console::Cmd_VideoInfo(int argc, const char **argv) { diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp index c3b29febff..887bb75bb4 100644 --- a/engines/chewy/graphics.cpp +++ b/engines/chewy/graphics.cpp @@ -21,10 +21,12 @@ */ #include "common/system.h" +#include "common/events.h" #include "graphics/palette.h" #include "chewy/graphics.h" #include "chewy/resource.h" +#include "chewy/video/cfo_decoder.h" namespace Chewy { @@ -41,4 +43,43 @@ void Graphics::drawImage(Common::String filename, int imageNum) { delete res; } +void Graphics::playVideo(uint num) { + CfoDecoder *cfoDecoder = new CfoDecoder(); + VideoResource *videoResource = new VideoResource("cut.tap"); + Common::SeekableReadStream *videoStream = videoResource->getVideoStream(num); + + if (!cfoDecoder->loadStream(videoStream)) { + delete videoResource; + delete cfoDecoder; + return; + } + + uint16 x = (g_system->getWidth() - cfoDecoder->getWidth()) / 2; + uint16 y = (g_system->getHeight() - cfoDecoder->getHeight()) / 2; + bool skipVideo = false; + + cfoDecoder->start(); + + while (!g_engine->shouldQuit() && !cfoDecoder->endOfVideo() && !skipVideo) { + if (cfoDecoder->needsUpdate()) { + const ::Graphics::Surface *frame = cfoDecoder->decodeNextFrame(); + if (frame) { + g_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h); + + if (cfoDecoder->hasDirtyPalette()) + g_system->getPaletteManager()->setPalette(cfoDecoder->getPalette(), 0, 256); + + g_system->updateScreen(); + } + } + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) + skipVideo = true; + } + + g_system->delayMillis(10); + } +} } // End of namespace Chewy diff --git a/engines/chewy/graphics.h b/engines/chewy/graphics.h index 601b419171..c7d303d2a2 100644 --- a/engines/chewy/graphics.h +++ b/engines/chewy/graphics.h @@ -33,6 +33,7 @@ public: ~Graphics() {} void drawImage(Common::String filename, int imageNum); + void playVideo(uint num); private: }; diff --git a/engines/chewy/module.mk b/engines/chewy/module.mk index 5b96ab9ba3..2e2535f47a 100644 --- a/engines/chewy/module.mk +++ b/engines/chewy/module.mk @@ -6,7 +6,8 @@ MODULE_OBJS = \ detection.o \ graphics.o \ resource.o \ - sound.o + sound.o \ + video/cfo_decoder.o # This module can be built as a plugin ifeq ($(ENABLE_CHEWY), DYNAMIC_PLUGIN) diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp index 6a1b860d5b..a873edf563 100644 --- a/engines/chewy/resource.cpp +++ b/engines/chewy/resource.cpp @@ -22,6 +22,7 @@ #include "common/debug.h" #include "common/stream.h" +#include "common/substream.h" #include "common/textconsole.h" #include "chewy/chewy.h" @@ -247,4 +248,11 @@ VideoChunk *VideoResource::getVideoHeader(uint num) { return vid; } +Common::SeekableReadStream *VideoResource::getVideoStream(uint num) { + assert(num < _chunkList.size()); + + Chunk *chunk = &_chunkList[num]; + return new Common::SeekableSubReadStream(&_stream, chunk->pos, chunk->pos + chunk->size); +} + } // End of namespace Chewy diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h index 238f0f2b60..d9665ceb4a 100644 --- a/engines/chewy/resource.h +++ b/engines/chewy/resource.h @@ -31,6 +31,7 @@ #include "common/hashmap.h" #include "common/hash-str.h" #include "common/random.h" +#include "common/stream.h" namespace Chewy { @@ -105,6 +106,11 @@ struct VideoChunk { uint32 firstFrameOffset; }; +enum VideoFrameType { + kVideoFrameNormal = 0xF1FA, + kVideoFrameCustom = 0xFAF1 +}; + typedef Common::Array<Chunk> ChunkList; typedef Common::Array<TBFChunk> TBFChunkList; @@ -157,6 +163,7 @@ public: ~VideoResource() {} VideoChunk *getVideoHeader(uint num); + Common::SeekableReadStream *getVideoStream(uint num); }; } // End of namespace Chewy diff --git a/engines/chewy/video/cfo_decoder.cpp b/engines/chewy/video/cfo_decoder.cpp new file mode 100644 index 0000000000..99fd665523 --- /dev/null +++ b/engines/chewy/video/cfo_decoder.cpp @@ -0,0 +1,261 @@ +/* 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. + * + */ + +#include "common/stream.h" +#include "video/flic_decoder.h" + +#include "chewy/video/cfo_decoder.h" + +namespace Chewy { + +enum CustomSubChunk { + kChunkFadeIn = 0, + kChunkFadeOut = 1, + kChunkLoadMusic = 2, + kChunkLoadRaw = 3, + kChunkLoadVoc = 4, + kChunkPlayMusic = 5, + kChunkPlaySeq = 6, + kChunkPlayPattern = 7, + kChunkStopMusic = 8, + kChunkWaitMusicEnd = 9, + kChunkSetMusicVolume = 10, + kChunkSetLoopMode = 11, + kChunkPlayRaw = 12, + kChunkPlayVoc = 13, + kChunkSetSoundVolume = 14, + kChunkSetChannelVolume = 15, + kChunkFreeSoundEffect = 16, + kChunkMusicFadeIn = 17, + kChunkMusicFadeOut = 18, + kChunkSetStero = 19, + kChunkSetSpeed = 20, + kChunkClearScreen = 21 +}; + +bool CfoDecoder::loadStream(Common::SeekableReadStream *stream) { + close(); + + if (stream->readUint32BE() != MKTAG('C', 'F', 'O', '\0')) + error("Corrupt video resource"); + + stream->readUint32LE(); // always 0 + + uint16 frameCount = stream->readUint16LE(); + uint16 width = stream->readUint16LE(); + uint16 height = stream->readUint16LE(); + + addTrack(new CfoVideoTrack(stream, frameCount, width, height)); + return true; +} + +CfoDecoder::CfoVideoTrack::CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height) : + Video::FlicDecoder::FlicVideoTrack(stream, frameCount, width, height, true) { + readHeader(); +} + +void CfoDecoder::CfoVideoTrack::readHeader() { + _frameDelay = _startFrameDelay = _fileStream->readUint32LE(); + _offsetFrame1 = _fileStream->readUint32LE(); + _offsetFrame2 = 0; // doesn't exist, as CFO videos aren't rewindable + + _fileStream->seek(_offsetFrame1); +} + +#define FRAME_TYPE 0xF1FA +#define CUSTOM_FRAME_TYPE 0xFAF1 + +const Graphics::Surface *CfoDecoder::CfoVideoTrack::decodeNextFrame() { + uint16 frameType; + + // Read chunk + /*uint32 frameSize =*/ _fileStream->readUint32LE(); + frameType = _fileStream->readUint16LE(); + + switch (frameType) { + case FRAME_TYPE: + handleFrame(); + break; + case CUSTOM_FRAME_TYPE: + handleCustomFrame(); + break; + default: + error("CfoDecoder::decodeFrame(): unknown main chunk type (type = 0x%02X)", frameType); + break; + } + + _curFrame++; + _nextFrameStartTime += _frameDelay; + + return _surface; +} + +#define FLI_SETPAL 4 +#define FLI_SS2 7 +#define FLI_BRUN 15 +#define FLI_COPY 16 +#define PSTAMP 18 + +void CfoDecoder::CfoVideoTrack::handleFrame() { + uint16 chunkCount = _fileStream->readUint16LE(); + + // Read subchunks + for (uint32 i = 0; i < chunkCount; ++i) { + uint32 frameSize = _fileStream->readUint32LE(); + uint16 frameType = _fileStream->readUint16LE(); + uint8 *data = new uint8[frameSize - 6]; + _fileStream->read(data, frameSize - 6); + + switch (frameType) { + case FLI_SETPAL: + unpackPalette(data); + _dirtyPalette = true; + break; + case FLI_SS2: + decodeDeltaFLC(data); + break; + case FLI_BRUN: + decodeByteRun(data); + break; + case FLI_COPY: + copyFrame(data); + break; + case PSTAMP: + /* PSTAMP - skip for now */ + break; + default: + error("FlicDecoder::decodeNextFrame(): unknown subchunk type (type = 0x%02X)", frameType); + break; + } + + delete[] data; + } +} + +void CfoDecoder::CfoVideoTrack::handleCustomFrame() { + uint16 chunkCount = _fileStream->readUint16LE(); + + // Read subchunks + for (uint32 i = 0; i < chunkCount; ++i) { + uint32 frameSize = _fileStream->readUint32LE(); + uint16 frameType = _fileStream->readUint16LE(); + uint8 *data = new uint8[frameSize]; + _fileStream->read(data, frameSize); + + switch (frameType) { + case kChunkFadeIn: + warning("kChunkFadeIn"); + // TODO + break; + case kChunkFadeOut: + warning("kChunkFadeOut"); + // TODO + break; + case kChunkLoadMusic: + warning("kChunkLoadMusic"); + // TODO + break; + case kChunkLoadRaw: + warning("kChunkLoadRaw"); + // TODO + break; + case kChunkLoadVoc: + warning("kChunkLoadVoc"); + // TODO + break; + case kChunkPlayMusic: + warning("kChunkPlayMusic"); + break; + case kChunkPlaySeq: + warning("kChunkPlaySeq"); + // TODO + break; + case kChunkPlayPattern: + warning("kChunkPlayPattern"); + // TODO + break; + case kChunkStopMusic: + warning("kChunkStopMusic"); + // TODO + break; + case kChunkWaitMusicEnd: + warning("kChunkWaitMusicEnd"); + // TODO + break; + case kChunkSetMusicVolume: + warning("kChunkSetMusicVolume"); + // TODO + break; + case kChunkSetLoopMode: + warning("kChunkSetLoopMode"); + // TODO + break; + case kChunkPlayRaw: + warning("kChunkPlayRaw"); + // TODO + break; + case kChunkPlayVoc: + warning("kChunkPlayVoc"); + // TODO + break; + case kChunkSetSoundVolume: + warning("kChunkSetSoundVolume"); + // TODO + break; + case kChunkSetChannelVolume: + warning("kChunkSetChannelVolume"); + // TODO + break; + case kChunkFreeSoundEffect: + warning("kChunkFreeSoundEffect"); + // TODO + break; + case kChunkMusicFadeIn: + warning("kChunkMusicFadeIn"); + // TODO + break; + case kChunkMusicFadeOut: + warning("kChunkMusicFadeOut"); + // TODO + break; + case kChunkSetStero: + warning("kChunkSetStero"); + // TODO + break; + case kChunkSetSpeed: + warning("kChunkSetSpeed"); + // TODO + break; + case kChunkClearScreen: + warning("kChunkClearScreen"); + // TODO + break; + default: + error("Unknown subchunk: %d", frameType); + break; + } + + delete[] data; + } +} + +} // End of namespace Chewy diff --git a/engines/chewy/video/cfo_decoder.h b/engines/chewy/video/cfo_decoder.h new file mode 100644 index 0000000000..57c083858f --- /dev/null +++ b/engines/chewy/video/cfo_decoder.h @@ -0,0 +1,59 @@ +/* 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. + * + */ + +#ifndef CHEWY_VIDEO_CFO_DECODER_H +#define CHEWY_VIDEO_CFO_DECODER_H + + +#include "graphics/surface.h" +#include "video/flic_decoder.h" + +namespace Chewy { + +// A FLIC decoder, with a modified header and additional custom frames +class CfoDecoder : public Video::FlicDecoder { +public: + CfoDecoder() : Video::FlicDecoder() {} + virtual ~CfoDecoder() {} + + bool loadStream(Common::SeekableReadStream *stream); + +protected: + class CfoVideoTrack : public Video::FlicDecoder::FlicVideoTrack { + public: + CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height); + ~CfoVideoTrack() {} + + void readHeader(); + + bool isRewindable() const { return false; } + bool rewind() { return false; } + + const ::Graphics::Surface *decodeNextFrame(); + void handleFrame(); + void handleCustomFrame(); + }; +}; + +} // End of namespace Chewy + +#endif |