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

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Sun Apr 27 05:19:19 CEST 2008


Revision: 31750
          http://scummvm.svn.sourceforge.net/scummvm/?rev=31750&view=rev
Author:   drmccoy
Date:     2008-04-26 20:19:19 -0700 (Sat, 26 Apr 2008)

Log Message:
-----------
Implemented support for VMDs substituting object animations.
Still far from being complete (and correct), but it's a start...

- Only VMD "command" -3 is followed
- Not all animation types are working
- Timing is still off in most cases
- Offsets are generally OK, but not always
- No sound yet
- Shouldn't segfault randomly, but I'm not entirely sure ;)

Modified Paths:
--------------
    scummvm/trunk/engines/gob/coktelvideo.cpp
    scummvm/trunk/engines/gob/coktelvideo.h
    scummvm/trunk/engines/gob/game_v2.cpp
    scummvm/trunk/engines/gob/goblin.h
    scummvm/trunk/engines/gob/goblin_v2.cpp
    scummvm/trunk/engines/gob/init.cpp
    scummvm/trunk/engines/gob/inter_bargon.cpp
    scummvm/trunk/engines/gob/inter_v2.cpp
    scummvm/trunk/engines/gob/inter_v4.cpp
    scummvm/trunk/engines/gob/module.mk
    scummvm/trunk/engines/gob/mult.h
    scummvm/trunk/engines/gob/mult_v2.cpp
    scummvm/trunk/engines/gob/scenery.cpp
    scummvm/trunk/engines/gob/scenery.h
    scummvm/trunk/engines/gob/util.cpp
    scummvm/trunk/engines/gob/videoplayer.cpp
    scummvm/trunk/engines/gob/videoplayer.h

Added Paths:
-----------
    scummvm/trunk/engines/gob/goblin_v4.cpp

Modified: scummvm/trunk/engines/gob/coktelvideo.cpp
===================================================================
--- scummvm/trunk/engines/gob/coktelvideo.cpp	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/coktelvideo.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -333,41 +333,44 @@
 		g_system->delayMillis(_frameLength);
 }
 
-void Imd::copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp) {
+void Imd::copyCurrentFrame(byte *dest,
+		uint16 left, uint16 top, uint16 width, uint16 height,
+		uint16 x, uint16 y, uint16 pitch, int16 transp) {
+
 	if (!_vidMem)
 		return;
 
-	dest += width * y;
+	if (((left + width) > _width) || ((top + height) > _height))
+		return;
 
-	uint16 copyWidth = MIN<int16>(width - x, _width);
-	uint16 destPitch = width - x;
-	byte *vidMem = _vidMem;
+	dest += pitch * y;
+	byte *vidMem = _vidMem + _width * top;
 
 	if (transp < 0) {
 		// No transparency
-		if ((x > 0) || (_width != width)) {
+		if ((x > 0) || (left > 0) || (pitch != _width) || (width != _width)) {
 			// Copy row-by-row
-			for (int i = 0; i < _height; i++) {
-				dest += x;
-				memcpy(dest, vidMem, copyWidth);
-				dest += destPitch;
+			for (int i = 0; i < height; i++) {
+				byte *d = dest + x;
+				byte *s = vidMem + left;
+
+				memcpy(d, s, width);
+
+				dest += pitch;
 				vidMem += _width;
 			}
-
 		} else
 			// Dimensions fit, copy everything at once
-			memcpy(dest, _vidMem, _width * _height);
+			memcpy(dest, vidMem, width * height);
 
 		return;
 	}
 
-	// Transparency, copy per pixel
-	for (int i = 0; i < _height; i++) {
-		byte *s = vidMem;
-		byte *d = dest;
+	for (int i = 0; i < height; i++) {
+		byte *d = dest + x;
+		byte *s = vidMem + left;
 
-		d += x;
-		for (int j = 0; j < _width; j++) {
+		for (int j = 0; j < width; j++) {
 			if (*s != transp)
 				*d = *s;
 
@@ -375,9 +378,10 @@
 			d++;
 		}
 
-		dest += width;
+		dest += pitch;
 		vidMem += _width;
 	}
+
 }
 
 void Imd::deleteVidMem(bool del) {
@@ -938,9 +942,9 @@
 	} else
 		_frameLength = 1000 / _frameRate;
 
-	uint32 frameInfoOffset = _stream->readUint32LE();
+	_frameInfoOffset = _stream->readUint32LE();
 
-	_stream->seek(frameInfoOffset);
+	_stream->seek(_frameInfoOffset);
 	_frames = new Frame[_framesCount];
 	for (uint16 i = 0; i < _framesCount; i++) {
 		_frames[i].parts = new Part[_partsPerFrame];
@@ -1350,4 +1354,43 @@
 	}
 }
 
+bool Vmd::getAnchor(int16 frame, uint16 partType,
+		int16 &x, int16 &y, int16 &width, int16 &height) {
+
+	uint32 pos = _stream->pos();
+
+	_stream->seek(_frameInfoOffset);
+	// Offsets to frames
+	_stream->skip(_framesCount * 6);
+	// Jump to the specified frame
+	_stream->skip(_partsPerFrame * frame * 16);
+
+	// Find the anchor part
+	uint16 i;
+	for (i = 0; i < _partsPerFrame; i++) {
+		byte type = _stream->readByte();
+
+		if ((type == 0) || (type == partType))
+			break;
+
+		_stream->skip(15);
+	}
+
+	if (i == _partsPerFrame) {
+		// No anchor
+
+		_stream->seek(pos);
+		return false;
+	}
+
+	_stream->skip(5);
+	x = _stream->readSint16LE();
+	y = _stream->readSint16LE();
+	width = _stream->readSint16LE() - x + 1;
+	height = _stream->readSint16LE() - y + 1;
+
+	_stream->seek(pos);
+	return true;
+}
+
 } // End of namespace Gob

Modified: scummvm/trunk/engines/gob/coktelvideo.h
===================================================================
--- scummvm/trunk/engines/gob/coktelvideo.h	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/coktelvideo.h	2008-04-27 03:19:19 UTC (rev 31750)
@@ -90,6 +90,8 @@
 
 	/** Returns the features the loaded video possesses. */
 	virtual uint16 getFeatures() const = 0;
+	/** Returns the flags the loaded video possesses. */
+	virtual uint16 getFlags() const = 0;
 	/** Returns the x coordinate of the video. */
 	virtual int16 getX() const = 0;
 	/** Returns the y coordinate of the video. */
@@ -113,6 +115,10 @@
 	/** Returns the current frame's palette. */
 	virtual const byte *getPalette() const = 0;
 
+	/** Reads the video's anchor pointer */
+	virtual bool getAnchor(int16 frame, uint16 partType,
+			int16 &x, int16 &y, int16 &width, int16 &height) = 0;
+
 	/** Load a video out of a stream. */
 	virtual bool load(Common::SeekableReadStream &stream) = 0;
 	/** Unload the currently loaded video. */
@@ -148,13 +154,19 @@
 
 	/** Copy the current frame.
 	 *
-	 *  @param dest The memory to which to copy the current frame
+	 *  @param dest The memory to which to copy the current frame.
+	 *  @param left The x position within the frame.
+	 *  @param top The y position within the frame.
+	 *  @param width The width of the area to copy.
+	 *  @param height The height of the area to copy.
 	 *  @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;
+	virtual void copyCurrentFrame(byte *dest,
+			uint16 left, uint16 top, uint16 width, uint16 height,
+			uint16 x, uint16 y, uint16 pitch, int16 transp = -1) = 0;
 };
 
 /** Coktel Vision's IMD files.
@@ -165,6 +177,7 @@
 	~Imd();
 
 	uint16 getFeatures() const { return _features; }
+	uint16 getFlags() const { return _flags; }
 	int16 getX() const { return _x; }
 	int16 getY() const { return _y; }
 	int16 getWidth() const { return _width; }
@@ -175,6 +188,9 @@
 	uint32 getSyncLag() const { return _skipFrames; }
 	const byte *getPalette() const { return _palette; }
 
+	bool getAnchor(int16 frame, uint16 partType,
+			int16 &x, int16 &y, int16 &width, int16 &height) { return false; }
+
 	void setFrameRate(int16 frameRate);
 
 	bool load(Common::SeekableReadStream &stream);
@@ -192,7 +208,9 @@
 	State nextFrame();
 	void waitEndFrame();
 
-	void copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp = -1);
+	void copyCurrentFrame(byte *dest,
+			uint16 left, uint16 top, uint16 width, uint16 height,
+			uint16 x, uint16 y, uint16 pitch, int16 transp = -1);
 
 protected:
 	struct Coord {
@@ -260,6 +278,9 @@
 	Vmd();
 	~Vmd();
 
+	bool getAnchor(int16 frame, uint16 partType,
+			int16 &x, int16 &y, int16 &width, int16 &height);
+
 	bool load(Common::SeekableReadStream &stream);
 	void unload();
 
@@ -295,6 +316,7 @@
 
 	bool _hasVideo;
 
+	uint32 _frameInfoOffset;
 	uint16 _partsPerFrame;
 	Frame *_frames;
 

Modified: scummvm/trunk/engines/gob/game_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/game_v2.cpp	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/game_v2.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -272,7 +272,7 @@
 						_vm->_snd->freeSample(_soundSamples[i]);
 			}
 
-			_vm->_vidPlayer->closeVideo();
+			_vm->_vidPlayer->primaryClose();
 			if (_totToLoad[0] == 0)
 				break;
 

Modified: scummvm/trunk/engines/gob/goblin.h
===================================================================
--- scummvm/trunk/engines/gob/goblin.h	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/goblin.h	2008-04-27 03:19:19 UTC (rev 31750)
@@ -315,6 +315,20 @@
 	virtual void advMovement(Mult::Mult_Object *obj, int8 state);
 };
 
+class Goblin_v4 : public Goblin_v3 {
+public:
+	virtual void movePathFind(Mult::Mult_Object *obj,
+			Gob_Object *gobDesc, int16 nextAct);
+	virtual void moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc,
+			int16 nextAct, int16 framesCount);
+
+	Goblin_v4(GobEngine *vm);
+	virtual ~Goblin_v4() {}
+
+private:
+	int16 sub_20430(int16 state, uint16 dir);
+};
+
 } // End of namespace Gob
 
 #endif // GOB_GOBLIN_H

Modified: scummvm/trunk/engines/gob/goblin_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/goblin_v2.cpp	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/goblin_v2.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -266,7 +266,7 @@
 		if (_vm->_map->_screenWidth == 640) {
 			if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10)
 				animData->nextState = 41;
-			if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY + 2) != 10)
+			if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY) != 10)
 				animData->nextState = 7;
 		}
 		break;

Added: scummvm/trunk/engines/gob/goblin_v4.cpp
===================================================================
--- scummvm/trunk/engines/gob/goblin_v4.cpp	                        (rev 0)
+++ scummvm/trunk/engines/gob/goblin_v4.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -0,0 +1,635 @@
+/* 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/gob.h"
+#include "gob/goblin.h"
+#include "gob/global.h"
+#include "gob/mult.h"
+#include "gob/map.h"
+#include "gob/scenery.h"
+
+namespace Gob {
+
+Goblin_v4::Goblin_v4(GobEngine *vm) : Goblin_v3(vm) {
+}
+
+void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 nextAct) {
+	Mult::Mult_AnimData *animData;
+	int16 framesCount;
+	int16 gobX;
+	int16 gobY;
+	int16 gobDestX;
+	int16 gobDestY;
+	int16 destX;
+	int16 destY;
+	int16 dir;
+
+	dir = 0;
+	animData = obj->pAnimData;
+	framesCount = _vm->_scenery->getAnimLayer(animData->animation, animData->layer)->framesCount;
+	animData->newCycle = framesCount;
+	gobX = obj->goblinX;
+	gobY = obj->goblinY;
+	animData->order = gobY;
+	gobDestX = obj->gobDestX;
+	gobDestY = obj->gobDestY;
+	animData->destX = gobDestX;
+	animData->destY = gobDestY;
+	destX = obj->destX;
+	destY = obj->destY;
+
+	if (animData->pathExistence == 1) {
+		dir = _vm->_map->getDirection(gobX, gobY, destX, destY);
+		if (dir == 0)
+			animData->pathExistence = 0;
+		if ((gobX == destX) && (gobY == destY))
+			animData->pathExistence = 4;
+	} else if (animData->pathExistence == 3) {
+		if ((gobX == gobDestX) && (gobY == gobDestY)) {
+			animData->pathExistence = 4;
+			destX = gobDestX;
+			destY = gobDestY;
+		} else {
+			if (_vm->_map->checkDirectPath(obj, gobX, gobY, gobDestX, gobDestY) != 1) {
+				if ((gobX == destX) && (gobY == destY)) {
+					if (obj->nearestWayPoint > obj->nearestDest) {
+						_vm->_map->optimizePoints(obj, gobX, gobY);
+						destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x;
+						destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y;
+						if (_vm->_map->checkDirectPath(obj, gobX, gobY, destX, destY) == 3) {
+							WRITE_VAR(56, 1);
+							animData->pathExistence = 0;
+						}
+						if (obj->nearestWayPoint > obj->nearestDest)
+							obj->nearestWayPoint--;
+					} else if (obj->nearestWayPoint < obj->nearestDest) {
+						_vm->_map->optimizePoints(obj, gobX, gobY);
+						destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x;
+						destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y;
+						if (_vm->_map->checkDirectPath(obj, gobX, gobY, destX, destY) == 3) {
+							WRITE_VAR(56, 1);
+							animData->pathExistence = 0;
+						}
+						if (obj->nearestWayPoint < obj->nearestDest)
+							obj->nearestWayPoint++;
+					} else {
+						if ((_vm->_map->checkDirectPath(obj, gobX, gobY, gobDestX, gobDestY) == 3) &&
+								(_vm->_map->getPass(gobDestX, gobDestY) != 0)) {
+							destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x;
+							destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y;
+							WRITE_VAR(56, 1);
+						} else {
+							animData->pathExistence = 1;
+							destX = gobDestX;
+							destY = gobDestY;
+						}
+					}
+				}
+			} else {
+				destX = gobDestX;
+				destY = gobDestY;
+			}
+			dir = _vm->_map->getDirection(gobX, gobY, destX, destY);
+		}
+	}
+
+	obj->goblinX = gobX;
+	obj->goblinY = gobY;
+	obj->gobDestX = gobDestX;
+	obj->gobDestY = gobDestY;
+	obj->destX = destX;
+	obj->destY = destY;
+
+	if (_vm->_map->_widthByte == 4) {
+		switch (dir) {
+		case Map::kDirNW:
+			animData->nextState = sub_20430(animData->state, Map::kDirNW);
+			if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) &&
+					(animData->nextState == 1))
+				animData->nextState = 40;
+			if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10)
+				animData->nextState = sub_20430(animData->state, Map::kDirNW);
+			break;
+
+		case Map::kDirN:
+			animData->nextState =
+				(animData->curLookDir == 2) ? 2 : sub_20430(animData->state, Map::kDirN);
+			if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) {
+				if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) {
+					if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) == 10)
+						animData->nextState = 42;
+					else
+						animData->nextState = 2;
+				} else
+					animData->nextState = 40;
+			}
+			if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20) &&
+			    (animData->nextState == 2))
+				animData->nextState = 38;
+			if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19) &&
+			   (animData->nextState == 2))
+				animData->nextState = 26;
+			break;
+
+		case Map::kDirNE:
+			animData->nextState = sub_20430(animData->state, Map::kDirNE);
+			if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) &&
+			    (animData->nextState == 3))
+				animData->nextState = 42;
+			if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) != 10)
+				animData->nextState = sub_20430(animData->state, Map::kDirNE);
+			break;
+
+		case Map::kDirW:
+			animData->nextState = sub_20430(animData->state, Map::kDirW);
+			break;
+
+		case Map::kDirE:
+			animData->nextState = sub_20430(animData->state, Map::kDirE);
+			break;
+
+		case Map::kDirSW:
+			animData->nextState = sub_20430(animData->state, Map::kDirSW);
+			if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) &&
+			    (animData->nextState == 7))
+				animData->nextState = 41;
+			if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY) != 10)
+				animData->nextState = sub_20430(animData->state, Map::kDirSW);
+			break;
+
+		case Map::kDirS:
+			animData->nextState =
+				(animData->curLookDir == 6) ? 6 : sub_20430(animData->state, Map::kDirS);
+			if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) {
+				if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY + 2) != 10) {
+					if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY + 2) == 10)
+						animData->nextState = 43;
+					else
+						animData->nextState = 6;
+				} else
+					animData->nextState = 41;
+			}
+			// loc_20AAD
+			if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20) &&
+			    (animData->nextState == 6))
+				animData->nextState = 39;
+			if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19) &&
+			   (animData->nextState == 6))
+				animData->nextState = 27;
+			break;
+
+		case Map::kDirSE:
+			animData->nextState = sub_20430(animData->state, Map::kDirSE);
+			if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) &&
+			    (animData->nextState == 5))
+				animData->nextState = 43;
+			if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY) != 10)
+				animData->nextState = sub_20430(animData->state, Map::kDirSE);
+			break;
+
+		default:
+			// loc_20D18
+			switch (animData->state) {
+			case 0:
+			case 8:
+				// loc_21134
+				animData->nextState = 8;
+				break;
+
+			case 1:
+			case 10:
+			case 40:
+				// loc_21152
+				animData->nextState = 10;
+				break;
+
+			case 2:
+			case 29:
+				// loc_2113E
+				animData->nextState = 29;
+				break;
+
+			case 3:
+			case 11:
+			case 42:
+				// loc_2115C
+				animData->nextState = 11;
+				break;
+
+			case 4:
+			case 9:
+				// loc_2112A
+				animData->nextState = 9;
+				break;
+
+			case 5:
+			case 30:
+			case 43:
+				// loc_21166
+				animData->nextState = 30;
+				break;
+
+			case 6:
+			case 28:
+				// loc_21148
+				animData->nextState = 28;
+				break;
+
+			case 7:
+			case 31:
+			case 41:
+				// loc_21170
+				animData->nextState = 31;
+				break;
+			}
+			break;
+		}
+	} else {
+		switch (dir) {
+		case Map::kDirNW:
+			animData->nextState = 1;
+			if (_vm->_map->_screenWidth == 640) {
+				if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10)
+					animData->nextState = 40;
+				if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10)
+					animData->nextState = 1;
+			}
+			break;
+
+		case Map::kDirN:
+			animData->nextState =
+				(animData->curLookDir == 2) ? 2 : rotateState(animData->curLookDir, 2);
+			if (_vm->_map->_screenWidth == 640) {
+				if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) {
+					if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) {
+						if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) == 10)
+							animData->nextState = 42;
+						else
+							animData->nextState = 2;
+					} else
+						animData->nextState = 40;
+				} else if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20)
+					animData->nextState = 38;
+				else if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19)
+					animData->nextState = 26;
+			}
+			break;
+
+		case Map::kDirNE:
+			animData->nextState =	3;
+			if (_vm->_map->_screenWidth == 640) {
+				if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10)
+					animData->nextState = 42;
+				if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) != 10)
+					animData->nextState = 3;
+			}
+			break;
+
+		case Map::kDirW:
+			animData->nextState = rotateState(animData->curLookDir, 0);
+			break;
+
+		case Map::kDirE:
+			animData->nextState = rotateState(animData->curLookDir, 4);
+			break;
+
+		case Map::kDirSW:
+			animData->nextState = 7;
+			if (_vm->_map->_screenWidth == 640) {
+				if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10)
+					animData->nextState = 41;
+				if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY + 2) != 10)
+					animData->nextState = 7;
+			}
+			break;
+
+		case Map::kDirS:
+			animData->nextState =
+				(animData->curLookDir == 6) ? 6 : rotateState(animData->curLookDir, 6);
+			if (_vm->_map->_screenWidth == 640) {
+				if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20)
+					animData->nextState = 39;
+				else if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19)
+					animData->nextState = 27;
+			}
+			break;
+
+		case Map::kDirSE:
+			animData->nextState = 5;
+			if (_vm->_map->_screenWidth == 640) {
+				if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10)
+					animData->nextState = 43;
+				if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY + 2) != 10)
+					animData->nextState = 5;
+			}
+			break;
+
+		default:
+			switch (animData->curLookDir) {
+			case 0:
+				animData->nextState = 8;
+				break;
+			case 1:
+				animData->nextState = 10;
+				break;
+			case 2:
+				animData->nextState = 29;
+				break;
+			case 3:
+				animData->nextState = 11;
+				break;
+			case 4:
+				animData->nextState = 9;
+				break;
+			case 5:
+				animData->nextState = 30;
+				break;
+			case 6:
+				animData->nextState = 28;
+				break;
+			case 7:
+				animData->nextState = 31;
+				break;
+			}
+			break;
+		}
+	}
+}
+
+void Goblin_v4::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc,
+		int16 nextAct, int16 framesCount) {
+	Mult::Mult_AnimData *animData;
+	int16 gobX;
+	int16 gobY;
+	int16 animation;
+	int16 state;
+	int16 layer;
+
+	if (!obj->goblinStates)
+		return;
+
+	movePathFind(obj, 0, 0);
+	playSounds(obj);
+
+	animData = obj->pAnimData;
+
+	framesCount = _vm->_scenery->getAnimLayer(animData->animation, animData->layer)->framesCount;
+
+	if (animData->isPaused == 0)
+		animData->frame++;
+
+	switch (animData->stateType) {
+	case 0:
+	case 1:
+		animData->isPaused = 0;
+		break;
+
+	case 4:
+		if (animData->frame == 0)
+			animData->isPaused = 1;
+		break;
+
+	case 6:
+		if (animData->frame >= framesCount)
+			animData->isPaused = 1;
+		break;
+	}
+
+	switch (animData->state) {
+	case 0:
+	case 1:
+	case 7:
+	case 13:
+	case 16:
+	case 23:
+		animData->curLookDir = 0;
+		break;
+
+	case 2:
+	case 15:
+	case 18:
+	case 21:
+		animData->curLookDir = 2;
+		break;
+
+	case 3:
+	case 4:
+	case 5:
+	case 12:
+	case 19:
+	case 22:
+		animData->curLookDir = 4;
+		break;
+
+	case 6:
+	case 14:
+	case 17:
+	case 20:
+		animData->curLookDir = 6;
+		break;
+
+	case 8:
+	case 9:
+	case 28:
+	case 29:
+		if (animData->pathExistence == 4)
+			animData->pathExistence = 5;
+		break;
+	}
+
+	if ((animData->newState != -1) && (animData->frame == framesCount) &&
+			(animData->newState != animData->state)) {
+		animData->nextState = animData->newState;
+		animData->newState = -1;
+		animData->state = animData->nextState;
+
+		Scenery::AnimLayer *animLayer =
+			_vm->_scenery->getAnimLayer(animData->animation, animData->layer);
+		*obj->pPosX += animLayer->animDeltaX;
+		*obj->pPosY += animLayer->animDeltaY;
+
+		animation = obj->goblinStates[animData->nextState][0].animation;
+		layer = obj->goblinStates[animData->nextState][0].layer;
+		animData->layer = layer;
+		animData->animation = animation;
+		animData->frame = 0;
+	} else {
+		if (isMovement(animData->state)) {
+			state = animData->nextState;
+			if (animData->frame == ((framesCount + 1) / 2)) {
+				gobX = obj->goblinX;
+				gobY = obj->goblinY;
+
+				advMovement(obj, state);
+
+				if (animData->state != state) {
+					animation = obj->goblinStates[state][0].animation;
+					layer = obj->goblinStates[state][0].layer;
+					animData->layer = layer;
+					animData->animation = animation;
+					animData->frame = 0;
+					animData->state = state;
+					_vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0);
+					if (_vm->_map->_bigTiles)
+						*obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) -
+							(_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (gobY + 1) / 2;
+					else
+						*obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) -
+							(_vm->_scenery->_animBottom - _vm->_scenery->_animTop);
+					*obj->pPosX = gobX * _vm->_map->_tilesWidth;
+				}
+			}
+		}
+
+		if (animData->frame >= framesCount) {
+			state = animData->nextState;
+			animation = obj->goblinStates[state][0].animation;
+			layer = obj->goblinStates[state][0].layer;
+			animData->layer = layer;
+			animData->animation = animation;
+			animData->frame = 0;
+			animData->state = state;
+			gobX = obj->goblinX;
+			gobY = obj->goblinY;
+
+			advMovement(obj, state);
+
+			_vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0);
+			if (_vm->_map->_bigTiles)
+				*obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) -
+					(_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (gobY + 1) / 2;
+			else
+				*obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) -
+					(_vm->_scenery->_animBottom - _vm->_scenery->_animTop);
+			*obj->pPosX = gobX * _vm->_map->_tilesWidth;
+		}
+	}
+}
+
+int16 Goblin_v4::sub_20430(int16 state, uint16 dir) {
+	static const int16 word_3F25E[8][8] = {
+		{0, 1, 10, 10, 10, 31, 31, 7},
+		{0, 1, 2, 29, 29, 29, 8, 8},
+		{10, 1, 2, 3, 11, 11, 11, 10},
+		{29, 29, 2, 3, 4, 9, 9, 9},
+		{30, 11, 11, 3, 4, 5, 30, 30},
+		{28, 28, 9, 9, 4, 5, 6, 28},
+		{31, 31, 31, 30, 30, 5, 6, 7},
+		{0, 8, 8, 8, 28, 28, 6, 7}
+	};
+	int16 dx = state, cx = 0;
+
+	switch (state) {
+	case 0:
+	case 8:
+		// loc_20447
+		dx = 0;
+		break;
+
+	case 1:
+	case 10:
+	case 40:
+		// loc_2044B
+		dx = 1;
+		break;
+
+	case 3:
+	case 11:
+	case 42:
+		// loc_20455
+		dx = 3;
+		break;
+
+	case 5:
+	case 30:
+	case 43:
+		// loc_2045F
+		dx = 5;
+		break;
+
+	case 7:
+	case 31:
+	case 41:
+		// loc_20469
+		dx = 7;
+		break;
+
+	case 9:
+		// loc_2045A
+		dx = 4;
+		break;
+
+	case 28:
+		// loc_20464
+		dx = 6;
+		break;
+
+	case 29:
+		// loc_20450
+		dx = 2;
+		break;
+	}
+
+	// loc_2046C
+
+
+	switch (dir) {
+	case Map::kDirNW:
+		cx = 1;
+		break;
+
+	case Map::kDirN:
+		cx = 2;
+		break;
+	
+	case Map::kDirNE:
+		cx = 3;
+		break;
+	
+	case Map::kDirW:
+		cx = 0;
+		break;
+	
+	case Map::kDirE:
+		cx = 4;
+		break;
+	
+	case Map::kDirSW:
+		cx = 7;
+		break;
+
+	case Map::kDirS:
+		cx = 6;
+		break;
+
+	case Map::kDirSE:
+		cx = 5;
+		break;
+	}
+
+	return word_3F25E[dx][cx];
+}
+
+} // End of namespace Gob


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

Modified: scummvm/trunk/engines/gob/init.cpp
===================================================================
--- scummvm/trunk/engines/gob/init.cpp	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/init.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -181,9 +181,9 @@
 
 			_vm->_util->longDelay(200); // Letting everything settle
 
-			if (_vm->_vidPlayer->openVideo("coktel.imd")) {
-				_vm->_vidPlayer->play();
-				_vm->_vidPlayer->closeVideo();
+			if (_vm->_vidPlayer->primaryOpen("coktel.imd")) {
+				_vm->_vidPlayer->primaryPlay();
+				_vm->_vidPlayer->primaryClose();
 			}
 
 			_vm->_draw->closeScreen();

Modified: scummvm/trunk/engines/gob/inter_bargon.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_bargon.cpp	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/inter_bargon.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -717,16 +717,16 @@
 }
 
 void Inter_Bargon::oBargon_intro0(OpGobParams &params) {
-	if (_vm->_vidPlayer->openVideo("scaa", 0, 160)) {
-		_vm->_vidPlayer->play(0, 92, 27, 0, 0, 0);
-		_vm->_vidPlayer->closeVideo();
+	if (_vm->_vidPlayer->primaryOpen("scaa", 0, 160)) {
+		_vm->_vidPlayer->primaryPlay(0, 92, 27, 0, 0, 0);
+		_vm->_vidPlayer->primaryClose();
 	}
 }
 
 void Inter_Bargon::oBargon_intro1(OpGobParams &params) {
-	if (_vm->_vidPlayer->openVideo("scaa", 0, 160)) {
-		_vm->_vidPlayer->play(0, -1, 27, 0, 0, 0, 0, 0, true, 23);
-		_vm->_vidPlayer->closeVideo();
+	if (_vm->_vidPlayer->primaryOpen("scaa", 0, 160)) {
+		_vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0, 0, 0, true, 23);
+		_vm->_vidPlayer->primaryClose();
 	}
 }
 
@@ -819,44 +819,44 @@
 }
 
 void Inter_Bargon::oBargon_intro4(OpGobParams &params) {
-	if (_vm->_vidPlayer->openVideo("scba", 191, 54)) {
-		_vm->_vidPlayer->play(0, -1, 27, 0, 0, 0, 0, 0, true);
-		_vm->_vidPlayer->closeVideo();
+	if (_vm->_vidPlayer->primaryOpen("scba", 191, 54)) {
+		_vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0, 0, 0, true);
+		_vm->_vidPlayer->primaryClose();
 	}
 }
 
 void Inter_Bargon::oBargon_intro5(OpGobParams &params) {
-	if (_vm->_vidPlayer->openVideo("scbb", 191, 54)) {
-		_vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
-		_vm->_vidPlayer->closeVideo();
+	if (_vm->_vidPlayer->primaryOpen("scbb", 191, 54)) {
+		_vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0);
+		_vm->_vidPlayer->primaryClose();
 	}
 }
 
 void Inter_Bargon::oBargon_intro6(OpGobParams &params) {
-	if (_vm->_vidPlayer->openVideo("scbc", 191, 54)) {
-		_vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
-		_vm->_vidPlayer->closeVideo();
+	if (_vm->_vidPlayer->primaryOpen("scbc", 191, 54)) {
+		_vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0);
+		_vm->_vidPlayer->primaryClose();
 	}
 }
 
 void Inter_Bargon::oBargon_intro7(OpGobParams &params) {
-	if (_vm->_vidPlayer->openVideo("scbf", 191, 54)) {
-		_vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
-		_vm->_vidPlayer->closeVideo();
+	if (_vm->_vidPlayer->primaryOpen("scbf", 191, 54)) {
+		_vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0);
+		_vm->_vidPlayer->primaryClose();
 	}
 }
 
 void Inter_Bargon::oBargon_intro8(OpGobParams &params) {
-	if (_vm->_vidPlayer->openVideo("scbc", 191, 54)) {
-		_vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
-		_vm->_vidPlayer->closeVideo();
+	if (_vm->_vidPlayer->primaryOpen("scbc", 191, 54)) {
+		_vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0);
+		_vm->_vidPlayer->primaryClose();
 	}
 }
 
 void Inter_Bargon::oBargon_intro9(OpGobParams &params) {
-	if (_vm->_vidPlayer->openVideo("scbd", 191, 54)) {
-		_vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
-		_vm->_vidPlayer->closeVideo();
+	if (_vm->_vidPlayer->primaryOpen("scbd", 191, 54)) {
+		_vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0);
+		_vm->_vidPlayer->primaryClose();
 	}
 }
 

Modified: scummvm/trunk/engines/gob/inter_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v2.cpp	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/inter_v2.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -988,13 +988,11 @@
 			_vm->_global->_inter_execPtr++;
 	}
 
-	if (_vm->_goblin->_gobsCount <= objIndex)
-		return;
-
 	Mult::Mult_Object &obj = _vm->_mult->_objects[objIndex];
 	Mult::Mult_AnimData &objAnim = *(obj.pAnimData);
-	if (objAnim.animType == 100) {
 
+	if ((objAnim.animType == 100) && (objIndex < _vm->_goblin->_gobsCount)) {
+
 		val = *(obj.pPosX) % 256;
 		obj.destX = val;
 		obj.gobDestX = val;
@@ -1029,7 +1027,7 @@
 				((obj.goblinY + 1) / 2);
 		*(obj.pPosX) = obj.goblinX * _vm->_map->_tilesWidth;
 
-	} else if (objAnim.animType == 101) {
+	} else if ((objAnim.animType == 101) && (objIndex < _vm->_goblin->_gobsCount)) {
 
 		layer = objAnim.layer;
 		animation = obj.goblinStates[layer][0].animation;
@@ -1048,6 +1046,21 @@
 		}
 		_vm->_scenery->updateAnim(layer, 0, animation, 0,
 				*(obj.pPosX), *(obj.pPosY), 0);
+
+	} else if ((objAnim.animType != 100) && (objAnim.animType != 101)) {
+
+		if ((*(obj.pPosX) == -1234) && (*(obj.pPosY) == -4321)) {
+
+			if (obj.videoSlot > 0)
+				_vm->_vidPlayer->slotClose(obj.videoSlot - 1);
+
+			obj.videoSlot = 0;
+			obj.lastLeft = -1;
+			obj.lastTop = -1;
+			obj.lastBottom = -1;
+			obj.lastRight = -1;
+		}
+
 	}
 }
 
@@ -1519,7 +1532,7 @@
 	palEnd = _vm->_parse->parseValExpr();
 	palCmd = 1 << (flags & 0x3F);
 
-	if ((imd[0] != 0) && !_vm->_vidPlayer->openVideo(imd, x, y, flags)) {
+	if ((imd[0] != 0) && !_vm->_vidPlayer->primaryOpen(imd, x, y, flags)) {
 		WRITE_VAR(11, -1);
 		return;
 	}
@@ -1532,12 +1545,12 @@
 
 	if (startFrame >= 0) {
 		_vm->_game->_preventScroll = true;
-		_vm->_vidPlayer->play(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
+		_vm->_vidPlayer->primaryPlay(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
 		_vm->_game->_preventScroll = false;
 	}
 
 	if (close)
-		_vm->_vidPlayer->closeVideo();
+		_vm->_vidPlayer->primaryClose();
 }
 
 void Inter_v2::o2_getImdInfo() {

Modified: scummvm/trunk/engines/gob/inter_v4.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v4.cpp	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/inter_v4.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -544,10 +544,10 @@
 
 	static const OpcodeGoblinEntryV4 opcodesGoblin[71] = {
 		/* 00 */
-		OPCODE(o2_loadInfogramesIns),
-		OPCODE(o2_startInfogrames),
-		OPCODE(o2_stopInfogrames),
 		{NULL, ""},
+		{NULL, ""},
+		{NULL, ""},
+		{NULL, ""},
 		/* 04 */
 		{NULL, ""},
 		{NULL, ""},
@@ -555,9 +555,9 @@
 		{NULL, ""},
 		/* 08 */
 		{NULL, ""},
-		OPCODE(o2_playInfogrames),
 		{NULL, ""},
 		{NULL, ""},
+		{NULL, ""},
 		/* 0C */
 		{NULL, ""},
 		{NULL, ""},
@@ -592,7 +592,7 @@
 		{NULL, ""},
 		{NULL, ""},
 		{NULL, ""},
-		OPCODE(o2_handleGoblins),
+		{NULL, ""},
 		/* 28 */
 		{NULL, ""},
 		{NULL, ""},
@@ -723,7 +723,6 @@
 	bool close;
 
 	evalExpr(0);
-	_vm->_global->_inter_resStr[8] = 0;
 	strncpy0(fileName, _vm->_global->_inter_resStr, 127);
 
 	x = _vm->_parse->parseValExpr();
@@ -740,8 +739,20 @@
 	if (lastFrame == -1) {
 		close = true;
 	} else if (lastFrame == -3) {
-		warning("Woodruff Stub: Video/Music command -3: Play background video %s", fileName);
-//		return;
+		warning("Woodruff Stub: Video/Music command -3: Play background video %s, %d, %d", fileName, x, y);
+
+		_vm->_mult->_objects[startFrame].pAnimData->animation = -startFrame - 1;
+
+		if (_vm->_mult->_objects[startFrame].videoSlot > 0)
+			_vm->_vidPlayer->slotClose(_vm->_mult->_objects[startFrame].videoSlot - 1);
+		_vm->_mult->_objects[startFrame].videoSlot = _vm->_vidPlayer->slotOpen(fileName) + 1;
+
+		if (x != -1) {
+			*_vm->_mult->_objects[startFrame].pPosX = x;
+			*_vm->_mult->_objects[startFrame].pPosY = y;
+		}
+
+		return;
 	} else if (lastFrame == -4) {
 		warning("Woodruff Stub: Video/Music command -4: Play background video %s", fileName);
 		return;
@@ -767,19 +778,19 @@
 		close = false;
 	}
 
-	if ((fileName[0] != 0) && !_vm->_vidPlayer->openVideo(fileName, x, y, flags)) {
+	if ((fileName[0] != 0) && !_vm->_vidPlayer->primaryOpen(fileName, x, y, flags)) {
 		WRITE_VAR(11, -1);
 		return;
 	}
 
 	if (startFrame >= 0) {
 		_vm->_game->_preventScroll = true;
-		_vm->_vidPlayer->play(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
+		_vm->_vidPlayer->primaryPlay(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
 		_vm->_game->_preventScroll = false;
 	}
 
 	if (close)
-		_vm->_vidPlayer->closeVideo();
+		_vm->_vidPlayer->primaryClose();
 }
 
 } // End of namespace Gob

Modified: scummvm/trunk/engines/gob/module.mk
===================================================================
--- scummvm/trunk/engines/gob/module.mk	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/module.mk	2008-04-27 03:19:19 UTC (rev 31750)
@@ -18,6 +18,7 @@
 	goblin_v1.o \
 	goblin_v2.o \
 	goblin_v3.o \
+	goblin_v4.o \
 	coktelvideo.o \
 	videoplayer.o \
 	init.o \

Modified: scummvm/trunk/engines/gob/mult.h
===================================================================
--- scummvm/trunk/engines/gob/mult.h	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/mult.h	2008-04-27 03:19:19 UTC (rev 31750)
@@ -36,7 +36,7 @@
 #include "common/pack-start.h"	// START STRUCT PACKING
 
 	struct Mult_AnimData {
-		uint8 animation;
+		int8 animation;
 		uint8 layer;
 		uint8 frame;
 		int8 animType;
@@ -104,6 +104,7 @@
 		int16 newTop;
 		int16 newRight;
 		int16 newBottom;
+		uint32 videoSlot;
 	} PACKED_STRUCT;
 
 	struct Mult_StaticKey {

Modified: scummvm/trunk/engines/gob/mult_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/mult_v2.cpp	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/mult_v2.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -463,8 +463,7 @@
 			int obj = _multData->animObjs[index][i];
 
 			if ((obj != -1) && (obj != 1024))
-				_objects[obj].pAnimData->animTypeBak =
-					_objects[obj].pAnimData->animType;
+				_objects[obj].pAnimData->animTypeBak = _objects[obj].pAnimData->animType;
 		}
 	}
 
@@ -472,8 +471,10 @@
 		_multData->animKeysIndices[index][i] = 0;
 
 		for (int j = 0; j < _multData->animKeysCount[i]; j++)
-			if (_multData->animKeys[i][j].frame == startFrame)
+			if (_multData->animKeys[i][j].frame >= startFrame) {
 				_multData->animKeysIndices[index][i] = j;
+				break;
+			}
 	}
 
 	if (_multData->animDirection == -1) {
@@ -487,6 +488,7 @@
 	firstFrame = (_multData->animDirection == 1) ? startFrame : stopFrame;
 	for (int i = 0; i < 4; i++) {
 		_multData->imdKeysIndices[index][i] = 0;
+
 		for (int j = 0; j < _multData->imdKeysCount[i]; j++)
 			if (_multData->imdKeys[i][j].frame >= firstFrame) {
 				_multData->imdKeysIndices[index][i] = j;
@@ -675,28 +677,54 @@
 
 void Mult_v2::newCycleAnim(Mult_Object &animObj) {
 	Mult_AnimData &animData = *(animObj.pAnimData);
-	int nAnim = animData.animation;
-	int nLayer = animData.layer;
+	Scenery::AnimLayer *animLayer = 0;
 
-	if (_vm->_scenery->getAnimLayersCount(nAnim) <= nLayer)
-		return;
+	if (animData.animation >= 0) {
+		int nAnim = animData.animation, nLayer = animData.layer;
 
-	Scenery::AnimLayer *animLayer = _vm->_scenery->getAnimLayer(nAnim, nLayer);
+		if (_vm->_scenery->getAnimLayersCount(nAnim) <= nLayer)
+			return;
 
+		animLayer = _vm->_scenery->getAnimLayer(nAnim, nLayer);
+	}
+
 	if (animData.animType == 4) {
+		// loc_1E091
 		animData.frame = 0;
 		animData.isPaused = 1;
+		if (animData.animation < 0)
+			warning("TODO: AnimType 4, animation: %d", animData.animation);
 		return;
 	}
 
+	if (animData.animType == 12)
+		animData.animType = 11;
+
+	if (animData.animType == 11) {
+		if (animData.isBusy != 0) {
+			warning("TODO: AnimType 11");
+		}
+		return;
+	}
+
 	if (animData.animType != 8)
 		animData.frame++;
 
-	if (animData.frame < animLayer->framesCount) {
-		animData.newCycle = 0;
-		return;
+	if (animData.animation < 0) {
+		if ((animObj.videoSlot > 0) &&
+		    (_vm->_vidPlayer->getCurrentFrame(animObj.videoSlot - 1) <
+		      _vm->_vidPlayer->getFramesCount(animObj.videoSlot - 1))) {
+			animData.newCycle = 0;
+			return;
+		}
+	} else {
+		if (animData.frame < animLayer->framesCount) {
+			animData.newCycle = 0;
+			return;
+		}
 	}
 
+
 	switch (animData.animType) {
 	case 0:
 		animData.frame = 0;
@@ -728,6 +756,12 @@
 	case 7:
 		animData.frame--;
 		animData.isPaused = 1;
+		if ((animData.animation < 0) && (animObj.videoSlot > 0)) {
+			if (_vm->_vidPlayer->getFlags(animObj.videoSlot - 1) & 0x1000) {
+				_vm->_vidPlayer->slotClose(animObj.videoSlot - 1);
+				animObj.videoSlot = 0;
+			}
+		}
 		break;
 	}
 	animData.newCycle = 1;
@@ -897,6 +931,9 @@
 			Mult_Object &animObj1 = *_renderObjs[orderArray[i]];
 			Mult_AnimData &animData1 = *(animObj1.pAnimData);
 
+			if (!animObj1.goblinStates)
+				continue;
+
 			for (int j = i+1; j < orderArrayPos; j++) {
 				Mult_Object &animObj2 = *_renderObjs[orderArray[j]];
 				Mult_AnimData &animData2 = *(animObj2.pAnimData);
@@ -1043,7 +1080,7 @@
 		x = y = -1;
 
 	if (key.imdFile == -1) {
-		_vm->_vidPlayer->closeVideo();
+		_vm->_vidPlayer->primaryClose();
 		_vm->_game->_preventScroll = false;
 		return;
 	}
@@ -1061,11 +1098,11 @@
 		if ((lastFrame - palFrame) < startFrame)
 			if (!(key.flags & 0x4000)) {
 				_vm->_game->_preventScroll = false;
-				_vm->_vidPlayer->closeVideo();
+				_vm->_vidPlayer->primaryClose();
 				return;
 			}
 
-	if (!_vm->_vidPlayer->openVideo(imdFile, x, y, flags)) {
+	if (!_vm->_vidPlayer->primaryOpen(imdFile, x, y, flags)) {
 		_vm->_game->_preventScroll = false;
 		return;
 	}
@@ -1077,7 +1114,7 @@
 		lastFrame = _vm->_vidPlayer->getFramesCount() - 1;
 
 	baseFrame = startFrame % (lastFrame - palFrame + 1);
-	_vm->_vidPlayer->play(baseFrame + palFrame, baseFrame + palFrame, 0,
+	_vm->_vidPlayer->primaryPlay(baseFrame + palFrame, baseFrame + palFrame, 0,
 			flags & 0x7F, palStart, palEnd, palFrame, lastFrame);
 }
 

Modified: scummvm/trunk/engines/gob/scenery.cpp
===================================================================
--- scummvm/trunk/engines/gob/scenery.cpp	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/scenery.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -33,6 +33,8 @@
 #include "gob/draw.h"
 #include "gob/game.h"
 #include "gob/inter.h"
+#include "gob/map.h"
+#include "gob/videoplayer.h"
 
 namespace Gob {
 
@@ -454,6 +456,7 @@
 	ptr->layers = new AnimLayer[ptr->layersCount];
 	ptr->pieces = new PieceDesc*[picsCount];
 	ptr->piecesFromExt = new bool[picsCount];
+	ptr->sizes = new uint16[picsCount];
 
 	for (i = 0; i < ptr->layersCount; i++) {
 		int16 offset = READ_LE_UINT16(dataPtr + i * 2);
@@ -492,13 +495,19 @@
 	for (i = 0; i < picsCount; i++) {
 		pictDescId = _vm->_inter->load16();
 		if (pictDescId >= 30000) {
+			uint32 size;
+
 			ptr->pieces[i] =
-				(PieceDesc *) _vm->_game->loadExtData(pictDescId, 0, 0);
+				(PieceDesc *) _vm->_game->loadExtData(pictDescId, 0, 0, &size);
 			ptr->piecesFromExt[i] = true;
+			ptr->sizes[i] = size / 8;
 		} else {
+			int16 size;
+
 			ptr->pieces[i] =
-				(PieceDesc *) _vm->_game->loadTotResource(pictDescId);
+				(PieceDesc *) _vm->_game->loadTotResource(pictDescId, &size);
 			ptr->piecesFromExt[i] = false;
+			ptr->sizes[i] = size / 8;
 		}
 
 		width = _vm->_inter->load16();
@@ -561,6 +570,7 @@
 	delete[] _animations[index].layers;
 	delete[] _animations[index].pieces;
 	delete[] _animations[index].piecesFromExt;
+	delete[] _animations[index].sizes;
 
 	_animPictCount[index] = 0;
 }
@@ -592,6 +602,135 @@
 	int16 destX;
 	int16 destY;
 
+	if (animation < 0) {
+		// Object video
+
+		if (flags & 1) { // Do capture
+			updateAnim(layer, frame, animation, 0, drawDeltaX, drawDeltaY, 0);
+
+			if (_toRedrawLeft == -12345)
+				return;
+
+			_vm->_game->capturePush(_toRedrawLeft, _toRedrawTop,
+					_toRedrawRight - _toRedrawLeft + 1,
+					_toRedrawBottom - _toRedrawTop + 1);
+
+			*_pCaptureCounter = *_pCaptureCounter + 1;
+		}
+
+		Mult::Mult_Object &obj = _vm->_mult->_objects[-animation - 1];
+
+		if (!_vm->_vidPlayer->slotIsOpen(obj.videoSlot - 1)) {
+			_toRedrawLeft = -1234;
+			return;
+		}
+
+		// Seek to frame
+		while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) <= frame)
+			_vm->_vidPlayer->slotPlay(obj.videoSlot - 1);
+
+		destX = 0;
+		destY = 0;
+		left = *(obj.pPosX);
+		top = *(obj.pPosY);
+		right = left + _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - 1;
+		bottom = top + _vm->_vidPlayer->getHeight(obj.videoSlot - 1) - 1;
+
+		if (flags & 2) {
+			if (left < _vm->_mult->_animLeft) {
+				destX += _vm->_mult->_animLeft - left;
+				left = _vm->_mult->_animLeft;
+			}
+
+			if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right)
+				right = _vm->_mult->_animLeft + _vm->_mult->_animWidth - 1;
+
+			if (top < _vm->_mult->_animTop) {
+				destY += _vm->_mult->_animTop - top;
+				top = _vm->_mult->_animTop;
+			}
+
+			if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom)
+				bottom = _vm->_mult->_animTop + _vm->_mult->_animHeight - 1;
+
+		} else if (flags & 4) {
+			if (left < _toRedrawLeft) {
+				destX += _toRedrawLeft - left;
+				left = _toRedrawLeft;
+			}
+
+			if (right > _toRedrawRight)
+				right = _toRedrawRight;
+
+			if (top < _toRedrawTop) {
+				destY += _toRedrawTop - top;
+				top = _toRedrawTop;
+			}
+
+			if (bottom > _toRedrawBottom)
+				bottom = _toRedrawBottom;
+
+		} else {
+			_toRedrawTop = top;
+			_toRedrawLeft = left;
+			_toRedrawRight = right;
+			_toRedrawBottom = bottom;
+		}
+
+		if (doDraw) {
+			if ((left > right) || (top > bottom))
+				return;
+
+			if (left < _vm->_mult->_animLeft) {
+				destX += _vm->_mult->_animLeft - left;
+				left = _vm->_mult->_animLeft;
+			}
+
+			if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right)
+				right = _vm->_mult->_animLeft + _vm->_mult->_animWidth - 1;
+
+			if (top < _vm->_mult->_animTop) {
+				destY += _vm->_mult->_animTop - top;
+				top = _vm->_mult->_animTop;
+			}
+
+			if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom)
+				bottom = _vm->_mult->_animTop + _vm->_mult->_animHeight - 1;
+
+			_vm->_draw->_spriteLeft = destX;
+			_vm->_draw->_spriteTop = destY;
+			_vm->_draw->_spriteRight = right - left + 1;
+			_vm->_draw->_spriteBottom = bottom - top + 1;
+			_vm->_draw->_destSpriteX = left;
+			_vm->_draw->_destSpriteY = top;
+			_vm->_draw->_transparency = layer;
+			if (layer & 0x80)
+				_vm->_draw->_spriteLeft = _vm->_vidPlayer->getWidth(obj.videoSlot - 1)  -
+					(destX + _vm->_draw->_spriteRight);
+
+			_vm->_vidPlayer->slotCopyFrame(obj.videoSlot - 1, _vm->_draw->_backSurface->getVidMem(),
+					_vm->_draw->_spriteLeft, _vm->_draw->_spriteTop,
+					_vm->_draw->_spriteRight, _vm->_draw->_spriteBottom,
+					_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY,
+					_vm->_draw->_backSurface->getWidth(),
+					(_vm->_draw->_transparency != 0) ? 0 : -1);
+
+			_vm->_draw->invalidateRect(_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY,
+					_vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1,
+					_vm->_draw->_destSpriteY + _vm->_draw->_spriteBottom - 1);
+
+		}
+
+		if (flags & 4) {
+			_animLeft = _toRedrawLeft = left;
+			_animTop = _toRedrawTop = top;
+			_animRight = _toRedrawRight = right;
+			_animBottom = _toRedrawBottom = bottom;
+		}
+
+		return;
+	}
+
 	if ((_animPictCount[animation] == 0) || (layer < 0))
 		return;
 	if (layer >= _animations[animation].layersCount)
@@ -670,6 +809,16 @@
 
 		pictIndex = (pictIndex & 15) - 1;
 
+		if ((pictIndex == 0xFFFF) || (_animPictCount[animation] <= pictIndex)) {
+			warning("Scenery::updateAnim: pictIndex out of range");
+			return;
+		}
+
+		if (_animations[animation].sizes[pictIndex] <= pieceIndex) {
+			warning("Scenery::updateAnim: pieceIndex out of range");
+			continue;
+		}
+
 		left = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].left);
 		right = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].right);
 		top = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].top);

Modified: scummvm/trunk/engines/gob/scenery.h
===================================================================
--- scummvm/trunk/engines/gob/scenery.h	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/scenery.h	2008-04-27 03:19:19 UTC (rev 31750)
@@ -92,6 +92,7 @@
 		AnimLayer *layers;
 		PieceDesc **pieces;
 		bool *piecesFromExt;
+		uint16 *sizes;
 		Animation() : layersCount(0), layers(0), pieces(0),
 			              piecesFromExt(0) {}
 	};

Modified: scummvm/trunk/engines/gob/util.cpp
===================================================================
--- scummvm/trunk/engines/gob/util.cpp	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/util.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -331,12 +331,12 @@
 void Util::setScrollOffset(int16 x, int16 y) {
 	processInput();
 
-	if(x >= 0)
+	if (x >= 0)
 		_vm->_video->_scrollOffsetX = x; 
 	else
 		_vm->_video->_scrollOffsetX = _vm->_draw->_scrollOffsetX;
 
-	if(y >= 0)
+	if (y >= 0)
 		_vm->_video->_scrollOffsetY = y; 
 	else
 		_vm->_video->_scrollOffsetY = _vm->_draw->_scrollOffsetY;

Modified: scummvm/trunk/engines/gob/videoplayer.cpp
===================================================================
--- scummvm/trunk/engines/gob/videoplayer.cpp	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/videoplayer.cpp	2008-04-27 03:19:19 UTC (rev 31750)
@@ -32,29 +32,105 @@
 #include "gob/game.h"
 #include "gob/palanim.h"
 #include "gob/inter.h"
+#include "gob/map.h"
 
 namespace Gob {
 
 const char *VideoPlayer::_extensions[] = { "IMD", "VMD" };
 
+VideoPlayer::Video::Video(GobEngine *vm) : _vm(vm), _fileName(0), _stream(0), _video(0) {
+}
+
+VideoPlayer::Video::~Video() {
+	close();
+}
+
+bool VideoPlayer::Video::open(const char *fileName, Type which) {
+	close();
+
+	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) {
+		_video = new Vmd();
+	} else {
+		warning("Couldn't open video \"%s\": Invalid video Type", fileName);
+		close();
+		return false;
+	}
+
+	if (!_video->load(*_stream)) {
+		warning("While loading video \"%s\"", fileName);
+		close();
+		return false;
+	}
+
+	_fileName = new char[strlen(fileName) + 1];
+	strcpy(_fileName, fileName);
+
+	return true;
+}
+
+void VideoPlayer::Video::close() {
+	delete _video;
+	delete _stream;
+	delete[] _fileName;
+
+	_video = 0;
+	_stream = 0;
+	_fileName = 0;
+	memset(&_state, 0, sizeof(CoktelVideo::State));
+}
+
+bool VideoPlayer::Video::isOpen() const {
+	return (_video != 0);
+}
+
+const char *VideoPlayer::Video::getFileName() const {
+	return _fileName ? _fileName : "";
+}
+
+CoktelVideo *VideoPlayer::Video::getVideo() {
+	return _video;
+}
+
+const CoktelVideo *VideoPlayer::Video::getVideo() const {
+	return _video;
+}
+
+CoktelVideo::State VideoPlayer::Video::getState() const {
+	return _state;
+}
+
+CoktelVideo::State VideoPlayer::Video::nextFrame() {
+	if (_video)
+		_state = _video->nextFrame();
+
+	return _state;
+}
+
 VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm) {
-	_curFile[0] = 0;
-	_stream = 0;
-	_video = 0;
+	_primaryVideo = new Video(vm);
 	_backSurf = false;
 	_needBlit = false;
 	_noCursorSwitch = false;
 }
 
 VideoPlayer::~VideoPlayer() {
-	closeVideo();
+	delete _primaryVideo;
+	for (uint i = 0; i < _videoSlots.size(); i++)
+		delete _videoSlots[i];
 }
 
-bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Type which) {
-	char fileName[256];
-
-	strncpy0(fileName, video, 250);
-
+bool VideoPlayer::findFile(char *fileName, Type &which) {
 	char *extStart = strrchr(fileName, '.');
 	// There's no empty extension
 	if (extStart == (fileName + strlen(fileName) - 1)) {
@@ -112,33 +188,22 @@
 
 	}
 
-	if (scumm_strnicmp(_curFile, fileName, strlen(fileName))) {
-		closeVideo();
+	return true;
+}
 
-		int16 handle = _vm->_dataIO->openData(fileName);
+bool VideoPlayer::primaryOpen(const char *videoFile, int16 x, int16 y,
+		int16 flags, Type which) {
 
-		if (handle < 0) {
-			warning("Couldn't open video \"%s\": No such file", fileName);
-			return false;
-		}
+	char fileName[256];
 
-		_stream = _vm->_dataIO->openAsStream(handle, true);
+	strncpy0(fileName, videoFile, 250);
 
-		if (which == kVideoTypeIMD) {
-			_video = new Imd();
-		} else if (which == kVideoTypeVMD) {
-			_video = new Vmd();
-		} else {
-			warning("Couldn't open video \"%s\": Invalid video Type", fileName);
-			closeVideo();
-			return false;
-		}
+	if (!findFile(fileName, which))
+		return false;
 
-		if (!_video->load(*_stream)) {
-			warning("While loading video \"%s\"", fileName);
-			closeVideo();
+	if (scumm_strnicmp(_primaryVideo->getFileName(), fileName, strlen(fileName))) {
+		if (!_primaryVideo->open(fileName, which))
 			return false;
-		}
 
 		// WORKAROUND: In some rare cases, the cursor should still be
 		// displayed while a video is playing.
@@ -153,53 +218,54 @@
 				_noCursorSwitch = true;
 		}
 
-		strcpy(_curFile, fileName);
-
 		if (!(flags & kFlagNoVideo)) {
 			_backSurf = ((flags & kFlagFrontSurface) == 0);
 			SurfaceDesc::Ptr surf = _vm->_draw->_spritesArray[_backSurf ? 21 : 20];
-			_video->setVideoMemory(surf->getVidMem(), surf->getWidth(), surf->getHeight());
+			_primaryVideo->getVideo()->setVideoMemory(surf->getVidMem(),
+					surf->getWidth(), surf->getHeight());
 		} else
-			_video->setVideoMemory();
+			_primaryVideo->getVideo()->setVideoMemory();
 
 		_needBlit = ((flags & kFlagUseBackSurfaceContent) != 0) && ((flags & kFlagFrontSurface) != 0);
 
-		_video->enableSound(*_vm->_mixer);
+		_primaryVideo->getVideo()->enableSound(*_vm->_mixer);
 	}
 
-	if (!_video)
+	if (!_primaryVideo->isOpen())
 		return false;
 
-	_video->setFrameRate(_vm->_util->getFrameRate());
-	_video->setXY(x, y);
-	WRITE_VAR(7, _video->getFramesCount());
+	_primaryVideo->getVideo()->setFrameRate(_vm->_util->getFrameRate());
+	_primaryVideo->getVideo()->setXY(x, y);
+	WRITE_VAR(7, _primaryVideo->getVideo()->getFramesCount());
 
 	return true;
 }
 
-void VideoPlayer::play(int16 startFrame, int16 lastFrame, int16 breakKey,
+void VideoPlayer::primaryPlay(int16 startFrame, int16 lastFrame, int16 breakKey,
 		uint16 palCmd, int16 palStart, int16 palEnd,
 		int16 palFrame, int16 endFrame, bool fade, int16 reverseTo) {
 
-	if (!_video)
+	if (!_primaryVideo->isOpen())
 		return;
 
+	CoktelVideo &video = *(_primaryVideo->getVideo());
+
 	breakKey = 27;
 	if (startFrame < 0)
-		startFrame = _video->getCurrentFrame();
+		startFrame = video.getCurrentFrame();
 	if (lastFrame < 0)
-		lastFrame = _video->getFramesCount() - 1;
+		lastFrame = video.getFramesCount() - 1;
 	if (palFrame < 0)
 		palFrame = startFrame;
 	if (endFrame < 0)
 		endFrame = lastFrame;
 	palCmd &= 0x3F;
 
-	if (_video->getCurrentFrame() != startFrame) {
-		if (_video->getFeatures() & CoktelVideo::kFeaturesSound)
-			startFrame = _video->getCurrentFrame();
+	if (video.getCurrentFrame() != startFrame) {
+		if (video.getFeatures() & CoktelVideo::kFeaturesSound)
+			startFrame = video.getCurrentFrame();
 		else
-			_video->seekFrame(startFrame);
+			video.seekFrame(startFrame);
 	}
 
 	_vm->_draw->_showCursor = _noCursorSwitch ? 3 : 0;
@@ -217,38 +283,158 @@
 		}
 
 		if (!_noCursorSwitch)
-			_video->waitEndFrame();
+			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);
+		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);
 			}
 			if (!_noCursorSwitch)
-				_video->waitEndFrame();
+				video.waitEndFrame();
 		}
 	}
 }
 
-int16 VideoPlayer::getFramesCount() const {
-	if (!_video)
-		return 0;
+void VideoPlayer::primaryClose() {
+	_primaryVideo->close();
+}
 
-	return _video->getFramesCount();
+int VideoPlayer::slotOpen(const char *videoFile, Type which) {
+	Video *video = new Video(_vm);
+	char fileName[256];
+
+	strncpy0(fileName, videoFile, 250);
+
+	if (!findFile(fileName, which)) {
+		delete video;
+		return -1;
+	}
+
+	if (!video->open(fileName, which)) {
+		delete video;
+		return -1;
+	}
+
+	video->getVideo()->setVideoMemory();
+	video->getVideo()->disableSound();
+
+	_videoSlots.push_back(video);
+
+	WRITE_VAR(7, video->getVideo()->getFramesCount());
+
+	return _videoSlots.size() - 1;
 }
 
-int16 VideoPlayer::getCurrentFrame() const {
-	if (!_video)
-		return 0;
+void VideoPlayer::slotPlay(int slot, int16 frame) {
+	if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+		return;
 
-	return _video->getCurrentFrame();
+	CoktelVideo &video = *(_videoSlots[slot]->getVideo());
+
+	if (frame < 0)
+		frame = video.getCurrentFrame();
+
+	if (video.getCurrentFrame() != frame)
+		video.seekFrame(frame);
+
+	_videoSlots[slot]->nextFrame();
+	WRITE_VAR(11, frame);
 }
 
+void VideoPlayer::slotClose(int slot) {
+	if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+		return;
+
+	delete _videoSlots[slot];
+	_videoSlots.remove_at(slot);
+}
+
+void VideoPlayer::slotCopyFrame(int slot, byte *dest,
+		uint16 left, uint16 top, uint16 width, uint16 height,
+		uint16 x, uint16 y, uint16 pitch, int16 transp) {
+
+	if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+		return;
+
+	_videoSlots[slot]->getVideo()->copyCurrentFrame(dest,
+			left, top, width, height, x, y, pitch, transp);
+}
+
+void VideoPlayer::slotCopyPalette(int slot, int16 palStart, int16 palEnd) {
+	if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+		return;
+
+	copyPalette(*(_videoSlots[slot]->getVideo()), palStart, palEnd);
+}
+
+bool VideoPlayer::slotIsOpen(int slot) const {
+	if ((slot >= 0) && (((uint) slot) < _videoSlots.size()))
+		return true;
+
+	return false;
+}
+
+const VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) const {
+	if (slot < 0) {
+		if (_primaryVideo->isOpen())
+			return _primaryVideo;
+	} else if (((uint) slot) < _videoSlots.size())
+		return _videoSlots[slot];
+
+	return 0;
+}
+
+uint16 VideoPlayer::getFlags(int slot) const {
+	const Video *video = getVideoBySlot(slot);
+
+	if (video)
+		return video->getVideo()->getFlags();
+
+	return 0;
+}
+
+int16 VideoPlayer::getFramesCount(int slot) const {
+	const Video *video = getVideoBySlot(slot);
+
+	if (video)
+		return video->getVideo()->getFramesCount();
+
+	return 0;
+}
+
+int16 VideoPlayer::getCurrentFrame(int slot) const {
+	const Video *video = getVideoBySlot(slot);
+
+	if (video)
+		return video->getVideo()->getCurrentFrame();
+
+	return 0;
+}
+
+int16 VideoPlayer::getWidth(int slot) const {
+	const Video *video = getVideoBySlot(slot);
+
+	if (video)
+		return video->getVideo()->getWidth();
+
+	return 0;
+}
+
+int16 VideoPlayer::getHeight(int slot) const {
+	const Video *video = getVideoBySlot(slot);
+
+	if (video)
+		return video->getVideo()->getHeight();
+
+	return 0;
+}
+
 bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
 		uint16 palCmd, int16 palStart, int16 palEnd,
 		int16 palFrame, int16 endFrame) {
@@ -260,7 +446,7 @@
 		_vm->_draw->_applyPal = true;
 
 		if (palCmd >= 4)
-			copyPalette(palStart, palEnd);
+			copyPalette(*(_primaryVideo->getVideo()), palStart, palEnd);
 	}
 
 	if (modifiedPal && (palCmd == 8) && !_backSurf)
@@ -270,7 +456,7 @@
 	if (_needBlit)
 		_vm->_draw->forceBlit();
 
-	CoktelVideo::State state = _video->nextFrame();
+	CoktelVideo::State state = _primaryVideo->nextFrame();
 	WRITE_VAR(11, frame);
 
 	if (_needBlit)
@@ -285,7 +471,7 @@
 	}
 
 	if (state.flags & CoktelVideo::kStatePalette) {
-		copyPalette(palStart, palEnd);
+		copyPalette(*(_primaryVideo->getVideo()), palStart, palEnd);
 
 		if (!_backSurf)
 			_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
@@ -311,7 +497,7 @@
 	_vm->_util->processInput();
 
 	if (_vm->_quitRequested) {
-		_video->disableSound();
+		_primaryVideo->getVideo()->disableSound();
 		return true;
 	}
 
@@ -321,7 +507,7 @@
 
 		_vm->_inter->storeKey(_vm->_util->checkKey());
 		if (VAR(0) == (unsigned) breakKey) {
-			_video->disableSound();
+			_primaryVideo->getVideo()->disableSound();
 			return true;
 		}
 	}
@@ -329,26 +515,37 @@
 	return false;
 }
 
-void VideoPlayer::copyPalette(int16 palStart, int16 palEnd) {
-	if ((palStart == -1) || (palEnd == -1))
-		memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
-				_video->getPalette(), 768);
+void VideoPlayer::copyPalette(CoktelVideo &video, int16 palStart, int16 palEnd) {
+	if ((palStart != -1) && (palEnd != -1))
+		memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) + palStart * 3,
+				video.getPalette() + palStart * 3,
+				(palEnd - palStart + 1) * 3);
 	else
-		memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) +
-				palStart * 3, _video->getPalette() + palStart * 3,
-				(palEnd - palStart + 1) * 3);
+		memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal, video.getPalette(), 768);
 }
 
-void VideoPlayer::writeVideoInfo(const char *video, int16 varX, int16 varY,
+void VideoPlayer::writeVideoInfo(const char *videoFile, 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();
+	if (primaryOpen(videoFile)) {
+		int16 x, y, width, height;
+
+		if ((VAR_OFFSET(varX) != 0xFFFFFFFF) ||
+		    !_primaryVideo->getVideo()->getAnchor(1, 2, x, y, width, height)) {
+
+			x = _primaryVideo->getVideo()->getX();
+			y = _primaryVideo->getVideo()->getY();
+			width = _primaryVideo->getVideo()->getWidth();
+			height = _primaryVideo->getVideo()->getHeight();
+		}
+
+		WRITE_VAR_OFFSET(varX, x);
+		WRITE_VAR_OFFSET(varY, y);
+		WRITE_VAR_OFFSET(varFrames, _primaryVideo->getVideo()->getFramesCount());
+		WRITE_VAR_OFFSET(varWidth, width);
+		WRITE_VAR_OFFSET(varHeight, height);
+
+		primaryClose();
 	} else {
 		WRITE_VAR_OFFSET(varX, -1);
 		WRITE_VAR_OFFSET(varY, -1);
@@ -358,13 +555,4 @@
 	}
 }
 
-void VideoPlayer::closeVideo() {
-	delete _video;
-	delete _stream;
-
-	_video = 0;
-	_stream = 0;
-	*_curFile = 0;
-}
-
 } // End of namespace Gob

Modified: scummvm/trunk/engines/gob/videoplayer.h
===================================================================
--- scummvm/trunk/engines/gob/videoplayer.h	2008-04-27 00:50:13 UTC (rev 31749)
+++ scummvm/trunk/engines/gob/videoplayer.h	2008-04-27 03:19:19 UTC (rev 31750)
@@ -26,6 +26,8 @@
 #ifndef GOB_VIDEOPLAYER_H
 #define GOB_VIDEOPLAYER_H
 
+#include "common/array.h"
+
 #include "gob/coktelvideo.h"
 #include "gob/dataio.h"
 
@@ -51,34 +53,75 @@
 	VideoPlayer(GobEngine *vm);
 	~VideoPlayer();
 
-	bool openVideo(const char *video, int16 x = -1, int16 y = -1,
+	bool primaryOpen(const char *videoFile, int16 x = -1, int16 y = -1,
 			int16 flags = kFlagFrontSurface, Type which = kVideoTypeTry);
-
-	void play(int16 startFrame = -1, int16 lastFrame = -1, int16 breakKey = 27,
+	void primaryPlay(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);
+	void primaryClose();
 
-	int16 getFramesCount() const;
-	int16 getCurrentFrame() const;
-	void writeVideoInfo(const char *video, int16 varX, int16 varY,
+	int slotOpen(const char *videoFile, Type which = kVideoTypeTry);
+	void slotPlay(int slot, int16 frame = -1);
+	void slotClose(int slot);
+	void slotCopyFrame(int slot, byte *dest,
+			uint16 left, uint16 top, uint16 width, uint16 height,
+			uint16 x, uint16 y, uint16 pitch, int16 transp = -1);
+	void slotCopyPalette(int slot, int16 palStart = -1, int16 palEnd = -1);
+
+	bool slotIsOpen(int slot) const;
+
+	uint16 getFlags(int slot = -1) const;
+	int16 getFramesCount(int slot = -1) const;
+	int16 getCurrentFrame(int slot = -1) const;
+	int16 getWidth(int slot = -1) const;
+	int16 getHeight(int slot = -1) const;
+
+	void writeVideoInfo(const char *videoFile, int16 varX, int16 varY,
 			int16 varFrames, int16 varWidth, int16 varHeight);
 
-	void closeVideo();
+private:
+	class Video {
+		public:
+			Video(GobEngine *vm);
+			~Video();
 
-private:
+			bool open(const char *fileName, Type which);
+			void close();
+
+			bool isOpen() const;
+
+			const char *getFileName() const;
+			CoktelVideo *getVideo();
+			const CoktelVideo *getVideo() const;
+			CoktelVideo::State getState() const;
+
+			CoktelVideo::State nextFrame();
+
+		private:
+			GobEngine *_vm;
+
+			char *_fileName;
+			DataStream *_stream;
+			CoktelVideo *_video;
+			CoktelVideo::State _state;
+	};
+
 	static const char *_extensions[];
 
 	GobEngine *_vm;
 
-	char _curFile[256];
-	DataStream *_stream;
-	CoktelVideo *_video;
+	Common::Array<Video *> _videoSlots;
+	Video *_primaryVideo;
 	bool _backSurf;
 	bool _needBlit;
 	bool _noCursorSwitch;
 
-	void copyPalette(int16 palStart = -1, int16 palEnd = -1);
+	bool findFile(char *fileName, Type &which);
+
+	const Video *getVideoBySlot(int slot = -1) const;
+
+	void copyPalette(CoktelVideo &video, int16 palStart = -1, int16 palEnd = -1);
 	bool doPlay(int16 frame, int16 breakKey,
 			uint16 palCmd, int16 palStart, int16 palEnd,
 			int16 palFrame, int16 endFrame);


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