diff options
-rw-r--r-- | engines/gob/gob.cpp | 1 | ||||
-rw-r--r-- | engines/gob/videoplayer.cpp | 9 | ||||
-rw-r--r-- | engines/gob/videoplayer.h | 2 | ||||
-rw-r--r-- | graphics/video/coktelvideo/coktelvideo.cpp | 378 | ||||
-rw-r--r-- | graphics/video/coktelvideo/coktelvideo.h | 35 |
5 files changed, 247 insertions, 178 deletions
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index 13f306fff1..6c8aceff33 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -306,7 +306,6 @@ void GobEngine::pauseEngineIntern(bool pause) { } else { uint32 duration = _system->getMillis() - _pauseStart; - _vidPlayer->notifyPaused(duration); _util->notifyPaused(duration); _game->_startTimeKey += duration; diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp index 43395db829..a3a9dde892 100644 --- a/engines/gob/videoplayer.cpp +++ b/engines/gob/videoplayer.cpp @@ -797,13 +797,4 @@ void VideoPlayer::evalBgShading(Graphics::CoktelVideo &video) { _vm->_sound->bgUnshade(); } -void VideoPlayer::notifyPaused(uint32 duration) { - if (_primaryVideo->isOpen()) - _primaryVideo->getVideo()->notifyPaused(duration); - - for (uint i = 0; i < _videoSlots.size(); i++) - if (_videoSlots[i] && _videoSlots[i]->isOpen()) - _videoSlots[i]->getVideo()->notifyPaused(duration); -} - } // End of namespace Gob diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h index 532d216d7e..28e72ab43a 100644 --- a/engines/gob/videoplayer.h +++ b/engines/gob/videoplayer.h @@ -103,8 +103,6 @@ public: void writeVideoInfo(const char *videoFile, int16 varX, int16 varY, int16 varFrames, int16 varWidth, int16 varHeight); - void notifyPaused(uint32 duration); - private: class Video { public: diff --git a/graphics/video/coktelvideo/coktelvideo.cpp b/graphics/video/coktelvideo/coktelvideo.cpp index 02893bb73e..2b0ae79186 100644 --- a/graphics/video/coktelvideo/coktelvideo.cpp +++ b/graphics/video/coktelvideo/coktelvideo.cpp @@ -101,47 +101,12 @@ Common::MemoryReadStream *Imd::getExtraData(const char *fileName) { return 0; } -bool Imd::load(Common::SeekableReadStream &stream) { - unload(); - - _stream = &stream; - - uint16 handle; - - handle = _stream->readUint16LE(); - _version = _stream->readByte(); - - // Version checking - if ((handle != 0) || (_version < 2)) { - warning("Imd::load(): Version incorrect (%d,%X)", handle, _version); - unload(); - return false; - } - - // Rest header - _features = _stream->readByte(); - _framesCount = _stream->readUint16LE(); - _x = _stream->readSint16LE(); - _y = _stream->readSint16LE(); - _width = _stream->readSint16LE(); - _height = _stream->readSint16LE(); - _flags = _stream->readUint16LE(); - _firstFramePos = _stream->readUint16LE(); - - // IMDs always have video - _features |= kFeaturesVideo; - // IMDs always have palettes - _features |= kFeaturesPalette; - - // Palette - _stream->read((byte *) _palette, 768); - +bool Imd::loadCoordinates() { // Standard coordinates if (_version >= 3) { _stdX = _stream->readUint16LE(); if (_stdX > 1) { warning("IMD: More than one standard coordinate quad found (%d)", _stdX); - unload(); return false; } if (_stdX != 0) { @@ -155,8 +120,14 @@ bool Imd::load(Common::SeekableReadStream &stream) { } else _stdX = -1; - // Offset to frame positions table - uint32 framesPosPos = 0; + return true; +} + +bool Imd::loadFrameTableOffsets(uint32 &framesPosPos, uint32 &framesCoordsPos) { + framesPosPos = 0; + framesCoordsPos = 0; + + // Frame positions if (_version >= 4) { framesPosPos = _stream->readUint32LE(); if (framesPosPos != 0) { @@ -166,12 +137,40 @@ bool Imd::load(Common::SeekableReadStream &stream) { } } - // Offset to frame coordinates - uint32 framesCoordsPos = 0; + // Frame coordinates if (_features & kFeaturesFrameCoords) framesCoordsPos = _stream->readUint32LE(); - // Sound + return true; +} + +bool Imd::assessVideoProperties() { + // Sizes of the frame data and extra video buffer + if (_features & kFeaturesDataSize) { + _frameDataSize = _stream->readUint16LE(); + if (_frameDataSize == 0) { + _frameDataSize = _stream->readUint32LE(); + _vidBufferSize = _stream->readUint32LE(); + } else + _vidBufferSize = _stream->readUint16LE(); + } else { + _frameDataSize = _width * _height + 500; + if (!(_flags & 0x100) || (_flags & 0x1000)) + _vidBufferSize = _frameDataSize; + } + + // Allocating working memory + _frameData = new byte[_frameDataSize + 500]; + assert(_frameData); + memset(_frameData, 0, _frameDataSize + 500); + _vidBuffer = new byte[_vidBufferSize + 500]; + assert(_vidBuffer); + memset(_vidBuffer, 0, _vidBufferSize + 500); + + return true; +} + +bool Imd::assessAudioProperties() { if (_features & kFeaturesSound) { _soundFreq = _stream->readSint16LE(); _soundSliceSize = _stream->readSint16LE(); @@ -185,7 +184,6 @@ bool Imd::load(Common::SeekableReadStream &stream) { if (_soundSlicesCount > 40) { warning("Imd::load(): More than 40 sound slices found (%d)", _soundSlicesCount); - unload(); return false; } @@ -200,28 +198,18 @@ bool Imd::load(Common::SeekableReadStream &stream) { } else _frameLength = 1000 / _frameRate; - // Sizes of the frame data and extra video buffer - if (_features & kFeaturesDataSize) { - _frameDataSize = _stream->readUint16LE(); - if (_frameDataSize == 0) { - _frameDataSize = _stream->readUint32LE(); - _vidBufferSize = _stream->readUint32LE(); - } else - _vidBufferSize = _stream->readUint16LE(); - } else { - _frameDataSize = _width * _height + 500; - if (!(_flags & 0x100) || (_flags & 0x1000)) - _vidBufferSize = _frameDataSize; - } + return true; +} - // Frame positions table +bool Imd::loadFrameTables(uint32 framesPosPos, uint32 framesCoordsPos) { + // Positions table if (_framesPos) { _stream->seek(framesPosPos, SEEK_SET); for (int i = 0; i < _framesCount; i++) _framesPos[i] = _stream->readUint32LE(); } - // Frame coordinates table + // Coordinates table if (_features & kFeaturesFrameCoords) { _stream->seek(framesCoordsPos, SEEK_SET); _frameCoords = new Coord[_framesCount]; @@ -234,17 +222,73 @@ bool Imd::load(Common::SeekableReadStream &stream) { } } + return true; +} + +bool Imd::load(Common::SeekableReadStream &stream) { + unload(); + + _stream = &stream; + + uint16 handle; + + handle = _stream->readUint16LE(); + _version = _stream->readByte(); + + // Version checking + if ((handle != 0) || (_version < 2)) { + warning("Imd::load(): Version incorrect (%d,%X)", handle, _version); + unload(); + return false; + } + + // Rest header + _features = _stream->readByte(); + _framesCount = _stream->readUint16LE(); + _x = _stream->readSint16LE(); + _y = _stream->readSint16LE(); + _width = _stream->readSint16LE(); + _height = _stream->readSint16LE(); + _flags = _stream->readUint16LE(); + _firstFramePos = _stream->readUint16LE(); + + // IMDs always have video + _features |= kFeaturesVideo; + // IMDs always have palettes + _features |= kFeaturesPalette; + + // Palette + _stream->read((byte *) _palette, 768); + + if (!loadCoordinates()) { + unload(); + return false; + } + + uint32 framesPosPos, frameCoordsPos; + if (!loadFrameTableOffsets(framesPosPos, frameCoordsPos)) { + unload(); + return false; + } + + if (!assessAudioProperties()) { + unload(); + return false; + } + + if (!assessVideoProperties()) { + unload(); + return false; + } + + if (!loadFrameTables(framesPosPos, frameCoordsPos)) { + unload(); + return false; + } + // Seek to the first frame _stream->seek(_firstFramePos, SEEK_SET); - // Allocating working memory - _frameData = new byte[_frameDataSize + 500]; - assert(_frameData); - memset(_frameData, 0, _frameDataSize + 500); - _vidBuffer = new byte[_vidBufferSize + 500]; - assert(_vidBuffer); - memset(_vidBuffer, 0, _vidBufferSize + 500); - return true; } @@ -252,9 +296,6 @@ void Imd::unload() { clear(); } -void Imd::notifyPaused(uint32 duration) { -} - void Imd::setFrameRate(int16 frameRate) { if (frameRate == 0) frameRate = 1; @@ -526,6 +567,88 @@ void Imd::clear(bool del) { _lastFrameTime = 0; } +void Imd::nextSoundSlice(bool hasNextCmd) { + if (hasNextCmd || !_soundEnabled) { + _stream->seek(_soundSliceSize, SEEK_CUR); + return; + } + + byte *soundBuf = new byte[_soundSliceSize]; + + _stream->read(soundBuf, _soundSliceSize); + unsignedToSigned(soundBuf, _soundSliceSize); + + _audioStream->queueBuffer(soundBuf, _soundSliceSize); +} + +bool Imd::initialSoundSlice(bool hasNextCmd) { + int dataLength = _soundSliceSize * _soundSlicesCount; + + if (hasNextCmd || !_soundEnabled) { + _stream->seek(dataLength, SEEK_CUR); + return false; + } + + byte *soundBuf = new byte[dataLength]; + + _stream->read(soundBuf, dataLength); + unsignedToSigned(soundBuf, dataLength); + + _audioStream->queueBuffer(soundBuf, dataLength); + + return _soundStage == 1; +} + +void Imd::emptySoundSlice(bool hasNextCmd) { + if (hasNextCmd || !_soundEnabled) + return; + + byte *soundBuf = new byte[_soundSliceSize]; + + memset(soundBuf, 0, _soundSliceSize); + + _audioStream->queueBuffer(soundBuf, _soundSliceSize); +} + +void Imd::videoData(uint32 size, State &state) { + _stream->read(_frameData, size); + _frameDataLen = size; + + if (_vidMemWidth <= state.right) { + state.left = 0; + state.right -= state.left; + } + if (_vidMemWidth <= state.right) + state.right = _vidMemWidth - 1; + if (_vidMemHeight <= state.bottom) { + state.top = 0; + state.bottom -= state.top; + } + if (_vidMemHeight <= state.bottom) + state.bottom = _vidMemHeight -1; + + state.flags |= renderFrame(state.left, state.top, state.right, state.bottom); + state.flags |= _frameData[0]; +} + +void Imd::calcFrameCoords(uint16 frame, State &state) { + if (_stdX != -1) { + state.left = _stdX; + state.top = _stdY; + state.right = _stdWidth + state.left - 1; + state.bottom = _stdHeight + state.top - 1; + state.flags |= kStateStdCoords; + } + if (_frameCoords && + (_frameCoords[frame].left != -1)) { + state.left = _frameCoords[frame].left; + state.top = _frameCoords[frame].top; + state.right = _frameCoords[frame].right; + state.bottom = _frameCoords[frame].bottom; + state.flags |= kStateFrameCoords; + } +} + CoktelVideo::State Imd::processFrame(uint16 frame) { State state; uint32 cmd = 0; @@ -551,41 +674,29 @@ CoktelVideo::State Imd::processFrame(uint16 frame) { state.bottom = _height + state.top - 1; do { - if (frame != 0) { - if (_stdX != -1) { - state.left = _stdX; - state.top = _stdY; - state.right = _stdWidth + state.left - 1; - state.bottom = _stdHeight + state.top - 1; - state.flags |= kStateStdCoords; - } - if (_frameCoords && - (_frameCoords[frame].left != -1)) { - state.left = _frameCoords[frame].left; - state.top = _frameCoords[frame].top; - state.right = _frameCoords[frame].right; - state.bottom = _frameCoords[frame].bottom; - state.flags |= kStateFrameCoords; - } - } + if (frame != 0) + calcFrameCoords(frame, state); cmd = _stream->readUint16LE(); - if ((cmd & 0xFFF8) == 0xFFF0) { - if (cmd == 0xFFF0) { + if ((cmd & kCommandBreakMask) == kCommandBreak) { + // Flow control + + if (cmd == kCommandBreak) { _stream->seek(2, SEEK_CUR); cmd = _stream->readUint16LE(); } - if (cmd == 0xFFF1) { + // Break + if (cmd == kCommandBreakSkip0) { state.flags = kStateBreak; continue; - } else if (cmd == 0xFFF2) { // Skip (16 bit) + } else if (cmd == kCommandBreakSkip16) { cmd = _stream->readUint16LE(); _stream->seek(cmd, SEEK_CUR); state.flags = kStateBreak; continue; - } else if (cmd == 0xFFF3) { // Skip (32 bit) + } else if (cmd == kCommandBreakSkip32) { cmd = _stream->readUint32LE(); _stream->seek(cmd, SEEK_CUR); state.flags = kStateBreak; @@ -593,59 +704,24 @@ CoktelVideo::State Imd::processFrame(uint16 frame) { } } + // Audio if (_soundStage != 0) { - byte *soundBuf; - - if (cmd == 0xFF00) { - // Next sound slice data - - if (!hasNextCmd && _soundEnabled) { - soundBuf = new byte[_soundSliceSize]; - assert(soundBuf); - - _stream->read(soundBuf, _soundSliceSize); - unsignedToSigned(soundBuf, _soundSliceSize); - _audioStream->queueBuffer(soundBuf, _soundSliceSize); - } else - _stream->seek(_soundSliceSize, SEEK_CUR); + if (cmd == kCommandNextSound) { + nextSoundSlice(hasNextCmd); cmd = _stream->readUint16LE(); - } else if (cmd == 0xFF01) { - // Initial sound data (all slices) - - int dataLength = _soundSliceSize * _soundSlicesCount; - - if (!hasNextCmd && _soundEnabled) { - soundBuf = new byte[dataLength]; - assert(soundBuf); - - _stream->read(soundBuf, dataLength); - unsignedToSigned(soundBuf, dataLength); - - if (_soundStage == 1) - startSound = true; - - _audioStream->queueBuffer(soundBuf, dataLength); - } else - _stream->seek(dataLength, SEEK_CUR); + } else if (cmd == kCommandStartSound) { + startSound = initialSoundSlice(hasNextCmd); cmd = _stream->readUint16LE(); - } else if (!hasNextCmd && (_soundEnabled)) { - // Empty sound slice - - soundBuf = new byte[_soundSliceSize]; - assert(soundBuf); - - memset(soundBuf, 0, _soundSliceSize); - - _audioStream->queueBuffer(soundBuf, _soundSliceSize); - } + } else + emptySoundSlice(hasNextCmd); } // Set palette - if (cmd == 0xFFF4) { + if (cmd == kCommandPalette) { _stream->seek(2, SEEK_CUR); state.flags |= kStatePalette; @@ -655,8 +731,8 @@ CoktelVideo::State Imd::processFrame(uint16 frame) { hasNextCmd = false; - // Jump to frame - if (cmd == 0xFFFD) { + if (cmd == kCommandJump) { + // Jump to frame frame = _stream->readSint16LE(); if (_framesPos) { @@ -667,37 +743,17 @@ CoktelVideo::State Imd::processFrame(uint16 frame) { state.flags |= kStateJump; } - } else if (cmd == 0xFFFC) { + } else if (cmd == kCommandVideoData) { + uint32 size = _stream->readUint32LE() + 2; - state.flags |= 1; - cmd = _stream->readUint32LE(); - _stream->read(_frameData, cmd + 2); - _frameDataLen = cmd + 2; - - if (_vidMemWidth <= state.right) { - state.left = 0; - state.right -= state.left; - } - if (_vidMemWidth <= state.right) - state.right = _vidMemWidth - 1; - if (_vidMemHeight <= state.bottom) { - state.top = 0; - state.bottom -= state.top; - } - if (_vidMemHeight <= state.bottom) - state.bottom = _vidMemHeight -1; + videoData(size, state); - state.flags |= renderFrame(state.left, state.top, state.right, state.bottom); - state.flags |= _frameData[0]; + state.flags |= 1; - // Frame video data } else if (cmd != 0) { + uint32 size = cmd + 2; - _stream->read(_frameData, cmd + 2); - _frameDataLen = cmd + 2; - - state.flags |= renderFrame(state.left, state.top, state.right, state.bottom); - state.flags |= _frameData[0]; + videoData(size, state); } else state.flags |= kStateNoVideoData; diff --git a/graphics/video/coktelvideo/coktelvideo.h b/graphics/video/coktelvideo/coktelvideo.h index ecb9a1505f..6a043233c9 100644 --- a/graphics/video/coktelvideo/coktelvideo.h +++ b/graphics/video/coktelvideo/coktelvideo.h @@ -175,9 +175,6 @@ public: /** Wait for the frame to end. */ virtual void waitEndFrame() = 0; - /** Notifies the video that it was paused for duration ms. */ - virtual void notifyPaused(uint32 duration) = 0; - /** Copy the current frame. * * @param dest The memory to which to copy the current frame. @@ -223,8 +220,6 @@ public: bool hasExtraData(const char *fileName) const; Common::MemoryReadStream *getExtraData(const char *fileName); - void notifyPaused(uint32 duration); - void setFrameRate(int16 frameRate); bool load(Common::SeekableReadStream &stream); @@ -251,6 +246,22 @@ public: uint16 x, uint16 y, uint16 pitch, int16 transp = -1); protected: + enum Command { + kCommandNextSound = 0xFF00, + kCommandStartSound = 0xFF01, + + kCommandBreak = 0xFFF0, + kCommandBreakSkip0 = 0xFFF1, + kCommandBreakSkip16 = 0xFFF2, + kCommandBreakSkip32 = 0xFFF3, + kCommandBreakMask = 0xFFF8, + + kCommandPalette = 0xFFF4, + kCommandVideoData = 0xFFFC, + + kCommandJump = 0xFFFD + }; + struct Coord { int16 left; int16 top; @@ -329,9 +340,23 @@ protected: void deleteVidMem(bool del = true); void clear(bool del = true); + bool loadCoordinates(); + bool loadFrameTableOffsets(uint32 &framesPosPos, uint32 &framesCoordsPos); + bool assessVideoProperties(); + bool assessAudioProperties(); + bool loadFrameTables(uint32 framesPosPos, uint32 framesCoordsPos); + State processFrame(uint16 frame); uint32 renderFrame(int16 left, int16 top, int16 right, int16 bottom); void deLZ77(byte *dest, byte *src); + + void calcFrameCoords(uint16 frame, State &state); + + void nextSoundSlice(bool hasNextCmd); + bool initialSoundSlice(bool hasNextCmd); + void emptySoundSlice(bool hasNextCmd); + + void videoData(uint32 size, State &state); }; class Vmd : public Imd { |