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
This commit is contained in:
parent
1d167da633
commit
ab1a3b0cc8
18 changed files with 1355 additions and 197 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
635
engines/gob/goblin_v4.cpp
Normal file
635
engines/gob/goblin_v4.cpp
Normal file
|
@ -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
|
|
@ -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();
|
||||
|
|
|
@ -717,16 +717,16 @@ const char *Inter_Bargon::getOpcodeGoblinDesc(int i) {
|
|||
}
|
||||
|
||||
void Inter_Bargon::oBargon_intro0(OpGobParams ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
|||
}
|
||||
|
||||
void Inter_Bargon::oBargon_intro4(OpGobParams ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -18,6 +18,7 @@ MODULE_OBJS := \
|
|||
goblin_v1.o \
|
||||
goblin_v2.o \
|
||||
goblin_v3.o \
|
||||
goblin_v4.o \
|
||||
coktelvideo.o \
|
||||
videoplayer.o \
|
||||
init.o \
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,27 +677,53 @@ 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 (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.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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -92,6 +92,7 @@ public:
|
|||
AnimLayer *layers;
|
||||
PieceDesc **pieces;
|
||||
bool *piecesFromExt;
|
||||
uint16 *sizes;
|
||||
Animation() : layersCount(0), layers(0), pieces(0),
|
||||
piecesFromExt(0) {}
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
||||
int16 handle = _vm->_dataIO->openData(fileName);
|
||||
|
||||
if (handle < 0) {
|
||||
warning("Couldn't open video \"%s\": No such file", fileName);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
_stream = _vm->_dataIO->openAsStream(handle, true);
|
||||
bool VideoPlayer::primaryOpen(const char *videoFile, int16 x, int16 y,
|
||||
int16 flags, Type which) {
|
||||
|
||||
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;
|
||||
}
|
||||
char fileName[256];
|
||||
|
||||
if (!_video->load(*_stream)) {
|
||||
warning("While loading video \"%s\"", fileName);
|
||||
closeVideo();
|
||||
strncpy0(fileName, videoFile, 250);
|
||||
|
||||
if (!findFile(fileName, which))
|
||||
return false;
|
||||
|
||||
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)
|
||||
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;
|
||||
|
||||
return _video->getFramesCount();
|
||||
}
|
||||
|
||||
int16 VideoPlayer::getCurrentFrame() const {
|
||||
if (!_video)
|
||||
return 0;
|
||||
uint16 VideoPlayer::getFlags(int slot) const {
|
||||
const Video *video = getVideoBySlot(slot);
|
||||
|
||||
return _video->getCurrentFrame();
|
||||
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,
|
||||
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
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();
|
||||
|
||||
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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue