diff options
Diffstat (limited to 'engines/gob/coktelvideo.h')
-rw-r--r-- | engines/gob/coktelvideo.h | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/engines/gob/coktelvideo.h b/engines/gob/coktelvideo.h new file mode 100644 index 0000000000..a4e5452cce --- /dev/null +++ b/engines/gob/coktelvideo.h @@ -0,0 +1,313 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_COKTELVIDEO_H +#define GOB_COKTELVIDEO_H + +#include "common/stream.h" +#include "sound/mixer.h" +#include "sound/audiostream.h" + +namespace Gob { + +/** Common interface for handling Coktel Vision videos and derivated formats. */ +class CoktelVideo { +public: + enum Features { + kFeaturesNone = 0, + /** Has an own palette. */ + kFeaturesPalette = 8, + /** Suggests a data size. */ + kFeaturesDataSize = 0x20, + /** Has sound. */ + kFeaturesSound = 0x40, + /** Has specific frame coordinates. */ + kFeaturesFrameCoords = 0x80, + /** Has general standard coordinates. */ + kFeaturesStdCoords = 0x100, + /** Has a frame positions table. */ + kFeaturesFramesPos = 0x200, + /** Has video. */ + kFeaturesVideo = 0x400 + }; + + enum StateFlags { + kStateNone = 0, + /** Changed the palette. */ + kStatePalette = 0x10, + /** Performed a jump to another frame. */ + kStateJump = 0x200, + /** Updated according to the specific frame coordinates. */ + kStateFrameCoords = 0x400, + /** Got no frame data. */ + kStateNoVideoData = 0x800, + /** Updated according to the general standard coordinates. */ + kStateStdCoords = 0x1000, + /** Had to explicitely seek to the frame. */ + kStateSeeked = 0x2000, + /** Reached a break-point. */ + kStateBreak = 0x8000 + }; + + struct State { + /** Left-most value of the updated rectangle. */ + int16 left; + /** Top-most value of the updated rectangle. */ + int16 top; + /** Right-most value of the updated rectangle. */ + int16 right; + /** Bottom-most value of the updated rectangle. */ + int16 bottom; + /** Set accordingly to what was done. */ + uint32 flags; + + State() : left(0), top(0), right(0), bottom(0), flags(0) { } + }; + + virtual ~CoktelVideo() { } + + /** Returns the features the loaded video possesses. */ + virtual uint16 getFeatures() const = 0; + /** Returns the x coordinate of the video. */ + virtual int16 getX() const = 0; + /** Returns the y coordinate of the video. */ + virtual int16 getY() const = 0; + /** Returns the width of the video. */ + 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. + * + * This is the current frame after the last nextFrame()-call, + * i.e. it's 0 after loading, 1 after the first nextFrame()-call, etc.. + */ + virtual uint16 getCurrentFrame() const = 0; + /** Returns the frame rate. */ + virtual int16 getFrameRate() const = 0; + /** Returns the number of frames the video lags behind the audio. */ + virtual uint32 getSyncLag() const = 0; + /** Returns the current frame's palette. */ + virtual const byte *getPalette() const = 0; + + /** Load a video out of a stream. */ + virtual bool load(Common::SeekableReadStream &stream) = 0; + /** Unload the currently loaded video. */ + virtual void unload() = 0; + + /** Set the coordinations where to draw the video. */ + virtual void setXY(int16 x, int16 y) = 0; + /** Use a specific memory block as video memory. */ + virtual void setVideoMemory(byte *vidMem, uint16 width, uint16 height) = 0; + /** Use an own memory block as video memory. */ + virtual void setVideoMemory() = 0; + + /** Play sound (if the IMD has sound). */ + virtual void enableSound(Audio::Mixer &mixer) = 0; + /** Don't play sound or stop currently playing sound. */ + virtual void disableSound() = 0; + + /** Seek to a specific frame. + * + * @param frame The frame to which to seek. + * @param whence The offset from whence the frame is given. + * @param restart Restart the video to reach an otherwise inaccessible frame? + */ + virtual void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false) = 0; + + /** Render the next frame. */ + virtual State nextFrame() = 0; + /** Wait for the frame to end. */ + virtual void waitEndFrame() = 0; + + /** Copy the current frame. + * + * @param dest The memory to which to copy the current frame + * @param x The x position to where to copy. + * @param y The y position to where to copy. + * @param pitch The buffer's width. + * @param transp Which color should be seen as transparent? + */ + virtual void copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp = -1) = 0; +}; + +/** Coktel Vision's IMD files. + */ +class Imd : public CoktelVideo { +public: + Imd(); + ~Imd(); + + uint16 getFeatures() const { return _features; } + int16 getX() const { return _x; } + int16 getY() const { return _y; } + int16 getWidth() const { return _width; } + int16 getHeight() const { return _height; } + uint16 getFramesCount() const { return _framesCount; } + uint16 getCurrentFrame() const { return _curFrame; } + int16 getFrameRate() const { if (_hasSound) return 1000 / _soundSliceLength; return 12; } + uint32 getSyncLag() const { return _skipFrames; } + const byte *getPalette() const { return _palette; } + + bool load(Common::SeekableReadStream &stream); + void unload(); + + void setXY(int16 x, int16 y); + void setVideoMemory(byte *vidMem, uint16 width, uint16 height); + void setVideoMemory(); + + void enableSound(Audio::Mixer &mixer); + void disableSound(); + + void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false); + + State nextFrame(); + void waitEndFrame(); + + void copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp = -1); + +protected: + struct Coord { + int16 left; + int16 top; + int16 right; + int16 bottom; + } PACKED_STRUCT; + + Common::SeekableReadStream *_stream; + uint16 _version; + uint16 _features; + uint16 _flags; + int16 _x, _y, _width, _height; + int16 _stdX, _stdY, _stdWidth, _stdHeight; + uint16 _framesCount, _curFrame; + uint32 *_framesPos; + uint32 _firstFramePos; + Coord *_frameCoords; + + uint32 _frameDataSize, _vidBufferSize; + byte *_frameData, *_vidBuffer; + + byte _palette[768]; + + bool _hasOwnVidMem; + byte *_vidMem; + uint16 _vidMemWidth, _vidMemHeight; + + bool _hasSound; + bool _soundEnabled; + uint8 _soundStage; // (0: no sound, 1: loaded, 2: playing) + uint32 _soundStartTime; + uint32 _skipFrames; + + uint16 _soundFlags; + int16 _soundFreq; + int16 _soundSliceSize; + int16 _soundSlicesCount; + uint16 _soundSliceLength; + + Audio::AppendableAudioStream *_audioStream; + Audio::SoundHandle _audioHandle; + + uint32 _frameLength; + uint32 _lastFrameTime; + + Audio::Mixer *_mixer; + + void unsignedToSigned(byte *buffer, int length) { + while (length-- > 0) *buffer++ ^= 0x80; + } + + void deleteVidMem(bool del = true); + void clear(bool del = true); + + State processFrame(uint16 frame); + uint32 renderFrame(int16 left, int16 top, int16 right, int16 bottom); + void deLZ77(byte *dest, byte *src); +}; + +class Vmd : public Imd { +public: + Vmd(); + ~Vmd(); + + bool load(Common::SeekableReadStream &stream); + void unload(); + + void setXY(int16 x, int16 y); + + void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false); + + State nextFrame(); + +protected: + enum PartType { + kPartTypeAudio = 1, + kPartTypeVideo = 2 + }; + struct Part { + PartType type; + uint32 size; + int16 left; + int16 top; + int16 right; + int16 bottom; + byte flags; + } PACKED_STRUCT; + struct Frame { + uint32 offset; + Part *parts; + + Frame() : parts(0) { } + ~Frame() { delete[] parts; } + } PACKED_STRUCT; + + static const uint16 _tableDPCM[128]; + + bool _hasVideo; + + uint16 _partsPerFrame; + Frame *_frames; + + byte _soundBytesPerSample; + byte _soundStereo; // (0: mono, 1: old-style stereo, 2: new-style stereo) + + void clear(bool del = true); + + State processFrame(uint16 frame); + uint32 renderFrame(int16 left, int16 top, int16 right, int16 bottom); + + void emptySoundSlice(uint32 size); + void soundSlice8bit(uint32 size); + void soundSlice16bit(uint32 size, int16 &init); + void filledSoundSlice(uint32 size); + void filledSoundSlices(uint32 size, uint32 mask); + void deDPCM(byte *soundBuf, byte *dataBuf, int16 &init, uint32 n); +}; + +} // End of namespace Gob + +#endif // GOB_COKTELVIDEO_H |