[Scummvm-cvs-logs] SF.net SVN: scummvm: [28327] scummvm/trunk/engines/gob

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Mon Jul 30 17:53:38 CEST 2007


Revision: 28327
          http://scummvm.svn.sourceforge.net/scummvm/?rev=28327&view=rev
Author:   drmccoy
Date:     2007-07-30 08:53:38 -0700 (Mon, 30 Jul 2007)

Log Message:
-----------
Restructured and cleaned-up IMD playing

Modified Paths:
--------------
    scummvm/trunk/engines/gob/dataio.cpp
    scummvm/trunk/engines/gob/dataio.h
    scummvm/trunk/engines/gob/game.cpp
    scummvm/trunk/engines/gob/game.h
    scummvm/trunk/engines/gob/game_v2.cpp
    scummvm/trunk/engines/gob/gob.cpp
    scummvm/trunk/engines/gob/gob.h
    scummvm/trunk/engines/gob/init.cpp
    scummvm/trunk/engines/gob/inter_bargon.cpp
    scummvm/trunk/engines/gob/inter_v2.cpp
    scummvm/trunk/engines/gob/module.mk
    scummvm/trunk/engines/gob/mult_v2.cpp
    scummvm/trunk/engines/gob/util.cpp

Added Paths:
-----------
    scummvm/trunk/engines/gob/coktelvideo.cpp
    scummvm/trunk/engines/gob/coktelvideo.h
    scummvm/trunk/engines/gob/videoplayer.cpp
    scummvm/trunk/engines/gob/videoplayer.h

Removed Paths:
-------------
    scummvm/trunk/engines/gob/imd.cpp
    scummvm/trunk/engines/gob/imd.h

Added: scummvm/trunk/engines/gob/coktelvideo.cpp
===================================================================
--- scummvm/trunk/engines/gob/coktelvideo.cpp	                        (rev 0)
+++ scummvm/trunk/engines/gob/coktelvideo.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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


Property changes on: scummvm/trunk/engines/gob/coktelvideo.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Added: scummvm/trunk/engines/gob/coktelvideo.h
===================================================================
--- scummvm/trunk/engines/gob/coktelvideo.h	                        (rev 0)
+++ scummvm/trunk/engines/gob/coktelvideo.h	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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


Property changes on: scummvm/trunk/engines/gob/coktelvideo.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Modified: scummvm/trunk/engines/gob/dataio.cpp
===================================================================
--- scummvm/trunk/engines/gob/dataio.cpp	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/dataio.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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 @@
 	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 @@
 	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 @@
 	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 @@
 	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

Modified: scummvm/trunk/engines/gob/dataio.h
===================================================================
--- scummvm/trunk/engines/gob/dataio.h	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/dataio.h	2007-07-30 15:53:38 UTC (rev 28327)
@@ -37,6 +37,32 @@
 #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 @@
 	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 @@
 	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 @@
 	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

Modified: scummvm/trunk/engines/gob/game.cpp
===================================================================
--- scummvm/trunk/engines/gob/game.cpp	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/game.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -379,10 +379,12 @@
 		_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();
 }

Modified: scummvm/trunk/engines/gob/game.h
===================================================================
--- scummvm/trunk/engines/gob/game.h	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/game.h	2007-07-30 15:53:38 UTC (rev 28327)
@@ -147,7 +147,8 @@
 
 	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);

Modified: scummvm/trunk/engines/gob/game_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/game_v2.cpp	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/game_v2.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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.
+	/* 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.
+	 * 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$
- *
- */
+	 * 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 @@
 						_vm->_snd->freeSample(_soundSamples[i]);
 			}
 
-			_vm->_imdPlayer->closeImd();
+			_vm->_vidPlayer->closeVideo();
 			if (_totToLoad[0] == 0)
 				break;
 

Modified: scummvm/trunk/engines/gob/gob.cpp
===================================================================
--- scummvm/trunk/engines/gob/gob.cpp	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/gob.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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 @@
 
 	_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 @@
 	_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 @@
 	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;

Modified: scummvm/trunk/engines/gob/gob.h
===================================================================
--- scummvm/trunk/engines/gob/gob.h	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/gob.h	2007-07-30 15:53:38 UTC (rev 28327)
@@ -42,7 +42,7 @@
 class CDROM;
 class DataIO;
 class Goblin;
-class ImdPlayer;
+class VideoPlayer;
 class Init;
 class Inter;
 class Map;
@@ -216,7 +216,7 @@
 	Inter *_inter;
 	SaveLoad *_saveLoad;
 	Adlib *_adlib;
-	ImdPlayer *_imdPlayer;
+	VideoPlayer *_vidPlayer;
 
 	void shutdown();
 

Deleted: scummvm/trunk/engines/gob/imd.cpp
===================================================================
--- scummvm/trunk/engines/gob/imd.cpp	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/imd.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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

Deleted: scummvm/trunk/engines/gob/imd.h
===================================================================
--- scummvm/trunk/engines/gob/imd.h	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/imd.h	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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

Modified: scummvm/trunk/engines/gob/init.cpp
===================================================================
--- scummvm/trunk/engines/gob/init.cpp	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/init.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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 @@
 			_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();

Modified: scummvm/trunk/engines/gob/inter_bargon.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_bargon.cpp	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/inter_bargon.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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 @@
 }
 
 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_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

Modified: scummvm/trunk/engines/gob/inter_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v2.cpp	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/inter_v2.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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 @@
 	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 @@
 	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_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) {

Modified: scummvm/trunk/engines/gob/module.mk
===================================================================
--- scummvm/trunk/engines/gob/module.mk	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/module.mk	2007-07-30 15:53:38 UTC (rev 28327)
@@ -18,7 +18,8 @@
 	goblin_v1.o \
 	goblin_v2.o \
 	goblin_v3.o \
-	imd.o \
+	coktelvideo.o \
+	videoplayer.o \
 	init.o \
 	init_v1.o \
 	init_v2.o \

Modified: scummvm/trunk/engines/gob/mult_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/mult_v2.cpp	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/mult_v2.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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 @@
 		x = y = -1;
 
 	if (key.imdFile == -1) {
-		_vm->_imdPlayer->closeImd();
+		_vm->_vidPlayer->closeVideo();
 		_vm->_game->_preventScroll = false;
 		return;
 	}
@@ -1059,23 +1059,24 @@
 		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) {

Modified: scummvm/trunk/engines/gob/util.cpp
===================================================================
--- scummvm/trunk/engines/gob/util.cpp	2007-07-30 14:35:26 UTC (rev 28326)
+++ scummvm/trunk/engines/gob/util.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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 @@
 
 	_vm->_global->_frameWaitTime = 1000 / rate;
 	_vm->_global->_startFrameTime = getTimeKey();
-	_vm->_imdPlayer->_frameDelay = 0;
 }
 
 void Util::waitEndFrame() {
@@ -312,17 +310,13 @@
 	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) {

Added: scummvm/trunk/engines/gob/videoplayer.cpp
===================================================================
--- scummvm/trunk/engines/gob/videoplayer.cpp	                        (rev 0)
+++ scummvm/trunk/engines/gob/videoplayer.cpp	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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


Property changes on: scummvm/trunk/engines/gob/videoplayer.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Added: scummvm/trunk/engines/gob/videoplayer.h
===================================================================
--- scummvm/trunk/engines/gob/videoplayer.h	                        (rev 0)
+++ scummvm/trunk/engines/gob/videoplayer.h	2007-07-30 15:53:38 UTC (rev 28327)
@@ -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


Property changes on: scummvm/trunk/engines/gob/videoplayer.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list