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

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Thu Mar 29 19:55:39 CEST 2007


Revision: 26316
          http://scummvm.svn.sourceforge.net/scummvm/?rev=26316&view=rev
Author:   drmccoy
Date:     2007-03-29 10:55:39 -0700 (Thu, 29 Mar 2007)

Log Message:
-----------
- Properly implemented the ImdPlayer
- Some more clean-up

Modified Paths:
--------------
    scummvm/trunk/engines/gob/cdrom.cpp
    scummvm/trunk/engines/gob/dataio.cpp
    scummvm/trunk/engines/gob/dataio.h
    scummvm/trunk/engines/gob/draw.cpp
    scummvm/trunk/engines/gob/draw.h
    scummvm/trunk/engines/gob/draw_v1.cpp
    scummvm/trunk/engines/gob/draw_v2.cpp
    scummvm/trunk/engines/gob/game.cpp
    scummvm/trunk/engines/gob/game_v2.cpp
    scummvm/trunk/engines/gob/global.h
    scummvm/trunk/engines/gob/gob.cpp
    scummvm/trunk/engines/gob/gob.h
    scummvm/trunk/engines/gob/imd.cpp
    scummvm/trunk/engines/gob/imd.h
    scummvm/trunk/engines/gob/init.cpp
    scummvm/trunk/engines/gob/inter_v1.cpp
    scummvm/trunk/engines/gob/inter_v2.cpp
    scummvm/trunk/engines/gob/mult.cpp
    scummvm/trunk/engines/gob/palanim.cpp
    scummvm/trunk/engines/gob/parse.h
    scummvm/trunk/engines/gob/sound.cpp
    scummvm/trunk/engines/gob/sound.h
    scummvm/trunk/engines/gob/util.cpp
    scummvm/trunk/engines/gob/video.cpp
    scummvm/trunk/engines/gob/video.h

Modified: scummvm/trunk/engines/gob/cdrom.cpp
===================================================================
--- scummvm/trunk/engines/gob/cdrom.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/cdrom.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -66,23 +66,17 @@
 
 	handle = _vm->_dataIO->openData(tmp);
 
-	_vm->_dataIO->readData(handle, (char *)&version, 2);
-	version = READ_LE_UINT16(&version);
+	version = _vm->_dataIO->readUint16(handle);
+	startChunk = _vm->_dataIO->readUint16(handle);
+	_numTracks = _vm->_dataIO->readUint16(handle);
 
-	_vm->_dataIO->readData(handle, (char *)&startChunk, 2);
-	startChunk = READ_LE_UINT16(&startChunk);
-
-	_vm->_dataIO->readData(handle, (char *)&_numTracks, 2);
-	_numTracks = READ_LE_UINT16(&_numTracks);
-
 	if (version != 3)
 		error("%s: Unknown version %d", fname, version);
 
 	_vm->_dataIO->seekData(handle, 50, SEEK_SET);
 
 	for (int i = 0; i < startChunk; i++) {
-		_vm->_dataIO->readData(handle, (char *)&pos, 2);
-		pos = READ_LE_UINT16(&pos);
+		pos = _vm->_dataIO->readUint16(handle);
 
 		if (!pos)
 			break;
@@ -91,7 +85,7 @@
 	}
 
 	_LICbuffer = new byte[_numTracks * 22];
-	_vm->_dataIO->readData(handle, (char *)_LICbuffer, _numTracks * 22);
+	_vm->_dataIO->readData(handle, (char *) _LICbuffer, _numTracks * 22);
 
 	_vm->_dataIO->closeData(handle);
 }

Modified: scummvm/trunk/engines/gob/dataio.cpp
===================================================================
--- scummvm/trunk/engines/gob/dataio.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/dataio.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -39,6 +39,14 @@
 	_packedSize = 0;
 }
 
+DataIO::~DataIO() {
+	for (int i = 0; i < MAX_DATA_FILES; i++) {
+		if (_dataFiles[i])
+			file_getHandle(_dataFileHandles[i])->close();
+		delete[] _dataFiles[i];
+	}
+}
+
 int32 DataIO::unpackData(char *sourceBuf, char *destBuf) {
 	uint32 realSize;
 	uint32 counter;
@@ -104,7 +112,7 @@
 }
 
 Common::File *DataIO::file_getHandle(int16 handle) {
-	return &_vm->_global->_filesHandles[handle];
+	return &_filesHandles[handle];
 }
 
 int16 DataIO::file_open(const char *path, Common::File::AccessMode mode) {
@@ -156,7 +164,7 @@
 }
 
 char DataIO::freeChunk(int16 handle) {
-	if ((handle >= 50) && (handle < 100)) {
+	if ((handle >= 50) && (handle < 128)) {
 		handle -= 50;
 		_chunkPos[(handle / 10) * MAX_SLOT_COUNT + (handle % 10)] = -1;
 		return 0;
@@ -170,7 +178,7 @@
 	int16 i;
 	int32 offset;
 
-	if ((handle < 50) || (handle >= 100))
+	if ((handle < 50) || (handle >= 128))
 		return -2;
 
 	file = (handle - 50) / 10;
@@ -204,7 +212,7 @@
 	int16 file;
 	int16 slot;
 
-	if ((handle < 50) || (handle >= 100))
+	if ((handle < 50) || (handle >= 128))
 		return -1;
 
 	file = (handle - 50) / 10;
@@ -218,6 +226,19 @@
 	return _chunkPos[file * MAX_SLOT_COUNT + slot];
 }
 
+uint32 DataIO::getChunkPos(int16 handle) {
+	int16 file;
+	int16 slot;
+
+	if ((handle < 50) || (handle >= 128))
+		return 0xFFFFFFFF;
+
+	file = (handle - 50) / 10;
+	slot = (handle - 50) % 10;
+
+	return _chunkPos[file * MAX_SLOT_COUNT + slot];
+}
+
 int32 DataIO::getChunkSize(const char *chunkName) {
 	int16 file;
 	int16 chunk;
@@ -370,6 +391,27 @@
 	return file_getHandle(handle)->read(buf, size);
 }
 
+byte DataIO::readByte(int16 handle) {
+	char buf;
+
+	readData(handle, &buf, 1);
+	return ((byte) buf);
+}
+
+uint16 DataIO::readUint16(int16 handle) {
+	char buf[2];
+
+	readData(handle, buf, 2);
+	return READ_LE_UINT16(buf);
+}
+
+uint32 DataIO::readUint32(int16 handle) {
+	char buf[4];
+
+	readData(handle, buf, 4);
+	return READ_LE_UINT32(buf);
+}
+
 int32 DataIO::writeData(int16 handle, char *buf, uint16 size) {
 	return file_getHandle(handle)->write(buf, size);
 }
@@ -384,7 +426,13 @@
 	file_getHandle(handle)->seek(pos, from);
 }
 
-int32 DataIO::getPos(int16 handle) {
+uint32 DataIO::getPos(int16 handle) {
+	uint32 resPos;
+
+	resPos = getChunkPos(handle);
+	if (resPos != 0xFFFFFFFF)
+		return resPos;
+
 	return file_getHandle(handle)->pos();
 }
 

Modified: scummvm/trunk/engines/gob/dataio.h
===================================================================
--- scummvm/trunk/engines/gob/dataio.h	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/dataio.h	2007-03-29 17:55:39 UTC (rev 26316)
@@ -24,10 +24,14 @@
 #ifndef GOB_DATAIO_H
 #define GOB_DATAIO_H
 
+#include "common/stdafx.h"
+#include "common/endian.h"
+
 #include "common/file.h"
 
 namespace Gob {
 
+#define MAX_FILES	30
 #define MAX_DATA_FILES	8
 #define MAX_SLOT_COUNT	4
 
@@ -50,15 +54,20 @@
 	int16 openData(const char *path,
 			Common::File::AccessMode mode = Common::File::kFileReadMode);
 	int32 readData(int16 handle, char *buf, uint16 size);
+	byte readByte(int16 handle);
+	uint16 readUint16(int16 handle);
+	uint32 readUint32(int16 handle);
 	int32 writeData(int16 handle, char *buf, uint16 size);
 	void seekData(int16 handle, int32 pos, int16 from);
-	int32 getPos(int16 handle);
+	uint32 getPos(int16 handle);
 	int32 getDataSize(const char *name);
 	char *getData(const char *path);
 
 	DataIO(class GobEngine *vm);
+	~DataIO();
 
 protected:
+	Common::File _filesHandles[MAX_FILES];
 	struct ChunkDesc *_dataFiles[MAX_DATA_FILES];
 	int16 _numDataChunks[MAX_DATA_FILES];
 	int16 _dataFileHandles[MAX_DATA_FILES];
@@ -79,6 +88,7 @@
 	char freeChunk(int16 handle);
 	int32 readChunk(int16 handle, char *buf, uint16 size);
 	int16 seekChunk(int16 handle, int32 pos, int16 from);
+	uint32 getChunkPos(int16 handle);
 	int32 getChunkSize(const char *chunkName);
 };
 

Modified: scummvm/trunk/engines/gob/draw.cpp
===================================================================
--- scummvm/trunk/engines/gob/draw.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/draw.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -246,10 +246,7 @@
 	_showCursor = (_showCursor & ~2) | ((_showCursor & 1) << 1);
 	if (_applyPal) {
 		clearPalette();
-
-		_vm->_video->drawSprite(_backSurface, _frontSurface,
-				0, 0, _vm->_video->_surfWidth - 1,
-				_vm->_video->_surfHeight - 1, 0, 0, 0);
+		forceBlit();
 		setPalette();
 		_invalidatedCount = 0;
 		_noInvalidated = true;
@@ -390,4 +387,24 @@
 	return _spritesArray[index]->getWidth() * _spritesArray[index]->getHeight();
 }
 
+void Draw::forceBlit(bool backwards) {
+	if ((_frontSurface == 0) || (_backSurface == 0))
+		return;
+	if (_frontSurface == _backSurface)
+		return;
+	if (_spritesArray[20] != _frontSurface)
+		return;
+	if (_spritesArray[21] != _backSurface)
+		return;
+
+	if (backwards)
+		_vm->_video->drawSprite(_frontSurface, _backSurface, 0, 0,
+				_frontSurface->getWidth() - 1, _frontSurface->getHeight() - 1,
+				0, 0, 0);
+	else
+		_vm->_video->drawSprite(_backSurface, _frontSurface, 0, 0,
+				_backSurface->getWidth() - 1, _backSurface->getHeight() - 1,
+				0, 0, 0);
+}
+
 } // End of namespace Gob

Modified: scummvm/trunk/engines/gob/draw.h
===================================================================
--- scummvm/trunk/engines/gob/draw.h	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/draw.h	2007-03-29 17:55:39 UTC (rev 26316)
@@ -144,6 +144,7 @@
 	void printTextCentered(int16 id, int16 left, int16 top, int16 right,
 			int16 bottom, char *str, int16 fontIndex, int16 color);
 	int32 getSpriteRectSize(int16 index);
+	void forceBlit(bool backwards = false);
 
 	virtual void initScreen() = 0;
 	virtual void closeScreen() = 0;

Modified: scummvm/trunk/engines/gob/draw_v1.cpp
===================================================================
--- scummvm/trunk/engines/gob/draw_v1.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/draw_v1.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -99,7 +99,7 @@
 			} else {
 				if (_noInvalidated && (_vm->_global->_inter_mouseX == _cursorX) &&
 						(_vm->_global->_inter_mouseY == _cursorY)) {
-					_vm->_video->waitRetrace(_vm->_global->_videoMode);
+					_vm->_video->waitRetrace();
 					return;
 				}
 			}
@@ -144,7 +144,7 @@
 				blitInvalidated();
 				_cursorIndex = tmp;
 			} else {
-				_vm->_video->waitRetrace(_vm->_global->_videoMode);
+				_vm->_video->waitRetrace();
 				if (MIN(newY, _cursorY) < 50)
 					_vm->_util->delay(5);
 				_showCursor = 0;

Modified: scummvm/trunk/engines/gob/draw_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/draw_v2.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/draw_v2.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -126,7 +126,7 @@
 			} else {
 				if (_noInvalidated && (_vm->_global->_inter_mouseX == _cursorX) &&
 						(_vm->_global->_inter_mouseY == _cursorY)) {
-					_vm->_video->waitRetrace(_vm->_global->_videoMode);
+					_vm->_video->waitRetrace();
 					return;
 				}
 			}
@@ -170,7 +170,7 @@
 				_cursorIndex = tmp;
 			} else {
 				_showCursor = 3;
-				_vm->_video->waitRetrace(_vm->_global->_videoMode);
+				_vm->_video->waitRetrace();
 				if (MIN(newY, _cursorY) < 50)
 					_vm->_util->delay(5);
 			}

Modified: scummvm/trunk/engines/gob/game.cpp
===================================================================
--- scummvm/trunk/engines/gob/game.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/game.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -352,28 +352,22 @@
 	if (_extHandle < 0)
 		return;
 
-	_vm->_dataIO->readData(_extHandle, (char *) &count, 2);
-	count = FROM_LE_16(count);
+	count = _vm->_dataIO->readUint16(_extHandle);
 
-	_vm->_dataIO->seekData(_extHandle, 0, 0);
+	_vm->_dataIO->seekData(_extHandle, 0, SEEK_SET);
 	_extTable = new ExtTable;
 	_extTable->items = 0;
 	if (count)
 		_extTable->items = new ExtItem[count];
 
-	_vm->_dataIO->readData(_extHandle, (char *) &_extTable->itemsCount, 2);
-	_extTable->itemsCount = FROM_LE_16(_extTable->itemsCount);
-	_vm->_dataIO->readData(_extHandle, (char *) &_extTable->unknown, 1);
+	_extTable->itemsCount = _vm->_dataIO->readUint16(_extHandle);
+	_extTable->unknown = _vm->_dataIO->readByte(_extHandle);
 
 	for (int i = 0; i < count; i++) {
-		_vm->_dataIO->readData(_extHandle, (char *) &_extTable->items[i].offset, 4);
-		_extTable->items[i].offset = FROM_LE_32(_extTable->items[i].offset);
-		_vm->_dataIO->readData(_extHandle, (char *) &_extTable->items[i].size, 2);
-		_extTable->items[i].size = FROM_LE_16(_extTable->items[i].size);
-		_vm->_dataIO->readData(_extHandle, (char *) &_extTable->items[i].width, 2);
-		_extTable->items[i].width = FROM_LE_16(_extTable->items[i].width);
-		_vm->_dataIO->readData(_extHandle, (char *) &_extTable->items[i].height, 2);
-		_extTable->items[i].height = FROM_LE_16(_extTable->items[i].height);
+		_extTable->items[i].offset = _vm->_dataIO->readUint32(_extHandle);
+		_extTable->items[i].size = _vm->_dataIO->readUint16(_extHandle);
+		_extTable->items[i].width = _vm->_dataIO->readUint16(_extHandle);
+		_extTable->items[i].height = _vm->_dataIO->readUint16(_extHandle);
 	}
 }
 

Modified: scummvm/trunk/engines/gob/game_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/game_v2.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/game_v2.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -439,7 +439,7 @@
 				_vm->_draw->animateCursor(-1);
 			else
 				_vm->_draw->blitInvalidated();
-			_vm->_video->waitRetrace(_vm->_global->_videoMode);
+			_vm->_video->waitRetrace();
 		}
 
 		key = checkKeys(&_vm->_global->_inter_mouseX,

Modified: scummvm/trunk/engines/gob/global.h
===================================================================
--- scummvm/trunk/engines/gob/global.h	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/global.h	2007-03-29 17:55:39 UTC (rev 26316)
@@ -55,8 +55,6 @@
 #define ESCAPE	0x001B
 #define ENTER	0x000D
 
-#define MAX_FILES	30
-
 /* Video drivers */
 #define UNK_DRIVER	0
 #define VGA_DRIVER	1
@@ -94,8 +92,6 @@
 
 	char _useJoystick;
 
-	Common::File _filesHandles[MAX_FILES];
-
 	int16 _primaryWidth;
 	int16 _primaryHeight;
 

Modified: scummvm/trunk/engines/gob/gob.cpp
===================================================================
--- scummvm/trunk/engines/gob/gob.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/gob.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -410,9 +410,8 @@
 		_vm->_video->drawSprite(_global->_savedBack, destDesc, 0, 0,
 				destDesc->getWidth() - 1, destDesc->getHeight() - 1, 0, 0, 0);
 		if (index == 21) {
-			_video->drawSprite(_draw->_backSurface, _draw->_frontSurface, 0, 0,
-					_draw->_frontSurface->getWidth() - 1, _draw->_frontSurface->getHeight() - 1, 0, 0, 0);
-			_video->waitRetrace(_global->_videoMode);
+			_vm->_draw->forceBlit();
+			_video->waitRetrace();
 		}
 
 		WRITE_VAR(1, 0);

Modified: scummvm/trunk/engines/gob/gob.h
===================================================================
--- scummvm/trunk/engines/gob/gob.h	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/gob.h	2007-03-29 17:55:39 UTC (rev 26316)
@@ -109,11 +109,14 @@
 public:
 	class Ptr {
 	public:
-		T* operator-> () { return _p; }
-		T& operator* () { return *_p; }
+		bool operator==(const Ptr &p) const { return _p == p._p; }
+		bool operator==(const ReferenceCounter *p) const { return _p == p; }
+
+		T *operator-> () { return _p; }
+		T &operator* () { return *_p; }
 		operator T*() { return _p; }
 
-		Ptr(T* p) : _p(p) { ++_p->_references; }
+		Ptr(T *p) : _p(p) { ++_p->_references; }
 		Ptr() : _p(0) { }
 
 		~Ptr() {
@@ -121,16 +124,16 @@
 				delete _p;
 		}
 
-		Ptr(const Ptr& p) : _p(p._p) { ++_p->_references; }
+		Ptr(const Ptr &p) : _p(p._p) { ++_p->_references; }
 
-		Ptr& operator= (const Ptr& p) {
+		Ptr &operator= (const Ptr &p) {
 			++p._p->_references;
 			if (_p && (--_p->_references == 0))
 				delete _p;
 			_p = p._p;
 			return *this;
 		}
-		Ptr* operator= (const Ptr* p) {
+		Ptr *operator= (const Ptr *p) {
 			if (p)
 				++p->_p->_references;
 			if (_p && (--_p->_references == 0))
@@ -141,7 +144,7 @@
 		}
 
 	private:
-		T* _p;
+		T *_p;
 	};
 
 	ReferenceCounter() : _references(0) { }

Modified: scummvm/trunk/engines/gob/imd.cpp
===================================================================
--- scummvm/trunk/engines/gob/imd.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/imd.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -44,9 +44,11 @@
 
 	_curX = 0;
 	_curY = 0;
+	_left = 0;
+	_top = 0;
+	_right = 0;
+	_bottom = 0;
 
-	_frameDataSize = 0;
-	_vidBufferSize = 0;
 	_frameData = 0;
 	_vidBuffer = 0;
 
@@ -54,35 +56,42 @@
 	_backSurf = 21;
 	_frontMem = 0;
 	_frameDelay = 0;
+
+	_noSound = true;
+	_soundBuffer = 0;
+
+	_soundFreq = 0;
+	_soundSliceSize = 0;
+	_soundSlicesCount = 0;
+
+	_soundSliceLength = 0;
+	_curSoundSlice = 0;
+	_soundStage = 0;
 }
 
 ImdPlayer::~ImdPlayer() {
 	if (_curImd) {
-		_curImd->surfDesc = 0;
 		delete[] _curImd->palette;
 		delete[] _curImd->framesPos;
 		delete[] _curImd->frameCoords;
+		delete[] _curImd->extraPalette;
 	}
 	delete[] _frameData;
 	delete[] _vidBuffer;
 	delete[] _frontMem;
+	delete[] _soundBuffer;
 	delete _curImd;
 }
 
-// flagsBit: 0 = read and set palette
-//           1 = read palette
+// flag bits: 0 = read and set palette
+//            1 = read palette
 ImdPlayer::Imd *ImdPlayer::loadImdFile(const char *path, SurfaceDesc *surfDesc, int8 flags) {
-	int i;
 	Imd *imdPtr;
 	int16 handle;
-	bool setAllPalBak;
 	char buf[18];
-	Video::Color *palBak;
+	uint32 framesPosPos = 0;
+	uint32 framesCordsPos = 0;
 
-	int32 byte_31449 = 0;
-	int32 byte_3144D = 0;
-
-	buf[0] = 0;
 	strcpy(buf, path);
 	strcat(buf, ".IMD");
 
@@ -94,226 +103,204 @@
 	}
 
 	imdPtr = new Imd;
+	assert(imdPtr);
 	memset(imdPtr, 0, sizeof(Imd));
 
-	_vm->_dataIO->readData(handle, buf, 18);
+	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);
 
-	// "fileHandle" holds the major version while loading
-	imdPtr->fileHandle = READ_LE_UINT16(buf);
-	imdPtr->verMin = READ_LE_UINT16(buf + 2);
-	imdPtr->framesCount = READ_LE_UINT16(buf + 4);
-	imdPtr->x = READ_LE_UINT16(buf + 6);
-	imdPtr->y = READ_LE_UINT16(buf + 8);
-	imdPtr->width = READ_LE_UINT16(buf + 10);
-	imdPtr->height = READ_LE_UINT16(buf + 12);
-	imdPtr->field_E = READ_LE_UINT16(buf + 14);
-	imdPtr->curFrame = READ_LE_UINT16(buf + 16);
-
-	if (imdPtr->fileHandle != 0)
-		imdPtr->verMin = 0;
-
-	if ((imdPtr->verMin & 0xFF) < 2) {
-		warning("IMD version incorrect (%d,%d)", imdPtr->fileHandle, imdPtr->verMin);
+	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;
 	
-/*
-	imdPtr->field_3A = 0;
 	if ((imdPtr->verMin & 0x800) && ((flags & 3) != 3))
-		imdPtr->field_3A = new Video::Color[256];
-*/
+		imdPtr->extraPalette = new Video::Color[256];
 
 	if (flags & 3) {
 		imdPtr->palette = new Video::Color[256];
+		assert(imdPtr->palette);
 		_vm->_dataIO->readData(handle, (char *) imdPtr->palette, 768);
-	} else {
-		imdPtr->palette = 0;
-		_vm->_dataIO->seekData(handle, 768, 1);
-	}
+	} else
+		_vm->_dataIO->seekData(handle, 768, SEEK_CUR);
 
-	if ((flags & 3) == 1) {
-		palBak = _vm->_global->_pPaletteDesc->vgaPal;
-		setAllPalBak = _vm->_global->_setAllPalette;
+	if ((flags & 3) == 1)
+		_vm->_video->setPalette(imdPtr->palette);
 
-		_vm->_global->_pPaletteDesc->vgaPal = imdPtr->palette;
-		_vm->_global->_setAllPalette = true;
-		_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
-
-		_vm->_global->_setAllPalette = setAllPalBak;
-		_vm->_global->_pPaletteDesc->vgaPal = palBak;
-	}
-
 	if ((imdPtr->verMin & 0xFF) >= 3) {
-		_vm->_dataIO->readData(handle, buf, 2);
-		imdPtr->stdX = READ_LE_UINT16(buf);
+		imdPtr->stdX = _vm->_dataIO->readUint16(handle);
 		if (imdPtr->stdX > 1) {
-			warning("IMD ListI incorrect (%d)", imdPtr->stdX);
-			_vm->_dataIO->closeData(handle);
-			delete imdPtr;
+			warning("%s: More than one standard coordinate quad found (%d)",
+					buf, imdPtr->stdX);
+			finishImd(imdPtr);
 			return 0;
 		}
 		if (imdPtr->stdX != 0) {
-			_vm->_dataIO->readData(handle, buf, 8);
-			imdPtr->stdX = READ_LE_UINT16(buf);
-			imdPtr->stdY = READ_LE_UINT16(buf + 2);
-			imdPtr->stdWidth = READ_LE_UINT16(buf + 4);
-			imdPtr->stdHeight = READ_LE_UINT16(buf + 6);
+			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;
 
-	imdPtr->framesPos = 0;
 	if ((imdPtr->verMin & 0xFF) >= 4) {
-		_vm->_dataIO->readData(handle, buf, 4);
-		byte_31449 = READ_LE_UINT32(buf);
-		if (byte_31449 != 0)
+		framesPosPos = _vm->_dataIO->readUint32(handle);
+		if (framesPosPos != 0) {
 			imdPtr->framesPos = new int32[imdPtr->framesCount];
+			assert(imdPtr->framesPos);
+		}
 	}
 
-	if (imdPtr->verMin & 0x8000) {
-		_vm->_dataIO->readData(handle, buf, 4);
-		byte_3144D = READ_LE_UINT32(buf);
-	}
+	if (imdPtr->verMin & 0x8000)
+		framesCordsPos = _vm->_dataIO->readUint32(handle);
 
-	if (imdPtr->verMin & 0x4000) { // loc_29C4F
-		int16 word_3145B[3];
+	_noSound = true;
+	if (imdPtr->verMin & 0x4000) {
+		_soundFreq = _vm->_dataIO->readUint16(handle);
+		_soundSliceSize = _vm->_dataIO->readUint16(handle);
+		_soundSlicesCount = _vm->_dataIO->readUint16(handle);
 
-		flags &= 0x7F;
-		_vm->_dataIO->readData(handle, buf, 6);
-		word_3145B[0] = READ_LE_UINT16(buf);
-		word_3145B[1] = READ_LE_UINT16(buf + 2);
-		word_3145B[2] = READ_LE_UINT16(buf + 4);
+		if (_soundFreq < 0)
+			_soundFreq = -_soundFreq;
 
-		if (word_3145B[0] < 0)
-			word_3145B[0] = -word_3145B[0];
-		if (word_3145B[2] < 0)
-			word_3145B[2] = -word_3145B[2];
+		if (_soundSlicesCount < 0)
+			_soundSlicesCount = -_soundSlicesCount - 1;
 
-		warning("Imd Stub! Sound stuff!");
-		return 0;
-	} // loc_29E43
+		if (_soundSlicesCount >= 40) {
+			warning("%s: More than 40 sound slices found (%d)",
+					buf, _soundSlicesCount + 1);
+			finishImd(imdPtr);
+			return 0;
+		}
 
+		_soundSliceLength = 1000 / (_soundFreq / _soundSliceSize);
+
+		delete[] _soundBuffer;
+		_soundBuffer = new byte[_soundSliceSize * _soundSlicesCount];
+		assert(_soundBuffer);
+		memset(_soundBuffer, 0, _soundSliceSize * _soundSlicesCount);
+
+		_vm->_snd->stopSound(0);
+		_soundDesc.set(SOUND_SND, SOUND_TOT, _soundBuffer,
+				_soundSliceSize * _soundSlicesCount);
+
+		_curSoundSlice = 0;
+		_soundStage = 1;
+		_noSound = false;
+	}
+
 	if (imdPtr->verMin & 0x2000) {
-		_vm->_dataIO->readData(handle, buf, 2);
-		imdPtr->frameDataSize = READ_LE_UINT16(buf);
+		imdPtr->frameDataSize = _vm->_dataIO->readUint16(handle);
 		if (imdPtr->frameDataSize == 0) {
-			_vm->_dataIO->readData(handle, buf, 8);
-			imdPtr->frameDataSize = READ_LE_UINT32(buf);
-			imdPtr->vidBufferSize = READ_LE_UINT32(buf + 4);
-		} else {
-			_vm->_dataIO->readData(handle, buf, 2);
-			imdPtr->vidBufferSize = READ_LE_UINT16(buf);
-		}
+			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;
-		imdPtr->vidBufferSize = 0;
 		if (!(imdPtr->field_E & 0x100) || (imdPtr->field_E & 0x1000))
-			imdPtr->vidBufferSize = imdPtr->width * imdPtr->height + 500;
+			imdPtr->vidBufferSize = imdPtr->frameDataSize;
 	}
-	warning("-> %d, %d", imdPtr->frameDataSize, imdPtr->vidBufferSize);
 
-	if (imdPtr->framesPos != 0) {
-		_vm->_dataIO->seekData(handle, byte_31449, 0);
-		for (i = 0; i < imdPtr->framesCount; i++) {
-			_vm->_dataIO->readData(handle, buf, 4);
-			imdPtr->framesPos[i] = READ_LE_UINT32(buf);
-		}
+	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, byte_3144D, 0);
+		_vm->_dataIO->seekData(handle, framesCordsPos, SEEK_SET);
 		imdPtr->frameCoords = new ImdCoord[imdPtr->framesCount];
-		for (i = 0; i < imdPtr->framesCount; i++) {
-			_vm->_dataIO->readData(handle, buf, 8);
-			imdPtr->frameCoords[i].left = READ_LE_UINT16(buf);
-			imdPtr->frameCoords[i].top = READ_LE_UINT16(buf + 2);
-			imdPtr->frameCoords[i].right = READ_LE_UINT16(buf + 4);
-			imdPtr->frameCoords[i].bottom = READ_LE_UINT16(buf + 6);
+		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);
 		}
-	} else
-		imdPtr->frameCoords = 0;
-
-	_vm->_dataIO->seekData(handle, imdPtr->firstFramePos, 0);
-	imdPtr->curFrame = 0;
-	imdPtr->fileHandle = handle;
-	imdPtr->filePos = imdPtr->firstFramePos;
-	_frameDataSize = imdPtr->frameDataSize;
-	_vidBufferSize = imdPtr->vidBufferSize;
-	if (flags & 0x80) {
-		imdPtr->verMin |= 0x1000;
-		warning("Imd Stub! loadImdFile(), flags & 0x80");
 	}
 
+	_vm->_dataIO->seekData(handle, imdPtr->firstFramePos, SEEK_SET);
 	return imdPtr;
 }
 
-void ImdPlayer::finishImd(ImdPlayer::Imd *imdPtr) {
-	if (imdPtr == 0)
+void ImdPlayer::finishImd(ImdPlayer::Imd *&imdPtr) {
+	if (!imdPtr)
 		return;
 
-/*
-	if (dword_31345 != 0) {
-		_vm->_sound->stopSound(0);
-		dword_31345 = 0;
-		delete off_31461;
-		byte_31344 = 0;
-	}
-*/
+	_soundDesc.free();
+	if (_soundStage == 2)
+		_vm->_snd->stopSound(0);
 
-	_vm->_dataIO->closeData(imdPtr->fileHandle);
+	_vm->_dataIO->closeData(imdPtr->handle);
 
-	if (imdPtr->frameCoords != 0)
-		delete[] imdPtr->frameCoords;
-	if (imdPtr->palette != 0)
-		delete[] imdPtr->palette;
-	if (imdPtr->framesPos != 0)
-		delete[] imdPtr->framesPos;
+	delete[] imdPtr->frameCoords;
+	delete[] imdPtr->palette;
+	delete[] imdPtr->framesPos;
+	delete[] imdPtr->extraPalette;
 
 	delete imdPtr;
-	imdPtr = 0;
 }
 
-int8 ImdPlayer::openImd(const char *path, int16 x, int16 y, int16 repeat, int16 flags) {
-	int i;
-	int j;
+int8 ImdPlayer::openImd(const char *path, int16 x, int16 y,
+		int16 startFrame, int16 flags) {
 	const char *src;
 	byte *vidMem;
 	SurfaceDesc *surfDesc;
 
-	if (path[0] != 0) {
+	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)
-			_curFile[0] = 0;
+			return 0;
 
-		src = strrchr(path, '\\');
-		src = src == 0 ? path : src+1;
+		_curX = _curImd->x;
+		_curY = _curImd->y;
+		strcpy(_curFile, src);
 
-		if (strcmp(_curFile, src) != 0) {
-			closeImd();
+		delete[] _frameData;
+		_frameData = new byte[_curImd->frameDataSize + 500];
+		assert(_frameData);
+		memset(_frameData, 0, _curImd->frameDataSize + 500);
 
-			_curImd = loadImdFile(path, 0, 2);
-			if (!_curImd)
-				return 0;
+		delete[] _vidBuffer;
+		_vidBuffer = new byte[_curImd->vidBufferSize + 500];
+		assert(_vidBuffer);
+		memset(_vidBuffer, 0, _curImd->vidBufferSize + 500);
 
-			_curX = _curImd->x;
-			_curY = _curImd->y;
-			strcpy(_curFile, src);
-			_frameData = new byte[_frameDataSize + 500];
-			_vidBuffer = new byte[_vidBufferSize + 500];
-			memset(_frameData, 0, _frameDataSize + 500);
-			memset(_vidBuffer, 0, _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);
+						_vm->_video->initSurfDesc(0x13,
+								_curImd->width, _curImd->height, 0);
 				} else {
 					_curImd->surfDesc = _vm->_draw->_spritesArray[_frontSurf];
 					if ((x != -1) || (y != -1)) {
@@ -322,44 +309,51 @@
 						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);
+						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 (i = 0; i < _curImd->height; i++)
-							for (j = 0; j < _curImd->width; j++, vidMem++) {
+						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;
+					_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 (repeat == -1) {
+	if (startFrame == -1) {
 		closeImd();
 		return 0;
 	}
 
-	_curX = x != -1 ? x : _curX;
-	_curY = y != -1 ? y : _curY;
+	_curX = (x != -1) ? x : _curX;
+	_curY = (y != -1) ? y : _curY;
 
 	WRITE_VAR(7, _curImd->framesCount);
 
@@ -367,16 +361,14 @@
 }
 
 void ImdPlayer::closeImd(void) {
-	if (_curImd == 0)
-		return;
-
-	_curImd->surfDesc = 0;
 	finishImd(_curImd);
 
 	delete[] _frameData;
 	delete[] _vidBuffer;
+	delete[] _soundBuffer;
 	_frameData = 0;
 	_vidBuffer = 0;
+	_soundBuffer = 0;
 
 	_curImd = 0;
 }
@@ -389,317 +381,23 @@
 		imdPtr->stdY = imdPtr->stdY - imdPtr->y + y;
 	}
 	
-	if (imdPtr->frameCoords != 0) {
+	if (imdPtr->frameCoords) {
 		for (i = 0; i < imdPtr->framesCount; i++) {
-			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::play(int16 frame, uint16 palCmd, int16 palStart, int16 palEnd, int16 palFrame, int16 lastFrame) {
-	int16 viewRet = 0;
-	bool modifiedPal = false;
-	SurfaceDesc *surfDescBak;
-
-	_vm->_draw->_showCursor = 0;
-
-	int8 byte_31344 = 0;
-
-	if ((frame < 0) || (frame > lastFrame))
-		return;
-
-	if ((frame == palFrame) || ((frame == lastFrame) && (palCmd == 8))) { // loc_1C3F0
-		modifiedPal = true;
-		_vm->_draw->_applyPal = false;
-		if (palCmd >= 4) {
-			if (palStart != -1)
-				memcpy( ((char *) (_vm->_global->_pPaletteDesc->vgaPal)) + palStart * 3,
-						((char *) (_curImd->palette)) + palStart * 3, (palEnd - palStart + 1) * 3);
-			else
-				memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal, (char *) _curImd->palette, 768);
-		}
-	}
-
-	if (modifiedPal && (palCmd == 8) && (_backSurf == 20))
-		_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
-
-	if (_curImd->surfDesc->_vidMode == 0x14) {
-		if ((_frontSurf == 20) && (_frontMem == _vm->_draw->_spritesArray[20]->getVidMem())) {
-			_vm->_draw->_spritesArray[20]->swap(_vm->_draw->_spritesArray[21]);
-			viewRet = view(_curImd, frame);
-			_vm->_draw->_spritesArray[20]->swap(_vm->_draw->_spritesArray[21]);
-		} else
-			viewRet = view(_curImd, frame);
-		if (_frontSurf == 21) {
-			if ((_curImd->frameCoords == 0) || (_curImd->frameCoords[frame].left == -1))
-				_vm->_draw->invalidateRect(_curX, _curY,
-						_curX + _curImd->width - 1, _curY + _curImd->height - 1);
-			else
-				_vm->_draw->invalidateRect(_curImd->frameCoords[frame].left,
-						_curImd->frameCoords[frame].top, _curImd->frameCoords[frame].right,
-						_curImd->frameCoords[frame].bottom);
-		}
-	} else {
-		if ((_curImd->field_E & 0x100) && (_vm->_global->_videoMode == 0x14) &&
-				(_frontSurf == 20) && (sub_2C825(_curImd) & 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)) {
-				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]);
-							if ((_curImd->frameCoords == 0) || (_curImd->frameCoords[frame].left == -1))
-								_vm->_draw->invalidateRect(_curX, _curY, _curX + _curImd->width - 1,
-										_curY + _curImd->height - 1);
-							else
-								_vm->_draw->invalidateRect(_curImd->frameCoords[frame].left,
-										_curImd->frameCoords[frame].top, _curImd->frameCoords[frame].right,
-										_curImd->frameCoords[frame].bottom);
-						} else {
-							if (_frontMem == _vm->_draw->_spritesArray[20]->getVidMem()) { // loc_1C68D
-								_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 {
-						if ((_curImd->frameCoords == 0) || (_curImd->frameCoords[frame].left == -1))
-							_vm->_draw->invalidateRect(_curX, _curY, _curX + _curImd->width - 1,
-									_curY + _curImd->height - 1);
-						else
-							_vm->_draw->invalidateRect(_curImd->frameCoords[frame].left,
-									_curImd->frameCoords[frame].top, _curImd->frameCoords[frame].right,
-									_curImd->frameCoords[frame].bottom);
-					}
-				} else
-					if (_vm->_global->_videoMode == 0x14)
-						drawFrame(_curImd, frame, _curX, _curY);
+			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;
 			}
 		}
 	}
 
-	if (modifiedPal && (palCmd == 16)) {
-		if ((_vm->_draw->_spritesArray[20] != _vm->_draw->_spritesArray[21]) && (_backSurf == 21))
-			_vm->_video->drawSprite(_vm->_draw->_spritesArray[21],
-					_vm->_draw->_spritesArray[20], 0, 0,
-					_vm->_draw->_spritesArray[21]->getWidth() - 1,
-					_vm->_draw->_spritesArray[21]->getHeight() - 1, 0, 0, 0);
-		_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
-		_vm->_draw->_noInvalidated = true;
-	}
-	if (modifiedPal && (palCmd == 8) && (_backSurf == 21))
-		_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
-
-	if (!(viewRet & 0x800)) {
-		if (_vm->_draw->_cursorIndex == -1) {
-			if (_frontSurf == 20) {
-				if (_frontMem == _vm->_draw->_spritesArray[20]->getVidMem())
-					_frontMem = _vm->_draw->_spritesArray[21]->getVidMem();
-				else
-					_frontMem = _vm->_draw->_spritesArray[20]->getVidMem();
-				warning("GOB2 Stub! sub_1BC3A(_frontMem);");
-			} 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 (byte_31344 != 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();
-}
-
-int16 ImdPlayer::view(ImdPlayer::Imd *imdPtr, int16 frame) {
-	int16 x;
-	int16 y;
-	int16 width;
-	int16 height;
-	int16 retVal;
-	uint32 tmp;
-	char buf[4];
-
-	int8 var_4;
-	int32 var_12 = 0;
-
-	// .---
-	int16 word_31451 = 0;
-	int8 byte_31344 = 0;
-	int8 byte_2DA60 = 0;
-	int16 word_2DA61 = -1;
-	// '---
-
-	word_31451 = 0;
-
-	if (imdPtr == 0)
-		return (int16)0x8000;
-
-	retVal = 0;
-	var_4 = 0;
-
-	if (frame != imdPtr->curFrame) {
-		retVal |= 0x2000;
-		if (frame == 0)
-			imdPtr->filePos = imdPtr->firstFramePos;
-		else if (frame == 1) {
-			imdPtr->filePos = imdPtr->firstFramePos;
-			_vm->_dataIO->seekData(imdPtr->fileHandle, imdPtr->filePos, 0);
-			_vm->_dataIO->readData(imdPtr->fileHandle, buf, 2);
-			tmp = READ_LE_UINT16(buf);
-			imdPtr->filePos += tmp + 4;
-		} else if (imdPtr->framesPos != 0)
-			imdPtr->filePos = imdPtr->framesPos[frame];
-		else
-			error("Image %d inaccessible in IMD", frame);
-		imdPtr->curFrame = frame;
-		_vm->_dataIO->seekData(imdPtr->fileHandle, imdPtr->filePos, 0);
-	}
-
-	x = imdPtr->x;
-	y = imdPtr->y;
-	width = imdPtr->width;
-	height = imdPtr->height;
-
-	do {
-		if (frame != 0) {
-			if (imdPtr->stdX != -1) {
-				imdPtr->x = imdPtr->stdX;
-				imdPtr->y = imdPtr->stdY;
-				imdPtr->width = imdPtr->stdWidth;
-				imdPtr->height = imdPtr->stdHeight;
-				retVal |= 0x1000;
-			}
-			if ((imdPtr->frameCoords != 0) && (imdPtr->frameCoords[frame].left != -1)) {
-				var_4 |= 0x400;
-				imdPtr->x = imdPtr->frameCoords[frame].left;
-				imdPtr->y = imdPtr->frameCoords[frame].top;
-				imdPtr->width = imdPtr->frameCoords[frame].right - imdPtr->x + 1;
-				imdPtr->height = imdPtr->frameCoords[frame].bottom - imdPtr->y + 1;
-			}
-		}
-
-		_vm->_dataIO->readData(imdPtr->fileHandle, buf, 2);
-		tmp = READ_LE_UINT16(buf);
-
-		imdPtr->filePos += 2;
-
-		if ((tmp & 0xFFF8) == 0xFFF0) {
-			if (tmp == 0xFFF0) {
-				_vm->_dataIO->readData(imdPtr->fileHandle, buf, 2);
-				tmp = READ_LE_UINT16(buf);
-				if (var_4 == 0)
-					word_31451 = tmp;
-				_vm->_dataIO->readData(imdPtr->fileHandle, buf, 2);
-				tmp = READ_LE_UINT16(buf);
-				imdPtr->filePos += 4;
-			} else if (tmp == 0xFFF1) {
-				retVal = (int16)0x8000;
-				continue;
-			} else if (tmp == 0xFFF2) {
-				_vm->_dataIO->readData(imdPtr->fileHandle, buf, 2);
-				tmp = READ_LE_UINT16(buf);
-				imdPtr->filePos += 2;
-				_vm->_dataIO->seekData(imdPtr->fileHandle, tmp, 1);
-				imdPtr->filePos += tmp;
-				retVal = (int16)0x8000;
-				continue;
-			} else if (tmp == 0xFFF3) {
-				_vm->_dataIO->readData(imdPtr->fileHandle, buf, 4);
-				tmp = READ_LE_UINT32(buf);
-				imdPtr->filePos += 4;
-				_vm->_dataIO->seekData(imdPtr->fileHandle, tmp, 1);
-				imdPtr->filePos += tmp;
-				retVal = (int16)0x8000;
-				continue;
-			}
-		}
-		if (byte_31344 != 0) {
-			if ((var_4 == 0) && (_vm->_global->_soundFlags & 0x14) && (byte_31344 == 2)) { // loc_2A503
-				var_12 = _vm->_util->getTimeKey();
-				warning("GOB2 Stub! view, IMD sound stuff");
-			}
-		}
-		var_4 = 0;
-		if (tmp == 0xFFFD) {
-			_vm->_dataIO->readData(imdPtr->fileHandle, buf, 2);
-			frame = READ_LE_UINT16(buf);
-			if ((imdPtr->framesPos != 0) && (byte_2DA60 == 0)) {
-				word_2DA61 = frame;
-				imdPtr->filePos = imdPtr->framesPos[frame];
-				_vm->_dataIO->seekData(imdPtr->fileHandle, imdPtr->filePos, 0);
-				var_4 = 1;
-				retVal |= 0x200;
-				imdPtr->curFrame = frame;
-			} else
-				imdPtr->filePos += 2;
-			continue;
-		}
-		if (tmp != 0) {
-			imdPtr->filePos += tmp + 2;
-			if (byte_2DA60 != 0) {
-				_vm->_dataIO->seekData(imdPtr->fileHandle, tmp + 2, 1);
-			} else {
-				_vm->_dataIO->readData(imdPtr->fileHandle, (char *) _frameData, tmp + 2);
-				retVal |= *_frameData;
-				if (imdPtr->surfDesc == 0)
-					continue;
-				if (imdPtr->surfDesc->_vidMode != 0x14)
-					renderframe(imdPtr);
-				else
-					warning("GOB2 Stub! viedImd, sub_2C69A(imdPtr);");
-			}
-		} else
-			retVal |= 0x800;
-	} while (var_4 != 0);
-
-	if (byte_2DA60 != 0) {
-		byte_2DA60 = 0;
-		retVal |= 0x100;
-	}
-
 	imdPtr->x = x;
 	imdPtr->y = y;
-	imdPtr->width = width;
-	imdPtr->height = height;
-	imdPtr->curFrame++;
-	
-	return retVal;
 }
 
 void ImdPlayer::drawFrame(Imd *imdPtr, int16 frame, int16 x, int16 y,
@@ -710,7 +408,7 @@
 	if (frame == 0)
 		_vm->_video->drawSprite(imdPtr->surfDesc, dest, 0, 0,
 				imdPtr->width - 1, imdPtr->height - 1, x, y, 1);
-	else if ((imdPtr->frameCoords != 0) && (imdPtr->frameCoords[frame].left != -1))
+	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,
@@ -725,12 +423,9 @@
 				imdPtr->width - 1, imdPtr->height - 1, x, y, 0);
 }
 
-void ImdPlayer::renderframe(Imd *imdPtr) {
-	int i;
-	int16 imdX;
-	int16 imdY;
-	int16 imdW;
-	int16 imdH;
+void ImdPlayer::renderFrame(Imd *imdPtr) {
+	int16 imdX, imdY;
+	int16 imdW, imdH;
 	int16 sW;
 	uint16 pixCount, pixWritten;
 	uint8 type;
@@ -738,7 +433,6 @@
 	byte *imdVidMemBak;
 	byte *dataPtr = 0;
 	byte *srcPtr = 0;
-	byte *srcPtrBak = 0;
 
 	dataPtr = (byte *) _frameData;
 	imdX = imdPtr->x;
@@ -751,14 +445,13 @@
 	type = *dataPtr++;
 	srcPtr = dataPtr;
 
-	if (type & 0x10) {
+	if (type & 0x10) { // Palette data
 		type ^= 0x10;
-		dataPtr++; // => 0x3C8       |_ palette
-		dataPtr += 48; // => 0x3C9   |  stuff
+		dataPtr += 49;
 	}
 
 	srcPtr = dataPtr;
-	if (type & 0x80) {
+	if (type & 0x80) { // Frame data is compressed
 		srcPtr = (byte *) _vidBuffer;
 		type &= 0x7F;
 		if ((type == 2) && (imdW == sW)) {
@@ -768,27 +461,26 @@
 			frameUncompressor(srcPtr, dataPtr);
 	}
 
-	if (type == 2) {
-		for (i = 0; i < imdH; i++) {
+	if (type == 2) { // Whole block
+		for (int i = 0; i < imdH; i++) {
 			memcpy(imdVidMem, srcPtr, imdW);
 			srcPtr += imdW;
 			imdVidMem += sW;
 		}
-	} else if (type == 1) {
+	} else if (type == 1) { // Sparse block
 		imdVidMemBak = imdVidMem;
-		for (i = 0; i < imdH; i++) {
+		for (int i = 0; i < imdH; i++) {
 			pixWritten = 0;
 			while (pixWritten < imdW) {
 				pixCount = *srcPtr++;
-				if (pixCount & 0x80) {
-					pixCount = (pixCount & 0x7F) + 1;
-					// Just to be safe
-					pixCount = (pixWritten + pixCount) > imdW ? imdW - pixWritten : pixCount;
+				if (pixCount & 0x80) { // data
+					pixCount = MIN((pixCount & 0x7F) + 1, imdW - pixWritten);
+					memcpy(imdVidMem, srcPtr, pixCount);
+
 					pixWritten += pixCount;
-					memcpy(imdVidMem, srcPtr, pixCount);
 					imdVidMem += pixCount;
 					srcPtr += pixCount;
-				} else {
+				} else { // "hole"
 					pixCount = (pixCount + 1) % 256;
 					pixWritten += pixCount;
 					imdVidMem += pixCount;
@@ -797,33 +489,45 @@
 			imdVidMemBak += sW;
 			imdVidMem = imdVidMemBak;
 		}
-	} else if (type == 0x42) { // loc_2AFC4
-		warning("=> type == 0x42");
-	} else if ((type & 0xF) == 2) { // loc_2AFEC
-		warning("=> (type & 0xF) == 2");
-	} else { // loc_2B021
-		srcPtrBak = srcPtr;
-		for (i = 0; i < imdH; i += 2) {
+	} 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) {
-					pixCount = (pixCount & 0x7F) + 1;
-					// Just to be safe
-					pixCount = (pixWritten + pixCount) > imdW ? imdW - pixWritten : pixCount;
-					pixWritten += pixCount;
+				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 {
+				} else { // "hole"
 					pixCount = (pixCount + 1) % 256;
 					pixWritten += pixCount;
 					imdVidMem += pixCount;
 				}
 			}
-			srcPtrBak += sW + sW;
-			srcPtr = srcPtrBak;
+			imdVidMemBak += sW + sW;
+			imdVidMem = imdVidMemBak;
 		}
 	}
 }
@@ -831,8 +535,8 @@
 void ImdPlayer::frameUncompressor(byte *dest, byte *src) {
 	int i;
 	byte buf[4370];
-	int16 chunkLength;
-	int16 frameLength;
+	uint16 chunkLength;
+	uint16 frameLength;
 	uint16 bufPos1;
 	uint16 bufPos2;
 	uint16 tmp;
@@ -842,13 +546,16 @@
 
 	frameLength = READ_LE_UINT16(src);
 	src += 4;
-	bufPos1 = 4078;
-	mode = 0; // 275h (jnz +2)
+
 	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;
@@ -874,99 +581,644 @@
 		src += 2;
 		chunkLength = ((tmp & 0xF00) >> 8) + 3;
 
-		if ((mode && ((chunkLength & 0xFF) == 0x12)) || (!mode && (chunkLength == 0)))
+		if ((mode && ((chunkLength & 0xFF) == 0x12)) ||
+				(!mode && (chunkLength == 0)))
 			chunkLength = *src++ + 0x12;
 
 		bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
-		if (((tmp + chunkLength) >= 4096) || ((chunkLength + bufPos1) >= 4096)) {
+		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;
 			}
-			frameLength -= chunkLength;
-		} else if (((tmp + chunkLength) < bufPos1) || ((chunkLength + bufPos1) < bufPos2)) {
+
+		} else if (((tmp + chunkLength) < bufPos1) ||
+				((chunkLength + bufPos1) < bufPos2)) {
+
 			memcpy(dest, buf + bufPos2, chunkLength);
+			memmove(buf + bufPos1, buf + bufPos2, chunkLength);
+
 			dest += chunkLength;
-			memmove(buf + bufPos1, buf + bufPos2, chunkLength);
 			bufPos1 += chunkLength;
 			bufPos2 += chunkLength;
-			frameLength -= chunkLength;
+
 		} else {
+
 			for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
 				*dest = buf[bufPos2];
 				buf[bufPos1] = buf[bufPos2];
 			}
-			frameLength -= chunkLength;
+
 		}
+		frameLength -= chunkLength;
+
 	}
 }
 
-void ImdPlayer::play(const char *path, int16 x, int16 y, int16 startFrame, int16 frames,
-		bool fade, bool interruptible) {
+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 curFrame;
 	int endFrame;
-	int backFrame;
 
 	_vm->_util->setFrameRate(12);
-	openImd(path, 0, 0, 0, 0);
-	_vm->_video->fillRect(_vm->_draw->_frontSurface, x, y, x + _curImd->width - 1,
-			y + _curImd->height - 1, 0);
+	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 (curFrame = 0; curFrame < endFrame; curFrame++) {
-		view(_curImd, curFrame);
-		drawFrame(_curImd, curFrame, x, y);
+	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(_vm->_global->_videoMode);
-		if ((interruptible && (_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B)) ||
-				_vm->_quitRequested) {
+		_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 (curFrame = _curImd->framesCount - 1; curFrame >= endFrame; curFrame--) {
-			for (backFrame = 0; backFrame <= curFrame; backFrame++)
-				view(_curImd, backFrame);
-			drawFrame(_curImd, curFrame, x, y);
-			_vm->_video->waitRetrace(_vm->_global->_videoMode);
-			if ((interruptible && (_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B)) ||
-					_vm->_quitRequested) {
+		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();
 }
 
-int16 ImdPlayer::sub_2C825(Imd *imdPtr) {
-	warning("GOB2 Stub! sub_2C825()");
-	return 0;
+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)
+		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, (char *) _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;
+
+	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;
+
+	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) {
+			char *soundBuf =
+				(char *) (_soundBuffer + _curSoundSlice * _soundSliceSize);
+
+			if (!hasNextCmd)
+				waitEndSoundSlice();
+
+			// Next sound slice data
+			if (cmd == 0xFF00) {
+
+				if (!hasNextCmd && !_noSound) {
+					_vm->_dataIO->readData(imdPtr->handle, soundBuf,
+							_soundSliceSize);
+					_vm->_snd->convToSigned((byte *) 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) {
+					_vm->_dataIO->readData(imdPtr->handle,
+							(char *) _soundBuffer, dataLength);
+					_vm->_snd->convToSigned(_soundBuffer, dataLength);
+
+					_curSoundSlice = _soundSlicesCount - 1;
+					_soundStage = 1;
+					startSound = true;
+				} else
+					_vm->_dataIO->seekData(imdPtr->handle, dataLength, SEEK_CUR);
+
+				cmd = _vm->_dataIO->readUint16(imdPtr->handle);
+
+			// Clear sound slice
+			} else if (!hasNextCmd && (!_noSound))
+				memset(soundBuf, 0, _soundSliceSize);
+
+			if (!hasNextCmd)
+				_curSoundSlice = (_curSoundSlice + 1) % _soundSlicesCount;
+		}
+
+		// Set palette
+		if (cmd == 0xFFF4) {
+			_vm->_dataIO->seekData(imdPtr->handle, 2, SEEK_CUR);
+			retVal |= 0x10;
+			if (imdPtr->extraPalette) {
+				_vm->_dataIO->readData(imdPtr->handle,
+						(char *) imdPtr->extraPalette, 768);
+				_vm->_video->setPalette(imdPtr->extraPalette);
+			} else if (imdPtr->palette)
+				_vm->_dataIO->readData(imdPtr->handle,
+						(char *) imdPtr->palette, 768);
+			else
+				_vm->_dataIO->readData(imdPtr->handle,
+						(char *) _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,
+					(char *) _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, (char *) _frameData, cmd + 2);
+			if (imdPtr->surfDesc)
+				renderFrame(imdPtr);
+
+			retVal |= _frameData[0];
+
+		} else
+			retVal |= 0x800;
+
+	} while (hasNextCmd);
+
+	if (startSound) {
+		_vm->_snd->stopSound(0);
+		_vm->_snd->playSample(_soundDesc, -1, _soundFreq);
+		_soundStage = 2;
+	}
+
+	imdPtr->x = xBak;
+	imdPtr->y = yBak;
+	imdPtr->width = widthBak;
+	imdPtr->height = heightBak;
+
+	imdPtr->curFrame++;
+	if ((imdPtr->curFrame == (imdPtr->framesCount - 1)) && (_soundStage == 2)) {
+		// Clear the remaining sound buffer
+		if (_curSoundSlice > 0)
+			memset(_soundBuffer + _curSoundSlice * _soundSliceSize, 0,
+					_soundSliceSize * _soundSlicesCount -
+					_curSoundSlice * _soundSliceSize);
+
+		_vm->_snd->setRepeating(0);
+		_vm->_snd->waitEndPlay();
+	}
+
+	return retVal;
+}
+
+inline void ImdPlayer::waitEndSoundSlice() {
+	_vm->_video->retrace();
+	_vm->_util->delay(_soundSliceLength);
+}
+
 } // End of namespace Gob

Modified: scummvm/trunk/engines/gob/imd.h
===================================================================
--- scummvm/trunk/engines/gob/imd.h	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/imd.h	2007-03-29 17:55:39 UTC (rev 26316)
@@ -25,6 +25,7 @@
 #define GOB_IMD_H
 
 #include "gob/video.h"
+#include "gob/sound.h"
 
 namespace Gob {
 
@@ -41,7 +42,7 @@
 	};
 
 	struct Imd {
-		int16 fileHandle;
+		int16 handle;
 		int16 verMin;
 		int16 framesCount;
 		int16 x;
@@ -58,10 +59,10 @@
 		int16 stdY;
 		int16 stdWidth;
 		int16 stdHeight;
-		int32 filePos;
 		ImdCoord *frameCoords;
 		int32 frameDataSize;
 		int32 vidBufferSize;
+		Video::Color *extraPalette;
 	};
 
 #include "common/pack-end.h"	// END STRUCT PACKING
@@ -72,38 +73,65 @@
 	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 repeat, int16 flags);
+	void finishImd(Imd *&imdPtr);
+
+	int8 openImd(const char *path, int16 x, int16 y,
+			int16 startFrame, int16 flags);
 	void closeImd(void);
-	void setXY(Imd *imdPtr, int16 x, int16 y);
 
-	void play(int16 arg_0, uint16 palCmd, int16 palStart,
-			int16 playEnd, int16 palFrame, int16 arg_A);
+	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);
-	int16 view(ImdPlayer::Imd *imdPtr, int16 arg_4);
-	void drawFrame(Imd *imdPtr, int16 frame, int16 x, int16 y,
-			SurfaceDesc *dest = 0);
-	void renderframe(Imd *imdPtr);
-	void frameUncompressor(byte *dest, byte *src);
-	int16 sub_2C825(Imd *imdPtr);
 
 protected:
 	char _curFile[15];
 
 	int16 _curX;
 	int16 _curY;
+	int16 _left;
+	int16 _top;
+	int16 _right;
+	int16 _bottom;
 
-	uint16 _frameDataSize;
-	uint16 _vidBufferSize;
 	byte *_frameData;
 	byte *_vidBuffer;
 
+	bool _noSound;
+	byte *_soundBuffer;
+
+	int16 _soundFreq;
+	uint16 _soundSliceSize;
+	int16 _soundSlicesCount;
+
+	uint16 _soundSliceLength;
+	uint16 _curSoundSlice;
+	SoundDesc _soundDesc;
+
 	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

Modified: scummvm/trunk/engines/gob/init.cpp
===================================================================
--- scummvm/trunk/engines/gob/init.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/init.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -34,6 +34,7 @@
 #include "gob/game.h"
 #include "gob/sound.h"
 #include "gob/video.h"
+#include "gob/imd.h"
 
 namespace Gob {
 
@@ -55,6 +56,7 @@
 void Init::initGame(char *totName) {
 	int16 handle2;
 	int16 handle;
+	int16 imdHandle;
 	char *infBuf;
 	char *infPtr;
 	char *infEnd;
@@ -144,8 +146,7 @@
 	if (handle >= 0) {
 		// Get variables count
 		_vm->_dataIO->seekData(handle, 0x2C, SEEK_SET);
-		_vm->_dataIO->readData(handle, (char *) &varsCount, 2);
-		varsCount = FROM_LE_16(varsCount);
+		varsCount = _vm->_dataIO->readUint16(handle);
 		_vm->_dataIO->closeData(handle);
 
 		_vm->_global->_inter_variables = new char[varsCount * 4];
@@ -157,6 +158,24 @@
 
 		_vm->_cdrom->testCD(1, "GOB");
 		_vm->_cdrom->readLIC("gob.lic");
+
+		_vm->_draw->_cursorIndex = -1;
+		imdHandle = _vm->_dataIO->openData("coktel2.imd");
+		if (imdHandle >= 0) {
+			_vm->_dataIO->closeData(imdHandle);
+			_vm->_draw->initScreen();
+			_vm->_imdPlayer->play("coktel2", -1, -1, true);
+			_vm->_draw->closeScreen();
+		} else {
+			imdHandle = _vm->_dataIO->openData("coktel.imd");
+			if (imdHandle >= 0) {
+				_vm->_dataIO->closeData(imdHandle);
+				_vm->_draw->initScreen();
+				_vm->_imdPlayer->play("coktel", -1, -1, true);
+				_vm->_draw->closeScreen();
+			}
+		}
+
 		_vm->_game->start();
 
 		_vm->_cdrom->stopPlaying();

Modified: scummvm/trunk/engines/gob/inter_v1.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v1.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/inter_v1.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -2215,7 +2215,6 @@
 	int16 dataVar;
 	int16 offset;
 	int16 handle;
-	char buf[4];
 
 	evalExpr(0);
 	dataVar = _vm->_parse->parseVarIndex();
@@ -2230,14 +2229,13 @@
 	if (handle >= 0) {
 		_vm->_draw->animateCursor(4);
 		if (offset < 0)
-			_vm->_dataIO->seekData(handle, -offset - 1, 2);
+			_vm->_dataIO->seekData(handle, -offset - 1, SEEK_END);
 		else
-			_vm->_dataIO->seekData(handle, offset, 0);
+			_vm->_dataIO->seekData(handle, offset, SEEK_SET);
 
-		if (((dataVar >> 2) == 59) && (size == 4)) {
-			retSize = _vm->_dataIO->readData(handle, buf, 4);
-			WRITE_VAR(59, READ_LE_UINT32(buf));
-		} else
+		if (((dataVar >> 2) == 59) && (size == 4))
+			WRITE_VAR(59, _vm->_dataIO->readUint32(handle));
+		else
 			retSize = _vm->_dataIO->readData(handle,
 					_vm->_global->_inter_variables + dataVar, size);
 
@@ -3009,7 +3007,7 @@
 	if (_animPalDir[0] == 0)
 		return;
 
-	_vm->_video->waitRetrace(_vm->_global->_videoMode);
+	_vm->_video->waitRetrace();
 
 	if (_animPalDir[0] == -1) {
 		col = _vm->_draw->_vgaSmallPalette[_animPalLowIndex[0]];

Modified: scummvm/trunk/engines/gob/inter_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v2.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/inter_v2.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -1472,24 +1472,36 @@
 	palEnd = _vm->_parse->parseValExpr();
 	palCmd = 1 << (flags & 0x3F);
 	
-	if (!_vm->_imdPlayer->openImd(imd, x, y, startFrame, flags))
+	if (!_vm->_imdPlayer->openImd(imd, x, y, startFrame, 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;
+	}
 
 	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 (VAR(0) == (unsigned) breakKey) {
+				if (_vm->_imdPlayer->_soundStage == 2)
+					_vm->_snd->stopSound(0);
 				return;
+			}
 		}
 	}
 
@@ -1553,15 +1565,9 @@
 	_vm->_imdPlayer->_frontSurf = 21;
 	if (_vm->_imdPlayer->_frontMem) {
 		_vm->_imdPlayer->_frontMem = _vm->_draw->_frontSurface->getVidMem();
-		_vm->_video->drawSprite(_vm->_draw->_backSurface,
-				_vm->_draw->_frontSurface, 0, 0,
-				_vm->_draw->_backSurface->getWidth() - 1,
-				_vm->_draw->_backSurface->getHeight() - 1, 0, 0, 0);
+		_vm->_draw->forceBlit();
 	} else
-		_vm->_video->drawSprite(_vm->_draw->_frontSurface,
-				_vm->_draw->_backSurface, 0, 0,
-				_vm->_draw->_backSurface->getWidth() - 1,
-				_vm->_draw->_backSurface->getHeight() - 1, 0, 0, 0);
+		_vm->_draw->forceBlit(true);
 }
 
 bool Inter_v2::o2_evaluateStore(OpFuncParams &params) {
@@ -1811,7 +1817,6 @@
 	int16 dataVar;
 	int16 handle;
 	char *buf;
-	char tmp[4];
 
 	evalExpr(0);
 	dataVar = _vm->_parse->parseVarIndex();
@@ -1861,13 +1866,12 @@
 
 	_vm->_draw->animateCursor(4);
 	if (offset < 0)
-		_vm->_dataIO->seekData(handle, -offset - 1, 2);
+		_vm->_dataIO->seekData(handle, -offset - 1, SEEK_END);
 	else
-		_vm->_dataIO->seekData(handle, offset, 0);
+		_vm->_dataIO->seekData(handle, offset, SEEK_SET);
 
 	if (((dataVar >> 2) == 59) && (size == 4)) {
-		retSize = _vm->_dataIO->readData(handle, tmp, 4);
-		WRITE_VAR(59, READ_LE_UINT32(tmp));
+		WRITE_VAR(59, _vm->_dataIO->readUint32(handle));
 		// The scripts in some versions divide through 256^3 then,
 		// effectively doing a LE->BE conversion
 		if ((_vm->_platform != Common::kPlatformPC) && (VAR(59) < 256))
@@ -2037,6 +2041,8 @@
 		source = SOUND_EXT;
 
 		dataPtr = (byte *) _vm->_game->loadExtData(id, 0, 0, &dataSize);
+		if (_vm->_game->_totFileData[0x29] >= 51)
+			_vm->_snd->convToSigned(dataPtr, dataSize);
 	} else {
 		int16 totSize;
 
@@ -2069,7 +2075,7 @@
 			continue;
 
 		if (first) {
-			_vm->_video->waitRetrace(_vm->_global->_videoMode);
+			_vm->_video->waitRetrace();
 			first = false;
 		}
 

Modified: scummvm/trunk/engines/gob/mult.cpp
===================================================================
--- scummvm/trunk/engines/gob/mult.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/mult.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -336,7 +336,7 @@
 	}
 
 	if (_vm->_global->_colorCount == 256) {
-		_vm->_video->waitRetrace(_vm->_global->_videoMode);
+		_vm->_video->waitRetrace();
 
 		palPtr = _vm->_global->_pPaletteDesc->vgaPal;
 		for (_counter = 0; _counter < 16; _counter++, palPtr++)

Modified: scummvm/trunk/engines/gob/palanim.cpp
===================================================================
--- scummvm/trunk/engines/gob/palanim.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/palanim.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -176,7 +176,7 @@
 	if (allColors == 0) {
 		do {
 			stop = fadeStep(0);
-			_vm->_video->waitRetrace(_vm->_global->_videoMode);
+			_vm->_video->waitRetrace();
 
 			if (fadeV > 0)
 				_vm->_util->delay(fadeV);
@@ -190,17 +190,17 @@
 
 	if (allColors == 1) {
 		do {
-			_vm->_video->waitRetrace(_vm->_global->_videoMode);
+			_vm->_video->waitRetrace();
 			stop = fadeStep(1);
 		} while (!stop);
 
 		do {
-			_vm->_video->waitRetrace(_vm->_global->_videoMode);
+			_vm->_video->waitRetrace();
 			stop = fadeStep(2);
 		} while (!stop);
 
 		do {
-			_vm->_video->waitRetrace(_vm->_global->_videoMode);
+			_vm->_video->waitRetrace();
 			stop = fadeStep(3);
 		} while (!stop);
 

Modified: scummvm/trunk/engines/gob/parse.h
===================================================================
--- scummvm/trunk/engines/gob/parse.h	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/parse.h	2007-03-29 17:55:39 UTC (rev 26316)
@@ -59,7 +59,7 @@
 	virtual ~Parse_v1() {};
 
 	virtual int16 parseVarIndex(void);
-	virtual int16 parseValExpr(unsigned stopToken=99);
+	virtual int16 parseValExpr(unsigned stopToken = 99);
 	virtual int16 parseExpr(char stopToken, byte *resultPtr);
 };
 
@@ -69,7 +69,7 @@
 	virtual ~Parse_v2() {};
 
 	virtual int16 parseVarIndex(void);
-	virtual int16 parseValExpr(unsigned stopToken=99);
+	virtual int16 parseValExpr(unsigned stopToken = 99);
 	virtual int16 parseExpr(char stopToken, byte *resultPtr);
 };
 

Modified: scummvm/trunk/engines/gob/sound.cpp
===================================================================
--- scummvm/trunk/engines/gob/sound.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/sound.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -33,6 +33,17 @@
 
 namespace Gob {
 
+void SoundDesc::set(SoundType type, SoundSource src,
+		byte *data, uint32 dSize) {
+
+	free();
+
+	_type = type;
+	_source = src;
+	_data = _dataPtr = data;
+	_size = dSize;
+}
+
 void SoundDesc::load(SoundType type, SoundSource src,
 		byte *data, uint32 dSize) {
 
@@ -225,6 +236,12 @@
 	_curFadeSamples = 0;
 }
 
+void Snd::setRepeating(int32 repCount) {
+	Common::StackLock slock(_mutex);
+
+	_repCount = repCount;
+}
+
 void Snd::waitEndPlay(bool interruptible, bool stopComp) {
 	if (stopComp)
 		_compositionPos = -1;

Modified: scummvm/trunk/engines/gob/sound.h
===================================================================
--- scummvm/trunk/engines/gob/sound.h	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/sound.h	2007-03-29 17:55:39 UTC (rev 26316)
@@ -54,6 +54,7 @@
 	bool isId(int16 id) { return _dataPtr && _id == id; };
 	SoundType getType() { return _type; }
 
+	void set(SoundType type, SoundSource src, byte *data, uint32 dSize);
 	void load(SoundType type, SoundSource src, byte *data, uint32 dSize);
 	void free();
 	void flip();
@@ -104,8 +105,14 @@
 	void playComposition(int16 *composition, int16 freqVal,
 			SoundDesc *sndDescs = 0, int8 sndCount = 60);
 	void stopComposition();
+	void setRepeating(int32 repCount);
 	void waitEndPlay(bool interruptible = false, bool stopComp = true);
 
+	static void convToSigned(byte *buffer, int length) {
+		while (length-- > 0)
+			*buffer++ ^= 0x80;
+	}
+
 	int readBuffer(int16 *buffer, const int numSamples);
 	bool isStereo() const { return false; }
 	bool endOfData() const { return _end; }

Modified: scummvm/trunk/engines/gob/util.cpp
===================================================================
--- scummvm/trunk/engines/gob/util.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/util.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -66,7 +66,7 @@
 void Util::longDelay(uint16 msecs) {
 	uint32 time = g_system->getMillis() + msecs;
 	do {
-		_vm->_video->waitRetrace(_vm->_global->_videoMode);
+		_vm->_video->waitRetrace();
 		processInput();
 		delay(15);
 	} while (!_vm->_quitRequested && (g_system->getMillis() < time));
@@ -275,7 +275,7 @@
 void Util::waitEndFrame() {
 	int32 time;
 
-	_vm->_video->waitRetrace(_vm->_global->_videoMode);
+	_vm->_video->waitRetrace();
 
 	time = getTimeKey() - _vm->_global->_startFrameTime;
 	if ((time > 1000) || (time < 0)) {
@@ -297,7 +297,7 @@
 	processInput();
 	_vm->_video->_scrollOffsetX = x >= 0 ? x : _vm->_draw->_scrollOffsetX;
 	_vm->_video->_scrollOffsetY = y >= 0 ? y : _vm->_draw->_scrollOffsetY;
-	_vm->_video->waitRetrace(_vm->_global->_videoMode);
+	_vm->_video->waitRetrace();
 }
 
 Video::FontDesc *Util::loadFont(const char *path) {

Modified: scummvm/trunk/engines/gob/video.cpp
===================================================================
--- scummvm/trunk/engines/gob/video.cpp	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/video.cpp	2007-03-29 17:55:39 UTC (rev 26316)
@@ -152,21 +152,25 @@
 	return descPtr;
 }
 
-void Video::waitRetrace(bool mouse) {
-	uint32 time;
-
+void Video::retrace(bool mouse) {
 	if (mouse)
 		CursorMan.showMouse((_vm->_draw->_showCursor & 2) != 0);
 	if (_vm->_global->_primarySurfDesc) {
-		time = _vm->_util->getTimeKey();
 		g_system->copyRectToScreen(_vm->_global->_primarySurfDesc->getVidMem() +
 				_scrollOffsetY * _surfWidth + _scrollOffsetX, _surfWidth,
 				0, 0, 320, 200);
 		g_system->updateScreen();
-		_vm->_util->delay(MAX(1, 10 - (int)(_vm->_util->getTimeKey() - time)));
 	}
 }
 
+void Video::waitRetrace(bool mouse) {
+	uint32 time;
+
+	time = _vm->_util->getTimeKey();
+	retrace(mouse);
+	_vm->_util->delay(MAX(1, 10 - (int)(_vm->_util->getTimeKey() - time)));
+}
+
 void Video::putPixel(int16 x, int16 y, int16 color, SurfaceDesc *dest) {
 	if ((x >= dest->getWidth()) || (x < 0) ||
 	    (y >= dest->getHeight()) || (y < 0))
@@ -403,4 +407,19 @@
 		Video::setPalette(palDesc);
 }
 
+void Video::setPalette(Color *palette) {
+	Color *palBak;
+	bool setAllPalBak;
+
+	palBak = _vm->_global->_pPaletteDesc->vgaPal;
+	setAllPalBak = _vm->_global->_setAllPalette;
+
+	_vm->_global->_pPaletteDesc->vgaPal = palette;
+	_vm->_global->_setAllPalette = true;
+	setFullPalette(_vm->_global->_pPaletteDesc);
+
+	_vm->_global->_setAllPalette = setAllPalBak;
+	_vm->_global->_pPaletteDesc->vgaPal = palBak;
+}
+
 } // End of namespace Gob

Modified: scummvm/trunk/engines/gob/video.h
===================================================================
--- scummvm/trunk/engines/gob/video.h	2007-03-29 16:50:06 UTC (rev 26315)
+++ scummvm/trunk/engines/gob/video.h	2007-03-29 17:55:39 UTC (rev 26316)
@@ -104,6 +104,7 @@
 	void initPrimary(int16 mode);
 	SurfaceDesc *initSurfDesc(int16 vidMode, int16 width,
 			int16 height, int16 flags);
+	void retrace(bool mouse = true);
 	void waitRetrace(bool mouse = true);
 
 	void putPixel(int16 x, int16 y, int16 color, SurfaceDesc *dest);
@@ -137,6 +138,7 @@
 			int16 unused, int16 vidMode);
 	void setPalette(PalDesc *palDesc);
 	void setFullPalette(PalDesc *palDesc);
+	void setPalette(Color *palette);
 
 	virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth,
 			int16 srcHeight, int16 x, int16 y, int16 transp,


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