aboutsummaryrefslogtreecommitdiff
path: root/engines/gob
diff options
context:
space:
mode:
authorSven Hesse2008-04-27 03:19:19 +0000
committerSven Hesse2008-04-27 03:19:19 +0000
commitab1a3b0cc89686fa2e9ef864a429ae27ed7b2d2f (patch)
tree201eb24a9d3c98d641bb44dd811d69ba2a882ec4 /engines/gob
parent1d167da633a7dd666bb946156dd9e0ec29be2b53 (diff)
downloadscummvm-rg350-ab1a3b0cc89686fa2e9ef864a429ae27ed7b2d2f.tar.gz
scummvm-rg350-ab1a3b0cc89686fa2e9ef864a429ae27ed7b2d2f.tar.bz2
scummvm-rg350-ab1a3b0cc89686fa2e9ef864a429ae27ed7b2d2f.zip
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 ;) svn-id: r31750
Diffstat (limited to 'engines/gob')
-rw-r--r--engines/gob/coktelvideo.cpp85
-rw-r--r--engines/gob/coktelvideo.h28
-rw-r--r--engines/gob/game_v2.cpp2
-rw-r--r--engines/gob/goblin.h14
-rw-r--r--engines/gob/goblin_v2.cpp2
-rw-r--r--engines/gob/goblin_v4.cpp635
-rw-r--r--engines/gob/init.cpp6
-rw-r--r--engines/gob/inter_bargon.cpp48
-rw-r--r--engines/gob/inter_v2.cpp29
-rw-r--r--engines/gob/inter_v4.cpp33
-rw-r--r--engines/gob/module.mk1
-rw-r--r--engines/gob/mult.h3
-rw-r--r--engines/gob/mult_v2.cpp67
-rw-r--r--engines/gob/scenery.cpp153
-rw-r--r--engines/gob/scenery.h1
-rw-r--r--engines/gob/util.cpp4
-rw-r--r--engines/gob/videoplayer.cpp366
-rw-r--r--engines/gob/videoplayer.h67
18 files changed, 1351 insertions, 193 deletions
diff --git a/engines/gob/coktelvideo.cpp b/engines/gob/coktelvideo.cpp
index c6286fba3b..d508dc75f9 100644
--- a/engines/gob/coktelvideo.cpp
+++ b/engines/gob/coktelvideo.cpp
@@ -333,41 +333,44 @@ void Imd::waitEndFrame() {
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 @@ void Imd::copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 t
d++;
}
- dest += width;
+ dest += pitch;
vidMem += _width;
}
+
}
void Imd::deleteVidMem(bool del) {
@@ -938,9 +942,9 @@ bool Vmd::load(Common::SeekableReadStream &stream) {
} 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 @@ void Vmd::deDPCM(byte *soundBuf, byte *dataBuf, int16 &init, uint32 n) {
}
}
+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
diff --git a/engines/gob/coktelvideo.h b/engines/gob/coktelvideo.h
index 84271073f6..4f9543e8d0 100644
--- a/engines/gob/coktelvideo.h
+++ b/engines/gob/coktelvideo.h
@@ -90,6 +90,8 @@ public:
/** 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 @@ public:
/** 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 @@ public:
/** 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 @@ public:
~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 @@ public:
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 @@ public:
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 @@ public:
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 @@ protected:
bool _hasVideo;
+ uint32 _frameInfoOffset;
uint16 _partsPerFrame;
Frame *_frames;
diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp
index c69db45f15..45542541e3 100644
--- a/engines/gob/game_v2.cpp
+++ b/engines/gob/game_v2.cpp
@@ -272,7 +272,7 @@ void Game_v2::playTot(int16 skipPlay) {
_vm->_snd->freeSample(_soundSamples[i]);
}
- _vm->_vidPlayer->closeVideo();
+ _vm->_vidPlayer->primaryClose();
if (_totToLoad[0] == 0)
break;
diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h
index 0da4b5ace5..f7ac4aa549 100644
--- a/engines/gob/goblin.h
+++ b/engines/gob/goblin.h
@@ -315,6 +315,20 @@ protected:
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
diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp
index c9e155ad08..8af4015c1b 100644
--- a/engines/gob/goblin_v2.cpp
+++ b/engines/gob/goblin_v2.cpp
@@ -266,7 +266,7 @@ void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16
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;
diff --git a/engines/gob/goblin_v4.cpp b/engines/gob/goblin_v4.cpp
new file mode 100644
index 0000000000..0defd32289
--- /dev/null
+++ b/engines/gob/goblin_v4.cpp
@@ -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
diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp
index f38d5ac115..4d184c53d3 100644
--- a/engines/gob/init.cpp
+++ b/engines/gob/init.cpp
@@ -181,9 +181,9 @@ void Init::initGame(const char *totName) {
_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();
diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp
index 0de8245dea..702950d539 100644
--- a/engines/gob/inter_bargon.cpp
+++ b/engines/gob/inter_bargon.cpp
@@ -717,16 +717,16 @@ const char *Inter_Bargon::getOpcodeGoblinDesc(int i) {
}
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_intro3(OpGobParams &params) {
}
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();
}
}
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 46d40d1553..9b474a08d6 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -988,12 +988,10 @@ void Inter_v2::o2_loadMultObject() {
_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;
@@ -1029,7 +1027,7 @@ void Inter_v2::o2_loadMultObject() {
((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 @@ void Inter_v2::o2_loadMultObject() {
}
_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 @@ void Inter_v2::o2_playImd() {
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 @@ void Inter_v2::o2_playImd() {
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() {
diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp
index d2269e5b2c..71c0f293ec 100644
--- a/engines/gob/inter_v4.cpp
+++ b/engines/gob/inter_v4.cpp
@@ -544,9 +544,9 @@ void Inter_v4::setupOpcodes() {
static const OpcodeGoblinEntryV4 opcodesGoblin[71] = {
/* 00 */
- OPCODE(o2_loadInfogramesIns),
- OPCODE(o2_startInfogrames),
- OPCODE(o2_stopInfogrames),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
{NULL, ""},
/* 04 */
{NULL, ""},
@@ -555,7 +555,7 @@ void Inter_v4::setupOpcodes() {
{NULL, ""},
/* 08 */
{NULL, ""},
- OPCODE(o2_playInfogrames),
+ {NULL, ""},
{NULL, ""},
{NULL, ""},
/* 0C */
@@ -592,7 +592,7 @@ void Inter_v4::setupOpcodes() {
{NULL, ""},
{NULL, ""},
{NULL, ""},
- OPCODE(o2_handleGoblins),
+ {NULL, ""},
/* 28 */
{NULL, ""},
{NULL, ""},
@@ -723,7 +723,6 @@ void Inter_v4::o4_playVmdOrMusic() {
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 @@ void Inter_v4::o4_playVmdOrMusic() {
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 @@ void Inter_v4::o4_playVmdOrMusic() {
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
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index 8a428b4d34..734996ddd5 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -18,6 +18,7 @@ MODULE_OBJS := \
goblin_v1.o \
goblin_v2.o \
goblin_v3.o \
+ goblin_v4.o \
coktelvideo.o \
videoplayer.o \
init.o \
diff --git a/engines/gob/mult.h b/engines/gob/mult.h
index 90f6e61f9a..9d43435184 100644
--- a/engines/gob/mult.h
+++ b/engines/gob/mult.h
@@ -36,7 +36,7 @@ public:
#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 @@ public:
int16 newTop;
int16 newRight;
int16 newBottom;
+ uint32 videoSlot;
} PACKED_STRUCT;
struct Mult_StaticKey {
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index 37c360d53a..95617a704a 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -463,8 +463,7 @@ void Mult_v2::multSub(uint16 multIndex) {
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 @@ void Mult_v2::multSub(uint16 multIndex) {
_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 @@ void Mult_v2::multSub(uint16 multIndex) {
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::drawAnims(bool &stop) { // loc_50D5
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;
+
+ if (_vm->_scenery->getAnimLayersCount(nAnim) <= nLayer)
+ return;
- Scenery::AnimLayer *animLayer = _vm->_scenery->getAnimLayer(nAnim, nLayer);
+ 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 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) {
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 @@ void Mult_v2::animate() {
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 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir,
x = y = -1;
if (key.imdFile == -1) {
- _vm->_vidPlayer->closeVideo();
+ _vm->_vidPlayer->primaryClose();
_vm->_game->_preventScroll = false;
return;
}
@@ -1061,11 +1098,11 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir,
if ((lastFrame - palFrame) < startFrame)
if (!(key.flags & 0x4000)) {
_vm->_game->_preventScroll = false;
- _vm->_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 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir,
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);
}
diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp
index 5979927dfa..7338dab15b 100644
--- a/engines/gob/scenery.cpp
+++ b/engines/gob/scenery.cpp
@@ -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 @@ int16 Scenery::loadAnim(char search) {
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 @@ int16 Scenery::loadAnim(char search) {
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 @@ void Scenery::freeAnim(int16 index) {
delete[] _animations[index].layers;
delete[] _animations[index].pieces;
delete[] _animations[index].piecesFromExt;
+ delete[] _animations[index].sizes;
_animPictCount[index] = 0;
}
@@ -592,6 +602,135 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
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 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
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);
diff --git a/engines/gob/scenery.h b/engines/gob/scenery.h
index 290d67d2d5..a1a1304d4d 100644
--- a/engines/gob/scenery.h
+++ b/engines/gob/scenery.h
@@ -92,6 +92,7 @@ public:
AnimLayer *layers;
PieceDesc **pieces;
bool *piecesFromExt;
+ uint16 *sizes;
Animation() : layersCount(0), layers(0), pieces(0),
piecesFromExt(0) {}
};
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index 6ca694c11a..7ed2fb044b 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -331,12 +331,12 @@ void Util::waitEndFrame() {
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;
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index c3cecea318..25b80c89d9 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -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::VideoPlayer(GobEngine *vm) : _vm(vm) {
- _curFile[0] = 0;
- _stream = 0;
+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) {
+ _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 @@ bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Ty
}
- 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 @@ bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Ty
_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,36 +283,156 @@ void VideoPlayer::play(int16 startFrame, int16 lastFrame, int16 breakKey,
}
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();
+}
+
+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;
+}
+
+void VideoPlayer::slotPlay(int slot, int16 frame) {
+ if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+ return;
+
+ 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);
- return _video->getFramesCount();
+ if (video)
+ return video->getVideo()->getWidth();
+
+ return 0;
}
-int16 VideoPlayer::getCurrentFrame() const {
- if (!_video)
- return 0;
+int16 VideoPlayer::getHeight(int slot) const {
+ const Video *video = getVideoBySlot(slot);
+
+ if (video)
+ return video->getVideo()->getHeight();
- return _video->getCurrentFrame();
+ return 0;
}
bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
@@ -260,7 +446,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
_vm->_draw->_applyPal = true;
if (palCmd >= 4)
- copyPalette(palStart, palEnd);
+ copyPalette(*(_primaryVideo->getVideo()), palStart, palEnd);
}
if (modifiedPal && (palCmd == 8) && !_backSurf)
@@ -270,7 +456,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
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 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
}
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 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
_vm->_util->processInput();
if (_vm->_quitRequested) {
- _video->disableSound();
+ _primaryVideo->getVideo()->disableSound();
return true;
}
@@ -321,7 +507,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
_vm->_inter->storeKey(_vm->_util->checkKey());
if (VAR(0) == (unsigned) breakKey) {
- _video->disableSound();
+ _primaryVideo->getVideo()->disableSound();
return true;
}
}
@@ -329,26 +515,37 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
return false;
}
-void VideoPlayer::copyPalette(int16 palStart, int16 palEnd) {
- if ((palStart == -1) || (palEnd == -1))
- memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
- _video->getPalette(), 768);
- else
- memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) +
- palStart * 3, _video->getPalette() + palStart * 3,
+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, 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::writeVideoInfo(const char *video, int16 varX, int16 varY,
}
}
-void VideoPlayer::closeVideo() {
- delete _video;
- delete _stream;
-
- _video = 0;
- _stream = 0;
- *_curFile = 0;
-}
-
} // End of namespace Gob
diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h
index 7b9a3ca687..3a6ec0d9da 100644
--- a/engines/gob/videoplayer.h
+++ b/engines/gob/videoplayer.h
@@ -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 @@ public:
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,
- int16 varFrames, int16 varWidth, int16 varHeight);
+ 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;
- void closeVideo();
+ 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);
private:
+ class Video {
+ public:
+ Video(GobEngine *vm);
+ ~Video();
+
+ 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);