aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorjohndoe1232014-03-19 13:59:13 +0100
committerEugene Sandulenko2018-07-20 06:43:33 +0000
commite881db073200fb2b3d7087c076ff3da77135516a (patch)
tree6e552b6fe387e77fbde6ad161e1a1c3345103c1d /engines
parent18540a5e385997815f5a7c237328d7bc0b10c174 (diff)
downloadscummvm-rg350-e881db073200fb2b3d7087c076ff3da77135516a.tar.gz
scummvm-rg350-e881db073200fb2b3d7087c076ff3da77135516a.tar.bz2
scummvm-rg350-e881db073200fb2b3d7087c076ff3da77135516a.zip
ILLUSIONS: Implement more sequence opcodes and work on the graphics system
Diffstat (limited to 'engines')
-rw-r--r--engines/illusions/actor.cpp106
-rw-r--r--engines/illusions/actor.h10
-rw-r--r--engines/illusions/actorresource.cpp9
-rw-r--r--engines/illusions/backgroundresource.cpp12
-rw-r--r--engines/illusions/backgroundresource.h8
-rw-r--r--engines/illusions/illusions.cpp88
-rw-r--r--engines/illusions/illusions.h10
-rw-r--r--engines/illusions/sequenceopcodes.cpp182
-rw-r--r--engines/illusions/sequenceopcodes.h20
-rw-r--r--engines/illusions/spritedecompressqueue.cpp13
10 files changed, 421 insertions, 37 deletions
diff --git a/engines/illusions/actor.cpp b/engines/illusions/actor.cpp
index 74443c3aac..e1aa5f772f 100644
--- a/engines/illusions/actor.cpp
+++ b/engines/illusions/actor.cpp
@@ -27,6 +27,7 @@
#include "illusions/input.h"
#include "illusions/screen.h"
#include "illusions/scriptman.h"
+#include "illusions/scriptopcodes.h"
#include "illusions/sequenceopcodes.h"
namespace Illusions {
@@ -53,6 +54,8 @@ void DefaultSequences::set(uint32 sequenceId, uint32 newSequenceId) {
Actor::Actor(IllusionsEngine *vm)
: _vm(vm), _pauseCtr(0) {
_pauseCtr = 0;
+ _spriteFlags = 0;
+ _drawFlags = 0;
_flags = 0;
_scale = 100;
_frameIndex = 0;
@@ -84,15 +87,16 @@ Actor::Actor(IllusionsEngine *vm)
_seqCodeValue1 = 0;
_seqCodeValue2 = 600;
_seqCodeValue3 = 0;
+
+ _notifyId3C = 0;
_pathCtrY = 0;
+
+ _controlRoutine = 0;
+ setControlRoutine(new Common::Functor2Mem<Control*, uint32, void, Controls>(_vm->_controls, &Controls::actorControlRouine));
#if 0 // TODO
_field2 = 0;
- _spriteFlags = 0;
- _drawFlags = 0;
- _controlRoutine = Actor_defaultControlRoutine;
- _notifyId3C = 0;
_path40 = 0;
_path4C = 0;
_pathFlag50 = 0;
@@ -166,6 +170,16 @@ int16 Actor::popSequenceStack() {
return _seqStack[--_seqStackCount];
}
+void Actor::setControlRoutine(ActorControlRoutine *controlRoutine) {
+ delete _controlRoutine;
+ _controlRoutine = controlRoutine;
+}
+
+void Actor::runControlRoutine(Control *control, uint32 deltaTime) {
+ if (_controlRoutine)
+ (*_controlRoutine)(control, deltaTime);
+}
+
// Control
Control::Control(IllusionsEngine *vm)
@@ -501,10 +515,8 @@ void Control::stopActor() {
_actor->_path40 = 0;
}
*/
-
_vm->notifyThreadId(_actor->_notifyThreadId1);
_vm->notifyThreadId(_actor->_notifyId3C);
-
}
void Control::startSequenceActor(uint32 sequenceId, int value, uint32 notifyThreadId) {
@@ -528,7 +540,52 @@ void Control::stopSequenceActor() {
}
void Control::sequenceActor() {
- // TODO
+
+ if (_actor->_pauseCtr > 0)
+ return;
+
+ OpCall opCall;
+ bool sequenceFinished = false;
+
+ opCall._result = 0;
+ _actor->_seqCodeValue3 -= _actor->_seqCodeValue1;
+
+ while (_actor->_seqCodeValue3 <= 0 && !sequenceFinished) {
+ bool breakInner = false;
+ while (!breakInner) {
+ debug("op: %08X", _actor->_seqCodeIp[0]);
+ opCall._op = _actor->_seqCodeIp[0] & 0x7F;
+ opCall._opSize = _actor->_seqCodeIp[1];
+ opCall._code = _actor->_seqCodeIp + 2;
+ opCall._deltaOfs = opCall._opSize;
+ if (_actor->_seqCodeIp[0] & 0x80)
+ breakInner = true;
+ execSequenceOpcode(opCall);
+ if (opCall._result == 1) {
+ sequenceFinished = true;
+ breakInner = true;
+ } else if (opCall._result == 2) {
+ breakInner = true;
+ }
+ _actor->_seqCodeIp += opCall._deltaOfs;
+ }
+ _actor->_seqCodeValue3 += _actor->_seqCodeValue2;
+ }
+
+ if (_actor->_newFrameIndex != 0) {
+ debug("New frame %d", _actor->_newFrameIndex);
+ setActorFrameIndex(_actor->_newFrameIndex);
+ if (!(_actor->_flags & 1) && (_actor->_flags & 0x1000) && (_objectId != 0x40004)) {
+ appearActor();
+ _actor->_flags &= ~0x1000;
+ }
+ }
+
+ if (sequenceFinished) {
+ debug("Sequence has finished");
+ _actor->_seqCodeIp = 0;
+ }
+
}
void Control::startSequenceActorIntern(uint32 sequenceId, int value, int value2, uint32 notifyThreadId) {
@@ -567,7 +624,7 @@ void Control::startSequenceActorIntern(uint32 sequenceId, int value, int value2,
_actor->_notifyThreadId2 = notifyThreadId;
}
- // TODO sequenceActor();
+ sequenceActor();
}
@@ -672,7 +729,7 @@ void Controls::placeSequenceLessActor(uint32 objectId, Common::Point placePt, Wi
control->_position.y = 0;
control->_actorTypeId = 0x50004;
control->_actor = actor;
- // TODO actor->setControlRoutine(0);
+ actor->setControlRoutine(0);
actor->_surfInfo._pixelSize = dimensions._width * dimensions._height;
actor->_surfInfo._dimensions = dimensions;
actor->createSurface(actor->_surfInfo);
@@ -743,4 +800,35 @@ void Controls::destroyControl(Control *control) {
delete control;
}
+void Controls::actorControlRouine(Control *control, uint32 deltaTime) {
+ //debug("Controls::actorControlRouine()");
+
+ Actor *actor = control->_actor;
+
+ if (actor->_pauseCtr > 0)
+ return;
+
+ if (false/*actor->_pathNode*/) {
+ // TODO Update pathwalking
+ } else {
+ actor->_seqCodeValue1 = 100 * deltaTime;
+ }
+
+ if (actor->_flags & 4) {
+ int scale = actor->_scaleLayer->getScale(actor->_position);
+ control->setActorScale(scale);
+ }
+
+ if (actor->_flags & 8) {
+ int16 priority = actor->_priorityLayer->getPriority(actor->_position);
+ if (priority)
+ control->setPriority(priority + 1);
+ }
+
+ if (actor->_flags & 0x20) {
+ // TODO Update transition sequence (seems to be unused in BBDOU?)
+ }
+
+}
+
} // End of namespace Illusions
diff --git a/engines/illusions/actor.h b/engines/illusions/actor.h
index 0684ce1834..6a682c6a9e 100644
--- a/engines/illusions/actor.h
+++ b/engines/illusions/actor.h
@@ -27,6 +27,7 @@
#include "illusions/backgroundresource.h"
#include "illusions/graphics.h"
#include "common/algorithm.h"
+#include "common/func.h"
#include "common/list.h"
#include "graphics/surface.h"
@@ -64,6 +65,8 @@ protected:
Common::Array<DefaultSequence> _items;
};
+typedef Common::Functor2<Control*, uint32, void> ActorControlRoutine;
+
class Actor {
public:
Actor(IllusionsEngine *vm);
@@ -74,6 +77,8 @@ public:
void initSequenceStack();
void pushSequenceStack(int16 value);
int16 popSequenceStack();
+ void setControlRoutine(ActorControlRoutine *controlRoutine);
+ void runControlRoutine(Control *control, uint32 deltaTime);
public:
IllusionsEngine *_vm;
byte _drawFlags;
@@ -117,6 +122,8 @@ public:
int _surfaceTextFlag;
+ ActorControlRoutine *_controlRoutine;
+
byte *_seqCodeIp;
uint32 _sequenceId;
int _seqCodeValue1;
@@ -187,7 +194,8 @@ public:
~Controls();
void placeActor(uint32 actorTypeId, Common::Point placePt, uint32 sequenceId, uint32 objectId, uint32 notifyThreadId);
void placeSequenceLessActor(uint32 objectId, Common::Point placePt, WidthHeight dimensions, int16 priority);
- void placeActorLessObject(uint32 objectId, Common::Point feetPt, Common::Point pt, int16 priority, uint flags);
+ void placeActorLessObject(uint32 objectId, Common::Point feetPt, Common::Point pt, int16 priority, uint flags);
+ void actorControlRouine(Control *control, uint32 deltaTime);
public:
typedef Common::List<Control*> Items;
typedef Items::iterator ItemsIterator;
diff --git a/engines/illusions/actorresource.cpp b/engines/illusions/actorresource.cpp
index 426fff653d..831a932b7a 100644
--- a/engines/illusions/actorresource.cpp
+++ b/engines/illusions/actorresource.cpp
@@ -95,6 +95,8 @@ void Sequence::load(byte *dataStart, Common::SeekableReadStream &stream) {
debug(5, "Sequence::load() _sequenceId: %08X; _unk4: %d; sequenceCodeOffs: %08X",
_sequenceId, _unk4, sequenceCodeOffs);
+
+ debug("_sequenceId: %08X", _sequenceId);
}
void ActorType::load(byte *dataStart, Common::SeekableReadStream &stream) {
@@ -125,6 +127,9 @@ void ActorType::load(byte *dataStart, Common::SeekableReadStream &stream) {
_pathWalkPointsIndex, _scaleLayerIndex, _pathWalkRectIndex);
debug(5, "ActorType::load() _priorityLayerIndex: %d; _regionLayerIndex: %d; _flags: %04X",
_priorityLayerIndex, _regionLayerIndex,_flags);
+
+ debug("_actorTypeId: %08X; dimensions: (%d, %d)", _actorTypeId, _surfInfo._dimensions._width, _surfInfo._dimensions._height);
+
}
// ActorResource
@@ -159,7 +164,7 @@ void ActorResource::load(byte *data, uint32 dataSize) {
stream.seek(0x14);
uint32 sequencesOffs = stream.readUint32LE();
stream.seek(sequencesOffs);
- _actorTypes.reserve(sequencesCount);
+ _sequences.reserve(sequencesCount);
for (uint i = 0; i < sequencesCount; ++i) {
Sequence sequence;
sequence.load(data, stream);
@@ -172,7 +177,7 @@ void ActorResource::load(byte *data, uint32 dataSize) {
stream.seek(0x18);
uint32 framesOffs = stream.readUint32LE();
stream.seek(framesOffs);
- _actorTypes.reserve(framesCount);
+ _frames.reserve(framesCount);
for (uint i = 0; i < framesCount; ++i) {
Frame frame;
frame.load(data, stream);
diff --git a/engines/illusions/backgroundresource.cpp b/engines/illusions/backgroundresource.cpp
index bdce1c4669..6c7808c33e 100644
--- a/engines/illusions/backgroundresource.cpp
+++ b/engines/illusions/backgroundresource.cpp
@@ -173,6 +173,18 @@ void BackgroundResource::load(byte *data, uint32 dataSize) {
_scaleLayers[i].load(data, stream);
}
+ // Load priority layers
+ stream.seek(0x14);
+ _priorityLayersCount = stream.readUint16LE();
+ _priorityLayers = new PriorityLayer[_priorityLayersCount];
+ stream.seek(0x34);
+ uint32 priorityLayersOffs = stream.readUint32LE();
+ debug("_priorityLayersCount: %d", _priorityLayersCount);
+ for (uint i = 0; i < _priorityLayersCount; ++i) {
+ stream.seek(priorityLayersOffs + i * 12);
+ _priorityLayers[i].load(data, stream);
+ }
+
}
int BackgroundResource::findMasterBgIndex() {
diff --git a/engines/illusions/backgroundresource.h b/engines/illusions/backgroundresource.h
index de6204e94b..d3865d1c75 100644
--- a/engines/illusions/backgroundresource.h
+++ b/engines/illusions/backgroundresource.h
@@ -90,13 +90,13 @@ protected:
#if 0
BgResource_PathWalkRects struc ; (sizeof=0x8)
-count dd ?
-rects dd ?
+count dd ?
+rects dd ?
BgResource_PathWalkRects ends
BgResource_PathWalkPoints struc ; (sizeof=0x8)
-count dd ?
-points dd ?
+count dd ?
+points dd ?
BgResource_PathWalkPoints ends
#endif
diff --git a/engines/illusions/illusions.cpp b/engines/illusions/illusions.cpp
index ddb4d6039e..2a92d94d35 100644
--- a/engines/illusions/illusions.cpp
+++ b/engines/illusions/illusions.cpp
@@ -97,6 +97,11 @@ Common::Error IllusionsEngine::run() {
_camera = new Camera(this);
_controls = new Controls(this);
+ // TODO Move to own class
+ _resGetCtr = 0;
+ _unpauseControlActorFlag = false;
+ _lastUpdateTime = 0;
+
#if 0
// ActorResource test
_resSys->loadResource(0x00100006, 0, 0);
@@ -134,18 +139,25 @@ Common::Error IllusionsEngine::run() {
#if 1
// Actor/graphics test
- _resSys->loadResource(0x00110007, 0, 0);
- _resSys->loadResource(0x00100006, 0, 0);
- _controls->placeActor(0x00050008, Common::Point(200, 200), 0x00060136, 0x00040001, 0);
+
+ /* TODO 0x0010000B LinkIndex 0x00060AAB 0x00060556
+ */
+
+ _resSys->loadResource(0x0011000B, 0, 0);
+ _resSys->loadResource(0x0010000B, 0, 0);
+ _controls->placeActor(0x00050009, Common::Point(0, 0), 0x00060573, 0x00040001, 0);
Control *control = *_controls->_controls.begin();
control->setActorFrameIndex(1);
control->appearActor();
//_camera->panToPoint(Common::Point(800, 0), 500, 0);
while (!shouldQuit()) {
+ updateActors();
+ updateSequences();
updateGraphics();
_screen->updateSprites();
_system->updateScreen();
updateEvents();
+ _system->delayMillis(10);
}
#endif
@@ -235,18 +247,58 @@ bool IllusionsEngine::hideCursor() {
return false;
}
+uint32 IllusionsEngine::getElapsedUpdateTime() {
+ uint32 result = 0;
+ uint32 currTime = getCurrentTime();
+ if (_resGetCtr <= 0 ) {
+ if (_unpauseControlActorFlag) {
+ _unpauseControlActorFlag = false;
+ result = 0;
+ } else {
+ result = currTime - _lastUpdateTime;
+ }
+ _lastUpdateTime = currTime;
+ } else {
+ result = _resGetTime - _lastUpdateTime;
+ _lastUpdateTime = _resGetTime;
+ }
+ return result;
+}
+
+int IllusionsEngine::updateActors() {
+ // TODO Move to Controls class
+ uint32 deltaTime = getElapsedUpdateTime();
+ //debug("deltaTime: %d", deltaTime);
+ for (Controls::ItemsIterator it = _controls->_controls.begin(); it != _controls->_controls.end(); ++it) {
+ Control *control = *it;
+ if (control->_pauseCtr == 0 && control->_actor && control->_actor->_controlRoutine)
+ control->_actor->runControlRoutine(control, deltaTime);
+ }
+ return 1;
+}
+
+int IllusionsEngine::updateSequences() {
+ // TODO Move to Controls class
+ for (Controls::ItemsIterator it = _controls->_controls.begin(); it != _controls->_controls.end(); ++it) {
+ Control *control = *it;
+ if (control->_pauseCtr == 0 && control->_actor && control->_actor->_seqCodeIp)
+ control->sequenceActor();
+ }
+ return 1;
+}
+
int IllusionsEngine::updateGraphics() {
Common::Point panPoint(0, 0);
uint32 currTime = getCurrentTime();
- _camera->update(currTime);
-
- // TODO Move to BackgroundItems class
- BackgroundItem *backgroundItem = _backgroundItems->findActiveBackground();
- if (backgroundItem) {
- BackgroundResource *bgRes = backgroundItem->_bgRes;
- for (uint i = 0; i < bgRes->_bgInfosCount; ++i) {
- BgInfo *bgInfo = &bgRes->_bgInfos[i];
+ _camera->update(currTime);
+
+ // TODO Move to BackgroundItems class
+ BackgroundItem *backgroundItem = _backgroundItems->findActiveBackground();
+ if (backgroundItem) {
+ BackgroundResource *bgRes = backgroundItem->_bgRes;
+ for (uint i = 0; i < bgRes->_bgInfosCount; ++i) {
+ BgInfo *bgInfo = &bgRes->_bgInfos[i];
// TODO int16 priority = artcntrlGetPriorityFromBase(bgInfos[v7].priorityBase);
int16 priority = -1;
_screen->_drawQueue->insertSurface(backgroundItem->_surfaces[i],
@@ -261,11 +313,8 @@ int IllusionsEngine::updateGraphics() {
Control *control = *it;
Actor *actor = control->_actor;
- debug("control->_pauseCtr: %d; actor->_flags: %04X", control->_pauseCtr, actor->_flags);
-
if (control->_pauseCtr == 0 && actor && (actor->_flags & 1) && !(actor->_flags & 0x0200)) {
Common::Point drawPosition = control->calcPosition(panPoint);
- debug("drawPosition: %d, %d", drawPosition.x, drawPosition.y);
if (actor->_flags & 0x2000) {
Frame *frame = &(*actor->_frames)[actor->_frameIndex - 1];
_screen->_decompressQueue->insert(&actor->_drawFlags, frame->_flags,
@@ -296,8 +345,17 @@ int IllusionsEngine::updateGraphics() {
_textInfo._position, priority);
}
#endif
-
+
return 1;
}
+int IllusionsEngine::getRandom(int max) {
+ return _random->getRandomNumber(max - 1);
+}
+
+int IllusionsEngine::convertPanXCoord(int16 x) {
+ // TODO
+ return 0;
+}
+
} // End of namespace Illusions
diff --git a/engines/illusions/illusions.h b/engines/illusions/illusions.h
index d262690a7f..33e0a70ff1 100644
--- a/engines/illusions/illusions.h
+++ b/engines/illusions/illusions.h
@@ -91,6 +91,11 @@ public:
BackgroundItems *_backgroundItems;
Camera *_camera;
Controls *_controls;
+
+ int _resGetCtr;
+ uint32 _resGetTime;
+ bool _unpauseControlActorFlag;
+ uint32 _lastUpdateTime;
Common::Point *getObjectActorPositionPtr(uint32 objectId);
@@ -100,7 +105,12 @@ public:
void placeCursor(Control *control, uint32 sequenceId);
bool showCursor();
bool hideCursor();
+ uint32 getElapsedUpdateTime();
+ int updateActors();
+ int updateSequences();
int updateGraphics();
+ int getRandom(int max);
+ int convertPanXCoord(int16 x);
#if 0
diff --git a/engines/illusions/sequenceopcodes.cpp b/engines/illusions/sequenceopcodes.cpp
index 22845f0944..e19d8cdf7d 100644
--- a/engines/illusions/sequenceopcodes.cpp
+++ b/engines/illusions/sequenceopcodes.cpp
@@ -46,7 +46,7 @@ void SequenceOpcodes::execOpcode(Control *control, OpCall &opCall) {
(*_opcodes[opCall._op])(control, opCall);
}
-typedef Common::Functor2Mem<ScriptThread*, OpCall&, void, SequenceOpcodes> SequenceOpcodeI;
+typedef Common::Functor2Mem<Control*, OpCall&, void, SequenceOpcodes> SequenceOpcodeI;
#define OPCODE(op, func) _opcodes[op] = new SequenceOpcodeI(this, &SequenceOpcodes::func);
void SequenceOpcodes::initOpcodes() {
@@ -54,7 +54,24 @@ void SequenceOpcodes::initOpcodes() {
for (uint i = 0; i < 256; ++i)
_opcodes[i] = 0;
// Register opcodes
- //OPCODE(42, opIncBlockCounter);
+ OPCODE(2, opSetFrameIndex);
+ OPCODE(3, opEndSequence);
+ OPCODE(5, opSetRandomFrameDelay);
+ OPCODE(6, opSetFrameSpeed);
+ OPCODE(7, opJump);
+ OPCODE(9, opGotoSequence);
+ OPCODE(11, opBeginLoop);
+ OPCODE(12, opNextLoop);
+ OPCODE(15, opJumpIfNotFacing);
+ OPCODE(28, opNotifyThreadId1);
+ OPCODE(29, opSetPathCtrY);
+ OPCODE(33, opSetPathWalkPoints);
+ OPCODE(36, opSetScaleLayer);
+ OPCODE(38, opSetPathWalkRects);
+ OPCODE(39, opSetPriority);
+ OPCODE(40, opSetPriorityLayer);
+ OPCODE(50, opPlaySound);
+ OPCODE(51, opStopSound);
}
#undef OPCODE
@@ -69,6 +86,165 @@ void SequenceOpcodes::freeOpcodes() {
// Convenience macros
#define ARG_SKIP(x) opCall.skip(x);
#define ARG_INT16(name) int16 name = opCall.readSint16(); debug("ARG_INT16(" #name " = %d)", name);
-#define ARG_UINT32(name) uint32 name = opCall.readUint32(); debug("ARG_UINT32(" #name " = %d)", name);
+#define ARG_UINT32(name) uint32 name = opCall.readUint32(); debug("ARG_UINT32(" #name " = %08X)", name);
+
+void SequenceOpcodes::opSetFrameIndex(Control *control, OpCall &opCall) {
+ ARG_INT16(frameIndex);
+ if (control->_actor->_flags & 0x80) {
+ debug("opSetFrameIndex TODO");
+ /* TODO
+ v9 = actor->field30;
+ if (*(_WORD *)v9) {
+ LOWORD(flag) = *(_WORD *)v9;
+ v6 = v6 + flag - 1;
+ actor->field30 = v9 + 2;
+ } else {
+ actor->flags &= 0xFF7Fu;
+ v10 = actor->notifyThreadId1;
+ actor->field30 = 0;
+ actor->notifyThreadId2 = 0;
+ if (v10) {
+ actor->notifyThreadId1 = 0;
+ ThreadList_notifyId__(v10);
+ }
+ actorDead = 1;
+ breakInner = 1;
+ }
+ */
+ }
+ control->_actor->_flags &= ~0x0100;
+ if (control->_actor->_flags & 0x8000) {
+ control->appearActor();
+ control->_actor->_flags &= ~0x800;
+ }
+ control->_actor->_newFrameIndex = frameIndex;
+}
+
+void SequenceOpcodes::opEndSequence(Control *control, OpCall &opCall) {
+ control->_actor->_seqCodeIp = 0;
+ if (control->_actor->_flags & 0x0800) {
+ control->_actor->_flags &= ~0x0800;
+ control->_actor->_frames = 0;
+ control->_actor->_frameIndex = 0;
+ control->_actor->_newFrameIndex = 0;
+ // TODO _vm->_resSys->unloadResourceById(control->_actor->_sequenceId);
+ }
+ _vm->notifyThreadId(control->_actor->_notifyThreadId1);
+ opCall._result = 1;
+}
+
+void SequenceOpcodes::opSetRandomFrameDelay(Control *control, OpCall &opCall) {
+ ARG_INT16(minFrameDelay);
+ ARG_INT16(maxFrameDelay);
+ control->_actor->_seqCodeValue3 += 0;//DEBUG minFrameDelay + _vm->getRandom(maxFrameDelay);
+}
+
+void SequenceOpcodes::opSetFrameSpeed(Control *control, OpCall &opCall) {
+ ARG_INT16(frameSpeed);
+ control->_actor->_seqCodeValue2 = frameSpeed;
+}
+
+void SequenceOpcodes::opJump(Control *control, OpCall &opCall) {
+ ARG_INT16(jumpOffs);
+ opCall._deltaOfs += jumpOffs;
+}
+
+void SequenceOpcodes::opGotoSequence(Control *control, OpCall &opCall) {
+ ARG_SKIP(2);
+ ARG_UINT32(nextSequenceId);
+ uint32 notifyThreadId1 = control->_actor->_notifyThreadId1;
+ control->clearNotifyThreadId1();
+ if (false/*TODO control->_actor->_pathNode*/) {
+ control->startSequenceActor(nextSequenceId, 1, notifyThreadId1);
+ } else {
+ control->startSequenceActor(nextSequenceId, 2, notifyThreadId1);
+ }
+ opCall._deltaOfs = 0;
+}
+
+void SequenceOpcodes::opBeginLoop(Control *control, OpCall &opCall) {
+ ARG_INT16(loopCount);
+ control->_actor->pushSequenceStack(loopCount);
+}
+
+void SequenceOpcodes::opNextLoop(Control *control, OpCall &opCall) {
+ ARG_INT16(jumpOffs);
+ int16 currLoopCount = control->_actor->popSequenceStack();
+ if (currLoopCount > 0) {
+ control->_actor->pushSequenceStack(currLoopCount - 1);
+ opCall._deltaOfs = -jumpOffs;
+ }
+}
+
+void SequenceOpcodes::opJumpIfNotFacing(Control *control, OpCall &opCall) {
+ ARG_INT16(facing);
+ ARG_INT16(jumpOffs);
+ if (!(control->_actor->_facing & facing))
+ opCall._deltaOfs += jumpOffs;
+}
+
+void SequenceOpcodes::opNotifyThreadId1(Control *control, OpCall &opCall) {
+ _vm->notifyThreadId(control->_actor->_notifyThreadId1);
+}
+
+void SequenceOpcodes::opSetPathCtrY(Control *control, OpCall &opCall) {
+ ARG_INT16(pathCtrY);
+ control->_actor->_pathCtrY = pathCtrY;
+}
+
+void SequenceOpcodes::opSetPathWalkPoints(Control *control, OpCall &opCall) {
+ ARG_INT16(pathWalkPointsIndex);
+ BackgroundResource *bgRes = _vm->_backgroundItems->getActiveBgResource();
+ control->_actor->_flags |= 2;
+ // TODO control->_actor->_pathWalkPoints = bgRes->getPathWalkPoints(pathWalkPointsIndex - 1);
+}
+
+void SequenceOpcodes::opSetScaleLayer(Control *control, OpCall &opCall) {
+ ARG_INT16(scaleLayerIndex);
+ BackgroundResource *bgRes = _vm->_backgroundItems->getActiveBgResource();
+ control->_actor->_flags |= 4;
+ control->_actor->_scaleLayer = bgRes->getScaleLayer(scaleLayerIndex - 1);
+ int scale = control->_actor->_scaleLayer->getScale(control->_actor->_position);
+ control->setActorScale(scale);
+}
+
+void SequenceOpcodes::opSetPathWalkRects(Control *control, OpCall &opCall) {
+ ARG_INT16(pathWalkRectsIndex);
+ BackgroundResource *bgRes = _vm->_backgroundItems->getActiveBgResource();
+ control->_actor->_flags |= 0x10;
+ // TODO control->_actor->_pathWalkRects = bgRes->getPathWalkRects(pathWalkRectsIndex - 1);
+}
+
+void SequenceOpcodes::opSetPriority(Control *control, OpCall &opCall) {
+ ARG_INT16(priority);
+ control->_actor->_flags &= ~8;
+ control->setPriority(priority);
+}
+
+void SequenceOpcodes::opSetPriorityLayer(Control *control, OpCall &opCall) {
+ ARG_INT16(priorityLayerIndex);
+ BackgroundResource *bgRes = _vm->_backgroundItems->getActiveBgResource();
+ control->_actor->_flags |= 8;
+ control->_actor->_priorityLayer = bgRes->getPriorityLayer(priorityLayerIndex - 1);
+ int priority = control->_actor->_priorityLayer->getPriority(control->_actor->_position);
+ control->setPriority(priority);
+}
+
+void SequenceOpcodes::opPlaySound(Control *control, OpCall &opCall) {
+ ARG_INT16(flags);
+ ARG_INT16(volume);
+ ARG_INT16(pan);
+ ARG_UINT32(soundEffectId);
+ if (!(flags & 1))
+ volume = 255;
+ if (!(flags & 2))
+ pan = _vm->convertPanXCoord(control->_actor->_position.x);
+ // TODO _vm->startSound(soundEffectId, volume, pan);
+}
+
+void SequenceOpcodes::opStopSound(Control *control, OpCall &opCall) {
+ ARG_UINT32(soundEffectId);
+ // TODO _vm->stopSound(soundEffectId);
+}
} // End of namespace Illusions
diff --git a/engines/illusions/sequenceopcodes.h b/engines/illusions/sequenceopcodes.h
index aa31a76176..366fbba6b7 100644
--- a/engines/illusions/sequenceopcodes.h
+++ b/engines/illusions/sequenceopcodes.h
@@ -44,7 +44,25 @@ protected:
void initOpcodes();
void freeOpcodes();
- // Opcodes
+ // Opcodes
+ void opSetFrameIndex(Control *control, OpCall &opCall);
+ void opEndSequence(Control *control, OpCall &opCall);
+ void opSetRandomFrameDelay(Control *control, OpCall &opCall);
+ void opSetFrameSpeed(Control *control, OpCall &opCall);
+ void opJump(Control *control, OpCall &opCall);
+ void opGotoSequence(Control *control, OpCall &opCall);
+ void opBeginLoop(Control *control, OpCall &opCall);
+ void opNextLoop(Control *control, OpCall &opCall);
+ void opJumpIfNotFacing(Control *control, OpCall &opCall);
+ void opNotifyThreadId1(Control *control, OpCall &opCall);
+ void opSetPathCtrY(Control *control, OpCall &opCall);
+ void opSetPathWalkPoints(Control *control, OpCall &opCall);
+ void opSetScaleLayer(Control *control, OpCall &opCall);
+ void opSetPathWalkRects(Control *control, OpCall &opCall);
+ void opSetPriority(Control *control, OpCall &opCall);
+ void opSetPriorityLayer(Control *control, OpCall &opCall);
+ void opPlaySound(Control *control, OpCall &opCall);
+ void opStopSound(Control *control, OpCall &opCall);
};
diff --git a/engines/illusions/spritedecompressqueue.cpp b/engines/illusions/spritedecompressqueue.cpp
index acb4547a76..c20b0dba28 100644
--- a/engines/illusions/spritedecompressqueue.cpp
+++ b/engines/illusions/spritedecompressqueue.cpp
@@ -55,11 +55,20 @@ void SpriteDecompressQueue::decompressAll() {
void SpriteDecompressQueue::decompress(SpriteDecompressQueueItem *item) {
byte *src = item->_compressedPixels;
Graphics::Surface *dstSurface = item->_surface;
- int dstSize = item->_dimensions._height * item->_dimensions._width;
+ int dstSize = item->_dimensions._width * item->_dimensions._height;
int processedSize = 0;
int xincr, x, xstart;
int yincr, y;
-
+
+ // Safeguard
+ if (item->_dimensions._width > item->_surface->w ||
+ item->_dimensions._height > item->_surface->h) {
+ debug("Incorrect frame dimensions (%d, %d <> %d, %d)",
+ item->_dimensions._width, item->_dimensions._height,
+ item->_surface->w, item->_surface->h);
+ return;
+ }
+
if (item->_flags & 1) {
x = xstart = item->_dimensions._width - 1;
xincr = -1;