aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjohndoe1232014-03-25 19:57:21 +0100
committerEugene Sandulenko2018-07-20 06:43:33 +0000
commite05a7899755011f860f2b09ce6d5b4e0a15107b9 (patch)
treeb16815bcf51d3b776e63563d04f9997cb4a4567f
parent28cb39eb2b48d8c6e80e35ef6e26e02cc209fc0f (diff)
downloadscummvm-rg350-e05a7899755011f860f2b09ce6d5b4e0a15107b9.tar.gz
scummvm-rg350-e05a7899755011f860f2b09ce6d5b4e0a15107b9.tar.bz2
scummvm-rg350-e05a7899755011f860f2b09ce6d5b4e0a15107b9.zip
ILLUSIONS: More work on BBDOU specific code (cursor, bubble)
- Add input handling code
-rw-r--r--engines/illusions/actor.cpp91
-rw-r--r--engines/illusions/actor.h7
-rw-r--r--engines/illusions/bbdou/bbdou_bubble.cpp150
-rw-r--r--engines/illusions/bbdou/bbdou_bubble.h81
-rw-r--r--engines/illusions/bbdou/bbdou_cursor.cpp167
-rw-r--r--engines/illusions/bbdou/bbdou_cursor.h77
-rw-r--r--engines/illusions/bbdou/bbdou_specialcode.cpp304
-rw-r--r--engines/illusions/bbdou/bbdou_specialcode.h33
-rw-r--r--engines/illusions/illusions.cpp23
-rw-r--r--engines/illusions/input.cpp86
-rw-r--r--engines/illusions/input.h24
-rw-r--r--engines/illusions/module.mk1
-rw-r--r--engines/illusions/scriptopcodes.cpp5
13 files changed, 1011 insertions, 38 deletions
diff --git a/engines/illusions/actor.cpp b/engines/illusions/actor.cpp
index b813ff0cc9..fbc5958ecc 100644
--- a/engines/illusions/actor.cpp
+++ b/engines/illusions/actor.cpp
@@ -95,7 +95,7 @@ Actor::Actor(IllusionsEngine *vm)
_pathCtrY = 0;
_controlRoutine = 0;
- setControlRoutine(new Common::Functor2Mem<Control*, uint32, void, Controls>(_vm->_controls, &Controls::actorControlRouine));
+ setControlRoutine(new Common::Functor2Mem<Control*, uint32, void, Controls>(_vm->_controls, &Controls::actorControlRoutine));
#if 0 // TODO
_field2 = 0;
@@ -283,7 +283,7 @@ void Control::activateObject() {
}
void Control::deactivateObject() {
- _flags |= ~1;
+ _flags &= ~1;
if (_actor) {
for (uint i = 0; i < kSubObjectsCount; ++i)
if (_actor->_subobjects[i]) {
@@ -377,11 +377,11 @@ int Control::getPriority() {
int16 positionY, priority, priority1;
if (_actor) {
if (_actor->_parentObjectId && (_actor->_flags & 0x40)) {
- uint32 objectId2 = getSubActorParent();
- Control *control2 = _vm->_dict->getObjectControl(objectId2);
- objectId = control2->_objectId;
- priority = control2->_priority;
- positionY = control2->_actor->_position.y;
+ uint32 parentObjectId = getSubActorParent();
+ Control *parentControl = _vm->_dict->getObjectControl(parentObjectId);
+ objectId = parentControl->_objectId;
+ priority = parentControl->_priority;
+ positionY = parentControl->_actor->_position.y;
priority1 = _priority;
} else {
objectId = _objectId;
@@ -475,6 +475,24 @@ void Control::getCollisionRectAccurate(Common::Rect &collisionRect) {
}
+void Control::getCollisionRect(Common::Rect &collisionRect) {
+ collisionRect = Common::Rect(_unkPt.x, _unkPt.y, _pt.x, _pt.y);
+ if (_actor) {
+ if (_actor->_scale != 100) {
+ // scaledValue = value * scale div 100
+ collisionRect.left = collisionRect.left * _actor->_scale / 100;
+ collisionRect.top = collisionRect.top * _actor->_scale / 100;
+ collisionRect.right = collisionRect.right * _actor->_scale / 100;
+ collisionRect.bottom = collisionRect.bottom * _actor->_scale / 100;
+ }
+ collisionRect.translate(_actor->_position.x, _actor->_position.y);
+ }
+ if (_flags & 8) {
+ Common::Point screenOffs = _vm->_camera->getScreenOffset();
+ collisionRect.translate(screenOffs.x, screenOffs.y);
+ }
+}
+
void Control::setActorUsePan(int usePan) {
if (usePan == 1)
_flags &= ~8;
@@ -602,6 +620,14 @@ void Control::sequenceActor() {
}
+void Control::setActorIndexTo1() {
+ _actor->_actorIndex = 1;
+}
+
+void Control::setActorIndexTo2() {
+ _actor->_actorIndex = 2;
+}
+
void Control::startSequenceActorIntern(uint32 sequenceId, int value, byte *entryTblPtr, uint32 notifyThreadId) {
stopActor();
@@ -618,10 +644,18 @@ void Control::startSequenceActorIntern(uint32 sequenceId, int value, byte *entry
_actor->_path40 = 0;
Sequence *sequence = _vm->_dict->findSequence(sequenceId);
+ //debug("sequence: %p", (void*)sequence);
_actor->_seqCodeIp = sequence->_sequenceCode;
_actor->_frames = _vm->_actorItems->findSequenceFrames(sequence);
+ /*
+ for (int i = 0; i < 64; ++i) {
+ debugN("%02X ", sequence->_sequenceCode[i]);
+ }
+ debug(".");
+ */
+
_actor->_seqCodeValue3 = 0;
_actor->_seqCodeValue1 = 0;
_actor->_seqCodeValue2 = value == 1 ? 350 : 600;
@@ -815,7 +849,48 @@ void Controls::unpauseControlsByTag(uint32 tag) {
}
}
-void Controls::actorControlRouine(Control *control, uint32 deltaTime) {
+bool Controls::getOverlappedObject(Control *control, Common::Point pt, Control **outOverlappedControl, int minPriority) {
+ Control *foundControl = 0;
+ int foundPriority = 0;
+ // TODO minPriority = artcntrlGetPriorityFromBase(minPriority);
+
+ for (ItemsIterator it = _controls.begin(); it != _controls.end(); ++it) {
+ Control *testControl = *it;
+ if (testControl != control && testControl->_pauseCtr == 0 &&
+ (testControl->_flags & 1) && !(testControl->_flags & 0x10) &&
+ (!testControl->_actor || (testControl->_actor->_flags & 1))) {
+ Common::Rect collisionRect;
+ testControl->getCollisionRect(collisionRect);
+ debug("collisionRect(%d, %d, %d, %d)", collisionRect.left, collisionRect.top, collisionRect.right, collisionRect.bottom);
+ debug("pt(%d, %d)", pt.x, pt.y);
+ if (!collisionRect.isEmpty() && collisionRect.contains(pt)) {
+ int testPriority = testControl->getPriority();
+ debug("testPriority: %d; minPriority: %d", testPriority, minPriority);
+ if ((!foundControl || foundPriority < testPriority) &&
+ testPriority >= minPriority) {
+ debug("overlapped() %08X; pauseCtr: %d; flags: %04X",
+ testControl->_objectId, testControl->_pauseCtr, testControl->_flags);
+ foundControl = testControl;
+ foundPriority = testPriority;
+ }
+ }
+ }
+ }
+
+ debug("OVERLAPPED DONE\n");
+
+ if (foundControl) {
+ if (foundControl->_actor && foundControl->_actor->_parentObjectId && (foundControl->_actor->_flags & 0x40)) {
+ uint32 parentObjectId = foundControl->getSubActorParent();
+ foundControl = _vm->_dict->getObjectControl(parentObjectId);
+ }
+ *outOverlappedControl = foundControl;
+ }
+
+ return foundControl != 0;
+}
+
+void Controls::actorControlRoutine(Control *control, uint32 deltaTime) {
Actor *actor = control->_actor;
diff --git a/engines/illusions/actor.h b/engines/illusions/actor.h
index fe5564e0a7..9ddfc9cf16 100644
--- a/engines/illusions/actor.h
+++ b/engines/illusions/actor.h
@@ -134,7 +134,6 @@ public:
int _pathCtrY;
int _path40;
-
};
class Control {
@@ -162,6 +161,7 @@ public:
Common::Point calcPosition(Common::Point posDelta);
uint32 getSubActorParent();
void getCollisionRectAccurate(Common::Rect &collisionRect);
+ void getCollisionRect(Common::Rect &collisionRect);
void setActorUsePan(int usePan);
void setActorFrameIndex(int16 frameIndex);
void stopActor();
@@ -169,6 +169,8 @@ public:
void stopSequenceActor();
void startTalkActor(uint32 sequenceId, byte *entryTblPtr, uint32 threadId);
void sequenceActor();
+ void setActorIndexTo1();
+ void setActorIndexTo2();
public:
IllusionsEngine *_vm;
uint _flags;
@@ -201,7 +203,8 @@ public:
void destroyControlsByTag(uint32 tag);
void pauseControlsByTag(uint32 tag);
void unpauseControlsByTag(uint32 tag);
- void actorControlRouine(Control *control, uint32 deltaTime);
+ bool getOverlappedObject(Control *control, Common::Point pt, Control **outOverlappedControl, int minPriority);
+ void actorControlRoutine(Control *control, uint32 deltaTime);
public:
typedef Common::List<Control*> Items;
typedef Items::iterator ItemsIterator;
diff --git a/engines/illusions/bbdou/bbdou_bubble.cpp b/engines/illusions/bbdou/bbdou_bubble.cpp
new file mode 100644
index 0000000000..3256bc404d
--- /dev/null
+++ b/engines/illusions/bbdou/bbdou_bubble.cpp
@@ -0,0 +1,150 @@
+/* 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.
+ *
+ */
+
+#include "illusions/illusions.h"
+#include "illusions/bbdou/bbdou_bubble.h"
+#include "illusions/actor.h"
+#include "illusions/camera.h"
+#include "illusions/dictionary.h"
+#include "illusions/input.h"
+
+namespace Illusions {
+
+BbdouBubble::BbdouBubble(IllusionsEngine *vm, BbdouSpecialCode *bbdou)
+ : _vm(vm), _bbdou(bbdou) {
+}
+
+BbdouBubble::~BbdouBubble() {
+}
+
+void BbdouBubble::init() {
+
+ static const uint32 kObjectIds3[] = {
+ 0x0004003B, 0x0004003C, 0x0004003D, 0x0004003E,
+ 0x0004003F, 0x00040040, 0x00040041, 0x00040042,
+ 0x00040043, 0x00040044, 0x00040045, 0x00040046,
+ 0x00040047, 0x00040048, 0x00040049, 0x0004004A,
+ 0x0004004B, 0x0004004C, 0x0004004D, 0x0004004E,
+ 0x0004004F, 0x00040050, 0x00040051, 0x00040052,
+ 0x00040053, 0x00040054, 0x00040055, 0x00040056,
+ 0x00040057, 0x00040058, 0x00040059, 0x0004005A
+ };
+
+ static const uint32 kObjectIds2[] = {
+ 0x0004001B, 0x0004001C, 0x0004001D, 0x0004001E,
+ 0x0004001F, 0x00040020, 0x00040021, 0x00040022,
+ 0x00040023, 0x00040024, 0x00040025, 0x00040026,
+ 0x00040027, 0x00040028, 0x00040029, 0x0004002A,
+ 0x0004002B, 0x0004002C, 0x0004002D, 0x0004002E,
+ 0x0004002F, 0x00040030, 0x00040031, 0x00040032,
+ 0x00040033, 0x00040034, 0x00040035, 0x00040036,
+ 0x00040037, 0x00040038, 0x00040039, 0x0004003A
+ };
+
+ _field1414 = 0x4005B;
+ _field1418 = 0x4005C;
+
+ for (uint i = 0; i < 32; ++i)
+ _objectIds[i] = kObjectIds3[i];
+
+ for (uint i = 0; i < 32; ++i) {
+ _items[i]._objectId = kObjectIds2[i];
+ _items[i]._enabled = 0;
+ _items[i]._position.x = 0;
+ _items[i]._position.y = 0;
+ _items[i]._sequenceId = 0;
+ }
+
+ _currItem0 = 0;
+ _prevItem0 = 0;
+ _someItem0 = 0;
+ _pt1.x = 0;
+ _pt1.y = 0;
+ _pt2.x = 0;
+ _pt2.y = 0;
+
+}
+
+void BbdouBubble::addItem0(uint32 sequenceId1, uint32 sequenceId2, uint32 progResKeywordId,
+ uint32 namedPointId, int16 count, uint32 *namedPointIds) {
+ Item0 item0;
+ item0._sequenceId1 = sequenceId1;
+ item0._sequenceId2 = sequenceId2;
+ item0._progResKeywordId = progResKeywordId;
+ item0._baseNamedPointId = namedPointId;
+ item0._count = count;
+ for (int16 i = 0; i < count; ++i)
+ item0._namedPointIds[i] = FROM_LE_32(namedPointIds[i]);
+ item0._objectId = 0;
+ item0._pt.x = 0;
+ item0._pt.y = 0;
+ _item0s.push_back(item0);
+}
+
+void BbdouBubble::show() {
+
+ if (_prevItem0) {
+ hide();
+ }
+
+ _prevItem0 = _currItem0;
+ _currItem0 = 0;
+
+ // TODO calcBubbles(_pt1, _pt2);
+
+ Control *control = _vm->_dict->getObjectControl(_prevItem0->_objectId);
+ control->setActorPosition(_pt2);
+ control->startSequenceActor(0x60057, 2, 0);
+ control->startSequenceActor(_prevItem0->_sequenceId1, 2, 0);
+ control->appearActor();
+ control->deactivateObject();
+
+ for (uint i = 0; i < 32; ++i) {
+ if (_items[i]._enabled == 1) {
+ Control *subControl = _vm->_dict->getObjectControl(_items[i]._objectId);
+ subControl->setActorPosition(_items[i]._position);
+ subControl->startSequenceActor(_items[i]._sequenceId, 2, 0);
+ }
+ }
+
+}
+
+void BbdouBubble::hide() {
+ _someItem0 = _prevItem0;
+ _prevItem0 = 0;
+ if (_someItem0) {
+ Control *control = _vm->_dict->getObjectControl(_someItem0->_objectId);
+ control->startSequenceActor(_someItem0->_sequenceId2, 2, 0);
+ for (uint i = 0; i < 32; ++i) {
+ Control *subControl = _vm->_dict->getObjectControl(_objectIds[i]);
+ subControl->stopActor();
+ subControl->disappearActor();
+ }
+ for (uint i = 0; i < 32; ++i) {
+ Control *subControl = _vm->_dict->getObjectControl(_items[i]._objectId);
+ subControl->stopActor();
+ subControl->disappearActor();
+ }
+ }
+}
+
+} // End of namespace Illusions
diff --git a/engines/illusions/bbdou/bbdou_bubble.h b/engines/illusions/bbdou/bbdou_bubble.h
new file mode 100644
index 0000000000..9064acd08c
--- /dev/null
+++ b/engines/illusions/bbdou/bbdou_bubble.h
@@ -0,0 +1,81 @@
+/* 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.
+ *
+ */
+
+#ifndef ILLUSIONS_BBDOU_BBDOU_BUBBLE_H
+#define ILLUSIONS_BBDOU_BBDOU_BUBBLE_H
+
+#include "illusions/specialcode.h"
+#include "common/rect.h"
+
+namespace Illusions {
+
+class IllusionsEngine;
+class BbdouSpecialCode;
+class Control;
+
+struct Item0 {
+ uint32 _sequenceId1;
+ uint32 _sequenceId2;
+ int16 _count;
+ uint32 _progResKeywordId;
+ uint32 _baseNamedPointId;
+ uint32 _namedPointIds[32];
+ uint32 _objectId;
+ Common::Point _pt;
+ Item0() : _count(0) {}
+};
+
+struct Item141C {
+ uint32 _objectId;
+ int16 _enabled;
+ Common::Point _position;
+ int16 _fieldA;
+ uint32 _sequenceId;
+};
+
+class BbdouBubble {
+public:
+ BbdouBubble(IllusionsEngine *vm, BbdouSpecialCode *bbdou);
+ ~BbdouBubble();
+ void init();
+ void addItem0(uint32 sequenceId1, uint32 sequenceId2, uint32 progResKeywordId,
+ uint32 namedPointId, int16 count, uint32 *namedPointIds);
+ void show();
+ void hide();
+protected:
+ IllusionsEngine *_vm;
+ BbdouSpecialCode *_bbdou;
+ Common::Array<Item0> _item0s;
+ Item0 *_currItem0;
+ Item0 *_prevItem0;
+ Item0 *_someItem0;
+ uint32 _objectIds[32];
+ Common::Point _pt1;
+ Common::Point _pt2;
+ int _field1414;
+ int _field1418;
+ Item141C _items[32];
+};
+
+} // End of namespace Illusions
+
+#endif // ILLUSIONS_BBDOU_BBDOU_BUBBLE_H
diff --git a/engines/illusions/bbdou/bbdou_cursor.cpp b/engines/illusions/bbdou/bbdou_cursor.cpp
index 9c0bcc8170..16cd82ade6 100644
--- a/engines/illusions/bbdou/bbdou_cursor.cpp
+++ b/engines/illusions/bbdou/bbdou_cursor.cpp
@@ -23,17 +23,178 @@
#include "illusions/illusions.h"
#include "illusions/bbdou/bbdou_cursor.h"
#include "illusions/actor.h"
+#include "illusions/camera.h"
+#include "illusions/dictionary.h"
+#include "illusions/input.h"
namespace Illusions {
-BbdouCursor::BbdouCursor(IllusionsEngine *vm)
- : _vm(vm) {
+// NOTE It's assumed there's only one game cursor object
+// The original stores the _data inside the actor, here it's inside the Cursor class.
+
+BbdouCursor::BbdouCursor(IllusionsEngine *vm, BbdouSpecialCode *bbdou)
+ : _vm(vm), _bbdou(bbdou) {
}
BbdouCursor::~BbdouCursor() {
}
-void BbdouCursor::init() {
+void BbdouCursor::init(uint32 objectId, uint32 progResKeywordId) {
+
+ Common::Point pos = _vm->_camera->getCurrentPan();
+ _vm->_controls->placeActor(0x50001, pos, 0x6000C, objectId, 0);
+
+ Control *control = _vm->_dict->getObjectControl(objectId);
+ //control->_actor->setControlRoutine(new Common::Functor2Mem<Control*, uint32, void, BbdouCursor>(this, &BbdouCursor::actorControlRoutine1));
+ control->_flags |= 8;
+
+ _data._mode = 1;
+ _data._mode2 = 0;
+ _data._verbId1 = 0x1B0000;
+ _data._progResKeywordId = progResKeywordId;
+ _data._currOverlappedObjectId = 0;
+ _data._overlappedObjectId = 0;
+ _data._sequenceId = 0x6000F;
+ _data._holdingObjectId = 0;
+ _data._holdingObjectId2 = 0;
+ _data._visibleCtr = 0;
+ _data._causeThreadId1 = 0;
+ _data._causeThreadId2 = 0;
+ _data._field90 = 0;
+ _data._flags = 0;
+ _data._item10._field58 = 1;
+ _data._sequenceId98 = 0;
+ _data._idleCtr = 0;
+ _data._item10._verbId = 0x1B0000;
+ _data._item10._field0 = 1;
+ _data._item10._playSound48 = 0;
+ _data._item10._objectIds[0] = 0;
+ _data._item10._objectIds[1] = 0;
+ _data._item10._index = 0;
+ _data._item10._flag56 = 0;
+
+ clearCursorDataField14();
+
+ control->setActorIndexTo1();
+
+}
+
+void BbdouCursor::enable(uint32 objectId) {
+ ++_data._visibleCtr;
+ if (_data._visibleCtr == 1) {
+ Control *control = _vm->_dict->getObjectControl(objectId);
+ show(control);
+ _vm->_camera->pushCameraMode();
+ _vm->_camera->panEdgeFollow(objectId, 360);
+ _data._idleCtr = 0;
+ }
+ _vm->_input->discardButtons(0xFFFF);
+}
+
+void BbdouCursor::disable(uint32 objectId) {
+ hide(objectId);
+}
+
+void BbdouCursor::addCursorSequence(uint32 objectId, uint32 sequenceId) {
+ for (uint i = 0; i < kMaxCursorSequences; ++i)
+ if (_cursorSequences[i]._objectId == 0) {
+ _cursorSequences[i]._objectId = objectId;
+ _cursorSequences[i]._sequenceId = sequenceId;
+ break;
+ }
+}
+
+uint32 BbdouCursor::findCursorSequenceId(uint32 objectId) {
+ for (uint i = 0; i < kMaxCursorSequences; ++i)
+ if (_cursorSequences[i]._objectId == objectId)
+ return _cursorSequences[i]._sequenceId;
+ return 0;
+}
+
+int BbdouCursor::findStruct8bsValue(uint32 objectId) {
+ for (uint i = 0; i < kMaxCursorSequences; ++i)
+ if (_cursorStruct8bs[i]._objectId == objectId)
+ return _cursorStruct8bs[i]._value;
+ return 11;
+}
+
+void BbdouCursor::saveInfo() {
+ _data._mode2 = _data._mode;
+ _data._sequenceId2 = _data._sequenceId;
+ _data._holdingObjectId2 = _data._holdingObjectId;
+}
+
+void BbdouCursor::restoreInfo() {
+ _data._mode = _data._mode2;
+ _data._holdingObjectId = _data._holdingObjectId2;
+ _data._sequenceId = _data._sequenceId2;
+ _data._mode2 = 0;
+ _data._holdingObjectId2 = 0;
+ _data._sequenceId2 = 0;
+}
+
+void BbdouCursor::restoreAfterTrackingCursor() {
+ _data._holdingObjectId = _data._holdingObjectId2;
+ if (_data._holdingObjectId2) {
+ _data._mode = 2;
+ _data._sequenceId = findCursorSequenceId(_data._holdingObjectId2);
+ } else {
+ _data._mode = 1;
+ _data._sequenceId = 0x6000F;
+ }
+ _data._mode2 = 0;
+ _data._sequenceId2 = 0;
+ _data._holdingObjectId2 = 0;
+ _data._sequenceId98 = 0;
+}
+
+uint32 BbdouCursor::getSequenceId1(int sequenceIndex) {
+ switch (sequenceIndex) {
+ case 2:
+ return 0x60010;
+ case 3:
+ return 0x60011;
+ case 4:
+ return 0x60012;
+ case 5:
+ return 0x60013;
+ case 6:
+ return 0x60015;
+ case 7:
+ return 0x60014;
+ default:
+ return 0;
+ }
+}
+
+void BbdouCursor::clearCursorDataField14() {
+ for (uint i = 0; i < 32; ++i)
+ _data._item10._verbActive[i] = 0;
+ if (_data._item10._field0 == 1) {
+ _data._item10._verbActive[1] = 1;
+ _data._item10._verbActive[2] = 1;
+ _data._item10._verbActive[3] = 1;
+ _data._item10._verbActive[5] = 1;
+ } else if (_data._item10._field0 == 3) {
+ _data._item10._verbActive[1] = 1;
+ _data._item10._verbActive[2] = 1;
+ }
+}
+
+void BbdouCursor::show(Control *control) {
+ control->startSequenceActor(_data._sequenceId, 2, 0);
+ control->appearActor();
+}
+
+void BbdouCursor::hide(uint32 objectId) {
+ --_data._visibleCtr;
+ if (_data._visibleCtr == 0) {
+ Control *control = _vm->_dict->getObjectControl(objectId);
+ control->startSequenceActor(0x60029, 2, 0);
+ // TODO item10_sub_10005040(objectId, &cursorData->item10);
+ _vm->_camera->popCameraMode();
+ }
+ _vm->_input->discardButtons(0xFFFF);
}
} // End of namespace Illusions
diff --git a/engines/illusions/bbdou/bbdou_cursor.h b/engines/illusions/bbdou/bbdou_cursor.h
index df3ed82f1a..8f02632857 100644
--- a/engines/illusions/bbdou/bbdou_cursor.h
+++ b/engines/illusions/bbdou/bbdou_cursor.h
@@ -28,14 +28,85 @@
namespace Illusions {
class IllusionsEngine;
+class BbdouSpecialCode;
+class Control;
+struct Item10;
+
+struct Item10 {
+ int _field0;
+ int16 _verbActive[32];
+ uint32 _verbId;
+ int16 _playSound48;
+ //field_4A dw
+ uint32 _objectIds[2];
+ int16 _index;
+ int16 _flag56;
+ int _field58;
+};
+
+struct CursorData {
+ int _mode;
+ int _mode2;
+ uint32 _verbId1;
+ uint32 _progResKeywordId;
+ Item10 _item10;
+ uint32 _currOverlappedObjectId;
+ uint32 _overlappedObjectId;
+ uint32 _sequenceId;
+ uint32 _sequenceId2;
+ uint32 _holdingObjectId;
+ uint32 _holdingObjectId2;
+ int _visibleCtr;
+ //field_86 dw
+ uint32 _causeThreadId1;
+ uint32 _causeThreadId2;
+ int16 _field90;
+ //field_92 dw
+ uint _flags;
+ uint32 _sequenceId98;
+ int16 _idleCtr;
+ //field_9E db
+ //field_9F db
+};
+
+struct CursorSequence {
+ uint32 _objectId;
+ uint32 _sequenceId;
+ CursorSequence() : _objectId(0), _sequenceId(0) {}
+};
+
+struct Struct8b {
+ uint32 _objectId;
+ int _value;
+ Struct8b() : _objectId(0), _value(0) {}
+};
+
+const uint kMaxCursorSequences = 100;
class BbdouCursor {
public:
- BbdouCursor(IllusionsEngine *vm);
+ BbdouCursor(IllusionsEngine *vm, BbdouSpecialCode *bbdou);
~BbdouCursor();
- void init();
-protected:
+ void init(uint32 objectId, uint32 progResKeywordId);
+ void enable(uint32 objectId);
+ void disable(uint32 objectId);
+ void addCursorSequence(uint32 objectId, uint32 sequenceId);
+ uint32 findCursorSequenceId(uint32 objectId);
+ int findStruct8bsValue(uint32 objectId);
+ void saveInfo();
+ void restoreInfo();
+ void restoreAfterTrackingCursor();
+ uint32 getSequenceId1(int sequenceIndex);
+public:
IllusionsEngine *_vm;
+ BbdouSpecialCode *_bbdou;
+ Control *_control;
+ CursorData _data;
+ CursorSequence _cursorSequences[kMaxCursorSequences];
+ Struct8b _cursorStruct8bs[512];
+ void clearCursorDataField14();
+ void show(Control *control);
+ void hide(uint32 objectId);
};
} // End of namespace Illusions
diff --git a/engines/illusions/bbdou/bbdou_specialcode.cpp b/engines/illusions/bbdou/bbdou_specialcode.cpp
index 028fdb54a8..e0d29e7265 100644
--- a/engines/illusions/bbdou/bbdou_specialcode.cpp
+++ b/engines/illusions/bbdou/bbdou_specialcode.cpp
@@ -22,7 +22,13 @@
#include "illusions/illusions.h"
#include "illusions/bbdou/bbdou_specialcode.h"
+#include "illusions/bbdou/bbdou_bubble.h"
#include "illusions/bbdou/bbdou_cursor.h"
+#include "illusions/actor.h"
+#include "illusions/camera.h"
+#include "illusions/dictionary.h"
+#include "illusions/input.h"
+#include "illusions/scriptman.h"
#include "illusions/scriptopcodes.h"
namespace Illusions {
@@ -31,15 +37,313 @@ namespace Illusions {
BbdouSpecialCode::BbdouSpecialCode(IllusionsEngine *vm)
: SpecialCode(vm) {
+ _bubble = new BbdouBubble(_vm, this);
+ _cursor = new BbdouCursor(_vm, this);
}
BbdouSpecialCode::~BbdouSpecialCode() {
+ delete _cursor;
+ delete _bubble;
}
+typedef Common::Functor1Mem<OpCall&, void, BbdouSpecialCode> SpecialCodeFunctionI;
+#define SPECIAL(id, func) _map[id] = new SpecialCodeFunctionI(this, &BbdouSpecialCode::func);
+
void BbdouSpecialCode::init() {
+ // TODO
+ SPECIAL(0x00160006, spcInitCursor);
+ SPECIAL(0x00160008, spcEnableCursor);
+ SPECIAL(0x00160009, spcDisableCursor);
+ SPECIAL(0x0016000A, spcAddCursorSequence);
+ SPECIAL(0x00160013, spcInitBubble);
+ SPECIAL(0x00160014, spcSetupBubble);
+ SPECIAL(0x00160015, spcSetObjectInteractMode);
}
void BbdouSpecialCode::run(uint32 specialCodeId, OpCall &opCall) {
+ MapIterator it = _map.find(specialCodeId);
+ if (it != _map.end()) {
+ (*(*it)._value)(opCall);
+ } else {
+ debug("BbdouSpecialCode::run() Unimplemented special code %08X", specialCodeId);
+ _vm->notifyThreadId(opCall._callerThreadId);
+ }
+}
+
+// Special codes
+
+// 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 " = %08X)", name);
+
+void BbdouSpecialCode::spcInitCursor(OpCall &opCall) {
+ ARG_UINT32(objectId);
+ ARG_UINT32(progResKeywordId);
+ _cursor->init(objectId, progResKeywordId);
+ setCursorControlRoutine(objectId, 0);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcEnableCursor(OpCall &opCall) {
+ ARG_UINT32(objectId);
+ _cursor->enable(objectId);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcDisableCursor(OpCall &opCall) {
+ ARG_UINT32(objectId);
+ _cursor->disable(objectId);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcAddCursorSequence(OpCall &opCall) {
+ ARG_SKIP(4);
+ ARG_UINT32(objectId);
+ ARG_UINT32(sequenceId);
+ _cursor->addCursorSequence(objectId, sequenceId);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcInitBubble(OpCall &opCall) {
+ _bubble->init();
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcSetupBubble(OpCall &opCall) {
+ ARG_UINT32(sequenceId1);
+ ARG_UINT32(sequenceId2);
+ ARG_UINT32(progResKeywordId);
+ ARG_UINT32(namedPointId);
+ ARG_INT16(count);
+ _bubble->addItem0(sequenceId1, sequenceId2, progResKeywordId, namedPointId,
+ count, (uint32*)opCall._code);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::spcSetObjectInteractMode(OpCall &opCall) {
+ ARG_SKIP(4);
+ ARG_UINT32(objectId);
+ ARG_INT16(value);
+ // TODO Cursor_updateStruct8bs(objectId, v3);
+ _vm->notifyThreadId(opCall._callerThreadId);
+}
+
+void BbdouSpecialCode::playSoundEffect(int soundIndex) {
+ static const uint32 kSoundEffectIds[] = {
+ 0, 1,
+ 0x900C1, 2,
+ 0, 3,
+ 0x900C0, 4,
+ 0x900C2, 5,
+ 0, 6
+ };
+ uint32 soundEffectId = kSoundEffectIds[2 * soundIndex];
+ if (soundEffectId) {
+ // TODO _vm->startSound(soundEffectId, 255, 0);
+ }
+}
+
+void BbdouSpecialCode::resetItem10(uint32 objectId, Item10 *item10) {
+ if (item10->_playSound48 == 1) {
+ _bubble->hide();
+ item10->_verbId = 0x1B0000;
+ item10->_playSound48 = 0;
+ item10->_objectIds[0] = 0;
+ item10->_objectIds[1] = 0;
+ }
+ _vm->_input->discardButtons(0xFFFF);
+}
+
+bool BbdouSpecialCode::testValueRange(int value) {
+ return value >= 2 && value <= 7;
+}
+
+void BbdouSpecialCode::setCursorControlRoutine(uint32 objectId, int num) {
+ Control *control = _vm->_dict->getObjectControl(objectId);
+ if (num == 0)
+ control->_actor->setControlRoutine(
+ new Common::Functor2Mem<Control*, uint32, void, BbdouSpecialCode>(this, &BbdouSpecialCode::cursorInteractControlRoutine));
+ else
+ control->_actor->setControlRoutine(
+ new Common::Functor2Mem<Control*, uint32, void, BbdouSpecialCode>(this, &BbdouSpecialCode::cursorControlRoutine2));
+}
+
+Common::Point BbdouSpecialCode::getBackgroundCursorPos(Common::Point cursorPos) {
+ Common::Point pt = _vm->_camera->getScreenOffset();
+ pt.x += cursorPos.x;
+ pt.y += cursorPos.y;
+ return pt;
+}
+
+bool BbdouSpecialCode::runCause(Control *control, CursorData &cursorData,
+ uint32 verbId, uint32 objectId1, uint32 objectId2, int soundIndex) {
+ // TODO
+ return false;
+}
+
+void BbdouSpecialCode::showBubble(uint32 objectId, uint32 overlappedObjectId, uint32 holdingObjectId,
+ Item10 *item10, uint32 progResKeywordId) {
+ // TODO
+}
+
+bool BbdouSpecialCode::findVerbId(Item10 *item10, uint32 currOverlappedObjectId, int always0, uint32 &outVerbId) {
+ // TODO
+ return false;
+}
+
+void BbdouSpecialCode::cursorInteractControlRoutine(Control *cursorControl, uint32 deltaTime) {
+ Actor *actor = cursorControl->_actor;
+ CursorData &cursorData = _cursor->_data;
+
+ if (cursorData._visibleCtr > 0) {
+
+ Common::Point cursorPos = _vm->_input->getCursorPosition();
+
+ if (cursorPos == actor->_position) {
+ cursorData._idleCtr += deltaTime;
+ if (cursorData._idleCtr > 3600)
+ cursorData._idleCtr = 0;
+ } else {
+ actor->_position.x = cursorPos.x;
+ actor->_position.y = cursorPos.y;
+ cursorData._idleCtr = 0;
+ }
+
+ if (updateTrackingCursor(cursorControl))
+ cursorData._flags |= 1;
+ else
+ cursorData._flags &= ~1;
+
+ cursorPos = getBackgroundCursorPos(cursorPos);
+ bool foundOverlapped = false;
+ Control *overlappedControl = 0;
+
+ if (cursorData._flags & 1) {
+ foundOverlapped = 0;
+ } else if (_vm->_scriptMan->_activeScenes.getCurrentScene() == 0x1000D) {
+ /* TODO foundOverlapped = artcntrlGetOverlappedObjectAccurate(cursorControl, cursorPos,
+ &overlappedControl, cursorData._item10._field58);*/
+ } else {
+ foundOverlapped = _vm->_controls->getOverlappedObject(cursorControl, cursorPos,
+ &overlappedControl, cursorData._item10._field58);
+ debug("overlappedControl: %p", (void*)overlappedControl);
+ }
+
+ if (foundOverlapped) {
+ if (overlappedControl->_objectId != cursorData._currOverlappedObjectId) {
+ if (cursorData._item10._playSound48)
+ playSoundEffect(4);
+ resetItem10(cursorControl->_objectId, &cursorData._item10);
+ int value = _cursor->findStruct8bsValue(overlappedControl->_objectId);
+ if (!testValueRange(value)) {
+ if (cursorData._mode == 3)
+ _cursor->restoreInfo();
+ _cursor->show(cursorControl);
+ cursorControl->setActorIndexTo2();
+ if (cursorData._overlappedObjectId != overlappedControl->_objectId) {
+ cursorData._overlappedObjectId = overlappedControl->_objectId;
+ runCause(cursorControl, cursorData, 0x1B0009, 0, overlappedControl->_objectId, 0);
+ }
+ if (value == 10) {
+ if (cursorData._holdingObjectId) {
+ cursorData._item10._verbId = 0x1B0003;
+ cursorData._currOverlappedObjectId = overlappedControl->_objectId;
+ }
+ else {
+ cursorData._item10._verbId = 0x1B0002;
+ cursorData._currOverlappedObjectId = overlappedControl->_objectId;
+ }
+ } else {
+ playSoundEffect(3);
+ showBubble(cursorControl->_objectId, overlappedControl->_objectId,
+ cursorData._holdingObjectId, &cursorData._item10,
+ cursorData._progResKeywordId);
+ cursorData._currOverlappedObjectId = overlappedControl->_objectId;
+ }
+ } else {
+ if (cursorData._mode != 3) {
+ _cursor->saveInfo();
+ cursorData._mode = 3;
+ cursorData._item10._verbId = 0x1B0006;
+ cursorData._holdingObjectId = 0;
+ }
+ cursorData._sequenceId = _cursor->getSequenceId1(value);
+ _cursor->show(cursorControl);
+ cursorData._currOverlappedObjectId = overlappedControl->_objectId;
+ }
+ }
+ } else {
+ if (cursorData._overlappedObjectId) {
+ runCause(cursorControl, cursorData, 0x1B0009, 0, 0x40003, 0);
+ cursorData._overlappedObjectId = 0;
+ }
+ if (cursorData._currOverlappedObjectId || cursorData._mode == 3) {
+ if (cursorData._mode == 3)
+ _cursor->restoreInfo();
+ _cursor->show(cursorControl);
+ cursorControl->setActorIndexTo1();
+ if (cursorData._item10._playSound48)
+ playSoundEffect(4);
+ resetItem10(cursorControl->_objectId, &cursorData._item10);
+ }
+ cursorData._currOverlappedObjectId = 0;
+ }
+ }
+
+ actor->_seqCodeValue1 = 100 * deltaTime;
+
+ if (cursorData._visibleCtr <= 0) {
+ if (cursorData._currOverlappedObjectId || cursorData._mode == 3 || cursorData._mode == 4) {
+ if (cursorData._mode == 3) {
+ _cursor->restoreInfo();
+ } else if (cursorData._mode == 4) {
+ _cursor->restoreAfterTrackingCursor();
+ }
+ cursorControl->setActorIndexTo1();
+ }
+ cursorData._currOverlappedObjectId = 0;
+ } else if (cursorData._currOverlappedObjectId) {
+ if (_vm->_input->pollButton(1)) {
+ cursorData._idleCtr = 0;
+ if (runCause(cursorControl, cursorData, cursorData._item10._verbId, cursorData._holdingObjectId, cursorData._currOverlappedObjectId, 1)) {
+ resetItem10(cursorControl->_objectId, &cursorData._item10);
+ cursorData._currOverlappedObjectId = 0;
+ cursorControl->setActorIndexTo1();
+ }
+ } else if (_vm->_input->pollButton(2)) {
+ uint32 verbId;
+ cursorData._idleCtr = 0;
+ if (cursorData._holdingObjectId) {
+ runCause(cursorControl, cursorData, 0x1B000B, 0, 0x40003, 0);
+ cursorData._currOverlappedObjectId = 0;
+ } else if (findVerbId(&cursorData._item10, cursorData._currOverlappedObjectId, 0, verbId) &&
+ runCause(cursorControl, cursorData, verbId, cursorData._holdingObjectId, cursorData._currOverlappedObjectId, 1)) {
+ resetItem10(cursorControl->_objectId, &cursorData._item10);
+ cursorData._currOverlappedObjectId = 0;
+ cursorControl->setActorIndexTo1();
+ }
+ }
+ } else {
+ if (_vm->_input->pollButton(1)) {
+ cursorData._idleCtr = 0;
+ runCause(cursorControl, cursorData, 0x1B0002, 0, 0x40003, 0);
+ } else if (_vm->_input->pollButton(4)) {
+ cursorData._idleCtr = 0;
+ if (cursorData._item10._field58 <= 1)
+ runCause(cursorControl, cursorData, cursorData._holdingObjectId != 0 ? 0x1B000B : 0x1B0004, 0, 0x40003, 0);
+ }
+ }
+
+}
+
+void BbdouSpecialCode::cursorControlRoutine2(Control *cursorControl, uint32 deltaTime) {
+ // TODO
+}
+
+bool BbdouSpecialCode::updateTrackingCursor(Control *cursorControl) {
+ // TODO
+ return false;
}
} // End of namespace Illusions
diff --git a/engines/illusions/bbdou/bbdou_specialcode.h b/engines/illusions/bbdou/bbdou_specialcode.h
index 98aef581be..1dda19fa78 100644
--- a/engines/illusions/bbdou/bbdou_specialcode.h
+++ b/engines/illusions/bbdou/bbdou_specialcode.h
@@ -24,11 +24,17 @@
#define ILLUSIONS_BBDOU_BBDOU_SPECIALCODE_H
#include "illusions/specialcode.h"
+#include "common/hashmap.h"
namespace Illusions {
class IllusionsEngine;
+class BbdouBubble;
class BbdouCursor;
+struct CursorData;
+struct Item10;
+
+typedef Common::Functor1<OpCall&, void> SpecialCodeFunction;
class BbdouSpecialCode : public SpecialCode {
public:
@@ -37,7 +43,34 @@ public:
virtual void init();
virtual void run(uint32 specialCodeId, OpCall &opCall);
public:
+ typedef Common::HashMap<uint32, SpecialCodeFunction*> Map;
+ typedef Map::iterator MapIterator;
+ Map _map;
BbdouCursor *_cursor;
+ BbdouBubble *_bubble;
+ // Special code interface functions
+ void spcInitCursor(OpCall &opCall);
+ void spcEnableCursor(OpCall &opCall);
+ void spcDisableCursor(OpCall &opCall);
+ void spcAddCursorSequence(OpCall &opCall);
+ void spcInitBubble(OpCall &opCall);
+ void spcSetupBubble(OpCall &opCall);
+ void spcSetObjectInteractMode(OpCall &opCall);
+protected:
+ // Internal functions
+ void playSoundEffect(int soundIndex);
+ void resetItem10(uint32 objectId, Item10 *item10);
+ bool testValueRange(int value);
+ void setCursorControlRoutine(uint32 objectId, int num);
+ Common::Point getBackgroundCursorPos(Common::Point cursorPos);
+ bool runCause(Control *control, CursorData &cursorData,
+ uint32 verbId, uint32 objectId1, uint32 objectId2, int soundIndex);
+ void showBubble(uint32 objectId, uint32 overlappedObjectId, uint32 holdingObjectId,
+ Item10 *item10, uint32 progResKeywordId);
+ bool findVerbId(Item10 *item10, uint32 currOverlappedObjectId, int always0, uint32 &outVerbId);
+ void cursorInteractControlRoutine(Control *cursorControl, uint32 deltaTime);
+ void cursorControlRoutine2(Control *cursorControl, uint32 deltaTime);
+ bool updateTrackingCursor(Control *cursorControl);
};
} // End of namespace Illusions
diff --git a/engines/illusions/illusions.cpp b/engines/illusions/illusions.cpp
index a59c568c8b..cf40801fff 100644
--- a/engines/illusions/illusions.cpp
+++ b/engines/illusions/illusions.cpp
@@ -213,23 +213,9 @@ bool IllusionsEngine::hasFeature(EngineFeature f) const {
void IllusionsEngine::updateEvents() {
Common::Event event;
-
while (_eventMan->pollEvent(event)) {
+ _input->processEvent(event);
switch (event.type) {
- case Common::EVENT_KEYDOWN:
- break;
- case Common::EVENT_KEYUP:
- break;
- case Common::EVENT_MOUSEMOVE:
- break;
- case Common::EVENT_LBUTTONDOWN:
- break;
- case Common::EVENT_LBUTTONUP:
- break;
- case Common::EVENT_RBUTTONDOWN:
- break;
- case Common::EVENT_RBUTTONUP:
- break;
case Common::EVENT_QUIT:
quitGame();
break;
@@ -240,7 +226,9 @@ void IllusionsEngine::updateEvents() {
}
Common::Point *IllusionsEngine::getObjectActorPositionPtr(uint32 objectId) {
- // TODO Dummy, to be replaced later
+ Control *control = _dict->getObjectControl(objectId);
+ if (control && control->_actor)
+ return &control->_actor->_position;
return 0;
}
@@ -296,6 +284,7 @@ int IllusionsEngine::updateGraphics() {
Common::Point panPoint(0, 0);
uint32 currTime = getCurrentTime();
+
_camera->update(currTime);
// TODO Move to BackgroundItems class
@@ -312,7 +301,7 @@ int IllusionsEngine::updateGraphics() {
panPoint = backgroundItem->_panPoints[i];
}
}
-
+
// TODO Move to Controls class
for (Controls::ItemsIterator it = _controls->_controls.begin(); it != _controls->_controls.end(); ++it) {
Control *control = *it;
diff --git a/engines/illusions/input.cpp b/engines/illusions/input.cpp
index fd922eca0d..b9ae53abd1 100644
--- a/engines/illusions/input.cpp
+++ b/engines/illusions/input.cpp
@@ -27,18 +27,45 @@ namespace Illusions {
Input::Input() {
_buttonStates = 0;
_newButtons = 0;
- // TODO? _buttonsDown = 0;
- // TODO? _unk6 = 0;
+ _buttonsDown = 0;
+ _newKeys = 0;
_enabledButtons = 0xFFFF;
_cursorPos.x = 0;
_cursorPos.y = 0;
_prevCursorPos.x = 0;
_prevCursorPos.y = 0;
// TODO Not sure if this is still needed newTimer(40, 0, 0, Input_onTimer);
+ initKeys();
}
void Input::processEvent(Common::Event event) {
// TODO
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ handleKey(event.kbd.keycode, MOUSE_NONE, true);
+ break;
+ case Common::EVENT_KEYUP:
+ handleKey(event.kbd.keycode, MOUSE_NONE, false);
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ _cursorPos.x = event.mouse.x;
+ _cursorPos.y = event.mouse.y;
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ handleMouseButton(MOUSE_BUTTON0, true);
+ break;
+ case Common::EVENT_LBUTTONUP:
+ handleMouseButton(MOUSE_BUTTON0, false);
+ break;
+ case Common::EVENT_RBUTTONDOWN:
+ handleMouseButton(MOUSE_BUTTON1, true);
+ break;
+ case Common::EVENT_RBUTTONUP:
+ handleMouseButton(MOUSE_BUTTON1, false);
+ break;
+ default:
+ break;
+ }
}
bool Input::pollButton(uint buttons) {
@@ -90,4 +117,59 @@ Common::Point Input::getCursorDelta() {
return deltaPos;
}
+void Input::initKeys() {
+ // NOTE Skipped debugging keys of the original engine, not sure if used
+ addKeyMapping(Common::KEYCODE_INVALID, MOUSE_BUTTON0, 0x01);
+ addKeyMapping(Common::KEYCODE_RETURN, MOUSE_NONE, 0x01);
+ addKeyMapping(Common::KEYCODE_TAB, MOUSE_NONE, 0x04);
+ addKeyMapping(Common::KEYCODE_INVALID, MOUSE_BUTTON1, 0x04);
+ addKeyMapping(Common::KEYCODE_ESCAPE, MOUSE_NONE, 0x08);
+ addKeyMapping(Common::KEYCODE_SPACE, MOUSE_NONE, 0x10);
+ addKeyMapping(Common::KEYCODE_F1, MOUSE_NONE, 0x20);
+ addKeyMapping(Common::KEYCODE_UP, MOUSE_NONE, 0x40);
+ addKeyMapping(Common::KEYCODE_DOWN, MOUSE_NONE, 0x80);
+ addKeyMapping(Common::KEYCODE_INVALID, MOUSE_BUTTON1, 0x80);
+}
+
+void Input::addKeyMapping(Common::KeyCode key, int mouseButton, uint bitMask) {
+ KeyMapping keyMapping;
+ keyMapping._key = key;
+ keyMapping._mouseButton = mouseButton;
+ keyMapping._bitMask = bitMask;
+ keyMapping._down = false;
+ _keyMap.push_back(keyMapping);
+}
+
+void Input::handleKey(Common::KeyCode key, int mouseButton, bool down) {
+ for (KeyMap::iterator it = _keyMap.begin(); it != _keyMap.end(); ++it) {
+ KeyMapping &keyMapping = *it;
+ if ((keyMapping._key != Common::KEYCODE_INVALID && keyMapping._key == key) ||
+ (keyMapping._mouseButton != MOUSE_NONE && keyMapping._mouseButton == mouseButton)) {
+ if (down && !keyMapping._down) {
+ _newKeys |= keyMapping._bitMask;
+ keyMapping._down = true;
+ } else if (!down)
+ keyMapping._down = false;
+ }
+ }
+ uint prevButtonStates = _buttonStates;
+
+ debug("_newKeys = %08X", _newKeys);
+
+ _buttonStates |= _newKeys;
+ _newKeys = 0;
+ _newButtons = ~prevButtonStates & _buttonStates;
+
+ debug("_buttonStates = %08X", _buttonStates);
+
+}
+
+void Input::handleMouseButton(int mouseButton, bool down) {
+ if (down)
+ _buttonsDown |= mouseButton;
+ else
+ _buttonsDown &= ~mouseButton;
+ handleKey(Common::KEYCODE_INVALID, mouseButton, down);
+}
+
} // End of namespace Illusions
diff --git a/engines/illusions/input.h b/engines/illusions/input.h
index 700d9ed644..f3c9654d37 100644
--- a/engines/illusions/input.h
+++ b/engines/illusions/input.h
@@ -23,11 +23,26 @@
#ifndef ILLUSIONS_INPUT_H
#define ILLUSIONS_INPUT_H
+#include "common/array.h"
#include "common/events.h"
+#include "common/keyboard.h"
#include "common/rect.h"
namespace Illusions {
+enum {
+ MOUSE_NONE = 0,
+ MOUSE_BUTTON0 = 1,
+ MOUSE_BUTTON1 = 2
+};
+
+struct KeyMapping {
+ Common::KeyCode _key;
+ int _mouseButton;
+ uint _bitMask;
+ bool _down;
+};
+
class Input {
public:
Input();
@@ -43,9 +58,16 @@ public:
void setCursorPosition(Common::Point mousePos);
Common::Point getCursorDelta();
protected:
- uint _buttonStates, _newButtons;
+ typedef Common::Array<KeyMapping> KeyMap;
+ uint _buttonStates, _newButtons, _buttonsDown;
uint _enabledButtons;
+ uint _newKeys;
Common::Point _cursorPos, _prevCursorPos;
+ KeyMap _keyMap;
+ void initKeys();
+ void addKeyMapping(Common::KeyCode key, int mouseButton, uint bitMask);
+ void handleKey(Common::KeyCode key, int mouseButton, bool down);
+ void handleMouseButton(int mouseButton, bool down);
};
} // End of namespace Illusions
diff --git a/engines/illusions/module.mk b/engines/illusions/module.mk
index 77f089ad03..762bd4c935 100644
--- a/engines/illusions/module.mk
+++ b/engines/illusions/module.mk
@@ -5,6 +5,7 @@ MODULE_OBJS := \
actor.o \
actorresource.o \
backgroundresource.o \
+ bbdou/bbdou_bubble.o \
bbdou/bbdou_cursor.o \
bbdou/bbdou_specialcode.o \
camera.o \
diff --git a/engines/illusions/scriptopcodes.cpp b/engines/illusions/scriptopcodes.cpp
index a191effb17..8abfa8b63b 100644
--- a/engines/illusions/scriptopcodes.cpp
+++ b/engines/illusions/scriptopcodes.cpp
@@ -29,6 +29,7 @@
#include "illusions/scriptman.h"
#include "illusions/scriptresource.h"
#include "illusions/scriptthread.h"
+#include "illusions/specialcode.h"
namespace Illusions {
@@ -559,11 +560,11 @@ void ScriptOpcodes::opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall)
ARG_SKIP(2);
ARG_UINT32(specialCodeId);
_vm->_scriptMan->_callerThreadId = opCall._callerThreadId;
- // TODO _vm->runSpecialCode(specialCodeId, opCall._code + 8, opCall._threadId);
+ _vm->_specialCode->run(specialCodeId, opCall);
_vm->_scriptMan->_callerThreadId = 0;
//DEBUG Resume calling thread, later done by the special code
- _vm->notifyThreadId(opCall._callerThreadId);
+ //_vm->notifyThreadId(opCall._callerThreadId);
}