From da7652deb3425427de3693cb21ef1bf8af3e8d96 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 15 Oct 2009 15:17:54 +0000 Subject: Changed the KQ6 floppy SEQ decoder to use the common VideoPlayer interface. Some cleanup svn-id: r45124 --- engines/sci/engine/kgraphics.cpp | 59 ++++----------- engines/sci/gfx/seq_decoder.cpp | 154 ++++++++++++++++++++++++--------------- engines/sci/gfx/seq_decoder.h | 57 ++++++++------- engines/sci/sci.cpp | 10 +-- 4 files changed, 145 insertions(+), 135 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 7fc77bbdff..c8782eb933 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1059,52 +1059,23 @@ static reg_t kShowMovie_Windows(EngineState *s, int argc, reg_t *argv) { static reg_t kShowMovie_DOS(EngineState *s, int argc, reg_t *argv) { Common::String filename = s->_segMan->getString(argv[0]); int delay = argv[1].toUint16(); // Time between frames in ticks - SeqDecoder seq; - if (!seq.loadFile(filename, s->resMan) && - !seq.loadFile(Common::String("SEQ/") + filename, s->resMan)) { + Common::Event stopEvent; + Common::List stopEvents; + stopEvents.clear(); + stopEvent.type = Common::EVENT_KEYDOWN; + stopEvent.kbd = Common::KEYCODE_ESCAPE; + stopEvents.push_back(stopEvent); + + Graphics::SeqDecoder *seqDecoder = new Graphics::SeqDecoder(); + Graphics::VideoPlayer *player = new Graphics::VideoPlayer(seqDecoder); + if (seqDecoder->loadFile(filename.c_str(), delay)) + player->playVideo(stopEvents); + else warning("Failed to open movie file %s", filename.c_str()); - return s->r_acc; - } - - bool play = true; - while (play) { - uint32 startTime = g_system->getMillis(); - SeqFrame *frame = seq.getFrame(play); - Common::Rect frameRect = frame->frameRect; - - byte *scr = (byte *)g_system->lockScreen()->pixels; - int cur = 0; - for (int y = frameRect.top; y < frameRect.bottom; y++) { - for (int x = frameRect.left; x < frameRect.right; x++) { - if (frame->data[cur] != frame->colorKey) - scr[y * 320 + x] = frame->data[cur]; - cur++; - } - } - g_system->unlockScreen(); - g_system->updateScreen(); - - delete frame->data; - delete frame; - - // Wait before showing the next frame - while (play && (g_system->getMillis() < startTime + (delay * 1000 / 60))) { - // FIXME: we should probably make a function that handles quitting in these kinds of situations - Common::Event curEvent; - Common::EventManager *eventMan = g_system->getEventManager(); - - // Process quit events - while (eventMan->pollEvent(curEvent)) { - if (curEvent.type == Common::EVENT_QUIT) { - play = false; - quit_vm(); - } - } - - g_system->delayMillis(10); - } - } + seqDecoder->closeFile(); + delete player; + delete seqDecoder; return s->r_acc; } diff --git a/engines/sci/gfx/seq_decoder.cpp b/engines/sci/gfx/seq_decoder.cpp index dc119551d0..829eea004a 100644 --- a/engines/sci/gfx/seq_decoder.cpp +++ b/engines/sci/gfx/seq_decoder.cpp @@ -23,40 +23,77 @@ * */ +#include "common/debug.h" +#include "common/endian.h" #include "common/archive.h" +#include "common/system.h" +#include "common/util.h" + +#include "graphics/surface.h" + #include "sci/gfx/seq_decoder.h" -#include "sci/resource.h" -#include "sci/gui/gui_screen.h" -#include "sci/gui/gui_palette.h" -namespace Sci { +namespace Graphics { + +enum seqPalTypes { + kSeqPalVariable = 0, + kSeqPalConstant = 1 +}; + +enum seqFrameTypes { + kSeqFrameFull = 0, + kSeqFrameDiff = 1 +}; SeqDecoder::~SeqDecoder() { closeFile(); } -bool SeqDecoder::loadFile(Common::String fileName, ResourceManager *resMan) { +bool SeqDecoder::loadFile(const char *fileName, int frameDelay) { closeFile(); _fileStream = SearchMan.createReadStreamForMember(fileName); if (!_fileStream) return false; - _frameCount = _fileStream->readUint16LE(); + // Seek to the first frame + _videoInfo.currentFrame = 0; + + _videoInfo.width = 320; + _videoInfo.height = 200; + _videoInfo.frameCount = _fileStream->readUint16LE(); + // Our frameDelay is calculated in 1/100 ms, so we convert it here + _videoInfo.frameDelay = 100 * frameDelay * 1000 / 60; + _videoFrameBuffer = new byte[_videoInfo.width * _videoInfo.height]; + + // Set palette int paletteSize = _fileStream->readUint32LE(); byte *paletteData = new byte[paletteSize]; _fileStream->read(paletteData, paletteSize); - GuiPalette seqPalette; - SciGuiScreen *videoScreen = new SciGuiScreen(320, 200, 1); - SciGuiPalette *pal = new SciGuiPalette(resMan, videoScreen, false); - pal->createFromData(paletteData, &seqPalette); - pal->set(&seqPalette, 2); - delete pal; - delete[] paletteData; - delete videoScreen; - _currentFrame = 0; + // SCI1.1 palette + byte palFormat = paletteData[32]; + uint16 palColorStart = READ_LE_UINT16(paletteData + 25); + uint16 palColorCount = READ_LE_UINT16(paletteData + 29); + + byte palette[256 * 4]; + int palOffset = 37; + + for (uint16 colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { + if (palFormat == kSeqPalVariable) + palOffset++; + palette[colorNo * 4 + 0] = paletteData[palOffset++]; + palette[colorNo * 4 + 1] = paletteData[palOffset++]; + palette[colorNo * 4 + 2] = paletteData[palOffset++]; + palette[colorNo * 4 + 3] = 0; + } + + g_system->setPalette(palette, 0, 256); + + delete paletteData; + + _videoInfo.firstframeOffset = _fileStream->pos(); return true; } @@ -67,26 +104,60 @@ void SeqDecoder::closeFile() { delete _fileStream; _fileStream = 0; + + delete[] _videoFrameBuffer; + _videoFrameBuffer = 0; +} + +bool SeqDecoder::decodeNextFrame() { + int16 frameWidth = _fileStream->readUint16LE(); + int16 frameHeight = _fileStream->readUint16LE(); + int16 frameLeft = _fileStream->readUint16LE(); + int16 frameTop = _fileStream->readUint16LE(); + byte colorKey = _fileStream->readByte(); + byte frameType = _fileStream->readByte(); + _fileStream->skip(2); + uint16 frameSize = _fileStream->readUint16LE(); + _fileStream->skip(2); + uint16 rleSize = _fileStream->readUint16LE(); + _fileStream->skip(6); + uint32 offset = _fileStream->readUint32LE(); + + _fileStream->seek(offset); + + if (_videoInfo.currentFrame == 0) + _videoInfo.startTime = g_system->getMillis(); + + if (frameType == kSeqFrameFull) { + assert (frameLeft == 0); + assert (frameWidth == 320); + _fileStream->read(_videoFrameBuffer + 320 * frameTop, frameSize); + } else { + byte *buf = new byte[frameSize]; + _fileStream->read(buf, frameSize); + decodeFrame(buf, rleSize, buf + rleSize, frameSize - rleSize, _videoFrameBuffer + 320 * frameTop, frameLeft, frameWidth, frameHeight, colorKey); + delete buf; + } + + return ++_videoInfo.currentFrame < _videoInfo.frameCount; } #define WRITE_TO_BUFFER(n) \ - if (writeRow * width + writeCol + (n) > width * height) { \ + if (writeRow * 320 + writeCol + (n) > 320 * height) { \ warning("SEQ player: writing out of bounds, aborting"); \ return false; \ } \ if (litPos + (n) > litSize) { \ warning("SEQ player: reading out of bounds, aborting"); \ } \ - memcpy(dest + writeRow * width + writeCol, litData + litPos, n); + memcpy(dest + writeRow * 320 + writeCol, litData + litPos, n); -bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int width, int height, int colorKey) { +bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey) { int writeRow = 0; - int writeCol = 0; + int writeCol = left; int litPos = 0; int rlePos = 0; - memset(dest, colorKey, width * height); - while (rlePos < rleSize) { int op = rleData[rlePos++]; @@ -95,7 +166,7 @@ bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litS if (op == 0) { // Go to next line in target buffer writeRow++; - writeCol = 0; + writeCol = left; } else { // Skip bytes on current line writeCol += op; @@ -104,11 +175,11 @@ bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litS op &= 0x3f; if (op == 0) { // Copy remainder of current line - int rem = width - writeCol; + int rem = width - (writeCol - left); WRITE_TO_BUFFER(rem); writeRow++; - writeCol = 0; + writeCol = left; litPos += rem; } else { // Copy bytes @@ -159,37 +230,4 @@ bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litS return true; } -SeqFrame *SeqDecoder::getFrame(bool &hasNext) { - int16 frameWidth = _fileStream->readUint16LE(); - int16 frameHeight = _fileStream->readUint16LE(); - int16 frameLeft = _fileStream->readUint16LE(); - int16 frameTop = _fileStream->readUint16LE(); - byte colorKey = _fileStream->readByte(); - byte type = _fileStream->readByte(); - _fileStream->skip(2); - uint16 bytes = _fileStream->readUint16LE(); - _fileStream->skip(2); - uint16 rle_bytes = _fileStream->readUint16LE(); - _fileStream->skip(6); - uint32 offset = _fileStream->readUint32LE(); - - _fileStream->seek(offset); - SeqFrame *frame = new SeqFrame(); - frame->frameRect = Common::Rect(frameLeft, frameTop, frameLeft + frameWidth, frameTop + frameHeight); - frame->data = new byte[frameWidth * frameHeight]; - frame->colorKey = colorKey; - - if (type == 0) - _fileStream->read(frame->data, bytes); - else { - byte *buf = new byte[bytes]; - _fileStream->read(buf, bytes); - decodeFrame(buf, rle_bytes, buf + rle_bytes, bytes - rle_bytes, frame->data, frameWidth, frameHeight, colorKey); - } - - hasNext = ++_currentFrame < _frameCount; - - return frame; -} - -} // End of namespace Sci +} // End of namespace Graphics diff --git a/engines/sci/gfx/seq_decoder.h b/engines/sci/gfx/seq_decoder.h index c4a9dc6d4a..cb528b0324 100644 --- a/engines/sci/gfx/seq_decoder.h +++ b/engines/sci/gfx/seq_decoder.h @@ -23,39 +23,46 @@ * */ -#include "common/file.h" -#include "common/rect.h" +#ifndef SEQ_DECODER_H +#define SEQ_DECODER_H -namespace Sci { +#include "graphics/video/video_player.h" -struct SeqFrame { - Common::Rect frameRect; - byte colorKey; - byte *data; -}; - -class ResourceManager; -class SciGuiScreen; +namespace Graphics { /** - * Decoder for image sequences + * Implementation of the KQ6 floppy SEQ decoder */ -class SeqDecoder { +class SeqDecoder : public VideoDecoder { public: - SeqDecoder() : _fileStream(0) { } - ~SeqDecoder(); - bool loadFile(Common::String fileName, ResourceManager *resMan); + SeqDecoder() {} + virtual ~SeqDecoder(); + + /** + * Load a SEQ encoded video file + * @param filename the filename to load + * @param frameDelay the delay between frames, in ms + */ + bool loadFile(const char *fileName) { return loadFile(fileName, 10); } + + /** + * Load a SEQ encoded video file + * @param filename the filename to load + * @param frameDelay the delay between frames, in ms + */ + bool loadFile(const char *fileName, int frameDelay); + + /** + * Close a SEQ encoded video file + */ void closeFile(); - SeqFrame *getFrame(bool &hasNext); -private: - bool decodeFrame(byte *runlength_data, int runlength_size, - byte *literal_data, int literal_size, byte *dest, int xl, int yl, - int color_key); + bool decodeNextFrame(); - Common::SeekableReadStream *_fileStream; - int _frameCount; - int _currentFrame; +private: + bool decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey); }; -} // End of namespace Sci +} // End of namespace Graphics + +#endif diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index a9f56f692e..3edf76d9eb 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -51,14 +51,6 @@ class GfxDriver; SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) : Engine(syst), _gameDescription(desc), _system(syst) { - // Put your engine in a sane state, but do nothing big yet; - // in particular, do not load data from files; rather, if you - // need to do such things, do them from init(). - - // However this is the place to specify all default directories - //File::addDefaultDirectory(_gameDataPath + "sound/"); - //printf("%s\n", _gameDataPath.c_str()); - _console = NULL; // Set up the engine specific debug levels @@ -86,6 +78,8 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) Common::addDebugChannel(kDebugLevelSci0Pic, "Sci0Pic", "SCI0 pic drawing debugging"); _gamestate = 0; + + SearchMan.addSubDirectoryMatching(_gameDataDir, "seq"); // KQ6 SEQ directory } SciEngine::~SciEngine() { -- cgit v1.2.3