aboutsummaryrefslogtreecommitdiff
path: root/graphics/video/coktelvideo
diff options
context:
space:
mode:
authorSven Hesse2010-03-11 06:14:52 +0000
committerSven Hesse2010-03-11 06:14:52 +0000
commit31f980ffde0edd77594b7eece673dd5f0ec35962 (patch)
treec56437f0fadf500bab534cbcff9438fb19e14539 /graphics/video/coktelvideo
parent802ed6eb40f085d5752f96ec2bac69903ca4302a (diff)
downloadscummvm-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.cpp506
-rw-r--r--graphics/video/coktelvideo/coktelvideo.h140
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);