aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/gob/coktelvideo.cpp935
-rw-r--r--engines/gob/coktelvideo.h248
-rw-r--r--engines/gob/dataio.cpp99
-rw-r--r--engines/gob/dataio.h34
-rw-r--r--engines/gob/game.cpp8
-rw-r--r--engines/gob/game.h3
-rw-r--r--engines/gob/game_v2.cpp52
-rw-r--r--engines/gob/gob.cpp8
-rw-r--r--engines/gob/gob.h4
-rw-r--r--engines/gob/imd.cpp1249
-rw-r--r--engines/gob/imd.h143
-rw-r--r--engines/gob/init.cpp10
-rw-r--r--engines/gob/inter_bargon.cpp42
-rw-r--r--engines/gob/inter_v2.cpp64
-rw-r--r--engines/gob/module.mk3
-rw-r--r--engines/gob/mult_v2.cpp15
-rw-r--r--engines/gob/util.cpp10
-rw-r--r--engines/gob/videoplayer.cpp334
-rw-r--r--engines/gob/videoplayer.h86
19 files changed, 1836 insertions, 1511 deletions
diff --git a/engines/gob/coktelvideo.cpp b/engines/gob/coktelvideo.cpp
new file mode 100644
index 0000000000..8f17810430
--- /dev/null
+++ b/engines/gob/coktelvideo.cpp
@@ -0,0 +1,935 @@
+/* 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$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "common/endian.h"
+#include "common/system.h"
+
+#include "gob/coktelvideo.h"
+
+namespace Gob {
+
+Imd::Imd() {
+ clear(false);
+}
+
+Imd::~Imd() {
+ clear();
+}
+
+bool Imd::load(Common::SeekableReadStream &stream) {
+ unload();
+
+ _stream = &stream;
+
+ // Version
+ uint16 handle = _stream->readUint16LE();
+ _version = _stream->readByte();
+
+ // Version checking
+ if ((handle != 0) || (_version < 2)) {
+ warning("IMD Version incorrect (%d,%X)", handle, _version);
+ unload();
+ return false;
+ }
+
+ // Rest header
+ _features = _stream->readByte();
+ _framesCount = _stream->readUint16LE();
+ _x = _stream->readUint16LE();
+ _y = _stream->readUint16LE();
+ _width = _stream->readUint16LE();
+ _height = _stream->readUint16LE();
+ _flags = _stream->readUint16LE();
+ _firstFramePos = _stream->readUint16LE();
+
+ // Palette
+ _stream->read((byte *) _palette, 768);
+
+ // 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) {
+ _stdX = _stream->readUint16LE();
+ _stdY = _stream->readUint16LE();
+ _stdWidth = _stream->readUint16LE();
+ _stdHeight = _stream->readUint16LE();
+ _features |= kFeaturesStdCoords;
+ } else
+ _stdX = -1;
+ } else
+ _stdX = -1;
+
+ // Offset to frame positions table
+ uint32 framesPosPos = 0;
+ if (_version >= 4) {
+ framesPosPos = _stream->readUint32LE();
+ if (framesPosPos != 0) {
+ _framesPos = new int32[_framesCount];
+ assert(_framesPos);
+ _features |= kFeaturesFramesPos;
+ }
+ }
+
+ // Offset to frame coordinates
+ uint32 framesCoordsPos = 0;
+ if (_features & kFeaturesFrameCoords)
+ framesCoordsPos = _stream->readUint32LE();
+
+ // Sound
+ if (_features & kFeaturesSound) {
+ _soundFreq = _stream->readUint16LE();
+ _soundSliceSize = _stream->readUint16LE();
+ _soundSlicesCount = _stream->readUint16LE();
+
+ if (_soundFreq < 0)
+ _soundFreq = -_soundFreq;
+
+ if (_soundSlicesCount < 0)
+ _soundSlicesCount = -_soundSlicesCount - 1;
+
+ if (_soundSlicesCount > 40) {
+ warning("IMD: More than 40 sound slices found (%d)", _soundSlicesCount);
+ unload();
+ return false;
+ }
+
+ _soundSliceLength = 1000 / (_soundFreq / _soundSliceSize);
+ _frameLength = _soundSliceLength;
+
+ _soundStage = 1;
+ _hasSound = true;
+
+ _audioStream = Audio::makeAppendableAudioStream(_soundFreq, 0);
+ } else
+ _frameLength = 1000 / 12; // 12 FPS for a video without sound
+
+ // 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;
+ }
+
+ // Frame positions table
+ if (_framesPos) {
+ _stream->seek(framesPosPos, SEEK_SET);
+ for (int i = 0; i < _framesCount; i++)
+ _framesPos[i] = _stream->readUint32LE();
+ }
+
+ // Frame coordinates table
+ if (_features & kFeaturesFrameCoords) {
+ _stream->seek(framesCoordsPos, SEEK_SET);
+ _frameCoords = new Coord[_framesCount];
+ assert(_frameCoords);
+ for (int i = 0; i < _framesCount; i++) {
+ _frameCoords[i].left = _stream->readUint16LE();
+ _frameCoords[i].top = _stream->readUint16LE();
+ _frameCoords[i].right = _stream->readUint16LE();
+ _frameCoords[i].bottom = _stream->readUint16LE();
+ }
+ }
+
+ // 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;
+}
+
+void Imd::unload() {
+ clear();
+}
+
+void Imd::setXY(int16 x, int16 y) {
+ // Adjusting the standard coordinates
+ if (_stdX != -1) {
+ if (x != -1)
+ _stdX = _stdX - _x + x;
+ if (y != -1)
+ _stdY = _stdY - _y + y;
+ }
+
+ // Going through the coordinate table as well
+ if (_frameCoords) {
+ for (int i = 0; i < _framesCount; i++) {
+ if (_frameCoords[i].left != -1) {
+ if (x != -1) {
+ _frameCoords[i].left = _frameCoords[i].left - _x + x;
+ _frameCoords[i].right = _frameCoords[i].right - _x + x;
+ }
+ if (y != -1) {
+ _frameCoords[i].top = _frameCoords[i].top - _y + y;
+ _frameCoords[i].bottom = _frameCoords[i].bottom - _y + y;
+ }
+ }
+ }
+ }
+
+ if (x != -1)
+ _x = x;
+ if (y != -1)
+ _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;
+ }
+}
+
+void Imd::enableSound(Audio::Mixer &mixer) {
+ // Only possible on the first frame
+ if (_curFrame > 0)
+ return;
+
+ _mixer = &mixer;
+ _soundEnabled = true;
+}
+
+void Imd::disableSound() {
+ if (_audioStream) {
+
+ if (_soundStage == 2) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ } else
+ delete _audioStream;
+
+ _audioStream = 0;
+ }
+ _soundEnabled = false;
+ _mixer = 0;
+}
+
+void Imd::seekFrame(int16 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 >= _framesCount) || (frame == _curFrame))
+ // Nothing to do
+ return;
+
+ // Try every possible way to find a file offset to that frame
+ uint32 framePos = 0;
+ if (frame == 0) {
+ framePos = _firstFramePos;
+ } else if (frame == 1) {
+ framePos = _firstFramePos;
+ _stream->seek(framePos, SEEK_SET);
+ framePos += _stream->readUint16LE() + 4;
+ } else if (_framesPos) {
+ framePos = _framesPos[frame];
+ } else if (restart && (_soundStage == 0)) {
+ for (int i = ((frame > _curFrame) ? _curFrame : 0); i <= frame; i++)
+ processFrame(i);
+ } else
+ error("Frame %d is not directly accessible", frame);
+
+ // Seek
+ _stream->seek(framePos, SEEK_SET);
+ _curFrame = frame;
+}
+
+CoktelVideo::State Imd::nextFrame() {
+ return processFrame(_curFrame);
+}
+
+void Imd::waitEndFrame() {
+ if (_soundEnabled && _hasSound) {
+ if (_soundStage != 2)
+ return;
+
+ if (_skipFrames == 0) {
+ int32 waitTime = (_curFrame * _soundSliceLength) -
+ (g_system->getMillis() - _soundStartTime);
+
+ if (waitTime < 0) {
+ _skipFrames = -waitTime / _soundSliceLength;
+ warning("IMD A/V sync broken, skipping %d frame(s)", _skipFrames + 1);
+ } else if (waitTime > 0)
+ g_system->delayMillis(waitTime);
+
+ } else
+ _skipFrames--;
+ } else
+ g_system->delayMillis(_frameLength);
+}
+
+void Imd::copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp) {
+ if (!_vidMem)
+ return;
+
+ dest += width * y;
+
+ uint16 copyWidth = MIN<int16>(width - x, _width);
+ uint16 destPitch = width - x;
+ byte *vidMem = _vidMem;
+
+ if (transp < 0) {
+ // No transparency
+ if ((x > 0) || (_width != width)) {
+ // Copy row-by-row
+ for (int i = 0; i < _height; i++) {
+ dest += x;
+ memcpy(dest, vidMem, copyWidth);
+ dest += destPitch;
+ vidMem += _width;
+ }
+
+ } else
+ // Dimensions fit, copy everything at once
+ memcpy(dest, _vidMem, _width * _height);
+
+ return;
+ }
+
+ // Transparency, copy per pixel
+ for (int i = 0; i < _height; i++) {
+ byte *s = vidMem;
+ byte *d = dest;
+
+ d += x;
+ for (int j = 0; j < _width; j++) {
+ if (*s != transp)
+ *d = *s;
+
+ s++;
+ d++;
+ }
+
+ dest += width;;
+ vidMem += _width;
+ }
+}
+
+void Imd::deleteVidMem(bool del) {
+ if (del) {
+ if (_hasOwnVidMem)
+ delete[] _vidMem;
+ }
+
+ _hasOwnVidMem = false;
+ _vidMem = 0;
+ _vidMemWidth = _vidMemHeight = 0;
+}
+
+void Imd::clear(bool del) {
+ if (del) {
+ delete[] _framesPos;
+ delete[] _frameCoords;
+ delete[] _frameData;
+ delete[] _vidBuffer;
+
+ disableSound();
+ }
+
+ _stream = 0;
+
+ _version = 0;
+ _features = 0;
+ _flags = 0;
+ _x = _y = _width = _height = 0;
+ _stdX = _stdY = _stdWidth = _stdHeight = 0;
+ _framesCount = _curFrame = 0;
+ _framesPos = 0;
+ _firstFramePos = 0;
+ _frameCoords = 0;
+
+ _frameDataSize = _vidBufferSize = 0;
+ _frameData = _vidBuffer = 0;
+
+ memset(_palette, 0, 768);
+
+ deleteVidMem(del);
+
+ _hasSound = false;
+ _soundEnabled = false;
+ _soundStage = 0;
+ _soundStartTime = 0;
+ _skipFrames = 0;
+
+ _soundFreq = 0;
+ _soundSliceSize = 0;
+ _soundSlicesCount = 0;
+ _soundSliceLength = 0;
+
+ _audioStream = 0;
+
+ _frameLength = 0;
+ _lastFrameTime = 0;
+}
+
+CoktelVideo::State Imd::processFrame(int16 frame) {
+ State state;
+ uint32 cmd = 0;
+ int16 xBak, yBak, heightBak, widthBak;
+ bool hasNextCmd = false;
+ bool startSound = false;
+
+ if (!_stream || (frame >= _framesCount)) {
+ state.flags = kStateBreak;
+ return state;
+ }
+
+ if (frame != _curFrame) {
+ state.flags |= kStateSeeked;
+ seekFrame(frame, SEEK_SET);
+ }
+
+ state.left = xBak = _x;
+ state.top = yBak = _y;
+ state.bottom = heightBak = _height;
+ state.right = widthBak = _width;
+ state.right += state.left - 1;
+ state.bottom += state.top - 1;
+
+/* if ((frame == 0) && (_features & 0x8))
+ _vm->_video->setPalette(_palette);*/
+
+ do {
+ if (frame != 0) {
+ if (_stdX != -1) {
+ state.left = _x = _stdX;
+ state.top = _y = _stdY;
+ state.right = _width = _stdWidth;
+ state.bottom = _height = _stdHeight;
+ state.right += state.left - 1;
+ state.bottom += state.top - 1;
+ state.flags |= kStateStdCoords;
+ }
+ if (_frameCoords &&
+ (_frameCoords[frame].left != -1)) {
+ state.left = _x = _frameCoords[frame].left;
+ state.top = _y = _frameCoords[frame].top;
+ state.right = _width =
+ _frameCoords[frame].right - _x + 1;
+ state.bottom = _height =
+ _frameCoords[frame].bottom - _y + 1;
+ state.right += state.left - 1;
+ state.bottom += state.top - 1;
+ state.flags |= kStateFrameCoords;
+ }
+ }
+
+ cmd = _stream->readUint16LE();
+
+ if ((cmd & 0xFFF8) == 0xFFF0) {
+ if (cmd == 0xFFF0) {
+ _stream->seek(2, SEEK_CUR);
+ cmd = _stream->readUint16LE();
+ }
+
+ if (cmd == 0xFFF1) {
+ state.flags = kStateBreak;
+ continue;
+ } else if (cmd == 0xFFF2) { // Skip (16 bit)
+ cmd = _stream->readUint16LE();
+ _stream->seek(cmd, SEEK_CUR);
+ state.flags = kStateBreak;
+ continue;
+ } else if (cmd == 0xFFF3) { // Skip (32 bit)
+ cmd = _stream->readUint32LE();
+ _stream->seek(cmd, SEEK_CUR);
+ state.flags = kStateBreak;
+ continue;
+ }
+ }
+
+ if (_soundStage != 0) {
+ byte *soundBuf;
+
+/* if (!hasNextCmd)
+ waitEndSoundSlice();*/
+
+ // Next sound slice data
+ if (cmd == 0xFF00) {
+
+ 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);
+
+ cmd = _stream->readUint16LE();
+
+ // Initial sound data (all slices)
+ } else if (cmd == 0xFF01) {
+ int dataLength = _soundSliceSize * _soundSlicesCount;
+
+ if (!hasNextCmd && _soundEnabled) {
+ soundBuf = new byte[dataLength];
+ assert(soundBuf);
+
+ _stream->read(soundBuf, dataLength);
+ unsignedToSigned(soundBuf, dataLength);
+
+ _soundStage = 1;
+ startSound = true;
+ _audioStream->queueBuffer(soundBuf, dataLength);
+ } else
+ _stream->seek(dataLength, SEEK_CUR);
+
+ cmd = _stream->readUint16LE();
+
+ // Empty sound slice
+ } else if (!hasNextCmd && (_soundEnabled)) {
+ soundBuf = new byte[_soundSliceSize];
+ assert(soundBuf);
+
+ memset(soundBuf, 0, _soundSliceSize);
+ _audioStream->queueBuffer(soundBuf, _soundSliceSize);
+ }
+ }
+
+ // Set palette
+ if (cmd == 0xFFF4) {
+ _stream->seek(2, SEEK_CUR);
+ state.flags |= kStatePalette;
+ _stream->read(_palette, 768);
+ cmd = _stream->readUint16LE();
+ }
+
+ hasNextCmd = false;
+
+ // Jump to frame
+ if (cmd == 0xFFFD) {
+
+ frame = _stream->readUint16LE();
+ if (_framesPos) {
+ _curFrame = frame;
+ _stream->seek(_framesPos[frame], SEEK_SET);
+
+ hasNextCmd = true;
+ state.flags |= kStateJump;
+ }
+
+ } else if (cmd == 0xFFFC) {
+
+ state.flags |= 1;
+ cmd = _stream->readUint32LE();
+ _stream->read(_frameData, cmd + 2);
+
+ int16 left = _x;
+ int16 top = _y;
+ int16 right = _width + left;
+ int16 bottom = _height + top;
+
+ if (!_vidMem)
+ setVideoMemory();
+
+ if (_vidMemWidth < right) {
+ left = 0;
+ right = _width;
+ }
+ if (_vidMemWidth < right)
+ right = _vidMemWidth;
+ if (_vidMemHeight < bottom) {
+ top = 0;
+ bottom = _height;
+ }
+ if (_vidMemHeight < bottom)
+ bottom = _vidMemHeight;
+
+ _x = left;
+ _y = top;
+ _height = bottom - top;
+ _width = right - left;
+
+ renderFrame();
+
+ state.flags |= _frameData[0];
+
+ // Frame video data
+ } else if (cmd != 0) {
+
+ _stream->read(_frameData, cmd + 2);
+
+ renderFrame();
+
+ state.flags |= _frameData[0];
+
+ } else
+ state.flags |= kStateNoData;
+
+ } while (hasNextCmd);
+
+ if (startSound && _soundEnabled) {
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_audioHandle, _audioStream);
+ _soundStartTime = g_system->getMillis();
+ _skipFrames = 0;
+ _soundStage = 2;
+ }
+
+ _x = xBak;
+ _y = yBak;
+ _width = widthBak;
+ _height = heightBak;
+
+ _curFrame++;
+ if ((_curFrame == _framesCount) && (_soundStage == 2)) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ _audioStream = 0;
+ _soundStage = 0;
+ }
+
+ _lastFrameTime = g_system->getMillis();
+ return state;
+}
+
+CoktelVideo::State Imd::peekFrame(int16 frame) {
+ State state;
+ uint32 posBak;
+ uint32 tmp;
+ uint16 cmd;
+ int16 frameBak;
+
+ if (!_stream) {
+ state.flags = kStateBreak;
+ return state;
+ }
+
+ posBak = _stream->pos();
+ frameBak = _curFrame;
+
+ if (_curFrame != frame) {
+ state.flags |= kStateSeeked;
+ seekFrame(frame, SEEK_SET);
+ }
+
+ do {
+ if (frame != 0) {
+ if (_stdX != -1)
+ state.flags |= kStateStdCoords;
+ if (_frameCoords && (_frameCoords[frame].left != -1))
+ state.flags |= kStateFrameCoords;
+ }
+
+ cmd = _stream->readUint16LE();
+
+ if ((cmd & 0xFFF8) == 0xFFF0) {
+ if (cmd == 0xFFF0) {
+ _stream->seek(2, SEEK_CUR);
+ cmd = _stream->readUint16LE();
+ }
+
+ if (cmd == 0xFFF1) {
+ state.flags = kStateBreak;
+ continue;
+ } else if (cmd == 0xFFF2) { // Skip (16 bit)
+ cmd = _stream->readUint16LE();
+ _stream->seek(cmd, SEEK_CUR);
+ state.flags = kStateBreak;
+ continue;
+ } else if (cmd == 0xFFF3) { // Skip (32 bit)
+ tmp = _stream->readUint32LE();
+ _stream->seek(cmd, SEEK_CUR);
+ state.flags = kStateBreak;
+ continue;
+ }
+ }
+
+ // Jump to frame
+ if (cmd == 0xFFFD) {
+ frame = _stream->readUint16LE();
+ if (_framesPos) {
+ _stream->seek(_framesPos[frame], SEEK_SET);
+ state.flags |= kStateJump;
+ continue;
+ }
+ break;
+ }
+
+ // Next sound slice data
+ if (cmd == 0xFF00) {
+ _stream->seek(_soundSliceSize, SEEK_CUR);
+ cmd = _stream->readUint16LE();
+ // Initial sound data (all slices)
+ } else if (cmd == 0xFF01) {
+ _stream->seek(_soundSliceSize * _soundSlicesCount, SEEK_CUR);
+ cmd = _stream->readUint16LE();
+ }
+
+ // Frame video data
+ if (cmd != 0) {
+ _stream->read(_frameData, 5);
+ state.flags |= _frameData[0];
+ } else
+ state.flags |= kStateNoData;
+
+ break;
+
+ } while (true);
+
+ _stream->seek(posBak, SEEK_SET);
+ _curFrame = frameBak;
+ return state;
+}
+
+void Imd::renderFrame() {
+ if (!_frameData || (_width <= 0) || (_height <= 0))
+ return;
+
+ if (!_vidMem)
+ setVideoMemory();
+
+ byte *dataPtr = _frameData;
+ int16 imdX = _x;
+ int16 imdY = _y;
+ int16 imdW = _width;
+ int16 imdH = _height;
+ int16 sW = _vidMemWidth;
+ byte *imdVidMem = _vidMem + sW * imdY + imdX;
+ uint8 type = *dataPtr++;
+ byte *srcPtr = dataPtr;
+
+
+ if (type & 0x10) { // Palette data
+ type ^= 0x10;
+ dataPtr += 49;
+ }
+
+ srcPtr = dataPtr;
+ if (type & 0x80) { // Frame data is compressed
+ srcPtr = _vidBuffer;
+ type &= 0x7F;
+ if ((type == 2) && (imdW == sW)) {
+ frameUncompressor(imdVidMem, dataPtr);
+ return;
+ } else
+ frameUncompressor(srcPtr, dataPtr);
+ }
+
+ uint16 pixCount, pixWritten;
+ byte *imdVidMemBak;
+
+ if (type == 2) { // Whole block
+ for (int i = 0; i < imdH; i++) {
+ memcpy(imdVidMem, srcPtr, imdW);
+ srcPtr += imdW;
+ imdVidMem += sW;
+ }
+ } else if (type == 1) { // Sparse block
+ imdVidMemBak = imdVidMem;
+ for (int i = 0; i < imdH; i++) {
+ pixWritten = 0;
+ while (pixWritten < imdW) {
+ pixCount = *srcPtr++;
+ if (pixCount & 0x80) { // data
+ pixCount = MIN((pixCount & 0x7F) + 1, imdW - pixWritten);
+ memcpy(imdVidMem, srcPtr, pixCount);
+
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ srcPtr += pixCount;
+ } else { // "hole"
+ pixCount = (pixCount + 1) % 256;
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ }
+ }
+ imdVidMemBak += sW;
+ imdVidMem = imdVidMemBak;
+ }
+ } else if (type == 0x42) { // Whole quarter-wide block
+ for (int i = 0; i < imdH; i++) {
+ imdVidMemBak = imdVidMem;
+
+ for (int j = 0; j < imdW; j += 4, imdVidMem += 4, srcPtr++)
+ memset(imdVidMem, *srcPtr, 4);
+
+ imdVidMemBak += sW;
+ imdVidMem = imdVidMemBak;
+ }
+ } else if ((type & 0xF) == 2) { // Whole half-high block
+ for (; imdH > 1; imdH -= 2, imdVidMem += sW + sW, srcPtr += imdW) {
+ memcpy(imdVidMem, srcPtr, imdW);
+ memcpy(imdVidMem + sW, srcPtr, imdW);
+ }
+ if (imdH == -1)
+ memcpy(imdVidMem, srcPtr, imdW);
+ } else { // Sparse half-high block
+ imdVidMemBak = imdVidMem;
+ for (int i = 0; i < imdH; i += 2) {
+ pixWritten = 0;
+ while (pixWritten < imdW) {
+ pixCount = *srcPtr++;
+ if (pixCount & 0x80) { // data
+ pixCount = MIN((pixCount & 0x7F) + 1, imdW - pixWritten);
+ memcpy(imdVidMem, srcPtr, pixCount);
+ memcpy(imdVidMem + sW, srcPtr, pixCount);
+
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ srcPtr += pixCount;
+ } else { // "hole"
+ pixCount = (pixCount + 1) % 256;
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ }
+ }
+ imdVidMemBak += sW + sW;
+ imdVidMem = imdVidMemBak;
+ }
+ }
+}
+
+void Imd::frameUncompressor(byte *dest, byte *src) {
+ int i;
+ byte buf[4370];
+ uint16 chunkLength;
+ uint16 frameLength;
+ uint16 bufPos1;
+ uint16 bufPos2;
+ uint16 tmp;
+ uint8 chunkBitField;
+ uint8 chunkCount;
+ bool mode;
+
+ frameLength = READ_LE_UINT16(src);
+ src += 4;
+
+ if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
+ src += 4;
+ bufPos1 = 273;
+ mode = 1; // 123Ch (cmp al, 12h)
+ } else {
+ bufPos1 = 4078;
+ mode = 0; // 275h (jnz +2)
+ }
+
+ memset(buf, 32, bufPos1);
+ chunkCount = 1;
+ chunkBitField = 0;
+
+ while (frameLength > 0) {
+ chunkCount--;
+ if (chunkCount == 0) {
+ tmp = *src++;
+ chunkCount = 8;
+ chunkBitField = tmp;
+ }
+ if (chunkBitField % 2) {
+ chunkBitField >>= 1;
+ buf[bufPos1] = *src;
+ *dest++ = *src++;
+ bufPos1 = (bufPos1 + 1) % 4096;
+ frameLength--;
+ continue;
+ }
+ chunkBitField >>= 1;
+
+ tmp = READ_LE_UINT16(src);
+ src += 2;
+ chunkLength = ((tmp & 0xF00) >> 8) + 3;
+
+ if ((mode && ((chunkLength & 0xFF) == 0x12)) ||
+ (!mode && (chunkLength == 0)))
+ chunkLength = *src++ + 0x12;
+
+ bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
+ if (((tmp + chunkLength) >= 4096) ||
+ ((chunkLength + bufPos1) >= 4096)) {
+
+ for (i = 0; i < chunkLength; i++, dest++) {
+ *dest = buf[bufPos2];
+ buf[bufPos1] = buf[bufPos2];
+ bufPos1 = (bufPos1 + 1) % 4096;
+ bufPos2 = (bufPos2 + 1) % 4096;
+ }
+
+ } else if (((tmp + chunkLength) < bufPos1) ||
+ ((chunkLength + bufPos1) < bufPos2)) {
+
+ memcpy(dest, buf + bufPos2, chunkLength);
+ memmove(buf + bufPos1, buf + bufPos2, chunkLength);
+
+ dest += chunkLength;
+ bufPos1 += chunkLength;
+ bufPos2 += chunkLength;
+
+ } else {
+
+ for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
+ *dest = buf[bufPos2];
+ buf[bufPos1] = buf[bufPos2];
+ }
+
+ }
+ frameLength -= chunkLength;
+
+ }
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/coktelvideo.h b/engines/gob/coktelvideo.h
new file mode 100644
index 0000000000..4e7512eb8b
--- /dev/null
+++ b/engines/gob/coktelvideo.h
@@ -0,0 +1,248 @@
+/* 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
+ };
+
+ 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. */
+ kStateNoData = 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;
+ };
+
+ 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 int16 getFramesCount() const = 0;
+ /** Returns the current frame number. */
+ virtual int16 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(int16 frame, int16 whence = SEEK_SET, bool restart = false) = 0;
+
+ /** Render the next frame. */
+ virtual State nextFrame() = 0;
+ /** Look at what a frame would do/have, without actually rendering the frame. */
+ virtual State peekFrame(int16 frame) = 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; }
+ int16 getFramesCount() const { return _framesCount; }
+ int16 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(int16 frame, int16 whence = SEEK_SET, bool restart = false);
+
+ State nextFrame();
+ State peekFrame(int16 frame);
+ 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;
+ uint8 _version;
+ uint16 _features;
+ int16 _flags;
+ int16 _x, _y, _width, _height;
+ int16 _stdX, _stdY, _stdWidth, _stdHeight;
+ int16 _framesCount, _curFrame;
+ int32 *_framesPos;
+ int32 _firstFramePos;
+ Coord *_frameCoords;
+
+ int32 _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;
+
+ int16 _soundFreq;
+ uint16 _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(int16 frame);
+ void renderFrame();
+ void frameUncompressor(byte *dest, byte *src);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_COKTELVIDEO_H
diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp
index 7ded953427..73318adc14 100644
--- a/engines/gob/dataio.cpp
+++ b/engines/gob/dataio.cpp
@@ -33,6 +33,83 @@
namespace Gob {
+DataStream::DataStream(DataIO &io, int16 handle, uint32 dSize, bool dispose) {
+ _io = &io;
+ _handle = handle;
+ _size = dSize;
+ _dispose = dispose;
+
+ _data = 0;
+ _stream = 0;
+}
+
+DataStream::DataStream(byte *buf, uint32 dSize, bool dispose) {
+ _data = buf;
+ _size = dSize;
+ _stream = new Common::MemoryReadStream(_data, _size);
+ _dispose = dispose;
+
+ _io = 0;
+ _handle = -1;
+}
+
+DataStream::~DataStream() {
+ delete _stream;
+
+ if (_dispose) {
+ delete[] _data;
+ if ((_handle >= 0) && _io)
+ _io->closeData(_handle);
+ }
+}
+
+uint32 DataStream::pos() const {
+ if (_stream)
+ return _stream->pos();
+
+ uint32 resPos = _io->getChunkPos(_handle);
+ if (resPos != 0xFFFFFFFF)
+ return resPos;
+
+ return _io->file_getHandle(_handle)->pos();
+}
+
+uint32 DataStream::size() const {
+ if (_stream)
+ return _stream->size();
+
+ return _size;
+}
+
+void DataStream::seek(int32 offset, int whence) {
+ if (_stream)
+ _stream->seek(offset, whence);
+
+ int32 resPos = _io->seekChunk(_handle, offset, whence);
+ if (resPos != -1)
+ return;
+
+ _io->file_getHandle(_handle)->seek(offset, whence);
+}
+
+bool DataStream::eos() const {
+ if (_stream)
+ return _stream->eos();
+
+ return pos() >= size();
+}
+
+uint32 DataStream::read(void *dataPtr, uint32 dataSize) {
+ if (_stream)
+ return _stream->read(dataPtr, dataSize);
+
+ int32 res = _io->readChunk(_handle, (byte *) dataPtr, dataSize);
+ if (res >= 0)
+ return res;
+
+ return _io->file_getHandle(_handle)->read((byte *) dataPtr, dataSize);
+}
+
DataIO::DataIO(GobEngine *vm) : _vm(vm) {
for (int i = 0; i < MAX_DATA_FILES; i++) {
_dataFiles[i] = 0;
@@ -115,6 +192,10 @@ Common::File *DataIO::file_getHandle(int16 handle) {
return &_filesHandles[handle];
}
+const Common::File *DataIO::file_getHandle(int16 handle) const {
+ return &_filesHandles[handle];
+}
+
int16 DataIO::file_open(const char *path, Common::File::AccessMode mode) {
int16 i;
@@ -226,7 +307,7 @@ int16 DataIO::seekChunk(int16 handle, int32 pos, int16 from) {
return _chunkPos[file * MAX_SLOT_COUNT + slot];
}
-uint32 DataIO::getChunkPos(int16 handle) {
+uint32 DataIO::getChunkPos(int16 handle) const {
int16 file;
int16 slot;
@@ -390,6 +471,15 @@ int16 DataIO::openData(const char *path, Common::File::AccessMode mode) {
return file_open(path, mode);
}
+DataStream *DataIO::openAsStream(int16 handle, bool dispose) {
+ uint32 curPos = getPos(handle);
+ seekData(handle, 0, SEEK_END);
+ uint32 size = getPos(handle);
+ seekData(handle, curPos, SEEK_SET);
+
+ return new DataStream(*this, handle, size, dispose);
+}
+
int32 DataIO::readData(int16 handle, byte *buf, uint16 size) {
int32 res;
@@ -492,4 +582,11 @@ byte *DataIO::getData(const char *path) {
return data;
}
+DataStream *DataIO::getDataStream(const char *path) {
+ uint32 size = getDataSize(path);
+ byte *data = getData(path);
+
+ return new DataStream(data, size);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h
index 08498a4f7e..3560093d9e 100644
--- a/engines/gob/dataio.h
+++ b/engines/gob/dataio.h
@@ -37,6 +37,32 @@ namespace Gob {
#define MAX_DATA_FILES 8
#define MAX_SLOT_COUNT 8
+class DataIO;
+
+class DataStream : public Common::SeekableReadStream {
+public:
+ DataStream(DataIO &io, int16 handle, uint32 dSize, bool dispose = false);
+ DataStream(byte *buf, uint32 dSize, bool dispose = true);
+ virtual ~DataStream();
+
+ virtual uint32 pos() const;
+ virtual uint32 size() const;
+
+ virtual void seek(int32 offset, int whence = SEEK_SET);
+
+ virtual bool eos() const;
+
+ virtual uint32 read(void *dataPtr, uint32 dataSize);
+
+private:
+ DataIO *_io;
+ int16 _handle;
+ uint32 _size;
+ byte *_data;
+ Common::MemoryReadStream *_stream;
+ bool _dispose;
+};
+
class DataIO {
public:
struct ChunkDesc {
@@ -55,6 +81,8 @@ public:
void closeData(int16 handle);
int16 openData(const char *path,
Common::File::AccessMode mode = Common::File::kFileReadMode);
+ DataStream *openAsStream(int16 handle, bool dispose = false);
+
int32 readData(int16 handle, byte *buf, uint16 size);
byte readByte(int16 handle);
uint16 readUint16(int16 handle);
@@ -64,6 +92,7 @@ public:
uint32 getPos(int16 handle);
int32 getDataSize(const char *name);
byte *getData(const char *path);
+ DataStream *getDataStream(const char *path);
DataIO(class GobEngine *vm);
~DataIO();
@@ -85,13 +114,16 @@ protected:
int16 file_open(const char *path,
Common::File::AccessMode mode = Common::File::kFileReadMode);
Common::File *file_getHandle(int16 handle);
+ const Common::File *file_getHandle(int16 handle) const;
int16 getChunk(const char *chunkName);
char freeChunk(int16 handle);
int32 readChunk(int16 handle, byte *buf, uint16 size);
int16 seekChunk(int16 handle, int32 pos, int16 from);
- uint32 getChunkPos(int16 handle);
+ uint32 getChunkPos(int16 handle) const;
int32 getChunkSize(const char *chunkName);
+
+friend class DataStream;
};
} // End of namespace Gob
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index e47dc1809f..b625a35258 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -379,10 +379,12 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY,
_vm->_inter->_soundEndTimeKey = 0;
}
- _vm->_util->getMouseState(pMouseX, pMouseY, pButtons);
+ if (pMouseX && pMouseY && pButtons) {
+ _vm->_util->getMouseState(pMouseX, pMouseY, pButtons);
- if (*pButtons == 3)
- *pButtons = 0;
+ if (*pButtons == 3)
+ *pButtons = 0;
+ }
return _vm->_util->checkKey();
}
diff --git a/engines/gob/game.h b/engines/gob/game.h
index 2b684a179f..c83497eaeb 100644
--- a/engines/gob/game.h
+++ b/engines/gob/game.h
@@ -147,7 +147,8 @@ public:
void evaluateScroll(int16 x, int16 y);
- int16 checkKeys(int16 *pMousex, int16 *pMouseY, int16 *pButtons, char handleMouse);
+ int16 checkKeys(int16 *pMousex = 0, int16 *pMouseY = 0,
+ int16 *pButtons = 0, char handleMouse = 0);
void start(void);
void totSub(int8 flags, const char *newTotFile);
void switchTotSub(int16 index, int16 skipPlay);
diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp
index 4ccd6d718e..f7f7a10b92 100644
--- a/engines/gob/game_v2.cpp
+++ b/engines/gob/game_v2.cpp
@@ -1,27 +1,27 @@
-/* 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$
- *
- */
+ /* 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$
+ *
+ */
#include "common/stdafx.h"
#include "common/endian.h"
@@ -34,13 +34,13 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/goblin.h"
-#include "gob/imd.h"
#include "gob/inter.h"
#include "gob/mult.h"
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/sound.h"
#include "gob/video.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -271,7 +271,7 @@ void Game_v2::playTot(int16 skipPlay) {
_vm->_snd->freeSample(_soundSamples[i]);
}
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
if (_totToLoad[0] == 0)
break;
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 9a14194972..f1bec2b8d5 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -48,7 +48,7 @@
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/music.h"
-#include "gob/imd.h"
+#include "gob/videoplayer.h"
#include "gob/saveload.h"
namespace Gob {
@@ -72,7 +72,7 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
_snd = 0; _adlib = 0; _mult = 0;
_game = 0; _global = 0; _cdrom = 0;
- _dataIO = 0; _goblin = 0; _imdPlayer = 0;
+ _dataIO = 0; _goblin = 0; _vidPlayer = 0;
_init = 0; _inter = 0; _map = 0;
_palAnim = 0; _parse = 0; _scenery = 0;
_draw = 0; _util = 0; _video = 0;
@@ -236,7 +236,7 @@ bool GobEngine::initGameParts() {
_util = new Util(this);
_dataIO = new DataIO(this);
_palAnim = new PalAnim(this);
- _imdPlayer = new ImdPlayer(this);
+ _vidPlayer = new VideoPlayer(this);
_cdrom = new CDROM(this);
_snd = new Snd(this);
@@ -364,7 +364,7 @@ void GobEngine::deinitGameParts() {
delete _cdrom; _cdrom = 0;
delete _dataIO; _dataIO = 0;
delete _goblin; _goblin = 0;
- delete _imdPlayer; _imdPlayer = 0;
+ delete _vidPlayer; _vidPlayer = 0;
delete _init; _init = 0;
delete _inter; _inter = 0;
delete _map; _map = 0;
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index 8c9583c95d..9a88571c0e 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -42,7 +42,7 @@ class Draw;
class CDROM;
class DataIO;
class Goblin;
-class ImdPlayer;
+class VideoPlayer;
class Init;
class Inter;
class Map;
@@ -216,7 +216,7 @@ public:
Inter *_inter;
SaveLoad *_saveLoad;
Adlib *_adlib;
- ImdPlayer *_imdPlayer;
+ VideoPlayer *_vidPlayer;
void shutdown();
diff --git a/engines/gob/imd.cpp b/engines/gob/imd.cpp
deleted file mode 100644
index 395fb01f9b..0000000000
--- a/engines/gob/imd.cpp
+++ /dev/null
@@ -1,1249 +0,0 @@
-/* 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$
- *
- */
-
-#include "common/stdafx.h"
-#include "common/endian.h"
-
-#include "gob/gob.h"
-#include "gob/imd.h"
-#include "gob/global.h"
-#include "gob/util.h"
-#include "gob/dataio.h"
-#include "gob/draw.h"
-#include "gob/game.h"
-#include "gob/inter.h"
-#include "gob/palanim.h"
-#include "gob/sound.h"
-#include "gob/video.h"
-
-namespace Gob {
-
-ImdPlayer::ImdPlayer(GobEngine *vm) : _vm(vm) {
- _curImd = 0;
- _curFile[0] = 0;
-
- _curX = 0;
- _curY = 0;
- _left = 0;
- _top = 0;
- _right = 0;
- _bottom = 0;
-
- _frameData = 0;
- _vidBuffer = 0;
-
- _frontSurf = 21;
- _backSurf = 21;
- _frontMem = 0;
- _frameDelay = 0;
-
- _noSound = true;
-
- _soundStartTime = 0;
- _skipFrames = 0;
-
- _soundFreq = 0;
- _soundSliceSize = 0;
- _soundSlicesCount = 0;
-
- _soundSliceLength = 0;
- _soundStage = 0;
-
- _audioStream = 0;
-}
-
-ImdPlayer::~ImdPlayer() {
- if (_curImd) {
- delete[] _curImd->palette;
- delete[] _curImd->framesPos;
- delete[] _curImd->frameCoords;
- delete[] _curImd->extraPalette;
- }
- delete[] _frameData;
- delete[] _vidBuffer;
- delete[] _frontMem;
- delete _curImd;
-}
-
-// flag bits: 0 = read and set palette
-// 1 = read palette
-ImdPlayer::Imd *ImdPlayer::loadImdFile(const char *path, SurfaceDesc *surfDesc, int8 flags) {
- Imd *imdPtr;
- int16 handle;
- char buf[18];
- uint32 framesPosPos = 0;
- uint32 framesCordsPos = 0;
-
- strncpy0(buf, path, 17);
- if (!strchr(buf, '.')) {
- buf[13] = 0;
- strcat(buf, ".IMD");
- }
-
- handle = _vm->_dataIO->openData(buf);
-
- if (handle < 0) {
- warning("Can't open IMD \"%s\"", buf);
- return 0;
- }
-
- imdPtr = new Imd;
- assert(imdPtr);
- memset(imdPtr, 0, sizeof(Imd));
-
- imdPtr->handle = _vm->_dataIO->readUint16(handle);
- imdPtr->verMin = _vm->_dataIO->readUint16(handle);
- imdPtr->framesCount = _vm->_dataIO->readUint16(handle);
- imdPtr->x = _vm->_dataIO->readUint16(handle);
- imdPtr->y = _vm->_dataIO->readUint16(handle);
- imdPtr->width = _vm->_dataIO->readUint16(handle);
- imdPtr->height = _vm->_dataIO->readUint16(handle);
- imdPtr->field_E = _vm->_dataIO->readUint16(handle);
- imdPtr->curFrame = _vm->_dataIO->readUint16(handle);
-
- if ((imdPtr->handle != 0) || ((imdPtr->verMin & 0xFF) < 2)) {
- warning("%s: Version incorrect (%d,%X)", buf, imdPtr->handle, imdPtr->verMin);
- _vm->_dataIO->closeData(handle);
- delete imdPtr;
- return 0;
- }
-
- imdPtr->handle = handle;
- imdPtr->surfDesc = surfDesc;
- imdPtr->firstFramePos = imdPtr->curFrame;
- imdPtr->curFrame = 0;
-
- if ((imdPtr->verMin & 0x800) && ((flags & 3) != 3))
- imdPtr->extraPalette = new Video::Color[256];
-
- if (flags & 3) {
- imdPtr->palette = new Video::Color[256];
- assert(imdPtr->palette);
- _vm->_dataIO->readData(handle, (byte *) imdPtr->palette, 768);
- } else
- _vm->_dataIO->seekData(handle, 768, SEEK_CUR);
-
- if ((flags & 3) == 1)
- _vm->_video->setPalette(imdPtr->palette);
-
- if ((imdPtr->verMin & 0xFF) >= 3) {
- imdPtr->stdX = _vm->_dataIO->readUint16(handle);
- if (imdPtr->stdX > 1) {
- warning("%s: More than one standard coordinate quad found (%d)",
- buf, imdPtr->stdX);
- finishImd(imdPtr);
- return 0;
- }
- if (imdPtr->stdX != 0) {
- imdPtr->stdX = _vm->_dataIO->readUint16(handle);
- imdPtr->stdY = _vm->_dataIO->readUint16(handle);
- imdPtr->stdWidth = _vm->_dataIO->readUint16(handle);
- imdPtr->stdHeight = _vm->_dataIO->readUint16(handle);
- } else
- imdPtr->stdX = -1;
- } else
- imdPtr->stdX = -1;
-
- if ((imdPtr->verMin & 0xFF) >= 4) {
- framesPosPos = _vm->_dataIO->readUint32(handle);
- if (framesPosPos != 0) {
- imdPtr->framesPos = new int32[imdPtr->framesCount];
- assert(imdPtr->framesPos);
- }
- }
-
- if (imdPtr->verMin & 0x8000)
- framesCordsPos = _vm->_dataIO->readUint32(handle);
-
- _noSound = true;
- _soundStage = 0;
- if (imdPtr->verMin & 0x4000) {
- _soundFreq = _vm->_dataIO->readUint16(handle);
- _soundSliceSize = _vm->_dataIO->readUint16(handle);
- _soundSlicesCount = _vm->_dataIO->readUint16(handle);
-
- if (_soundFreq < 0)
- _soundFreq = -_soundFreq;
-
- if (_soundSlicesCount < 0)
- _soundSlicesCount = -_soundSlicesCount - 1;
-
- if (_soundSlicesCount > 40) {
- warning("%s: More than 40 sound slices found (%d)",
- buf, _soundSlicesCount);
- finishImd(imdPtr);
- return 0;
- }
-
- _soundSliceLength = 1000 / (_soundFreq / _soundSliceSize);
-
- _soundStage = 1;
- _noSound = false;
-
- _audioStream = Audio::makeAppendableAudioStream(_soundFreq, 0);
- }
-
- if (imdPtr->verMin & 0x2000) {
- imdPtr->frameDataSize = _vm->_dataIO->readUint16(handle);
- if (imdPtr->frameDataSize == 0) {
- imdPtr->frameDataSize = _vm->_dataIO->readUint32(handle);
- imdPtr->vidBufferSize = _vm->_dataIO->readUint32(handle);
- } else
- imdPtr->vidBufferSize = _vm->_dataIO->readUint16(handle);
- } else {
- imdPtr->frameDataSize = imdPtr->width * imdPtr->height + 500;
- if (!(imdPtr->field_E & 0x100) || (imdPtr->field_E & 0x1000))
- imdPtr->vidBufferSize = imdPtr->frameDataSize;
- }
-
- if (imdPtr->framesPos) {
- _vm->_dataIO->seekData(handle, framesPosPos, SEEK_SET);
- for (int i = 0; i < imdPtr->framesCount; i++)
- imdPtr->framesPos[i] = _vm->_dataIO->readUint32(handle);
- }
-
- if (imdPtr->verMin & 0x8000) {
- _vm->_dataIO->seekData(handle, framesCordsPos, SEEK_SET);
- imdPtr->frameCoords = new ImdCoord[imdPtr->framesCount];
- assert(imdPtr->frameCoords);
- for (int i = 0; i < imdPtr->framesCount; i++) {
- imdPtr->frameCoords[i].left = _vm->_dataIO->readUint16(handle);
- imdPtr->frameCoords[i].top = _vm->_dataIO->readUint16(handle);
- imdPtr->frameCoords[i].right = _vm->_dataIO->readUint16(handle);
- imdPtr->frameCoords[i].bottom = _vm->_dataIO->readUint16(handle);
- }
- }
-
- _vm->_dataIO->seekData(handle, imdPtr->firstFramePos, SEEK_SET);
- return imdPtr;
-}
-
-void ImdPlayer::finishImd(ImdPlayer::Imd *&imdPtr) {
- if (!imdPtr)
- return;
-
- if (_soundStage == 2)
- _vm->_snd->stopSound(0);
-
- _vm->_dataIO->closeData(imdPtr->handle);
-
- delete[] imdPtr->frameCoords;
- delete[] imdPtr->palette;
- delete[] imdPtr->framesPos;
- delete[] imdPtr->extraPalette;
-
- delete imdPtr;
-
- if (_audioStream) {
- _audioStream->finish();
- _vm->_mixer->stopHandle(_audioHandle);
- _audioStream = 0;
- }
-}
-
-int8 ImdPlayer::openImd(const char *path, int16 x, int16 y,
- int16 startFrame, int16 flags) {
- const char *src;
- byte *vidMem;
- SurfaceDesc *surfDesc;
-
- if (!_curImd)
- _curFile[0] = 0;
-
- src = strrchr(path, '\\');
- src = !src ? path : src + 1;
-
- if ((path[0] != 0) && scumm_stricmp(_curFile, src)) {
- closeImd();
-
- _curImd = loadImdFile(path, 0, 3);
- if (!_curImd)
- return 0;
-
- _curX = _curImd->x;
- _curY = _curImd->y;
- strncpy0(_curFile, src, 17);
-
- delete[] _frameData;
- _frameData = new byte[_curImd->frameDataSize + 500];
- assert(_frameData);
- memset(_frameData, 0, _curImd->frameDataSize + 500);
-
- delete[] _vidBuffer;
- _vidBuffer = new byte[_curImd->vidBufferSize + 500];
- assert(_vidBuffer);
- memset(_vidBuffer, 0, _curImd->vidBufferSize + 500);
-
- if (!(flags & 0x100)) {
-
- if (_vm->_global->_videoMode == 0x14) {
-
- _backSurf = (flags & 0x80) ? 20 : 21;
- if (!(_curImd->field_E & 0x100) || (_curImd->field_E & 0x2000)) {
- setXY(_curImd, 0, 0);
- _curImd->surfDesc =
- _vm->_video->initSurfDesc(0x13,
- _curImd->width, _curImd->height, 0);
- } else {
- _curImd->surfDesc = _vm->_draw->_spritesArray[_frontSurf];
- if ((x != -1) || (y != -1)) {
- _curX = x != -1 ? x : _curX;
- _curY = y != -1 ? y : _curY;
- setXY(_curImd, _curX, _curY);
- }
- }
-
- if (flags & 0x40) {
- _curX = x != -1 ? x : _curX;
- _curY = y != -1 ? y : _curY;
- if (_curImd->surfDesc->_vidMode == 0x14) {
- surfDesc = _vm->_video->initSurfDesc(0x13,
- _curImd->width, _curImd->height, 0);
- _vm->_video->drawSprite(_vm->_draw->_spritesArray[21],
- surfDesc, _curX, _curY,
- _curX + _curImd->width - 1, _curY + _curImd->height - 1,
- 0, 0, 0);
-
- vidMem = _curImd->surfDesc->getVidMem();
- for (int i = 0; i < _curImd->height; i++)
- for (int j = 0; j < _curImd->width; j++, vidMem++) {
- *(vidMem) = *(surfDesc->getVidMem() +
- (j / 4) + (surfDesc->getWidth() / 4 * i));
- }
- surfDesc = 0;
- }
- }
-
- } else {
- if ((x != -1) || (y != -1)) {
- _curX = (x != -1) ? x : _curX;
- _curY = (y != -1) ? y : _curY;
- setXY(_curImd, _curX, _curY);
- }
- _backSurf = (flags & 0x80) ? 20 : 21;
- _curImd->surfDesc = _vm->_draw->_spritesArray[_backSurf];
- }
-
- }
- }
-
- if (!_curImd)
- return 0;
-
- if (startFrame == -1) {
- closeImd();
- return 0;
- }
-
- _curX = (x != -1) ? x : _curX;
- _curY = (y != -1) ? y : _curY;
-
- WRITE_VAR(7, _curImd->framesCount);
-
- return 1;
-}
-
-void ImdPlayer::closeImd(void) {
- finishImd(_curImd);
-
- delete[] _frameData;
- delete[] _vidBuffer;
- _frameData = 0;
- _vidBuffer = 0;
-
- _curImd = 0;
-}
-
-void ImdPlayer::setXY(ImdPlayer::Imd *imdPtr, int16 x, int16 y) {
- int i;
-
- if (imdPtr->stdX != -1) {
- imdPtr->stdX = imdPtr->stdX - imdPtr->x + x;
- imdPtr->stdY = imdPtr->stdY - imdPtr->y + y;
- }
-
- if (imdPtr->frameCoords) {
- for (i = 0; i < imdPtr->framesCount; i++) {
- if (imdPtr->frameCoords[i].left != -1) {
- imdPtr->frameCoords[i].left =
- imdPtr->frameCoords[i].left - imdPtr->x + x;
- imdPtr->frameCoords[i].top =
- imdPtr->frameCoords[i].top - imdPtr->y + y;
- imdPtr->frameCoords[i].right =
- imdPtr->frameCoords[i].right - imdPtr->x + x;
- imdPtr->frameCoords[i].bottom =
- imdPtr->frameCoords[i].bottom - imdPtr->y + y;
- }
- }
- }
-
- imdPtr->x = x;
- imdPtr->y = y;
-}
-
-void ImdPlayer::drawFrame(Imd *imdPtr, int16 frame, int16 x, int16 y,
- SurfaceDesc *dest) {
- if (!dest)
- dest = _vm->_draw->_frontSurface;
-
- if (frame == 0)
- _vm->_video->drawSprite(imdPtr->surfDesc, dest, 0, 0,
- imdPtr->width - 1, imdPtr->height - 1, x, y, 0);
- else if (imdPtr->frameCoords && (imdPtr->frameCoords[frame].left != -1))
- _vm->_video->drawSprite(imdPtr->surfDesc, dest,
- imdPtr->frameCoords[frame].left, imdPtr->frameCoords[frame].top,
- imdPtr->frameCoords[frame].right, imdPtr->frameCoords[frame].bottom,
- imdPtr->frameCoords[frame].left + x,
- imdPtr->frameCoords[frame].top + y, 0);
- else if (imdPtr->stdX != -1)
- _vm->_video->drawSprite(imdPtr->surfDesc, dest,
- imdPtr->stdX, imdPtr->stdY, imdPtr->stdX + imdPtr->stdWidth - 1,
- imdPtr->stdY + imdPtr->stdHeight - 1, x + imdPtr->stdX,
- y + imdPtr->stdY, 0);
- else
- _vm->_video->drawSprite(imdPtr->surfDesc, dest, 0, 0,
- imdPtr->width - 1, imdPtr->height - 1, x, y, 0);
-}
-
-void ImdPlayer::renderFrame(Imd *imdPtr) {
- int16 imdX, imdY;
- int16 imdW, imdH;
- int16 sW;
- uint16 pixCount, pixWritten;
- uint8 type;
- byte *imdVidMem;
- byte *imdVidMemBak;
- byte *dataPtr = 0;
- byte *srcPtr = 0;
-
- dataPtr = _frameData;
- imdX = imdPtr->x;
- imdY = imdPtr->y;
- imdW = imdPtr->width;
- imdH = imdPtr->height;
- sW = imdPtr->surfDesc->getWidth();
- imdVidMem = imdPtr->surfDesc->getVidMem() + sW * imdY + imdX;
-
- type = *dataPtr++;
- srcPtr = dataPtr;
-
- if (type & 0x10) { // Palette data
- type ^= 0x10;
- dataPtr += 49;
- }
-
- srcPtr = dataPtr;
- if (type & 0x80) { // Frame data is compressed
- srcPtr = _vidBuffer;
- type &= 0x7F;
- if ((type == 2) && (imdW == sW)) {
- frameUncompressor(imdVidMem, dataPtr);
- return;
- } else
- frameUncompressor(srcPtr, dataPtr);
- }
-
- if (type == 2) { // Whole block
- for (int i = 0; i < imdH; i++) {
- memcpy(imdVidMem, srcPtr, imdW);
- srcPtr += imdW;
- imdVidMem += sW;
- }
- } else if (type == 1) { // Sparse block
- imdVidMemBak = imdVidMem;
- for (int i = 0; i < imdH; i++) {
- pixWritten = 0;
- while (pixWritten < imdW) {
- pixCount = *srcPtr++;
- if (pixCount & 0x80) { // data
- pixCount = MIN((pixCount & 0x7F) + 1, imdW - pixWritten);
- memcpy(imdVidMem, srcPtr, pixCount);
-
- pixWritten += pixCount;
- imdVidMem += pixCount;
- srcPtr += pixCount;
- } else { // "hole"
- pixCount = (pixCount + 1) % 256;
- pixWritten += pixCount;
- imdVidMem += pixCount;
- }
- }
- imdVidMemBak += sW;
- imdVidMem = imdVidMemBak;
- }
- } else if (type == 0x42) { // Whole quarter-wide block
- for (int i = 0; i < imdH; i++) {
- imdVidMemBak = imdVidMem;
-
- for (int j = 0; j < imdW; j += 4, imdVidMem += 4, srcPtr++)
- memset(imdVidMem, *srcPtr, 4);
-
- imdVidMemBak += sW;
- imdVidMem = imdVidMemBak;
- }
- } else if ((type & 0xF) == 2) { // Whole half-high block
- for (; imdH > 1; imdH -= 2, imdVidMem += sW + sW, srcPtr += imdW) {
- memcpy(imdVidMem, srcPtr, imdW);
- memcpy(imdVidMem + sW, srcPtr, imdW);
- }
- if (imdH == -1)
- memcpy(imdVidMem, srcPtr, imdW);
- } else { // Sparse half-high block
- imdVidMemBak = imdVidMem;
- for (int i = 0; i < imdH; i += 2) {
- pixWritten = 0;
- while (pixWritten < imdW) {
- pixCount = *srcPtr++;
- if (pixCount & 0x80) { // data
- pixCount = MIN((pixCount & 0x7F) + 1, imdW - pixWritten);
- memcpy(imdVidMem, srcPtr, pixCount);
- memcpy(imdVidMem + sW, srcPtr, pixCount);
-
- pixWritten += pixCount;
- imdVidMem += pixCount;
- srcPtr += pixCount;
- } else { // "hole"
- pixCount = (pixCount + 1) % 256;
- pixWritten += pixCount;
- imdVidMem += pixCount;
- }
- }
- imdVidMemBak += sW + sW;
- imdVidMem = imdVidMemBak;
- }
- }
-}
-
-void ImdPlayer::frameUncompressor(byte *dest, byte *src) {
- int i;
- byte buf[4370];
- uint16 chunkLength;
- uint16 frameLength;
- uint16 bufPos1;
- uint16 bufPos2;
- uint16 tmp;
- uint8 chunkBitField;
- uint8 chunkCount;
- bool mode;
-
- frameLength = READ_LE_UINT16(src);
- src += 4;
-
- if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
- src += 4;
- bufPos1 = 273;
- mode = 1; // 123Ch (cmp al, 12h)
- } else {
- bufPos1 = 4078;
- mode = 0; // 275h (jnz +2)
- }
-
- memset(buf, 32, bufPos1);
- chunkCount = 1;
- chunkBitField = 0;
-
- while (frameLength > 0) {
- chunkCount--;
- if (chunkCount == 0) {
- tmp = *src++;
- chunkCount = 8;
- chunkBitField = tmp;
- }
- if (chunkBitField % 2) {
- chunkBitField >>= 1;
- buf[bufPos1] = *src;
- *dest++ = *src++;
- bufPos1 = (bufPos1 + 1) % 4096;
- frameLength--;
- continue;
- }
- chunkBitField >>= 1;
-
- tmp = READ_LE_UINT16(src);
- src += 2;
- chunkLength = ((tmp & 0xF00) >> 8) + 3;
-
- if ((mode && ((chunkLength & 0xFF) == 0x12)) ||
- (!mode && (chunkLength == 0)))
- chunkLength = *src++ + 0x12;
-
- bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
- if (((tmp + chunkLength) >= 4096) ||
- ((chunkLength + bufPos1) >= 4096)) {
-
- for (i = 0; i < chunkLength; i++, dest++) {
- *dest = buf[bufPos2];
- buf[bufPos1] = buf[bufPos2];
- bufPos1 = (bufPos1 + 1) % 4096;
- bufPos2 = (bufPos2 + 1) % 4096;
- }
-
- } else if (((tmp + chunkLength) < bufPos1) ||
- ((chunkLength + bufPos1) < bufPos2)) {
-
- memcpy(dest, buf + bufPos2, chunkLength);
- memmove(buf + bufPos1, buf + bufPos2, chunkLength);
-
- dest += chunkLength;
- bufPos1 += chunkLength;
- bufPos2 += chunkLength;
-
- } else {
-
- for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
- *dest = buf[bufPos2];
- buf[bufPos1] = buf[bufPos2];
- }
-
- }
- frameLength -= chunkLength;
-
- }
-}
-
-void ImdPlayer::play(const char *path, int16 x, int16 y, bool interruptible) {
- int16 mouseX;
- int16 mouseY;
- int16 buttons;
-
- _vm->_util->setFrameRate(12);
- if (!openImd(path, x, y, 0, 2))
- return;
-
- _vm->_video->fillRect(_vm->_draw->_frontSurface, x, y,
- x + _curImd->width - 1, y + _curImd->height - 1, 0);
-
- for (int i = 0; i < _curImd->framesCount; i++) {
- play(i, 4, 0, 255, 0, _curImd->framesCount - 1);
-
- if (_vm->_quitRequested || (interruptible &&
- (_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B)))
- break;
- }
-
- closeImd();
-}
-
-void ImdPlayer::play(const char *path, int16 x, int16 y, int16 startFrame,
- int16 frames, bool fade, bool interruptible) {
- int16 mouseX;
- int16 mouseY;
- int16 buttons = 0;
- int endFrame;
-
- _vm->_util->setFrameRate(12);
- if (!openImd(path, x, y, 0, 0))
- return;
-
- _vm->_video->fillRect(_vm->_draw->_frontSurface, x, y,
- x + _curImd->width - 1, y + _curImd->height - 1, 0);
-
- if (fade)
- _vm->_palAnim->fade(0, -2, 0);
-
- endFrame = frames > 0 ? frames : _curImd->framesCount;
- for (int i = startFrame; i < endFrame; i++) {
- view(_curImd, i);
- drawFrame(_curImd, i, x, y);
- if (fade) {
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
- fade = false;
- }
- _vm->_video->waitRetrace();
-
- if (_vm->_quitRequested || (interruptible &&
- (_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B))) {
- _vm->_palAnim->fade(0, -2, 0);
- _vm->_video->clearSurf(_vm->_draw->_frontSurface);
- memset((char *) _vm->_draw->_vgaPalette, 0, 768);
-
- WRITE_VAR(4, buttons);
- WRITE_VAR(0, 0x11B);
- WRITE_VAR(57, (uint32) -1);
- break;
- }
-
- _vm->_util->waitEndFrame();
- }
-
- if (frames < 0) {
- endFrame = _curImd->framesCount + frames;
- for (int i = _curImd->framesCount - 1; i >= endFrame; i--) {
- seekFrame(_curImd, i, SEEK_SET, true);
- drawFrame(_curImd, i, x, y);
- _vm->_video->waitRetrace();
-
- if (_vm->_quitRequested || (interruptible &&
- (_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B))) {
- _vm->_palAnim->fade(0, -2, 0);
- _vm->_video->clearSurf(_vm->_draw->_frontSurface);
- memset((char *) _vm->_draw->_vgaPalette, 0, 768);
-
- WRITE_VAR(4, buttons);
- WRITE_VAR(0, 0x11B);
- WRITE_VAR(57, (uint32) -1);
- break;
- }
-
- _vm->_util->waitEndFrame();
- }
- }
-
- closeImd();
-}
-
-void ImdPlayer::play(int16 frame, uint16 palCmd,
- int16 palStart, int16 palEnd, int16 palFrame, int16 lastFrame) {
- uint32 viewRet = 0;
- SurfaceDesc *surfDescBak;
- bool modifiedPal = false;
-
- _vm->_draw->_showCursor = 0;
-
- if ((frame < 0) || (frame > lastFrame))
- return;
-
- palCmd &= 0x3F;
- if ((frame == palFrame) || ((frame == lastFrame) && (palCmd == 8))) {
- modifiedPal = true;
- _vm->_draw->_applyPal = true;
-
- if (palCmd >= 4)
- copyPalette(palStart, palEnd);
- }
-
- if (modifiedPal && (palCmd == 8) && (_backSurf == 20))
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
-
- if (_curImd->surfDesc) {
- if (_curImd->surfDesc->_vidMode == 0x14) {
-
- if ((_frontMem == _vm->_draw->_frontSurface->getVidMem()) &&
- (_frontSurf == 20)) {
- _vm->_draw->_frontSurface->swap(_vm->_draw->_backSurface);
- viewRet = view(_curImd, frame);
- _vm->_draw->_frontSurface->swap(_vm->_draw->_backSurface);
- } else
- viewRet = view(_curImd, frame);
-
- if (_frontSurf == 21)
- _vm->_draw->invalidateRect(_left, _top, _right, _bottom);
-
- } else {
- if ((_curImd->field_E & 0x100) &&
- (_vm->_global->_videoMode == 0x14) &&
- (_frontSurf == 20) &&
- (checkFrameType(_curImd, frame) & 0x8000) &&
- (_backSurf == 21)) {
-
- surfDescBak = _curImd->surfDesc;
- if (_frontMem == _vm->_draw->_spritesArray[20]->getVidMem())
- _curImd->surfDesc = _vm->_draw->_spritesArray[21];
- else
- _curImd->surfDesc = _vm->_draw->_spritesArray[20];
- setXY(_curImd, _curX, _curY);
- viewRet = view(_curImd, frame);
- _curImd->surfDesc = surfDescBak;
- setXY(_curImd, 0, 0);
-
- } else {
- viewRet = view(_curImd, frame);
- if (!(viewRet & 0x800))
- drawFrame(frame);
- }
- }
- } else
- viewRet = view(_curImd, frame);
-
- if (modifiedPal && (palCmd == 16)) {
- if (_backSurf == 21)
- _vm->_draw->forceBlit();
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
- _vm->_draw->_noInvalidated = true;
- }
-
- if (viewRet & 0x10) {
- copyPalette(palStart, palEnd);
-
- if (_backSurf == 20)
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
- else
- _vm->_draw->_applyPal = true;
- }
-
- if (modifiedPal && (palCmd == 8) && (_backSurf == 21))
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
-
- if (!(viewRet & 0x800)) {
- if (_vm->_draw->_cursorIndex == -1) {
- if (_frontSurf == 20)
- flipFrontMem();
- else
- _vm->_draw->blitInvalidated();
- } else
- _vm->_draw->animateCursor(-1);
- }
-
- if (modifiedPal && ((palCmd == 2) || (palCmd == 4)))
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
-
- // To allow quitting, etc. during IMDs
- _vm->_util->processInput();
- if (_vm->_quitRequested)
- return;
-
- if (_soundStage != 2) {
- if (viewRet & 0x800) {
- if (_frameDelay == 0)
- _vm->_util->delay(30);
- else {
- _frameDelay -= 30;
- if (_frameDelay < 0)
- _frameDelay = 0;
- }
- } else
- _vm->_util->waitEndFrame();
- }
-
- _vm->_inter->animPalette();
-}
-
-inline void ImdPlayer::drawFrame(int16 frame) {
- if (_backSurf == 21) {
-
- if (_vm->_global->_videoMode == 0x14) {
- if (_frontSurf == 21) {
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- drawFrame(_curImd, frame, _curX, _curY);
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- _vm->_draw->invalidateRect(_curX + _left, _curY + _top,
- _curX + _right, _curY + _bottom);
- } else {
- if (_frontMem == _vm->_draw->_spritesArray[20]->getVidMem()) {
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- drawFrame(_curImd, frame, _curX, _curY);
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- } else
- drawFrame(_curImd, frame, _curX, _curY);
- }
- } else
- _vm->_draw->invalidateRect(_left, _top, _right, _bottom);
-
- } else if (_vm->_global->_videoMode == 0x14)
- drawFrame(_curImd, frame, _curX, _curY);
-}
-
-inline void ImdPlayer::copyPalette(int16 palStart, int16 palEnd) {
- if ((palStart == -1) || (palEnd == -1))
- memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
- (char *) _curImd->palette, 768);
- else
- memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) +
- palStart * 3, ((char *) (_curImd->palette)) + palStart * 3,
- (palEnd - palStart + 1) * 3);
-}
-
-inline void ImdPlayer::flipFrontMem() {
- if (_frontMem == _vm->_draw->_frontSurface->getVidMem())
- _frontMem = _vm->_draw->_backSurface->getVidMem();
- else
- _frontMem = _vm->_draw->_frontSurface->getVidMem();
-}
-
-uint16 ImdPlayer::checkFrameType(Imd *imdPtr, int16 frame) {
- uint16 retVal = 0;
- uint32 posBak;
- uint32 tmp;
- uint16 cmd;
- int16 frameBak;
-
- if (!imdPtr)
- return 0x8000;
-
- posBak = _vm->_dataIO->getPos(imdPtr->handle);
- frameBak = imdPtr->curFrame;
-
- if (imdPtr->curFrame != frame) {
- retVal |= 0x2000;
- seekFrame(imdPtr, frame, SEEK_SET);
- }
-
- do {
- if (frame != 0) {
- if (imdPtr->stdX != -1)
- retVal |= 0x1000;
- if (imdPtr->frameCoords && (imdPtr->frameCoords[frame].left != -1))
- retVal |= 0x400;
- }
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- if ((cmd & 0xFFF8) == 0xFFF0) {
- if (cmd == 0xFFF0) {
- _vm->_dataIO->seekData(imdPtr->handle, 2, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- if (cmd == 0xFFF1) {
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF2) { // Skip (16 bit)
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF3) { // Skip (32 bit)
- tmp = _vm->_dataIO->readUint32(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- }
- }
-
- // Jump to frame
- if (cmd == 0xFFFD) {
- frame = _vm->_dataIO->readUint16(imdPtr->handle);
- if (imdPtr->framesPos) {
- _vm->_dataIO->seekData(imdPtr->handle,
- imdPtr->framesPos[frame], SEEK_SET);
- retVal |= 0x200;
- continue;
- }
- break;
- }
-
- // Next sound slice data
- if (cmd == 0xFF00) {
- _vm->_dataIO->seekData(imdPtr->handle,
- _soundSliceSize, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- // Initial sound data (all slices)
- } else if (cmd == 0xFF01) {
- _vm->_dataIO->seekData(imdPtr->handle,
- _soundSliceSize * _soundSlicesCount, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- // Frame video data
- if (cmd != 0) {
- _vm->_dataIO->readData(imdPtr->handle, _frameData, 5);
- retVal |= _frameData[0];
- } else
- retVal |= 0x800;
-
- break;
-
- } while (true);
-
- _vm->_dataIO->seekData(imdPtr->handle, posBak, SEEK_SET);
- imdPtr->curFrame = frameBak;
- return retVal;
-}
-
-void ImdPlayer::seekFrame(Imd *imdPtr, int16 frame, int16 from, bool restart) {
- uint32 framePos = 0;
-
- if (!imdPtr)
- return;
-
- if (from == SEEK_CUR)
- frame += imdPtr->curFrame;
- else if (from == SEEK_END)
- frame = imdPtr->framesCount - frame - 1;
-
- if (frame >= imdPtr->framesCount)
- return;
-
- if (frame == 0) {
- framePos = imdPtr->firstFramePos;
- } else if (frame == 1) {
- framePos = imdPtr->firstFramePos;
- _vm->_dataIO->seekData(imdPtr->handle, framePos, SEEK_SET);
- framePos += _vm->_dataIO->readUint16(imdPtr->handle) + 4;
- } else if (imdPtr->framesPos) {
- framePos = imdPtr->framesPos[frame];
- } else if (restart && (_soundStage == 0)) {
- for (int i = 0; i <= frame; i++)
- view(_curImd, i);
- } else
- error("%s: Frame %d is not directly accessible", _curFile, frame);
-
- _vm->_dataIO->seekData(imdPtr->handle, framePos, SEEK_SET);
- imdPtr->curFrame = frame;
-}
-
-uint32 ImdPlayer::view(Imd *imdPtr, int16 frame) {
- uint32 retVal = 0;
- uint32 cmd = 0;
- int16 xBak, yBak, heightBak, widthBak;
- bool hasNextCmd = false;
- bool startSound = false;
-
- if (!imdPtr)
- return 0x8000;
-
- if (frame != imdPtr->curFrame) {
- retVal |= 0x2000;
- seekFrame(imdPtr, frame, SEEK_SET);
- }
-
- _left = xBak = imdPtr->x;
- _top = yBak = imdPtr->y;
- _bottom = heightBak= imdPtr->height;
- _right = widthBak = imdPtr->width;
- _right += _left - 1;
- _bottom += _top - 1;
-
- if ((frame == 0) && (imdPtr->verMin & 0x800))
- _vm->_video->setPalette(imdPtr->palette);
-
- do {
- if (frame != 0) {
- if (imdPtr->stdX != -1) {
- _left = imdPtr->x = imdPtr->stdX;
- _top = imdPtr->y = imdPtr->stdY;
- _right = imdPtr->width = imdPtr->stdWidth;
- _bottom = imdPtr->height = imdPtr->stdHeight;
- _right += _left - 1;
- _bottom += _top - 1;
- retVal |= 0x1000;
- }
- if (imdPtr->frameCoords &&
- (imdPtr->frameCoords[frame].left != -1)) {
- _left = imdPtr->x = imdPtr->frameCoords[frame].left;
- _top = imdPtr->y = imdPtr->frameCoords[frame].top;
- _right = imdPtr->width =
- imdPtr->frameCoords[frame].right - imdPtr->x + 1;
- _bottom = imdPtr->height =
- imdPtr->frameCoords[frame].bottom - imdPtr->y + 1;
- _right += _left - 1;
- _bottom += _top - 1;
- retVal |= 0x400;
- }
- }
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- if ((cmd & 0xFFF8) == 0xFFF0) {
- if (cmd == 0xFFF0) {
- _vm->_dataIO->seekData(imdPtr->handle, 2, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- if (cmd == 0xFFF1) {
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF2) { // Skip (16 bit)
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF3) { // Skip (32 bit)
- cmd = _vm->_dataIO->readUint32(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- }
- }
-
- if (_soundStage != 0) {
- byte *soundBuf;
-
- if (!hasNextCmd)
- waitEndSoundSlice();
-
- // Next sound slice data
- if (cmd == 0xFF00) {
-
- if (!hasNextCmd && !_noSound) {
- soundBuf = new byte[_soundSliceSize];
- assert(soundBuf);
-
- _vm->_dataIO->readData(imdPtr->handle, soundBuf,
- _soundSliceSize);
- _vm->_snd->convToSigned(soundBuf, _soundSliceSize);
- _audioStream->queueBuffer(soundBuf, _soundSliceSize);
- } else
- _vm->_dataIO->seekData(imdPtr->handle,
- _soundSliceSize, SEEK_CUR);
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- // Initial sound data (all slices)
- } else if (cmd == 0xFF01) {
- int dataLength = _soundSliceSize * _soundSlicesCount;
-
- if (!hasNextCmd && !_noSound) {
- soundBuf = new byte[dataLength];
- assert(soundBuf);
-
- _vm->_dataIO->readData(imdPtr->handle, soundBuf, dataLength);
- _vm->_snd->convToSigned(soundBuf, dataLength);
-
- _soundStage = 1;
- startSound = true;
- _audioStream->queueBuffer(soundBuf, dataLength);
- } else
- _vm->_dataIO->seekData(imdPtr->handle, dataLength, SEEK_CUR);
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- // Empty sound slice
- } else if (!hasNextCmd && (!_noSound)) {
- soundBuf = new byte[_soundSliceSize];
- assert(soundBuf);
-
- memset(soundBuf, 0, _soundSliceSize);
- _audioStream->queueBuffer(soundBuf, _soundSliceSize);
- }
- }
-
- // Set palette
- if (cmd == 0xFFF4) {
- _vm->_dataIO->seekData(imdPtr->handle, 2, SEEK_CUR);
- retVal |= 0x10;
- if (imdPtr->extraPalette) {
- _vm->_dataIO->readData(imdPtr->handle,
- (byte *) imdPtr->extraPalette, 768);
- _vm->_video->setPalette(imdPtr->extraPalette);
- } else if (imdPtr->palette)
- _vm->_dataIO->readData(imdPtr->handle,
- (byte *) imdPtr->palette, 768);
- else
- _vm->_dataIO->readData(imdPtr->handle, _frameData, 768);
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- hasNextCmd = false;
-
- // Jump to frame
- if (cmd == 0xFFFD) {
-
- frame = _vm->_dataIO->readUint16(imdPtr->handle);
- if (imdPtr->framesPos) {
- imdPtr->curFrame = frame;
- _vm->_dataIO->seekData(imdPtr->handle,
- imdPtr->framesPos[frame], SEEK_SET);
-
- hasNextCmd = true;
- retVal |= 0x200;
- }
-
- } else if (cmd == 0xFFFC) {
-
- retVal |= 1;
- cmd = _vm->_dataIO->readUint32(imdPtr->handle);
- _vm->_dataIO->readData(imdPtr->handle, _frameData, cmd + 2);
-
- if (imdPtr->surfDesc) {
- int16 left = imdPtr->x;
- int16 top = imdPtr->y;
- int16 right = imdPtr->width + left;
- int16 bottom = imdPtr->height + top;
-
- if (imdPtr->surfDesc->getWidth() < right) {
- left = 0;
- right = imdPtr->width;
- }
- if (imdPtr->surfDesc->getWidth() < right)
- right = imdPtr->surfDesc->getWidth();
- if (imdPtr->surfDesc->getHeight() < bottom) {
- top = 0;
- bottom = imdPtr->height;
- }
- if (imdPtr->surfDesc->getHeight() < bottom)
- bottom = imdPtr->surfDesc->getHeight();
-
- imdPtr->x = left;
- imdPtr->y = top;
- imdPtr->height = bottom - top;
- imdPtr->width = right - left;
-
- renderFrame(imdPtr);
- }
-
- retVal |= _frameData[0];
-
- // Frame video data
- } else if (cmd != 0) {
-
- _vm->_dataIO->readData(imdPtr->handle, _frameData, cmd + 2);
- if (imdPtr->surfDesc)
- renderFrame(imdPtr);
-
- retVal |= _frameData[0];
-
- } else
- retVal |= 0x800;
-
- } while (hasNextCmd);
-
- if (startSound) {
- _vm->_snd->stopSound(0);
- _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_audioHandle, _audioStream);
- _soundStartTime = _vm->_util->getTimeKey();
- _skipFrames = 0;
- _soundStage = 2;
- }
-
- imdPtr->x = xBak;
- imdPtr->y = yBak;
- imdPtr->width = widthBak;
- imdPtr->height = heightBak;
-
- imdPtr->curFrame++;
- if ((imdPtr->curFrame == imdPtr->framesCount) && (_soundStage == 2)) {
- waitEndSoundSlice();
- _audioStream->finish();
- _vm->_mixer->stopHandle(_audioHandle);
- _audioStream = 0;
- }
-
- return retVal;
-}
-
-inline void ImdPlayer::waitEndSoundSlice() {
- if (_soundStage != 2)
- return;
-
- if (_skipFrames == 0) {
-
- _vm->_video->retrace();
-
- int32 waitTime = (_curImd->curFrame * _soundSliceLength) -
- (_vm->_util->getTimeKey() - _soundStartTime);
-
- if (waitTime < 0) {
- _skipFrames = -waitTime / _soundSliceLength;
- warning("IMD A/V sync broken, skipping %d frame(s)", _skipFrames + 1);
- } else if (waitTime > 0)
- _vm->_util->delay(waitTime);
-
- } else
- _skipFrames--;
-}
-
-} // End of namespace Gob
diff --git a/engines/gob/imd.h b/engines/gob/imd.h
deleted file mode 100644
index 27d95cd579..0000000000
--- a/engines/gob/imd.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* 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_IMD_H
-#define GOB_IMD_H
-
-#include "gob/video.h"
-#include "gob/sound.h"
-
-namespace Gob {
-
-class ImdPlayer {
-public:
-
-#include "common/pack-start.h" // START STRUCT PACKING
-
- struct ImdCoord {
- int16 left;
- int16 top;
- int16 right;
- int16 bottom;
- } PACKED_STRUCT;
-
- struct Imd {
- int16 handle;
- int16 verMin;
- int16 framesCount;
- int16 x;
- int16 y;
- int16 width;
- int16 height;
- int16 field_E;
- int16 curFrame;
- Video::Color *palette;
- SurfaceDesc *surfDesc;
- int32 *framesPos;
- int32 firstFramePos;
- int16 stdX;
- int16 stdY;
- int16 stdWidth;
- int16 stdHeight;
- ImdCoord *frameCoords;
- int32 frameDataSize;
- int32 vidBufferSize;
- Video::Color *extraPalette;
- } PACKED_STRUCT;
-
-#include "common/pack-end.h" // END STRUCT PACKING
-
- Imd *_curImd;
- byte _frontSurf;
- int8 _backSurf;
- byte *_frontMem;
- int32 _frameDelay;
-
- uint8 _soundStage; // (0: no sound, 1: loaded, 2: playing)
-
- ImdPlayer(GobEngine *vm);
- virtual ~ImdPlayer();
-
- Imd *loadImdFile(const char *path, SurfaceDesc *surfDesc, int8 flags);
- void finishImd(Imd *&imdPtr);
-
- int8 openImd(const char *path, int16 x, int16 y,
- int16 startFrame, int16 flags);
- void closeImd(void);
-
- void play(int16 frame, uint16 palCmd, int16 palStart, int16 palEnd,
- int16 palFrame, int16 lastFrame);
- void play(const char *path, int16 x, int16 y, bool interruptible);
- void play(const char *path, int16 x, int16 y, int16 startFrame,
- int16 frames, bool fade, bool interruptible);
-
-protected:
- char _curFile[18];
-
- int16 _curX;
- int16 _curY;
- int16 _left;
- int16 _top;
- int16 _right;
- int16 _bottom;
-
- byte *_frameData;
- byte *_vidBuffer;
-
- bool _noSound;
-
- uint32 _soundStartTime;
- uint32 _skipFrames;
-
- int16 _soundFreq;
- uint16 _soundSliceSize;
- int16 _soundSlicesCount;
- uint16 _soundSliceLength;
-
- Audio::AppendableAudioStream *_audioStream;
- Audio::SoundHandle _audioHandle;
-
- GobEngine *_vm;
-
- void copyPalette(int16 palStart, int16 palEnd);
- void flipFrontMem();
- void drawFrame(int16 frame);
- void setXY(Imd *imdPtr, int16 x, int16 y);
-
- void seekFrame(Imd *imdPtr, int16 frame, int16 from, bool restart = false);
- uint16 checkFrameType(Imd *imdPtr, int16 frame);
- void drawFrame(Imd *imdPtr, int16 frame, int16 x, int16 y,
- SurfaceDesc *dest = 0);
-
- uint32 view(ImdPlayer::Imd *imdPtr, int16 arg_4);
- void renderFrame(Imd *imdPtr);
- void frameUncompressor(byte *dest, byte *src);
-
- void waitEndSoundSlice();
-};
-
-} // End of namespace Gob
-
-#endif // GOB_IMD_H
diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp
index 2f1dbe5326..85f95fb261 100644
--- a/engines/gob/init.cpp
+++ b/engines/gob/init.cpp
@@ -37,7 +37,7 @@
#include "gob/palanim.h"
#include "gob/sound.h"
#include "gob/video.h"
-#include "gob/imd.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -167,8 +167,14 @@ void Init::initGame(const char *totName) {
_vm->_dataIO->closeData(imdHandle);
_vm->_draw->initScreen();
_vm->_draw->_cursorIndex = -1;
+
_vm->_util->longDelay(200); // Letting everything settle
- _vm->_imdPlayer->play("coktel", -1, -1, true);
+
+ if (_vm->_vidPlayer->openVideo("coktel.imd")) {
+ _vm->_vidPlayer->play();
+ _vm->_vidPlayer->closeVideo();
+ }
+
_vm->_draw->closeScreen();
} else if ((imdHandle = _vm->_dataIO->openData("coktel.clt")) >= 0) {
_vm->_draw->initScreen();
diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp
index ffbe9e45ea..492ea198a1 100644
--- a/engines/gob/inter_bargon.cpp
+++ b/engines/gob/inter_bargon.cpp
@@ -33,10 +33,10 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
-#include "gob/imd.h"
#include "gob/palanim.h"
#include "gob/sound.h"
#include "gob/video.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -717,11 +717,17 @@ const char *Inter_Bargon::getOpcodeGoblinDesc(int i) {
}
void Inter_Bargon::oBargon_intro0(OpGobParams &params) {
- _vm->_imdPlayer->play("scaa", 0, 160, 0, 92, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scaa", 0, 160)) {
+ _vm->_vidPlayer->play(0, 92, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro1(OpGobParams &params) {
- _vm->_imdPlayer->play("scaa", 0, 160, 0, -23, 1, 1);
+ if (_vm->_vidPlayer->openVideo("scaa", 0, 160)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0, 0, 0, true, 23);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro2(OpGobParams &params) {
@@ -813,27 +819,45 @@ void Inter_Bargon::oBargon_intro3(OpGobParams &params) {
}
void Inter_Bargon::oBargon_intro4(OpGobParams &params) {
- _vm->_imdPlayer->play("scba", 191, 54, 0, 0, 1, 1);
+ if (_vm->_vidPlayer->openVideo("scba", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0, 0, 0, true);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro5(OpGobParams &params) {
- _vm->_imdPlayer->play("scbb", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbb", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro6(OpGobParams &params) {
- _vm->_imdPlayer->play("scbc", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbc", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro7(OpGobParams &params) {
- _vm->_imdPlayer->play("scbf", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbf", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro8(OpGobParams &params) {
- _vm->_imdPlayer->play("scbc", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbc", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro9(OpGobParams &params) {
- _vm->_imdPlayer->play("scbd", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbd", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
} // End of namespace Gob
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index c78aa9e017..58970d9fcd 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -38,7 +38,6 @@
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/goblin.h"
-#include "gob/imd.h"
#include "gob/map.h"
#include "gob/mult.h"
#include "gob/parse.h"
@@ -46,6 +45,7 @@
#include "gob/sound.h"
#include "gob/video.h"
#include "gob/saveload.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -1493,48 +1493,28 @@ void Inter_v2::o2_playImd() {
palEnd = _vm->_parse->parseValExpr();
palCmd = 1 << (flags & 0x3F);
- if (!_vm->_imdPlayer->openImd(imd, x, y, startFrame, flags)) {
+ if ((imd[0] != 0) && !_vm->_vidPlayer->openVideo(imd, x, y, flags)) {
WRITE_VAR(11, -1);
return;
}
close = (lastFrame == -1);
- if (lastFrame < 0)
- lastFrame = _vm->_imdPlayer->_curImd->framesCount - 1;
if (startFrame == -2) {
startFrame = lastFrame = 0;
close = false;
}
- _vm->_game->_preventScroll = true;
- for (int i = startFrame; i <= lastFrame; i++) {
- _vm->_imdPlayer->play(i, palCmd, palStart, palEnd, 0, lastFrame);
- WRITE_VAR(11, i);
-
- if (_vm->_quitRequested)
- break;
-
- if (breakKey != 0) {
- _vm->_util->getMouseState(&_vm->_global->_inter_mouseX,
- &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons);
-
- storeKey(_vm->_util->checkKey());
- if (VAR(0) == (unsigned) breakKey) {
- if (_vm->_imdPlayer->_soundStage == 2)
- _vm->_snd->stopSound(0);
- _vm->_game->_preventScroll = false;
- return;
- }
- }
+ if (startFrame >= 0) {
+ _vm->_game->_preventScroll = true;
+ _vm->_vidPlayer->play(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
+ _vm->_game->_preventScroll = false;
}
- _vm->_game->_preventScroll = false;
if (close)
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
}
void Inter_v2::o2_getImdInfo() {
- ImdPlayer::Imd *imd;
int16 varX, varY;
int16 varFrames;
int16 varWidth, varHeight;
@@ -1545,21 +1525,9 @@ void Inter_v2::o2_getImdInfo() {
varFrames = _vm->_parse->parseVarIndex();
varWidth = _vm->_parse->parseVarIndex();
varHeight = _vm->_parse->parseVarIndex();
- imd = _vm->_imdPlayer->loadImdFile(_vm->_global->_inter_resStr, 0, 2);
- if (!imd) {
- WRITE_VAR_OFFSET(varX, -1);
- WRITE_VAR_OFFSET(varY, -1);
- WRITE_VAR_OFFSET(varFrames, -1);
- WRITE_VAR_OFFSET(varWidth, -1);
- WRITE_VAR_OFFSET(varHeight, -1);
- } else {
- WRITE_VAR_OFFSET(varX, imd->x);
- WRITE_VAR_OFFSET(varY, imd->y);
- WRITE_VAR_OFFSET(varFrames, imd->framesCount);
- WRITE_VAR_OFFSET(varWidth, imd->width);
- WRITE_VAR_OFFSET(varHeight, imd->height);
- }
- _vm->_imdPlayer->finishImd(imd);
+
+ _vm->_vidPlayer->writeVideoInfo(_vm->_global->_inter_resStr, varX, varY,
+ varFrames, varWidth, varHeight);
}
void Inter_v2::o2_openItk() {
@@ -1577,21 +1545,9 @@ void Inter_v2::o2_closeItk() {
}
void Inter_v2::o2_setImdFrontSurf() {
- _vm->_imdPlayer->_frontSurf = 21;
- if (_vm->_global->_videoMode == 0x14) {
- _vm->_imdPlayer->_frontMem = _vm->_draw->_frontSurface->getVidMem();
- _vm->_draw->blitInvalidated();
- _vm->_imdPlayer->_frontSurf = 20;
- }
}
void Inter_v2::o2_resetImdFrontSurf() {
- _vm->_imdPlayer->_frontSurf = 21;
- if (_vm->_imdPlayer->_frontMem) {
- _vm->_imdPlayer->_frontMem = _vm->_draw->_frontSurface->getVidMem();
- _vm->_draw->forceBlit();
- } else
- _vm->_draw->forceBlit(true);
}
bool Inter_v2::o2_evaluateStore(OpFuncParams &params) {
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index 6c9a8d4b3e..7571853f27 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -18,7 +18,8 @@ MODULE_OBJS := \
goblin_v1.o \
goblin_v2.o \
goblin_v3.o \
- imd.o \
+ coktelvideo.o \
+ videoplayer.o \
init.o \
init_v1.o \
init_v2.o \
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index 86a2a260de..cced4aac63 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -34,11 +34,11 @@
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/goblin.h"
-#include "gob/imd.h"
#include "gob/inter.h"
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/video.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -1041,7 +1041,7 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir,
x = y = -1;
if (key.imdFile == -1) {
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
_vm->_game->_preventScroll = false;
return;
}
@@ -1059,23 +1059,24 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir,
if ((lastFrame - palFrame) < startFrame)
if (!(key.flags & 0x4000)) {
_vm->_game->_preventScroll = false;
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
return;
}
- if (!_vm->_imdPlayer->openImd(imdFile, x, y, 0, flags)) {
+ if (!_vm->_vidPlayer->openVideo(imdFile, x, y, flags)) {
_vm->_game->_preventScroll = false;
return;
}
if (palFrame == -1)
palFrame = 0;
+
if (lastFrame == -1)
- lastFrame = _vm->_imdPlayer->_curImd->framesCount - 1;
+ lastFrame = _vm->_vidPlayer->getFramesCount() - 1;
baseFrame = startFrame % (lastFrame - palFrame + 1);
- _vm->_imdPlayer->play(baseFrame + palFrame, flags & 0x7F,
- palStart, palEnd, palFrame, lastFrame);
+ _vm->_vidPlayer->play(baseFrame + palFrame, baseFrame + palFrame, 0,
+ flags & 0x7F, palStart, palEnd, palFrame, lastFrame);
}
void Mult_v2::advanceObjects(int16 index) {
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index 1b20ca249e..ec8bb59f06 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -32,7 +32,6 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
-#include "gob/imd.h"
#include "gob/sound.h"
#include "gob/video.h"
@@ -301,7 +300,6 @@ void Util::setFrameRate(int16 rate) {
_vm->_global->_frameWaitTime = 1000 / rate;
_vm->_global->_startFrameTime = getTimeKey();
- _vm->_imdPlayer->_frameDelay = 0;
}
void Util::waitEndFrame() {
@@ -312,17 +310,13 @@ void Util::waitEndFrame() {
time = getTimeKey() - _vm->_global->_startFrameTime;
if ((time > 1000) || (time < 0)) {
_vm->_global->_startFrameTime = getTimeKey();
- _vm->_imdPlayer->_frameDelay = 0;
return;
}
- if (_vm->_global->_frameWaitTime - time > 0) {
- _vm->_imdPlayer->_frameDelay = 0;
- delay(_vm->_global->_frameWaitTime - _vm->_imdPlayer->_frameDelay - time);
- }
+ if ((_vm->_global->_frameWaitTime - time) > 0)
+ delay(_vm->_global->_frameWaitTime - time);
_vm->_global->_startFrameTime = getTimeKey();
- _vm->_imdPlayer->_frameDelay = time - _vm->_global->_frameWaitTime;
}
void Util::setScrollOffset(int16 x, int16 y) {
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
new file mode 100644
index 0000000000..dfb06e6c2d
--- /dev/null
+++ b/engines/gob/videoplayer.cpp
@@ -0,0 +1,334 @@
+/* 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$
+ *
+ */
+
+#include "gob/videoplayer.h"
+#include "gob/global.h"
+#include "gob/util.h"
+#include "gob/dataio.h"
+#include "gob/video.h"
+#include "gob/draw.h"
+#include "gob/game.h"
+#include "gob/palanim.h"
+#include "gob/inter.h"
+
+namespace Gob {
+
+const char *VideoPlayer::_extensions[] = { "IMD", "VMD" };
+
+VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm) {
+ _curFile[0] = 0;
+ _stream = 0;
+ _video = 0;
+ _backSurf = false;
+}
+
+VideoPlayer::~VideoPlayer() {
+ closeVideo();
+}
+
+bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Type which) {
+ char fileName[256];
+
+ strncpy0(fileName, video, 250);
+
+ char *extStart = strchr(fileName, '.');
+ if (extStart) {
+ // The requested file already has an extension. Verifying.
+
+ int i;
+ for (i = 0; i < ARRAYSIZE(_extensions); i++) {
+ if (!scumm_stricmp(extStart + 1, _extensions[i])) {
+ if ((which != kVideoTypeTry) && (which == ((Type) i))) {
+ warning("Attempted to open video \"%s\", "
+ "but requested a different type", fileName);
+ return false;
+ }
+ which = (Type) i;
+ break;
+ }
+ }
+ if (i >= ARRAYSIZE(_extensions))
+ extStart = 0;
+
+ }
+
+ if (!extStart) {
+ // No or unrecognized extension. Probing.
+
+ int len = strlen(fileName);
+
+ int i;
+ for (i = 0; i < ARRAYSIZE(_extensions); i++) {
+ if ((which == kVideoTypeTry) || (which == ((Type) i))) {
+ int16 handle;
+
+ fileName[len] = '.';
+ fileName[len + 1] = 0;
+ strcat(fileName, _extensions[i]);
+
+ handle = _vm->_dataIO->openData(fileName);
+ if (handle >= 0) {
+ _vm->_dataIO->closeData(handle);
+ which = (Type) i;
+ break;
+ }
+ }
+ }
+ if ((i >= ARRAYSIZE(_extensions)) || (which == kVideoTypeTry)) {
+ fileName[len] = 0;
+ warning("Couldn't open video \"%s\"", fileName);
+ return false;
+ }
+
+ }
+
+ if (scumm_strnicmp(_curFile, fileName, strlen(fileName))) {
+ closeVideo();
+
+ int16 handle = _vm->_dataIO->openData(fileName);
+
+ if (handle < 0) {
+ warning("Couldn't open video \"%s\": No such file", fileName);
+ return false;
+ }
+
+ _stream = _vm->_dataIO->openAsStream(handle, true);
+
+ if (which == kVideoTypeIMD) {
+ _video = new Imd();
+ } else if (which == kVideoTypeVMD) {
+ warning("STUB: VMD");
+ closeVideo();
+ return false;
+ } else {
+ warning("Couldn't open video \"%s\": Invalid video Type", fileName);
+ closeVideo();
+ return false;
+ }
+
+ if (!_video->load(*_stream)) {
+ warning("While loading video \"%s\"", fileName);
+ closeVideo();
+ return false;
+ }
+
+ _video->setXY(x, y);
+
+ if (!(flags & kFlagNoVideo)) {
+ _backSurf = ((flags & kFlagFrontSurface) == 0);
+ SurfaceDesc::Ptr surf = _vm->_draw->_spritesArray[_backSurf ? 21 : 20];
+ _video->setVideoMemory(surf->getVidMem(), surf->getWidth(), surf->getHeight());
+ } else
+ _video->setVideoMemory();
+
+ _video->enableSound(*_vm->_mixer);
+ }
+
+ if (!_video)
+ return false;
+
+ WRITE_VAR(7, _video->getFramesCount());
+
+ return true;
+}
+
+void VideoPlayer::play(int16 startFrame, int16 lastFrame, int16 breakKey,
+ uint16 palCmd, int16 palStart, int16 palEnd,
+ int16 palFrame, int16 endFrame, bool fade, int16 reverseTo) {
+
+ if (!_video)
+ return;
+
+ if (startFrame < 0)
+ startFrame = _video->getCurrentFrame();
+ if (lastFrame < 0)
+ lastFrame = _video->getFramesCount() - 1;
+ if (palFrame < 0)
+ palFrame = startFrame;
+ if (endFrame < 0)
+ endFrame = lastFrame;
+ palCmd &= 0x3F;
+
+ if (_video->getCurrentFrame() != startFrame)
+ _video->seekFrame(startFrame);
+
+ _vm->_draw->_showCursor = 0;
+ _vm->_util->setFrameRate(12);
+
+ if (fade)
+ _vm->_palAnim->fade(0, -2, 0);
+
+ while (startFrame <= lastFrame) {
+ if (doPlay(startFrame, breakKey, palCmd, palStart, palEnd, palFrame, endFrame))
+ break;
+
+ if (fade) {
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+ fade = false;
+ }
+
+ _video->waitEndFrame();
+ startFrame++;
+ }
+
+ if (reverseTo >= 0) {
+ int16 toFrame = _video->getFramesCount() - reverseTo;
+ for (int i = _video->getCurrentFrame(); i >= toFrame; i--) {
+ _video->seekFrame(i, SEEK_SET, true);
+ if (doPlay(i, breakKey, 0, 0, 0, 0, 0)) {
+ _vm->_palAnim->fade(0, -2, 0);
+ memset((char *) _vm->_draw->_vgaPalette, 0, 768);
+ }
+ _video->waitEndFrame();
+ }
+ }
+}
+
+int16 VideoPlayer::getFramesCount() const {
+ if (!_video)
+ return 0;
+
+ return _video->getFramesCount();
+}
+
+int16 VideoPlayer::getCurrentFrame() const {
+ if (!_video)
+ return 0;
+
+ return _video->getCurrentFrame();
+}
+
+bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
+ uint16 palCmd, int16 palStart, int16 palEnd,
+ int16 palFrame, int16 endFrame) {
+
+ bool modifiedPal = false;
+
+ if ((frame == palFrame) || ((frame == endFrame) && (palCmd == 8))) {
+ modifiedPal = true;
+ _vm->_draw->_applyPal = true;
+
+ if (palCmd >= 4)
+ copyPalette(palStart, palEnd);
+ }
+
+ if (modifiedPal && (palCmd == 8) && !_backSurf)
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+
+
+ CoktelVideo::State state = _video->nextFrame();
+ WRITE_VAR(11, frame);
+
+
+ if (modifiedPal && (palCmd == 16)) {
+ if (_backSurf)
+ _vm->_draw->forceBlit();
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+ _vm->_draw->_noInvalidated = true;
+ }
+
+ if (state.flags & CoktelVideo::kStatePalette) {
+ copyPalette(palStart, palEnd);
+
+ if (!_backSurf)
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ else
+ _vm->_draw->_applyPal = true;
+ }
+
+ if (modifiedPal && (palCmd == 8) && _backSurf)
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+
+
+ if (_backSurf) {
+ _vm->_draw->invalidateRect(state.left, state.top, state.right, state.bottom);
+ _vm->_draw->blitInvalidated();
+ }
+ _vm->_video->retrace();
+
+
+ if (modifiedPal && ((palCmd == 2) || (palCmd == 4)))
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+
+
+ _vm->_util->processInput();
+
+ if (_vm->_quitRequested) {
+ _video->disableSound();
+ return true;
+ }
+
+ if (breakKey != 0) {
+ _vm->_util->getMouseState(&_vm->_global->_inter_mouseX,
+ &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons);
+
+ _vm->_inter->storeKey(_vm->_util->checkKey());
+ if (VAR(0) == (unsigned) breakKey) {
+ _video->disableSound();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void VideoPlayer::copyPalette(int16 palStart, int16 palEnd) {
+ if ((palStart == -1) || (palEnd == -1))
+ memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
+ _video->getPalette(), 768);
+ else
+ memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) +
+ palStart * 3, _video->getPalette() + palStart * 3,
+ (palEnd - palStart + 1) * 3);
+}
+
+void VideoPlayer::writeVideoInfo(const char *video, int16 varX, int16 varY,
+ int16 varFrames, int16 varWidth, int16 varHeight) {
+
+ if (openVideo(video)) {
+ WRITE_VAR_OFFSET(varX, _video->getX());
+ WRITE_VAR_OFFSET(varY, _video->getY());
+ WRITE_VAR_OFFSET(varFrames, _video->getFramesCount());
+ WRITE_VAR_OFFSET(varWidth, _video->getWidth());
+ WRITE_VAR_OFFSET(varHeight, _video->getHeight());
+ closeVideo();
+ } else {
+ WRITE_VAR_OFFSET(varX, -1);
+ WRITE_VAR_OFFSET(varY, -1);
+ WRITE_VAR_OFFSET(varFrames, -1);
+ WRITE_VAR_OFFSET(varWidth, -1);
+ WRITE_VAR_OFFSET(varHeight, -1);
+ }
+}
+
+void VideoPlayer::closeVideo() {
+ delete _video;
+ delete _stream;
+
+ _video = 0;
+ _stream = 0;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h
new file mode 100644
index 0000000000..c4c608dc99
--- /dev/null
+++ b/engines/gob/videoplayer.h
@@ -0,0 +1,86 @@
+/* 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_VIDEOPLAYER_H
+#define GOB_VIDEOPLAYER_H
+
+#include "gob/coktelvideo.h"
+#include "gob/dataio.h"
+
+namespace Gob {
+
+class GobEngine;
+
+class VideoPlayer {
+public:
+ enum Flags {
+ kFlagNone = 0,
+ kFlagFrontSurface = 0x80,
+ kFlagNoVideo = 0x100
+ };
+
+ enum Type {
+ kVideoTypeTry = -1,
+ kVideoTypeIMD = 0,
+ kVideoTypeVMD = 1
+ };
+
+ VideoPlayer(GobEngine *vm);
+ ~VideoPlayer();
+
+ bool openVideo(const char *video, int16 x = -1, int16 y = -1,
+ int16 flags = kFlagFrontSurface, Type which = kVideoTypeTry);
+
+ void play(int16 startFrame = -1, int16 lastFrame = -1, int16 breakKey = 27,
+ uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255,
+ int16 palFrame = -1, int16 endFrame = -1, bool fade = false,
+ int16 reverseTo = -1);
+
+ int16 getFramesCount() const;
+ int16 getCurrentFrame() const;
+ void writeVideoInfo(const char *video, int16 varX, int16 varY,
+ int16 varFrames, int16 varWidth, int16 varHeight);
+
+ void closeVideo();
+
+private:
+ static const char *_extensions[];
+
+ GobEngine *_vm;
+
+ char _curFile[256];
+ DataStream *_stream;
+ CoktelVideo *_video;
+ bool _backSurf;
+
+ void copyPalette(int16 palStart = -1, int16 palEnd = -1);
+ bool doPlay(int16 frame, int16 breakKey,
+ uint16 palCmd, int16 palStart, int16 palEnd,
+ int16 palFrame, int16 endFrame);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_VIDEOPLAYER_H