diff options
author | Sven Hesse | 2010-03-11 06:14:52 +0000 |
---|---|---|
committer | Sven Hesse | 2010-03-11 06:14:52 +0000 |
commit | 31f980ffde0edd77594b7eece673dd5f0ec35962 (patch) | |
tree | c56437f0fadf500bab534cbcff9438fb19e14539 /graphics/video/coktelvideo | |
parent | 802ed6eb40f085d5752f96ec2bac69903ca4302a (diff) | |
download | scummvm-rg350-31f980ffde0edd77594b7eece673dd5f0ec35962.tar.gz scummvm-rg350-31f980ffde0edd77594b7eece673dd5f0ec35962.tar.bz2 scummvm-rg350-31f980ffde0edd77594b7eece673dd5f0ec35962.zip |
Adding support for the very primitive and simply early IMD format used in Fascination
svn-id: r48233
Diffstat (limited to 'graphics/video/coktelvideo')
-rw-r--r-- | graphics/video/coktelvideo/coktelvideo.cpp | 506 | ||||
-rw-r--r-- | graphics/video/coktelvideo/coktelvideo.h | 140 |
2 files changed, 490 insertions, 156 deletions
diff --git a/graphics/video/coktelvideo/coktelvideo.cpp b/graphics/video/coktelvideo/coktelvideo.cpp index 7092826bf8..06c735a7d6 100644 --- a/graphics/video/coktelvideo/coktelvideo.cpp +++ b/graphics/video/coktelvideo/coktelvideo.cpp @@ -38,79 +38,407 @@ namespace Graphics { -Imd::Imd() { - clear(false); +PreImd::PreImd() { + zeroData(); + + _forcedWidth = 0; + _forcedHeight = 0; } -Imd::~Imd() { - clear(); +PreImd::PreImd(int16 width, int16 height) { + zeroData(); + + _forcedWidth = width; + _forcedHeight = height; } -uint32 Imd::getFeatures() const { +PreImd::~PreImd() { + deleteData(); + zeroData(); +} + +uint32 PreImd::getFeatures() const { return _features; } -uint16 Imd::getFlags() const { +uint16 PreImd::getFlags() const { return _flags; } -int16 Imd::getX() const { +int16 PreImd::getX() const { return _x; } -int16 Imd::getY() const { +int16 PreImd::getY() const { return _y; } -int16 Imd::getWidth() const { +int16 PreImd::getWidth() const { return _width; } -int16 Imd::getHeight() const { +int16 PreImd::getHeight() const { return _height; } -uint16 Imd::getFramesCount() const { +uint16 PreImd::getFramesCount() const { return _framesCount; } -uint16 Imd::getCurrentFrame() const { +uint16 PreImd::getCurrentFrame() const { return _curFrame; } -int16 Imd::getFrameRate() const { - if (!_hasSound) - return _frameRate; +void PreImd::setFrameRate(int16 frameRate) { + if (frameRate == 0) + frameRate = 1; - return 1000 / (_soundSliceLength >> 16); + _frameRate = frameRate; + _frameLength = 1000 / _frameRate; } -uint32 Imd::getSyncLag() const { - return _skipFrames; +int16 PreImd::getFrameRate() const { + return 0; +} + +uint32 PreImd::getSyncLag() const { + return 0; } -const byte *Imd::getPalette() const { +const byte *PreImd::getPalette() const { return _palette; } -bool Imd::getFrameCoords(int16 frame, +bool PreImd::getFrameCoords(int16 frame, int16 &x, int16 &y, int16 &width, int16 &height) { return false; } -bool Imd::hasExtraData() const { +bool PreImd::hasExtraData() const { return false; } -bool Imd::hasExtraData(const char *fileName) const { +bool PreImd::hasExtraData(const char *fileName) const { return false; } -Common::MemoryReadStream *Imd::getExtraData(const char *fileName) { +Common::MemoryReadStream *PreImd::getExtraData(const char *fileName) { return 0; } +bool PreImd::load(Common::SeekableReadStream &stream) { + warning("loading preIMD"); + + assert((_forcedWidth > 0) && (_forcedHeight > 0)); + + unload(); + + _stream = &stream; + + _stream->seek(0); + + _framesCount = _stream->readUint16LE(); + + _width = _forcedWidth; + _height = _forcedHeight; + + _vidBufferSize = _width * _height; + _vidBuffer = new byte[_vidBufferSize]; + memset(_vidBuffer, 0, _vidBufferSize); + + return true; +} + +void PreImd::unload() { + clear(); +} + +void PreImd::setXY(int16 x, int16 y) { + _x = x; + _y = y; +} + +void PreImd::setVideoMemory(byte *vidMem, uint16 width, uint16 height) { + deleteVidMem(); + + _hasOwnVidMem = false; + _vidMem = vidMem; + _vidMemWidth = width; + _vidMemHeight = height; +} + +void PreImd::setVideoMemory() { + deleteVidMem(); + + if ((_width > 0) && (_height > 0)) { + setXY(0, 0); + _hasOwnVidMem = true; + _vidMem = new byte[_width * _height]; + _vidMemWidth = _width; + _vidMemHeight = _height; + + memset(_vidMem, 0, _width * _height); + } +} + +void PreImd::setDoubleMode(bool doubleMode) { +} + +void PreImd::enableSound(Audio::Mixer &mixer) { +} + +void PreImd::disableSound() { +} + +bool PreImd::isSoundPlaying() const { + return false; +} + +void PreImd::seekFrame(int32 frame, int16 whence, bool restart) { + if (!_stream) + // Nothing to do + return; + + // Find the frame to which to seek + if (whence == SEEK_CUR) + frame += _curFrame; + else if (whence == SEEK_END) + frame = _framesCount - frame - 1; + else if (whence != SEEK_SET) + return; + + if ((frame < 0) || (frame >= _framesCount) || (frame == _curFrame)) + // Nothing to do + return; + + // Run through the frames + _curFrame = 0; + _stream->seek(2); + while (_curFrame != frame) { + uint16 frameSize = _stream->readUint16LE(); + + _stream->skip(frameSize + 2); + + _curFrame++; + } +} + +CoktelVideo::State PreImd::nextFrame() { + return processFrame(_curFrame); +} + +uint32 PreImd::getFrameWaitTime() { + return _frameLength; +} + +void PreImd::waitEndFrame() { + uint32 waitTime = getFrameWaitTime(); + if (waitTime > 0) + g_system->delayMillis(waitTime); +} + +void PreImd::copyCurrentFrame(byte *dest, + uint16 left, uint16 top, uint16 width, uint16 height, + uint16 x, uint16 y, uint16 pitch, int16 transp) { +} + +void PreImd::zeroVidMem() { + _hasOwnVidMem = false; + _vidMem = 0; + _vidMemWidth = 0; + _vidMemHeight = 0; +} + +void PreImd::deleteVidMem() { + if (_hasOwnVidMem) + delete[] _vidMem; + + zeroVidMem(); +} + +void PreImd::zeroData() { + _stream = 0; + + _features = 0; + _flags = 0; + + _x = 0; + _y = 0; + _width = 0; + _height = 0; + + _framesCount = 0; + _curFrame = 0; + _frameRate = 12; + _frameLength = 1000 / _frameRate; + + memset(_palette, 0, 768); + + zeroVidMem(); + + _vidBufferSize = 0; + _vidBuffer = 0; +} + +void PreImd::deleteData() { + deleteVidMem(); + + delete[] _vidBuffer; +} + +void PreImd::clear() { + deleteData(); + zeroData(); +} + +CoktelVideo::State PreImd::processFrame(uint16 frame) { + assert((_width > 0) && (_height > 0)); + + State state; + + if (!_stream || (frame >= _framesCount)) { + state.flags = kStateBreak; + return state; + } + + if (frame != _curFrame) { + state.flags |= kStateSeeked; + seekFrame(frame); + } + + if (!_vidMem) + setVideoMemory(); + + uint16 frameSize = _stream->readUint16LE(); + + uint32 nextFramePos = _stream->pos() + frameSize + 2; + + byte cmd; + + cmd = _stream->readByte(); + frameSize--; + + bool hasPalette = false; + if (cmd == 0) { + // Palette. Ignored by Fascination, though + + hasPalette = true; + + _stream->read(_palette, 768); + + frameSize -= 769; + + cmd = _stream->readByte(); + } + + if (cmd != 2) { + // Partial frame data + + uint32 fSize = frameSize; + uint32 vidSize = _vidBufferSize; + byte *vidBuffer = _vidBuffer; + + while ((fSize > 0) && (vidSize > 0)) { + uint32 n = _stream->readByte(); + fSize--; + + if ((n & 0x80) != 0) { + // Data + + n = MIN<uint32>((n & 0x7F) + 1, MIN(fSize, vidSize)); + + _stream->read(vidBuffer, n); + + vidBuffer += n; + vidSize -= n; + fSize -= n; + + } else { + // Skip + + n = MIN<uint32>(n + 1, vidSize); + + vidBuffer += n; + vidSize -= n; + } + } + + } else { + // Full direct frame + + uint32 vidSize = MIN<uint32>(_vidBufferSize, frameSize); + + _stream->read(_vidBuffer, vidSize); + } + + renderFrame(); + + _stream->seek(nextFramePos); + + _curFrame++; + + // Complete frame needs to be updated + state.left = _x; + state.top = _y; + state.right = _x + _width - 1; + state.bottom = _y + _height - 1; + + return state; +} + +void PreImd::renderFrame() { + assert(_vidMem); + + uint16 w = MIN<uint16>(_vidMemWidth , _width); + uint16 h = MIN<uint16>(_vidMemHeight, _height); + + const byte *src = _vidBuffer; + byte *dst = _vidMem + (_y * _vidMemWidth) + _x; + + uint32 frameDataSize = _vidBufferSize; + + while (h-- > 0) { + uint32 n = MIN<uint32>(w, frameDataSize); + + memcpy(dst, src, n); + + src += _width; + dst += _vidMemWidth; + + frameDataSize -= n; + } +} + + +Imd::Imd() { + zeroData(); +} + +Imd::~Imd() { + deleteData(); + zeroData(); +} + +void Imd::setFrameRate(int16 frameRate) { + if (frameRate == 0) + frameRate = 1; + + _frameRate = frameRate; + _frameLength = 1000 / _frameRate; +} + +int16 Imd::getFrameRate() const { + if (!_hasSound) + return _frameRate; + + return 1000 / (_soundSliceLength >> 16); +} + +uint32 Imd::getSyncLag() const { + return _skipFrames; +} + bool Imd::loadCoordinates() { // Standard coordinates if (_version >= 3) { @@ -306,14 +634,6 @@ void Imd::unload() { clear(); } -void Imd::setFrameRate(int16 frameRate) { - if (frameRate == 0) - frameRate = 1; - - _frameRate = frameRate; - _frameLength = 1000 / _frameRate; -} - void Imd::setXY(int16 x, int16 y) { // Adjusting the standard coordinates if (_stdX != -1) { @@ -345,32 +665,6 @@ void Imd::setXY(int16 x, int16 y) { _y = y; } -void Imd::setVideoMemory(byte *vidMem, uint16 width, uint16 height) { - deleteVidMem(); - - _hasOwnVidMem = false; - _vidMem = vidMem; - _vidMemWidth = width; - _vidMemHeight = height; -} - -void Imd::setVideoMemory() { - deleteVidMem(); - - if ((_width > 0) && (_height > 0)) { - setXY(0, 0); - _hasOwnVidMem = true; - _vidMem = new byte[_width * _height]; - _vidMemWidth = _width; - _vidMemHeight = _height; - - memset(_vidMem, 0, _width * _height); - } -} - -void Imd::setDoubleMode(bool doubleMode) { -} - void Imd::enableSound(Audio::Mixer &mixer) { // Sanity check if (mixer.getOutputRate() == 0) @@ -478,12 +772,6 @@ uint32 Imd::getFrameWaitTime() { return 0; } -void Imd::waitEndFrame() { - uint32 waitTime = getFrameWaitTime(); - if (waitTime > 0) - g_system->delayMillis(waitTime); -} - void Imd::copyCurrentFrame(byte *dest, uint16 left, uint16 top, uint16 width, uint16 height, uint16 x, uint16 y, uint16 pitch, int16 transp) { @@ -535,51 +823,24 @@ void Imd::copyCurrentFrame(byte *dest, } -void Imd::deleteVidMem(bool del) { - if (del) { - if (_hasOwnVidMem) - delete[] _vidMem; - } - - _hasOwnVidMem = false; - _vidMem = 0; - _vidMemWidth = 0; - _vidMemHeight = 0; -} - -void Imd::clear(bool del) { - if (del) { - delete[] _framesPos; - delete[] _frameCoords; - delete[] _frameData; - delete[] _vidBuffer; - - disableSound(); - } - - _stream = 0; +void Imd::zeroData() { + PreImd::zeroData(); _version = 0; - _features = 0; - _flags = 0; - - _x = _y = _width = _height = 0; - _stdX = _stdY = _stdWidth = _stdHeight = 0; - _framesCount = _curFrame = 0; + _stdX = 0; + _stdY = 0; + _stdWidth = 0; + _stdHeight = 0; _framesPos = 0; _firstFramePos = 0; _frameCoords = 0; - _frameDataSize = _vidBufferSize = 0; - _frameData = _vidBuffer = 0; + _frameDataSize = 0; + _frameData = 0; _frameDataLen = 0; - memset(_palette, 0, 768); - - deleteVidMem(del); - _hasSound = false; _soundEnabled = false; _soundStage = 0; @@ -592,11 +853,24 @@ void Imd::clear(bool del) { _soundSliceLength = 0; _audioStream = 0; - _frameRate = 12; - _frameLength = 0; _lastFrameTime = 0; } +void Imd::deleteData() { + PreImd::deleteData(); + + delete[] _framesPos; + delete[] _frameCoords; + delete[] _frameData; + + disableSound(); +} + +void Imd::clear() { + deleteData(); + zeroData(); +} + void Imd::nextSoundSlice(bool hasNextCmd) { if (hasNextCmd || !_soundEnabled) { _stream->seek(_soundSliceSize, SEEK_CUR); @@ -1133,11 +1407,12 @@ const int32 Vmd::_tableADPCMStep[] = { }; Vmd::Vmd(Graphics::PaletteLUT *palLUT) : _palLUT(palLUT) { - clear(false); + zeroData(); } Vmd::~Vmd() { - clear(); + deleteData(); + zeroData(); } bool Vmd::assessVideoProperties() { @@ -1578,16 +1853,8 @@ CoktelVideo::State Vmd::nextFrame() { return state; } -void Vmd::clear(bool del) { - Imd::clear(del); - - if (del) { -#ifdef USE_INDEO3 - delete _codecIndeo3; -#endif - delete[] _frames; - delete[] _vidMemBuffer; - } +void Vmd::zeroData() { + Imd::zeroData(); _hasVideo = true; _videoCodec = 0; @@ -1617,6 +1884,21 @@ void Vmd::clear(bool del) { _vidMemBuffer = 0; } +void Vmd::deleteData() { + Imd::deleteData(); + +#ifdef USE_INDEO3 + delete _codecIndeo3; +#endif + delete[] _frames; + delete[] _vidMemBuffer; +} + +void Vmd::clear() { + deleteData(); + zeroData(); +} + CoktelVideo::State Vmd::processFrame(uint16 frame) { State state; bool startSound = false; diff --git a/graphics/video/coktelvideo/coktelvideo.h b/graphics/video/coktelvideo/coktelvideo.h index 95176cd287..f7063e064c 100644 --- a/graphics/video/coktelvideo/coktelvideo.h +++ b/graphics/video/coktelvideo/coktelvideo.h @@ -125,6 +125,7 @@ public: virtual int16 getWidth() const = 0; /** Returns the height of the video. */ virtual int16 getHeight() const = 0; + /** Returns the number of frames the loaded video has. */ virtual uint16 getFramesCount() const = 0; /** Returns the current frame number. @@ -209,25 +210,29 @@ public: uint16 x, uint16 y, uint16 pitch, int16 transp = -1) = 0; }; -/** Coktel Vision's IMD files. +/** Coktel Vision's first simple IMD format, used by Fascination. */ -class Imd : public CoktelVideo { +class PreImd : public CoktelVideo { public: - Imd(); - ~Imd(); + PreImd(); + PreImd(int16 width, int16 height); + ~PreImd(); uint32 getFeatures() const; uint16 getFlags() const; - int16 getX() const; - int16 getY() const; - int16 getWidth() const; - int16 getHeight() const; + int16 getX() const; + int16 getY() const; + int16 getWidth() const; + int16 getHeight() const; uint16 getFramesCount() const; uint16 getCurrentFrame() const; - int16 getFrameRate() const; - uint32 getSyncLag() const; + + void setFrameRate(int16 frameRate); + int16 getFrameRate() const; + + uint32 getSyncLag() const; const byte *getPalette() const; @@ -238,8 +243,6 @@ public: bool hasExtraData(const char *fileName) const; Common::MemoryReadStream *getExtraData(const char *fileName); - void setFrameRate(int16 frameRate); - bool load(Common::SeekableReadStream &stream); void unload(); @@ -265,6 +268,80 @@ public: uint16 x, uint16 y, uint16 pitch, int16 transp = -1); protected: + Common::SeekableReadStream *_stream; + + // Properties + uint32 _features; + uint16 _flags; + + int16 _forcedWidth; + int16 _forcedHeight; + + // Current coordinates + int16 _x; + int16 _y; + int16 _width; + int16 _height; + + uint16 _framesCount; + uint16 _curFrame; + int16 _frameRate; + uint32 _frameLength; + + byte _palette[768]; + + // Video memory + bool _hasOwnVidMem; + byte *_vidMem; + uint16 _vidMemWidth; + uint16 _vidMemHeight; + + byte *_vidBuffer; + uint32 _vidBufferSize; + + void clear(); + void zeroData(); + void deleteData(); + + void zeroVidMem(); + void deleteVidMem(); + + State processFrame(uint16 frame); + void renderFrame(); +}; + +/** Coktel Vision's IMD files. + */ +class Imd : public PreImd { +public: + Imd(); + ~Imd(); + + void setFrameRate(int16 frameRate); + int16 getFrameRate() const; + + uint32 getSyncLag() const; + + bool load(Common::SeekableReadStream &stream); + void unload(); + + void setXY(int16 x, int16 y); + + void enableSound(Audio::Mixer &mixer); + void disableSound(); + + bool isSoundPlaying() const; + + void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false); + + State nextFrame(); + uint32 getFrameWaitTime(); + + void copyCurrentFrame(byte *dest, + uint16 left, uint16 top, uint16 width, uint16 height, + uint16 x, uint16 y, uint16 pitch, int16 transp = -1); + +protected: enum Command { kCommandNextSound = 0xFF00, kCommandStartSound = 0xFF01, @@ -288,18 +365,8 @@ protected: int16 bottom; } PACKED_STRUCT; - Common::SeekableReadStream *_stream; - // Properties uint16 _version; - uint32 _features; - uint16 _flags; - - // Current coordinates - int16 _x; - int16 _y; - int16 _width; - int16 _height; // Standard coordinates gives by the header int16 _stdX; @@ -307,9 +374,6 @@ protected: int16 _stdWidth; int16 _stdHeight; - uint16 _framesCount; - uint16 _curFrame; - uint32 *_framesPos; uint32 _firstFramePos; Coord *_frameCoords; @@ -319,18 +383,6 @@ protected: uint32 _frameDataSize; uint32 _frameDataLen; - // Buffer for uncompressed raw frame data - byte *_vidBuffer; - uint32 _vidBufferSize; - - byte _palette[768]; - - // Video memory - bool _hasOwnVidMem; - byte *_vidMem; - uint16 _vidMemWidth; - uint16 _vidMemHeight; - // Sound properties uint16 _soundFlags; int16 _soundFreq; @@ -347,17 +399,15 @@ protected: Audio::QueuingAudioStream *_audioStream; Audio::SoundHandle _audioHandle; - // Current video state - int16 _frameRate; - uint32 _frameLength; uint32 _lastFrameTime; Audio::Mixer *_mixer; - void unsignedToSigned(byte *buffer, int length); + void clear(); + void zeroData(); + void deleteData(); - void deleteVidMem(bool del = true); - void clear(bool del = true); + void unsignedToSigned(byte *buffer, int length); bool loadCoordinates(); bool loadFrameTableOffsets(uint32 &framesPosPos, uint32 &framesCoordsPos); @@ -500,7 +550,9 @@ protected: Indeo3 *_codecIndeo3; #endif - void clear(bool del = true); + void clear(); + void zeroData(); + void deleteData(); bool getPartCoords(int16 frame, PartType type, int16 &x, int16 &y, int16 &width, int16 &height); |