Changed the FLIC player to the common VideoDecoder interface. Note that currently the double animation in Bud Tucker's intro credits is broken, as the second background animation is not played

svn-id: r40638
This commit is contained in:
Filippos Karapetis 2009-05-17 08:44:20 +00:00
parent dc55a54365
commit 6f0b6b5aed
5 changed files with 163 additions and 239 deletions

View File

@ -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();

View File

@ -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;

View File

@ -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<Common::Rect>::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

View File

@ -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<Common::Rect> *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<Common::Rect> _dirtyRects;
};
} // End of namespace Graphics

View File

@ -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();