diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp index 4eec4e8778c..cf13d04ea69 100644 --- a/engines/tucker/sequences.cpp +++ b/engines/tucker/sequences.cpp @@ -892,6 +892,17 @@ uint8 *AnimationSequencePlayer::loadPicture(const char *fileName) { return p; } +void AnimationSequencePlayer::getRGBPalette(int index) { + byte rgbPalette[3 * 256]; + memcpy(rgbPalette, _flicPlayer[index].getPalette(), 3 * 256); + for (int i = 0; i < 256; i++) { + _animationPalette[i * 4 + 0] = rgbPalette[i * 3 + 0]; + _animationPalette[i * 4 + 1] = rgbPalette[i * 3 + 1]; + _animationPalette[i * 4 + 2] = rgbPalette[i * 3 + 2]; + _animationPalette[i * 4 + 3] = 0; + } +} + void AnimationSequencePlayer::openAnimation(int index, const char *fileName) { if (!_flicPlayer[index].loadFile(fileName)) { warning("Unable to open flc animation file '%s'", fileName); @@ -900,22 +911,24 @@ void AnimationSequencePlayer::openAnimation(int index, const char *fileName) { } _flicPlayer[index].decodeNextFrame(); if (index == 0) { - memcpy(_animationPalette, _flicPlayer[index].getPalette(), 1024); + getRGBPalette(index); _flicPlayer[index].copyDirtyRectsToBuffer(_offscreenBuffer, kScreenWidth); } } -void AnimationSequencePlayer::decodeNextAnimationFrame(int index) { - _flicPlayer[index].decodeNextFrame(); +bool AnimationSequencePlayer::decodeNextAnimationFrame(int index) { + bool framesLeft = _flicPlayer[index].decodeNextFrame(); _flicPlayer[index].copyDirtyRectsToBuffer(_offscreenBuffer, kScreenWidth); if (index == 0) { - if (_flicPlayer[index].isPaletteDirty()) { - memcpy(_animationPalette, _flicPlayer[index].getPalette(), 1024); + if (_flicPlayer[index].paletteChanged()) { + getRGBPalette(index); } } if (_seqNum != 19) { ++_frameCounter; } + + return framesLeft; } void AnimationSequencePlayer::loadIntroSeq17_18() { @@ -924,8 +937,7 @@ void AnimationSequencePlayer::loadIntroSeq17_18() { } void AnimationSequencePlayer::playIntroSeq17_18() { - decodeNextAnimationFrame(0); - if (_flicPlayer[0].isLastFrame()) { + if (!decodeNextAnimationFrame(0)) { _changeToNextSequence = true; } updateSounds(); @@ -939,20 +951,24 @@ void AnimationSequencePlayer::loadIntroSeq19_20() { } void AnimationSequencePlayer::playIntroSeq19_20() { + // The intro credits animation. This uses 2 animations: the foreground one, which + // is the actual intro credits, and the background one, which is an animation of + // cogs, and is being replayed when an intro credit appears + // FIXME: The background animation is not being played, as a result of the change + // to the FLIC video player in commit #40638 if (_flicPlayer[0].getCurFrame() >= 116) { - _flicPlayer[1].decodeNextFrame(); - if (_flicPlayer[1].isLastFrame()) { + if (!_flicPlayer[1].decodeNextFrame()) { _flicPlayer[1].reset(); } } - decodeNextAnimationFrame(0); + bool framesLeft = decodeNextAnimationFrame(0); for (int i = 0; i < kScreenWidth * kScreenHeight; ++i) { if (_offscreenBuffer[i] == 0) { - _offscreenBuffer[i] = _flicPlayer[1].getOffscreen()[i]; + _offscreenBuffer[i] = _flicPlayer[1].getPixel(i); } } updateSounds(); - if (_flicPlayer[0].isLastFrame()) { + if (!framesLeft) { _changeToNextSequence = true; } } @@ -1007,11 +1023,11 @@ void AnimationSequencePlayer::loadIntroSeq3_4() { void AnimationSequencePlayer::playIntroSeq3_4() { if (!_updateScreenPicture) { - decodeNextAnimationFrame(0); + bool framesLeft = decodeNextAnimationFrame(0); if (_flicPlayer[0].getCurFrame() == 706) { initPicPart4(); } - if (_flicPlayer[0].isLastFrame()) { + if (!framesLeft) { _changeToNextSequence = true; } } else { @@ -1051,7 +1067,7 @@ void AnimationSequencePlayer::drawPic1Part10() { int offset = 0; for (int y = 0; y < kScreenHeight; ++y) { for (int x = 0; x < kScreenWidth; ++x) { - uint8 color = _flicPlayer[0].getOffscreen()[offset]; + byte color = _flicPlayer[0].getPixel(offset); if (color == 0) { color = _picBufPtr[800 + y * 640 + _updateScreenWidth + x]; } @@ -1069,7 +1085,7 @@ void AnimationSequencePlayer::loadIntroSeq9_10() { } void AnimationSequencePlayer::playIntroSeq9_10() { - decodeNextAnimationFrame(0); + bool framesLeft = decodeNextAnimationFrame(0); if (_flicPlayer[0].getCurFrame() >= 264 && _flicPlayer[0].getCurFrame() <= 295) { drawPic1Part10(); _updateScreenWidth += 6; @@ -1082,7 +1098,7 @@ void AnimationSequencePlayer::playIntroSeq9_10() { _updateScreenWidth = 0; } } - if (_flicPlayer[0].isLastFrame()) { + if (!framesLeft) { _changeToNextSequence = true; } updateSounds(); @@ -1094,8 +1110,7 @@ void AnimationSequencePlayer::loadIntroSeq21_22() { } void AnimationSequencePlayer::playIntroSeq21_22() { - decodeNextAnimationFrame(0); - if (_flicPlayer[0].isLastFrame()) { + if (!decodeNextAnimationFrame(0)) { _changeToNextSequence = true; } updateSounds(); @@ -1107,8 +1122,7 @@ void AnimationSequencePlayer::loadIntroSeq13_14() { } void AnimationSequencePlayer::playIntroSeq13_14() { - decodeNextAnimationFrame(0); - if (_flicPlayer[0].isLastFrame()) { + if (!decodeNextAnimationFrame(0)) { _changeToNextSequence = true; } updateSounds(); @@ -1120,8 +1134,7 @@ void AnimationSequencePlayer::loadIntroSeq15_16() { } void AnimationSequencePlayer::playIntroSeq15_16() { - decodeNextAnimationFrame(0); - if (_flicPlayer[0].isLastFrame()) { + if (!decodeNextAnimationFrame(0)) { _changeToNextSequence = true; } updateSounds(); @@ -1133,8 +1146,7 @@ void AnimationSequencePlayer::loadIntroSeq27_28() { } void AnimationSequencePlayer::playIntroSeq27_28() { - decodeNextAnimationFrame(0); - if (_flicPlayer[0].isLastFrame()) { + if (!decodeNextAnimationFrame(0)) { _changeToNextSequence = true; } updateSounds(); diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h index 7a0cc81e3ea..651b0b0ab5b 100644 --- a/engines/tucker/tucker.h +++ b/engines/tucker/tucker.h @@ -885,7 +885,7 @@ private: void unloadAnimation(); uint8 *loadPicture(const char *fileName); void openAnimation(int index, const char *fileName); - void decodeNextAnimationFrame(int index); + bool decodeNextAnimationFrame(int index); void loadIntroSeq17_18(); void playIntroSeq17_18(); void loadIntroSeq19_20(); @@ -907,6 +907,7 @@ private: void playIntroSeq15_16(); void loadIntroSeq27_28(); void playIntroSeq27_28(); + void getRGBPalette(int index); OSystem *_system; Audio::Mixer *_mixer; @@ -916,7 +917,7 @@ private: bool _changeToNextSequence; const SequenceUpdateFunc *_updateFunc; int _updateFuncIndex; - ::Graphics::FlicPlayer _flicPlayer[2]; + ::Graphics::FlicDecoder _flicPlayer[2]; uint8 _animationPalette[256 * 4]; int _soundsList1Offset; int _soundsList1Count; diff --git a/graphics/video/flic_player.cpp b/graphics/video/flic_player.cpp index f5a4fd4e632..a05368a0ab5 100644 --- a/graphics/video/flic_player.cpp +++ b/graphics/video/flic_player.cpp @@ -27,123 +27,87 @@ #include "common/archive.h" #include "common/stream.h" #include "common/endian.h" +#include "common/system.h" namespace Graphics { -FlicPlayer::FlicPlayer() - : _paletteDirty(false), _offscreen(0), _currFrame(0), _fileStream(0) { - memset(&_flicInfo, 0, sizeof(_flicInfo)); +FlicDecoder::FlicDecoder() { + _paletteChanged = false; + _fileStream = 0; + _videoFrameBuffer = 0; + memset(&_videoInfo, 0, sizeof(_videoInfo)); } -FlicPlayer::~FlicPlayer() { +FlicDecoder::~FlicDecoder() { closeFile(); } -int FlicPlayer::getWidth() { - if (!_fileStream) - return 0; - return _flicInfo.width; -} - -int FlicPlayer::getHeight() { - if (!_fileStream) - return 0; - return _flicInfo.height; -} - -int32 FlicPlayer::getCurFrame() { - if (!_fileStream) - return -1; - return _currFrame; -} - -int32 FlicPlayer::getFrameCount() { - if (!_fileStream) - return 0; - return _flicInfo.numFrames; -} - -bool FlicPlayer::loadFile(const char *fileName) { +bool FlicDecoder::loadFile(const char *fileName) { closeFile(); _fileStream = SearchMan.createReadStreamForMember(fileName); if (!_fileStream) return false; - _flicInfo.size = _fileStream->readUint32LE(); - _flicInfo.type = _fileStream->readUint16LE(); + uint32 frameSize = _fileStream->readUint32LE(); + uint16 frameType = _fileStream->readUint16LE(); // Check FLC magic number - if (_flicInfo.type != 0xAF12) { - warning("FlicPlayer::FlicPlayer(): attempted to load non-FLC data (type = 0x%04X)", _flicInfo.type); + if (frameType != 0xAF12) { + warning("FlicDecoder::FlicDecoder(): attempted to load non-FLC data (type = 0x%04X)", frameType); delete _fileStream; _fileStream = 0; return false; } - _flicInfo.numFrames = _fileStream->readUint16LE(); - _flicInfo.width = _fileStream->readUint16LE(); - _flicInfo.height = _fileStream->readUint16LE(); - _fileStream->skip(4); - _flicInfo.speed = _fileStream->readUint32LE(); + _videoInfo.frameCount = _fileStream->readUint16LE(); + _videoInfo.width = _fileStream->readUint16LE(); + _videoInfo.height = _fileStream->readUint16LE(); + uint16 colorDepth = _fileStream->readUint16LE(); + if (colorDepth != 8) { + warning("FlicDecoder::FlicDecoder(): attempted to load an FLC with a palette of color depth %d. Only 8-bit color palettes are supported", frameType); + delete _fileStream; + _fileStream = 0; + return false; + } + _fileStream->readUint16LE(); // flags + // Note: The normal delay is a 32-bit integer (dword), whereas the overriden delay is a 16-bit integer (word) + _videoInfo.frameDelay = _fileStream->readUint32LE() * 1000; // "speed", in milliseconds + _videoInfo.frameRate = 1000 / _videoInfo.frameDelay; _fileStream->seek(80); - _flicInfo.offsetFrame1 = _fileStream->readUint32LE(); - _flicInfo.offsetFrame2 = _fileStream->readUint32LE(); + _offsetFrame1 = _fileStream->readUint32LE(); + _offsetFrame2 = _fileStream->readUint32LE(); - _offscreen = new uint8[_flicInfo.width * _flicInfo.height]; - memset(_palette, 0, sizeof(_palette)); - _paletteDirty = false; + _videoFrameBuffer = new byte[_videoInfo.width * _videoInfo.height]; + _palette = (byte *)malloc(3 * 256); + memset(_palette, 0, 3 * 256); + _paletteChanged = false; // Seek to the first frame - _currFrame = 0; - _fileStream->seek(_flicInfo.offsetFrame1); + _videoInfo.currentFrame = 0; + _fileStream->seek(_offsetFrame1); return true; } -void FlicPlayer::closeFile() { +void FlicDecoder::closeFile() { if (!_fileStream) return; delete _fileStream; _fileStream = 0; - delete[] _offscreen; - _offscreen = 0; + delete[] _videoFrameBuffer; + _videoFrameBuffer = 0; + + free(_palette); _dirtyRects.clear(); } -void FlicPlayer::redraw() { - _dirtyRects.clear(); - _dirtyRects.push_back(Common::Rect(0, 0, _flicInfo.width, _flicInfo.height)); -} - -ChunkHeader FlicPlayer::readChunkHeader() { - ChunkHeader head; - - head.size = _fileStream->readUint32LE(); - head.type = _fileStream->readUint16LE(); - - return head; -} - -FrameTypeChunkHeader FlicPlayer::readFrameTypeChunkHeader(ChunkHeader chunkHead) { - FrameTypeChunkHeader head; - - head.header = chunkHead; - head.numChunks = _fileStream->readUint16LE(); - head.delay = _fileStream->readUint16LE(); - head.reserved = _fileStream->readUint16LE(); - head.widthOverride = _fileStream->readUint16LE(); - head.heightOverride = _fileStream->readUint16LE(); - - return head; -} - -void FlicPlayer::decodeByteRun(uint8 *data) { - uint8 *ptr = (uint8 *)_offscreen; - while ((ptr - _offscreen) < (_flicInfo.width * _flicInfo.height)) { +void FlicDecoder::decodeByteRun(uint8 *data) { + byte *ptr = (uint8 *)_videoFrameBuffer; + while ((uint32)(ptr - _videoFrameBuffer) < (_videoInfo.width * _videoInfo.height)) { int chunks = *data++; while (chunks--) { int count = (int8)*data++; @@ -158,7 +122,9 @@ void FlicPlayer::decodeByteRun(uint8 *data) { } } - redraw(); + // Redraw + _dirtyRects.clear(); + _dirtyRects.push_back(Common::Rect(0, 0, _videoInfo.width, _videoInfo.height)); } #define OP_PACKETCOUNT 0 @@ -166,7 +132,7 @@ void FlicPlayer::decodeByteRun(uint8 *data) { #define OP_LASTPIXEL 2 #define OP_LINESKIPCOUNT 3 -void FlicPlayer::decodeDeltaFLC(uint8 *data) { +void FlicDecoder::decodeDeltaFLC(uint8 *data) { uint16 linesInChunk = READ_LE_UINT16(data); data += 2; uint16 currentLine = 0; uint16 packetCount = 0; @@ -185,8 +151,8 @@ void FlicPlayer::decodeDeltaFLC(uint8 *data) { case OP_UNDEFINED: break; case OP_LASTPIXEL: - _offscreen[currentLine * _flicInfo.width + _flicInfo.width - 1] = (opcode & 0xFF); - _dirtyRects.push_back(Common::Rect(_flicInfo.width - 1, currentLine, _flicInfo.width, currentLine + 1)); + _videoFrameBuffer[currentLine * _videoInfo.width + _videoInfo.width - 1] = (opcode & 0xFF); + _dirtyRects.push_back(Common::Rect(_videoInfo.width - 1, currentLine, _videoInfo.width, currentLine + 1)); break; case OP_LINESKIPCOUNT: currentLine += -(int16)opcode; @@ -201,14 +167,14 @@ void FlicPlayer::decodeDeltaFLC(uint8 *data) { column += *data++; int rleCount = (int8)*data++; if (rleCount > 0) { - memcpy(_offscreen + (currentLine * _flicInfo.width) + column, data, rleCount * 2); + memcpy(_videoFrameBuffer + (currentLine * _videoInfo.width) + column, data, rleCount * 2); data += rleCount * 2; _dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1)); } else if (rleCount < 0) { rleCount = -rleCount; uint16 dataWord = READ_UINT16(data); data += 2; for (int i = 0; i < rleCount; ++i) { - WRITE_UINT16(_offscreen + currentLine * _flicInfo.width + column + i * 2, dataWord); + WRITE_UINT16(_videoFrameBuffer + currentLine * _videoInfo.width + column + i * 2, dataWord); } _dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1)); } else { // End of cutscene ? @@ -227,31 +193,52 @@ void FlicPlayer::decodeDeltaFLC(uint8 *data) { #define PSTAMP 18 #define FRAME_TYPE 0xF1FA -void FlicPlayer::decodeNextFrame() { - FrameTypeChunkHeader frameHeader; +bool FlicDecoder::decodeNextFrame() { + if (_videoInfo.currentFrame == 0) + _videoInfo.startTime = g_system->getMillis(); // Read chunk - ChunkHeader cHeader = readChunkHeader(); - switch (cHeader.type) { - case FRAME_TYPE: - frameHeader = readFrameTypeChunkHeader(cHeader); - _currFrame++; + uint32 frameSize = _fileStream->readUint32LE(); + uint16 frameType = _fileStream->readUint16LE(); + uint16 chunkCount = 0; + + switch (frameType) { + case FRAME_TYPE: { + chunkCount = _fileStream->readUint16LE(); + // Note: The overriden delay is a 16-bit integer (word), whereas the normal delay is a 32-bit integer (dword) + uint16 newFrameDelay = _fileStream->readUint16LE() * 1000; // "speed", in milliseconds + if (newFrameDelay > 0) { + _videoInfo.frameDelay = newFrameDelay; + _videoInfo.frameRate = 1000 / _videoInfo.frameDelay; + } + _fileStream->readUint16LE(); // reserved, always 0 + uint16 newWidth = _fileStream->readUint16LE(); + uint16 newHeight = _fileStream->readUint16LE(); + if (newWidth > 0) + _videoInfo.width = newWidth; + if (newHeight > 0) + _videoInfo.height = newHeight; + + _videoInfo.currentFrame++; + } break; default: - error("FlicPlayer::decodeFrame(): unknown main chunk type (type = 0x%02X)", cHeader.type); + error("FlicDecoder::decodeFrame(): unknown main chunk type (type = 0x%02X)", frameType); break; } // Read subchunks - if (cHeader.type == FRAME_TYPE) { - for (int i = 0; i < frameHeader.numChunks; ++i) { - cHeader = readChunkHeader(); - uint8 *data = new uint8[cHeader.size - 6]; - _fileStream->read(data, cHeader.size - 6); - switch (cHeader.type) { + if (frameType == FRAME_TYPE) { + for (uint32 i = 0; i < chunkCount; ++i) { + frameSize = _fileStream->readUint32LE(); + frameType = _fileStream->readUint16LE(); + uint8 *data = new uint8[frameSize - 6]; + _fileStream->read(data, frameSize - 6); + switch (frameType) { case FLI_SETPAL: - setPalette(data); - _paletteDirty = true; + unpackPalette(data); + setPalette(_palette); + _paletteChanged = true; break; case FLI_SS2: decodeDeltaFLC(data); @@ -263,7 +250,7 @@ void FlicPlayer::decodeNextFrame() { /* PSTAMP - skip for now */ break; default: - error("FlicPlayer::decodeFrame(): unknown subchunk type (type = 0x%02X)", cHeader.type); + error("FlicDecoder::decodeFrame(): unknown subchunk type (type = 0x%02X)", frameType); break; } @@ -272,25 +259,26 @@ void FlicPlayer::decodeNextFrame() { } // If we just processed the ring frame, set the next frame - if (_currFrame == _flicInfo.numFrames + 1) { - _currFrame = 1; - _fileStream->seek(_flicInfo.offsetFrame2); + if (_videoInfo.currentFrame == _videoInfo.frameCount + 1) { + _videoInfo.currentFrame = 1; + _fileStream->seek(_offsetFrame2); } + + return _videoInfo.currentFrame < _videoInfo.frameCount; } -void FlicPlayer::reset() { - _currFrame = 0; - _fileStream->seek(_flicInfo.offsetFrame1); +void FlicDecoder::reset() { + _videoInfo.currentFrame = 0; + _fileStream->seek(_offsetFrame1); } -void FlicPlayer::setPalette(uint8 *mem) { +void FlicDecoder::unpackPalette(uint8 *mem) { uint16 numPackets = READ_LE_UINT16(mem); mem += 2; if (0 == READ_LE_UINT16(mem)) { //special case mem += 2; for (int i = 0; i < 256; ++i) { - memcpy(_palette + i * 4, mem + i * 3, 3); - _palette[i * 4 + 3] = 0; + memcpy(_palette + i * 3, mem + i * 3, 3); } } else { uint8 palPos = 0; @@ -300,8 +288,7 @@ void FlicPlayer::setPalette(uint8 *mem) { uint8 change = *mem++; for (int i = 0; i < change; ++i) { - memcpy(_palette + (palPos + i) * 4, mem + i * 3, 3); - _palette[(palPos + i) * 4 + 3] = 0; + memcpy(_palette + (palPos + i) * 3, mem + i * 3, 3); } palPos += change; @@ -310,28 +297,14 @@ void FlicPlayer::setPalette(uint8 *mem) { } } -void FlicPlayer::copyDirtyRectsToBuffer(uint8 *dst, uint pitch) { +void FlicDecoder::copyDirtyRectsToBuffer(uint8 *dst, uint pitch) { for (Common::List::const_iterator it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { for (int y = (*it).top; y < (*it).bottom; ++y) { const int x = (*it).left; - memcpy(dst + y * pitch + x, _offscreen + y * _flicInfo.width + x, (*it).right - x); + memcpy(dst + y * pitch + x, _videoFrameBuffer + y * _videoInfo.width + x, (*it).right - x); } } _dirtyRects.clear(); } -void FlicPlayer::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) { - uint h = _flicInfo.height; - uint w = _flicInfo.width; - - byte *src = (byte *)_offscreen; - dst += y * pitch + x; - - do { - memcpy(dst, src, w); - dst += pitch; - src += w; - } while (--h); -} - } // End of namespace Graphics diff --git a/graphics/video/flic_player.h b/graphics/video/flic_player.h index de65e0c47b2..4912c028843 100644 --- a/graphics/video/flic_player.h +++ b/graphics/video/flic_player.h @@ -28,10 +28,10 @@ * - tucker */ -#ifndef GRAPHICS_VIDEO_FLICPLAYER_H -#define GRAPHICS_VIDEO_FLICPLAYER_H +#ifndef GRAPHICS_VIDEO_FlicDecoder_H +#define GRAPHICS_VIDEO_FlicDecoder_H -#include "common/scummsys.h" +#include "graphics/video/video_player.h" #include "common/list.h" #include "common/rect.h" @@ -41,50 +41,10 @@ namespace Common { namespace Graphics { -struct ChunkHeader { - uint32 size; - uint16 type; -}; - -struct FrameTypeChunkHeader { - ChunkHeader header; - uint16 numChunks; - uint16 delay; - uint16 reserved; // always zero - uint16 widthOverride; - uint16 heightOverride; -}; - -// TOD: rewrite this based on VideoDecoder & VideoPlayer (this may -// require improvements to these two classes). -class FlicPlayer { +class FlicDecoder : public VideoDecoder { public: - FlicPlayer(); - ~FlicPlayer(); - - /** - * Returns the width of the video - * @return the width of the video - */ - int getWidth(); - - /** - * Returns the height of the video - * @return the height of the video - */ - int getHeight(); - - /** - * Returns the current frame number of the video - * @return the current frame number of the video - */ - int32 getCurFrame(); - - /** - * Returns the amount of frames in the video - * @return the amount of frames in the video - */ - int32 getFrameCount(); + FlicDecoder(); + virtual ~FlicDecoder(); /** * Load a FLIC encoded video file @@ -100,55 +60,29 @@ public: /** * Decode the next frame */ - void decodeNextFrame(); + bool decodeNextFrame(); - bool isLastFrame() const { return _currFrame == _flicInfo.numFrames; } - uint32 getSpeed() const { return _flicInfo.speed; } - bool isPaletteDirty() const { return _paletteDirty; } - const uint8 *getPalette() { _paletteDirty = false; return _palette; } - const uint8 *getOffscreen() const { return _offscreen; } const Common::List *getDirtyRects() const { return &_dirtyRects; } void clearDirtyRects() { _dirtyRects.clear(); } - void redraw(); - void reset(); - void copyDirtyRectsToBuffer(uint8 *dst, uint pitch); - /** - * Copy current frame into the specified position of the destination - * buffer. - * @param dst the buffer - * @param x the x position of the buffer - * @param y the y position of the buffer - * @param pitch the pitch of buffer - */ - void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch); + byte getPixel(int offset) { return _videoFrameBuffer[offset]; } + byte* getPalette() { _paletteChanged = false; return _palette; } + bool paletteChanged() { return _paletteChanged; } + void reset(); private: - struct FlicHeader { - uint32 size; - uint16 type; - uint16 numFrames; - uint16 width; - uint16 height; - uint32 speed; - uint16 offsetFrame1; - uint16 offsetFrame2; - }; + uint16 _offsetFrame1; + uint16 _offsetFrame2; + byte *_palette; + bool _paletteChanged; - ChunkHeader readChunkHeader(); - FrameTypeChunkHeader readFrameTypeChunkHeader(ChunkHeader chunkHead); void decodeByteRun(uint8 *data); void decodeDeltaFLC(uint8 *data); - void setPalette(uint8 *mem); + void unpackPalette(uint8 *mem); - Common::SeekableReadStream *_fileStream; - bool _paletteDirty; - uint8 *_offscreen; - uint8 _palette[256 * 4]; - FlicHeader _flicInfo; - uint16 _currFrame; Common::List _dirtyRects; + }; } // End of namespace Graphics diff --git a/graphics/video/smk_player.h b/graphics/video/smk_player.h index aa2ee305fc6..553575ade31 100644 --- a/graphics/video/smk_player.h +++ b/graphics/video/smk_player.h @@ -53,7 +53,7 @@ class BigHuffmanTree; /** * Implementation of a Smacker v2/v4 video decoder */ -class SmackerDecoder : public Graphics::VideoDecoder { +class SmackerDecoder : public VideoDecoder { public: SmackerDecoder(Audio::Mixer *mixer); virtual ~SmackerDecoder(); @@ -66,6 +66,10 @@ public: * @param filename the filename to load */ bool loadFile(const char *filename); + + /** + * Close an SMK encoded video file + */ void closeFile(); bool decodeNextFrame();