aboutsummaryrefslogtreecommitdiff
path: root/engines/illusions
diff options
context:
space:
mode:
authorjohndoe1232014-04-11 09:40:54 +0200
committerEugene Sandulenko2018-07-20 06:43:33 +0000
commit2e149cf651ee9344ee96ea904c5dce5a444aeaff (patch)
tree5fb2c760d303a4db0856cbc4de7c94609d8b4238 /engines/illusions
parent67366aa04b723fadec300cc6ce1d5c6ee9241af7 (diff)
downloadscummvm-rg350-2e149cf651ee9344ee96ea904c5dce5a444aeaff.tar.gz
scummvm-rg350-2e149cf651ee9344ee96ea904c5dce5a444aeaff.tar.bz2
scummvm-rg350-2e149cf651ee9344ee96ea904c5dce5a444aeaff.zip
ILLUSIONS: More work on Duckman
- Implement Duckman cursor and interaction handling - Add more script opcodes - Add TextDrawer and ScreenText (needs minor refactoring for BBDOU)
Diffstat (limited to 'engines/illusions')
-rw-r--r--engines/illusions/actor.cpp59
-rw-r--r--engines/illusions/backgroundresource.cpp4
-rw-r--r--engines/illusions/camera.cpp2
-rw-r--r--engines/illusions/camera.h2
-rw-r--r--engines/illusions/causethread_duckman.cpp58
-rw-r--r--engines/illusions/causethread_duckman.h45
-rw-r--r--engines/illusions/cursor_duckman.cpp82
-rw-r--r--engines/illusions/cursor_duckman.h30
-rw-r--r--engines/illusions/dictionary.cpp13
-rw-r--r--engines/illusions/dictionary.h8
-rw-r--r--engines/illusions/fontresource.cpp83
-rw-r--r--engines/illusions/fontresource.h37
-rw-r--r--engines/illusions/illusions.cpp26
-rw-r--r--engines/illusions/illusions.h13
-rw-r--r--engines/illusions/illusions_bbdou.cpp12
-rw-r--r--engines/illusions/illusions_bbdou.h2
-rw-r--r--engines/illusions/illusions_duckman.cpp380
-rw-r--r--engines/illusions/illusions_duckman.h49
-rw-r--r--engines/illusions/module.mk3
-rw-r--r--engines/illusions/screen.cpp29
-rw-r--r--engines/illusions/screen.h5
-rw-r--r--engines/illusions/screentext.cpp171
-rw-r--r--engines/illusions/screentext.h77
-rw-r--r--engines/illusions/scriptopcodes.h1
-rw-r--r--engines/illusions/scriptopcodes_duckman.cpp221
-rw-r--r--engines/illusions/scriptopcodes_duckman.h22
-rw-r--r--engines/illusions/scriptresource.cpp5
-rw-r--r--engines/illusions/scriptresource.h2
-rw-r--r--engines/illusions/talkthread_duckman.cpp34
-rw-r--r--engines/illusions/textdrawer.cpp195
-rw-r--r--engines/illusions/textdrawer.h68
-rw-r--r--engines/illusions/thread.h3
32 files changed, 1575 insertions, 166 deletions
diff --git a/engines/illusions/actor.cpp b/engines/illusions/actor.cpp
index bfb6fe2da2..f3677e4726 100644
--- a/engines/illusions/actor.cpp
+++ b/engines/illusions/actor.cpp
@@ -253,32 +253,49 @@ void Control::unpause() {
}
void Control::appearActor() {
- if (_objectId == 0x40004) {
- _vm->showCursor();
- } else {
- if (_actor->_frameIndex || _actorTypeId == 0x50004)
- _actor->_flags |= 1;
- else
- _actor->_flags |= 0x1000;
- for (uint i = 0; i < kSubObjectsCount; ++i)
- if (_actor->_subobjects[i]) {
- Control *subControl = _vm->_dict->getObjectControl(_actor->_subobjects[i]);
- subControl->appearActor();
+ if (_vm->getGameId() == kGameIdDuckman) {
+ _flags |= 1;
+ _actor->_flags |= 1;
+ if (_objectId == 0x40004) {
+ if (_actor->_frameIndex) {
+ _actor->_flags |= 0x2000;
+ _actor->_flags |= 0x4000;
}
+ _vm->_input->discardButtons(0xFFFF);
+ }
+ } else {
+ if (_objectId == 0x40004) {
+ _vm->showCursor();
+ } else {
+ if (_actor->_frameIndex || _actorTypeId == 0x50004)
+ _actor->_flags |= 1;
+ else
+ _actor->_flags |= 0x1000;
+ for (uint i = 0; i < kSubObjectsCount; ++i)
+ if (_actor->_subobjects[i]) {
+ Control *subControl = _vm->_dict->getObjectControl(_actor->_subobjects[i]);
+ subControl->appearActor();
+ }
+ }
}
}
void Control::disappearActor() {
- if (_objectId == 0x40004) {
- _vm->hideCursor();
- } else {
+ if (_vm->getGameId() == kGameIdDuckman) {
+ _flags &= ~1;
_actor->_flags &= ~1;
- _actor->_flags &= ~0x1000;
- for (uint i = 0; i < kSubObjectsCount; ++i)
- if (_actor->_subobjects[i]) {
- Control *subControl = _vm->_dict->getObjectControl(_actor->_subobjects[i]);
- subControl->disappearActor();
- }
+ } else {
+ if (_objectId == 0x40004) {
+ _vm->hideCursor();
+ } else {
+ _actor->_flags &= ~1;
+ _actor->_flags &= ~0x1000;
+ for (uint i = 0; i < kSubObjectsCount; ++i)
+ if (_actor->_subobjects[i]) {
+ Control *subControl = _vm->_dict->getObjectControl(_actor->_subobjects[i]);
+ subControl->disappearActor();
+ }
+ }
}
}
@@ -925,7 +942,7 @@ void Control::startSequenceActorIntern(uint32 sequenceId, int value, byte *entry
_actor->_seqCodeValue3 = 0;
_actor->_seqCodeValue1 = 0;
- if (_vm->getGameId() == kGameIdBBDOU) {
+ if (_vm->getGameId() == kGameIdBBDOU) {
_actor->_seqCodeValue2 = value == 1 ? 350 : 600;
} else if (_vm->getGameId() == kGameIdDuckman) {
_actor->_seqCodeValue2 = value == 1 ? 350 : 750;
diff --git a/engines/illusions/backgroundresource.cpp b/engines/illusions/backgroundresource.cpp
index a4111c7893..2841971d89 100644
--- a/engines/illusions/backgroundresource.cpp
+++ b/engines/illusions/backgroundresource.cpp
@@ -69,7 +69,7 @@ void BackgroundResourceLoader::unload(Resource *resource) {
// TODO Remove IDs from item48s
delete backgroundItem->_bgRes;
_vm->_backgroundItems->freeBackgroundItem(backgroundItem);
- // TODO _vm->setDefPointDimensions1();
+ _vm->setDefaultTextCoords();
debug("BackgroundResourceLoader::unload() Unloading background %08X OK", resource->_resId);
}
@@ -378,7 +378,7 @@ void BackgroundItem::pause() {
for (uint i = 0; i < _bgRes->_item48sCount; ++i)
krndictRemoveID(_bgRes->_item48s[i].id);
*/
- // TODO _vm->setDefPointDimensions1();
+ _vm->setDefaultTextCoords();
_vm->_camera->getActiveState(_savedCameraState);
_savedPalette = new byte[1024];
_vm->_screen->getPalette(_savedPalette);
diff --git a/engines/illusions/camera.cpp b/engines/illusions/camera.cpp
index 57d6f6fc51..b9d934284f 100644
--- a/engines/illusions/camera.cpp
+++ b/engines/illusions/camera.cpp
@@ -279,7 +279,7 @@ void Camera::update(uint32 currTime) {
}
-void Camera::setBounds(Common::Point &minPt, Common::Point &maxPt) {
+void Camera::setBounds(Common::Point minPt, Common::Point maxPt) {
_activeState._bounds._topLeft = minPt;
_activeState._bounds._bottomRight = maxPt;
}
diff --git a/engines/illusions/camera.h b/engines/illusions/camera.h
index a6f8a7333f..9fa12c4ebc 100644
--- a/engines/illusions/camera.h
+++ b/engines/illusions/camera.h
@@ -77,7 +77,7 @@ public:
void popCameraMode();
void clearCameraModeStack();
void update(uint32 currTime);
- void setBounds(Common::Point &minPt, Common::Point &maxPt);
+ void setBounds(Common::Point minPt, Common::Point maxPt);
void setBoundsToDimensions(WidthHeight &dimensions);
Common::Point getCurrentPan();
Common::Point getScreenOffset();
diff --git a/engines/illusions/causethread_duckman.cpp b/engines/illusions/causethread_duckman.cpp
new file mode 100644
index 0000000000..a10b03f546
--- /dev/null
+++ b/engines/illusions/causethread_duckman.cpp
@@ -0,0 +1,58 @@
+/* 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_duckman.h"
+#include "illusions/causethread_duckman.h"
+#include "illusions/actor.h"
+#include "illusions/input.h"
+
+namespace Illusions {
+
+// TalkThread
+
+CauseThread_Duckman::CauseThread_Duckman(IllusionsEngine_Duckman *vm, uint32 threadId, uint32 callingThreadId, uint notifyFlags,
+ uint32 triggerThreadId)
+ : Thread(vm, threadId, callingThreadId, notifyFlags), _vm(vm), _triggerThreadId(triggerThreadId), _flag(false) {
+ _type = kTTCauseThread;
+ _tag = _vm->getCurrentScene();
+}
+
+int CauseThread_Duckman::onUpdate() {
+ if (_flag) {
+ if (_vm->getCurrentScene() == _tag) {
+ Control *cursorCursor = _vm->getObjectControl(0x40004);
+ cursorCursor->appearActor();
+ _vm->_input->discardButtons(1);
+ }
+ return kTSTerminate;
+ } else {
+ _tag = _vm->getCurrentScene();
+ Control *cursorCursor = _vm->getObjectControl(0x40004);
+ cursorCursor->disappearActor();
+ _vm->_input->discardButtons(1);
+ _vm->startScriptThread(_triggerThreadId, _threadId);
+ _flag = true;
+ return kTSSuspend;
+ }
+}
+
+} // End of namespace Illusions
diff --git a/engines/illusions/causethread_duckman.h b/engines/illusions/causethread_duckman.h
new file mode 100644
index 0000000000..97bf00e7cb
--- /dev/null
+++ b/engines/illusions/causethread_duckman.h
@@ -0,0 +1,45 @@
+/* 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_CAUSETHREAD_DUCKMAN_H
+#define ILLUSIONS_CAUSETHREAD_DUCKMAN_H
+
+#include "illusions/thread.h"
+
+namespace Illusions {
+
+class IllusionsEngine_Duckman;
+
+class CauseThread_Duckman : public Thread {
+public:
+ CauseThread_Duckman(IllusionsEngine_Duckman *vm, uint32 threadId, uint32 callingThreadId, uint notifyFlags,
+ uint32 triggerThreadId);
+ virtual int onUpdate();
+public:
+ IllusionsEngine_Duckman *_vm;
+ bool _flag;
+ uint32 _triggerThreadId;
+};
+
+} // End of namespace Illusions
+
+#endif // ILLUSIONS_CAUSETHREAD_DUCKMAN_H
diff --git a/engines/illusions/cursor_duckman.cpp b/engines/illusions/cursor_duckman.cpp
new file mode 100644
index 0000000000..d23c9ee02c
--- /dev/null
+++ b/engines/illusions/cursor_duckman.cpp
@@ -0,0 +1,82 @@
+/* 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_duckman.h"
+#include "illusions/actor.h"
+#include "illusions/cursor_duckman.h"
+#include "illusions/input.h"
+
+namespace Illusions {
+
+Cursor_Duckman::Cursor_Duckman(IllusionsEngine_Duckman *vm)
+ : _vm(vm) {
+ _status = 1;
+ _control = 0;
+ _x = 320;
+ _y = 240;
+ _cursorNum = 1;
+ _field_10 = 0;
+ _sequenceId = 0;
+}
+
+void Cursor_Duckman::place(Control *control, uint32 sequenceId) {
+ _status = 2;
+ _control = control;
+ _cursorNum = 1;
+ _field_10 = 0;
+ _sequenceId = sequenceId;
+ _visibleCtr = 0;
+ _control->_flags |= 8;
+ setActorIndex(_cursorNum, 1, 0);
+ _vm->_input->setCursorPosition(_control->_actor->_position);
+}
+
+void Cursor_Duckman::setActorIndex(int a2, int a3, int a4) {
+ _control->_actor->_actorIndex = 1;// TODO?!? *((_BYTE *)&stru_42C040[30].y + 2 * ((always0 != 0) + 2 * a2) + a3 + 1);
+}
+
+void Cursor_Duckman::setControl(Control *control) {
+ _control = control;
+}
+
+void Cursor_Duckman::show() {
+ ++_visibleCtr;
+ if (_visibleCtr > 0) {
+ _control->_flags |= 1;
+ _control->_actor->_flags |= 1;
+ if (_control->_actor->_frameIndex) {
+ _control->_actor->_flags |= 0x2000;
+ _control->_actor->_flags |= 0x4000;
+ }
+ _vm->_input->discardButtons(0xFFFF);
+ }
+}
+
+void Cursor_Duckman::hide() {
+ --_visibleCtr;
+ if (_visibleCtr <= 0) {
+ _control->_flags &= ~1;
+ _control->_actor->_flags &= ~1;
+ }
+}
+
+} // End of namespace Illusions
diff --git a/engines/illusions/cursor_duckman.h b/engines/illusions/cursor_duckman.h
new file mode 100644
index 0000000000..152585738b
--- /dev/null
+++ b/engines/illusions/cursor_duckman.h
@@ -0,0 +1,30 @@
+/* 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_CURSOR_H
+#define ILLUSIONS_CURSOR_H
+
+namespace Illusions {
+
+} // End of namespace Illusions
+
+#endif // ILLUSIONS_CURSOR_H
diff --git a/engines/illusions/dictionary.cpp b/engines/illusions/dictionary.cpp
index 2d9d4b4812..5cf4cef652 100644
--- a/engines/illusions/dictionary.cpp
+++ b/engines/illusions/dictionary.cpp
@@ -24,6 +24,7 @@
#include "illusions/dictionary.h"
#include "illusions/actorresource.h"
#include "illusions/backgroundresource.h"
+#include "illusions/fontresource.h"
#include "illusions/talkresource.h"
namespace Illusions {
@@ -40,6 +41,18 @@ ActorType *Dictionary::findActorType(uint32 id) {
return _actorTypes.find(id);
}
+void Dictionary::addFont(uint32 id, FontResource *fontResource) {
+ _fontResources.add(id, fontResource);
+}
+
+void Dictionary::removeFont(uint32 id) {
+ _fontResources.remove(id);
+}
+
+FontResource *Dictionary::findFont(uint32 id) {
+ return _fontResources.find(id);
+}
+
void Dictionary::addSequence(uint32 id, Sequence *sequence) {
_sequences.add(id, sequence);
}
diff --git a/engines/illusions/dictionary.h b/engines/illusions/dictionary.h
index 11b05a6348..63cb9b1750 100644
--- a/engines/illusions/dictionary.h
+++ b/engines/illusions/dictionary.h
@@ -29,6 +29,7 @@ namespace Illusions {
class ActorType;
class Control;
+class FontResource;
class Sequence;
class TalkEntry;
@@ -86,6 +87,10 @@ public:
void removeActorType(uint32 id);
ActorType *findActorType(uint32 id);
+ void addFont(uint32 id, FontResource *fontResource);
+ void removeFont(uint32 id);
+ FontResource *findFont(uint32 id);
+
void addSequence(uint32 id, Sequence *sequence);
void removeSequence(uint32 id);
Sequence *findSequence(uint32 id);
@@ -99,9 +104,10 @@ public:
protected:
DictionaryHashMap<ActorType> _actorTypes;
+ DictionaryHashMap<Control> _controls;
+ DictionaryHashMap<FontResource> _fontResources;
DictionaryHashMap<Sequence> _sequences;
DictionaryHashMap<TalkEntry> _talkEntries;
- DictionaryHashMap<Control> _controls;
};
} // End of namespace Illusions
diff --git a/engines/illusions/fontresource.cpp b/engines/illusions/fontresource.cpp
index e0f48d051c..adfb135da5 100644
--- a/engines/illusions/fontresource.cpp
+++ b/engines/illusions/fontresource.cpp
@@ -22,6 +22,7 @@
#include "illusions/illusions.h"
#include "illusions/fontresource.h"
+#include "illusions/dictionary.h"
namespace Illusions {
@@ -30,11 +31,19 @@ namespace Illusions {
void FontResourceLoader::load(Resource *resource) {
debug("FontResourceLoader::load() Loading font %08X from %s...", resource->_resId, resource->_filename.c_str());
- // TODO
+ // TODO
+ FontResource *fontResource = new FontResource();
+ fontResource->load(resource);
+ resource->_refId = fontResource;
+
+ _vm->_dict->addFont(resource->_resId, fontResource);
}
void FontResourceLoader::unload(Resource *resource) {
+ FontResource *fontResource = _vm->_dict->findFont(resource->_resId);
+ delete fontResource;
+ _vm->_dict->removeFont(resource->_resId);
}
void FontResourceLoader::buildFilename(Resource *resource) {
@@ -46,4 +55,76 @@ bool FontResourceLoader::isFlag(int flag) {
flag == kRlfLoadFile;
}
+// CharInfo
+
+void CharInfo::load(byte *dataStart, Common::SeekableReadStream &stream) {
+ _width = stream.readUint16LE();
+ _field_2 = stream.readUint16LE();
+ uint32 pixelsOffs = stream.readUint32LE();
+ _pixels = dataStart + pixelsOffs;
+ debug("CharInfo::load() _width: %d; _field_2: %d; pixelsOffs: %08X",
+ _width, _field_2, pixelsOffs);
+}
+
+// CharRange
+
+void CharRange::load(byte *dataStart, Common::SeekableReadStream &stream) {
+ _firstChar = stream.readUint16LE();
+ _lastChar = stream.readUint16LE();
+ uint count = _lastChar - _firstChar + 1;
+ uint32 charInfosOffs = stream.readUint32LE();
+ _charInfos = new CharInfo[count];
+ for (uint i = 0; i < count; ++i) {
+ stream.seek(charInfosOffs + i * 8);
+ _charInfos[i].load(dataStart, stream);
+ }
+ debug("CharRange::load() _firstChar: %d; _lastChar: %d; charInfosOffs: %08X",
+ _firstChar, _lastChar, charInfosOffs);
+}
+
+CharInfo *CharRange::getCharInfo(uint16 c) {
+ return &_charInfos[c - _firstChar];
+}
+
+bool CharRange::containsChar(uint16 c) {
+ return c >= _firstChar && c <= _lastChar;
+}
+
+// FontResource
+
+FontResource::FontResource() {
+}
+
+FontResource::~FontResource() {
+}
+
+void FontResource::load(Resource *resource) {
+ byte *data = resource->_data;
+ uint32 dataSize = resource->_dataSize;
+ Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
+
+ _totalSize = stream.readUint32LE();
+ _charHeight = stream.readUint16LE();
+ _field_6 = stream.readUint16LE();
+ _colorIndex = stream.readUint16LE();
+ _lineIncr = stream.readUint16LE();
+ _widthC = stream.readUint16LE();
+ _charRangesCount = stream.readUint16LE();
+ uint32 charRangesOffs = stream.pos();
+ _charRanges = new CharRange[_charRangesCount];
+ for (uint i = 0; i < _charRangesCount; ++i) {
+ stream.seek(charRangesOffs + i * 8);
+ _charRanges[i].load(data, stream);
+ }
+ debug("FontResource::load() _charHeight: %d; _field_6: %d; _colorIndex: %d; _lineIncr: %d; _widthC: %d; _charRangesCount: %d",
+ _charHeight, _field_6, _colorIndex, _lineIncr, _widthC, _charRangesCount);
+}
+
+CharInfo *FontResource::getCharInfo(uint16 c) {
+ for (uint i = 0; i < _charRangesCount; ++i)
+ if (_charRanges[i].containsChar(c))
+ return _charRanges[i].getCharInfo(c);
+ return 0;
+}
+
} // End of namespace Illusions
diff --git a/engines/illusions/fontresource.h b/engines/illusions/fontresource.h
index 66860bb14b..33360d7968 100644
--- a/engines/illusions/fontresource.h
+++ b/engines/illusions/fontresource.h
@@ -42,6 +42,43 @@ protected:
IllusionsEngine *_vm;
};
+// TODO
+
+struct CharInfo {
+ int16 _width;
+ int16 _field_2;
+ byte *_pixels;
+ void load(byte *dataStart, Common::SeekableReadStream &stream);
+};
+
+struct CharRange {
+ uint16 _firstChar;
+ uint16 _lastChar;
+ CharInfo *_charInfos;
+ void load(byte *dataStart, Common::SeekableReadStream &stream);
+ CharInfo *getCharInfo(uint16 c);
+ bool containsChar(uint16 c);
+};
+
+class FontResource {
+public:
+ FontResource();
+ ~FontResource();
+ void load(Resource *resource);
+ CharInfo *getCharInfo(uint16 c);
+ int16 getColorIndex() const { return _colorIndex; }
+public:
+ uint32 _totalSize;
+ int16 _charHeight;
+ int16 _field_6;
+ int16 _colorIndex;
+ int16 _lineIncr;
+ int16 _widthC;
+ uint _charRangesCount;
+ CharRange *_charRanges;
+ CharRange *getCharRange(uint16 c);
+};
+
} // End of namespace Illusions
#endif // ILLUSIONS_FONTRESOURCE_H
diff --git a/engines/illusions/illusions.cpp b/engines/illusions/illusions.cpp
index 4d9f4a0702..f4ba0cd131 100644
--- a/engines/illusions/illusions.cpp
+++ b/engines/illusions/illusions.cpp
@@ -32,6 +32,7 @@
#include "illusions/input.h"
#include "illusions/resourcesystem.h"
#include "illusions/screen.h"
+#include "illusions/screentext.h"
#include "illusions/scriptresource.h"
#include "illusions/scriptman.h"
#include "illusions/soundresource.h"
@@ -159,7 +160,6 @@ int IllusionsEngine::updateGraphics() {
for (Controls::ItemsIterator it = _controls->_controls.begin(); it != _controls->_controls.end(); ++it) {
Control *control = *it;
Actor *actor = control->_actor;
-
if (control->_pauseCtr == 0 && actor && (actor->_flags & 1) && !(actor->_flags & 0x0200)) {
Common::Point drawPosition = control->calcPosition(panPoint);
if (actor->_flags & 0x2000) {
@@ -184,13 +184,11 @@ int IllusionsEngine::updateGraphics() {
}
}
-#if 0 // TODO
- if (_textInfo._surface) {
+ if (_screenText->_surface) {
int16 priority = getPriorityFromBase(99);
- _screen->_drawQueue->insertTextSurface(_textInfo._surface, _textInfo._dimensions,
- _textInfo._position, priority);
+ _screen->_drawQueue->insertTextSurface(_screenText->_surface, _screenText->_dimensions,
+ _screenText->_position, priority);
}
-#endif
return 1;
}
@@ -294,4 +292,20 @@ uint32 IllusionsEngine::clipTextDuration(uint32 duration) {
return duration;
}
+void IllusionsEngine::getDefaultTextDimensions(WidthHeight &dimensions) {
+ dimensions = _defaultTextDimensions;
+}
+
+void IllusionsEngine::setDefaultTextDimensions(WidthHeight &dimensions) {
+ _defaultTextDimensions = dimensions;
+}
+
+void IllusionsEngine::getDefaultTextPosition(Common::Point &position) {
+ position = _defaultTextPosition;
+}
+
+void IllusionsEngine::setDefaultTextPosition(Common::Point &position) {
+ _defaultTextPosition = position;
+}
+
} // End of namespace Illusions
diff --git a/engines/illusions/illusions.h b/engines/illusions/illusions.h
index ff7d2194af..3bfa8765cd 100644
--- a/engines/illusions/illusions.h
+++ b/engines/illusions/illusions.h
@@ -23,6 +23,7 @@
#ifndef ILLUSIONS_ILLUSIONS_H
#define ILLUSIONS_ILLUSIONS_H
+#include "illusions/graphics.h"
#include "audio/mixer.h"
#include "audio/decoders/aiff.h"
#include "common/array.h"
@@ -63,6 +64,7 @@ class Dictionary;
class FramesList;
class Input;
class Screen;
+class ScreenText;
class ScriptOpcodes;
class ScriptResource;
class Sequence;
@@ -97,6 +99,7 @@ public:
void updateEvents();
Screen *_screen;
+ ScreenText *_screenText;
Input *_input;
ActorItems *_actorItems;
BackgroundItems *_backgroundItems;
@@ -118,6 +121,9 @@ public:
int _field8;
uint32 _fieldA, _fieldE;
+ WidthHeight _defaultTextDimensions;
+ Common::Point _defaultTextPosition;
+
int16 _menuChoiceOfs;
int getGameId() const {
@@ -143,7 +149,12 @@ public:
void setCurrFontId(uint32 fontId);
bool checkActiveTalkThreads();
uint32 clipTextDuration(uint32 duration);
+ void getDefaultTextDimensions(WidthHeight &dimensions);
+ void setDefaultTextDimensions(WidthHeight &dimensions);
+ void getDefaultTextPosition(Common::Point &position);
+ void setDefaultTextPosition(Common::Point &position);
+ virtual void setDefaultTextCoords() = 0;
virtual void loadSpecialCode(uint32 resId) = 0;
virtual void unloadSpecialCode(uint32 resId) = 0;
virtual void notifyThreadId(uint32 &threadId) = 0;
@@ -152,14 +163,12 @@ public:
virtual uint32 getPriorityFromBase(int16 priority) = 0;
virtual uint32 getPrevScene() = 0;
virtual uint32 getCurrentScene() = 0;
-
virtual bool isCursorObject(uint32 actorTypeId, uint32 objectId) = 0;
virtual void setCursorControlRoutine(Control *control) = 0;
virtual void placeCursorControl(Control *control, uint32 sequenceId) = 0;
virtual void setCursorControl(Control *control) = 0;
virtual void showCursor() = 0;
virtual void hideCursor() = 0;
-
virtual void startScriptThreadSimple(uint32 threadId, uint32 callingThreadId) = 0;
virtual uint32 startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId,
uint32 value8, uint32 valueC, uint32 value10) = 0;
diff --git a/engines/illusions/illusions_bbdou.cpp b/engines/illusions/illusions_bbdou.cpp
index 84b3876e6c..d5e9713817 100644
--- a/engines/illusions/illusions_bbdou.cpp
+++ b/engines/illusions/illusions_bbdou.cpp
@@ -228,8 +228,9 @@ Common::Error IllusionsEngine_BBDOU::run() {
_globalSceneId = 0x00010003;
+ setDefaultTextCoords();
+
_resSys->loadResource(0x000D0001, 0, 0);
-
startScriptThread(0x00020004, 0, 0, 0, 0);
_doScriptThreadInit = true;
@@ -301,6 +302,15 @@ uint32 IllusionsEngine_BBDOU::causeTrigger(uint32 sceneId, uint32 verbId, uint32
return causeThreadId;
}
+void IllusionsEngine_BBDOU::setDefaultTextCoords() {
+ WidthHeight dimensions;
+ dimensions._width = 480;
+ dimensions._height = 48;
+ Common::Point pt(320, 448);
+ setDefaultTextDimensions(dimensions);
+ setDefaultTextPosition(pt);
+}
+
void IllusionsEngine_BBDOU::loadSpecialCode(uint32 resId) {
_specialCode = new BbdouSpecialCode(this);
_specialCode->init();
diff --git a/engines/illusions/illusions_bbdou.h b/engines/illusions/illusions_bbdou.h
index d50fe4ce1a..05aea8a863 100644
--- a/engines/illusions/illusions_bbdou.h
+++ b/engines/illusions/illusions_bbdou.h
@@ -108,6 +108,8 @@ public:
void causeDeclare(uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback);
uint32 causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId);
+ void setDefaultTextCoords();
+
void loadSpecialCode(uint32 resId);
void unloadSpecialCode(uint32 resId);
void notifyThreadId(uint32 &threadId);
diff --git a/engines/illusions/illusions_duckman.cpp b/engines/illusions/illusions_duckman.cpp
index 74c27889e4..0cd27e8a29 100644
--- a/engines/illusions/illusions_duckman.cpp
+++ b/engines/illusions/illusions_duckman.cpp
@@ -33,6 +33,7 @@
#include "illusions/midiresource.h"
#include "illusions/resourcesystem.h"
#include "illusions/screen.h"
+#include "illusions/screentext.h"
#include "illusions/scriptopcodes_duckman.h"
#include "illusions/scriptresource.h"
#include "illusions/scriptman.h"
@@ -40,11 +41,13 @@
#include "illusions/specialcode.h"
//TODO#include "illusions/bbdou/bbdou_specialcode.h"
#include "illusions/talkresource.h"
+#include "illusions/textdrawer.h"
#include "illusions/thread.h"
#include "illusions/time.h"
#include "illusions/updatefunctions.h"
#include "illusions/abortablethread.h"
+#include "illusions/causethread_duckman.h"
#include "illusions/scriptthread.h"
#include "illusions/talkthread_duckman.h"
#include "illusions/timerthread.h"
@@ -93,6 +96,7 @@ Common::Error IllusionsEngine_Duckman::run() {
_resSys->addResourceLoader(0x00120000, new FontResourceLoader(this));
_screen = new Screen(this, 320, 200, 8);
+ _screenText = new ScreenText(this);
_input = new Input();
_actorItems = new ActorItems(this);
_backgroundItems = new BackgroundItems(this);
@@ -115,11 +119,18 @@ Common::Error IllusionsEngine_Duckman::run() {
_fieldA = 0;
_fieldE = 240;
- _globalSceneId = 0x00010003;
-
- _resSys->loadResource(0x000D0001, 0x00010001, 0);
+ _globalSceneId = 0x00010003;
+ initSpecialCode();
+ setDefaultTextCoords();
+ initCursor();
initActiveScenes();
+
+ _resSys->loadResource(0x120001, 0x00010001, 0);
+ _resSys->loadResource(0x120002, 0x00010001, 0);
+ _resSys->loadResource(0x120003, 0x00010001, 0);
+
+ _resSys->loadResource(0x000D0001, 0x00010001, 0);
startScriptThread(0x00020004, 0);
_doScriptThreadInit = true;
@@ -145,6 +156,7 @@ Common::Error IllusionsEngine_Duckman::run() {
delete _backgroundItems;
delete _actorItems;
delete _input;
+ delete _screenText;
delete _screen;
delete _resSys;
delete _dict;
@@ -164,6 +176,15 @@ bool IllusionsEngine_Duckman::hasFeature(EngineFeature f) const {
*/
}
+void IllusionsEngine_Duckman::setDefaultTextCoords() {
+ WidthHeight dimensions;
+ dimensions._width = 300;
+ dimensions._height = 32;
+ Common::Point pt(160, 176);
+ setDefaultTextDimensions(dimensions);
+ setDefaultTextPosition(pt);
+}
+
void IllusionsEngine_Duckman::loadSpecialCode(uint32 resId) {
//TODO _specialCode = new BbdouSpecialCode(this);
//TODO _specialCode->init();
@@ -229,13 +250,40 @@ void IllusionsEngine_Duckman::setCursorControlRoutine(Control *control) {
}
void IllusionsEngine_Duckman::placeCursorControl(Control *control, uint32 sequenceId) {
+ _cursor._gameState = 2;
+ _cursor._control = control;
+ _cursor._actorIndex = 1;
+ _cursor._savedActorIndex = 1;
+ _cursor._currOverlappedControl = 0;
+ _cursor._sequenceId1 = sequenceId;
+ _cursor._field14[0] = true;
+ _cursor._field14[1] = true;
+ _cursor._field14[2] = false;
+ _cursor._field14[3] = false;
+ _cursor._field14[4] = false;
+ _cursor._field14[5] = false;
+ _cursor._field14[9] = false;
+ _cursor._field14[10] = false;
+ _cursor._field14[11] = false;
+ _cursor._field14[12] = false;
+ _cursor._field14[6] = _cursor._sequenceId2 != 0 && _cursor._objectId != 0;
+ _cursor._field14[7] = false;
+ _cursor._field14[8] = false;
+ _cursor._op113_choiceOfsPtr = 0;
+ _cursor._notifyThreadId30 = 0;
+ _cursor._op113_objectNumCtr = 0;
+ _cursor._overlappedObjectNum = 0;
+ _cursor._field40 = 0;
+ control->_flags |= 8;
+ setCursorActorIndex(_cursor._actorIndex, 1, 0);
+ // TODO Input_setMousePos(cursorControl->actor->position);
// TODO
- control->_actor->_actorIndex = 2;
+ //control->_actor->_actorIndex = 2;
// TODO _cursor->place(control, sequenceId);
}
void IllusionsEngine_Duckman::setCursorControl(Control *control) {
- // TODO
+ _cursor._control = control;
}
void IllusionsEngine_Duckman::showCursor() {
@@ -246,9 +294,108 @@ void IllusionsEngine_Duckman::hideCursor() {
// TODO
}
+void IllusionsEngine_Duckman::initCursor() {
+ _cursor._gameState = 1;
+ _cursor._control = 0;
+ _cursor._position.x = 160;
+ _cursor._position.y = 100;
+ _cursor._objectId = 0;
+ _cursor._actorIndex = 1;
+ _cursor._savedActorIndex = 1;
+ _cursor._currOverlappedControl = 0;
+ _cursor._sequenceId1 = 0;
+ _cursor._sequenceId2 = 0;
+ _cursor._field14[0] = true;
+ _cursor._field14[1] = true;
+ _cursor._field14[2] = false;
+ _cursor._field14[3] = false;
+ _cursor._field14[4] = false;
+ _cursor._field14[5] = false;
+ _cursor._field14[6] = false;
+ _cursor._field14[7] = false;
+ _cursor._field14[8] = false;
+ _cursor._field14[9] = false;
+ _cursor._field14[10] = false;
+ _cursor._field14[11] = false;
+ _cursor._field14[12] = false;
+ _cursor._op113_choiceOfsPtr = 0;
+ _cursor._notifyThreadId30 = 0;
+ _cursor._op113_objectNumCtr = 0;
+ _cursor._overlappedObjectNum = 0;
+ _cursor._field40 = 0;
+}
+
+void IllusionsEngine_Duckman::setCursorActorIndex(int actorIndex, int a, int b) {
+ static int kCursorMap[13][2][2] = {
+ {{ 1, 2}, { 0, 0}},
+ {{ 3, 4}, { 0, 0}},
+ {{ 5, 6}, {13, 14}},
+ {{ 7, 8}, { 0, 0}},
+ {{ 9, 10}, { 0, 0}},
+ {{11, 12}, { 0, 0}},
+ {{ 1, 2}, { 0, 0}},
+ {{ 0, 0}, { 0, 0}},
+ {{ 0, 0}, { 0, 0}},
+ {{15, 16}, { 0, 0}},
+ {{17, 18}, { 0, 0}},
+ {{19, 20}, { 0, 0}},
+ {{21, 22}, { 0, 0}}
+ };
+ _cursor._control->_actor->_actorIndex = kCursorMap[actorIndex - 1][b][a - 1];
+ debug("_cursor._control->_actor->_actorIndex: %d", _cursor._control->_actor->_actorIndex);
+}
+
+void IllusionsEngine_Duckman::enableCursorVerb(int verbNum) {
+ if (verbNum != 7 || _cursor._sequenceId2)
+ _cursor._field14[verbNum - 1] = true;
+}
+
+void IllusionsEngine_Duckman::disableCursorVerb(int verbNum) {
+ _cursor._field14[verbNum - 1] = false;
+ if (_cursor._actorIndex == verbNum) {
+ _cursor._actorIndex = getCursorActorIndex();
+ setCursorActorIndex(_cursor._actorIndex, 1, 0);
+ startCursorSequence();
+ _cursor._currOverlappedControl = 0;
+ }
+}
+
+void IllusionsEngine_Duckman::setCursorHandMode(int mode) {
+ if (mode == 1) {
+ enableCursorVerb(4);
+ disableCursorVerb(1);
+ disableCursorVerb(2);
+ disableCursorVerb(7);
+ _cursor._actorIndex = 4;
+ } else {
+ enableCursorVerb(1);
+ enableCursorVerb(2);
+ enableCursorVerb(7);
+ disableCursorVerb(4);
+ _cursor._actorIndex = 1;
+ }
+ _cursor._control->startSequenceActor(_cursor._sequenceId1, 2, 0);
+ if (_cursor._currOverlappedControl)
+ setCursorActorIndex(_cursor._actorIndex, 2, 0);
+ else
+ setCursorActorIndex(_cursor._actorIndex, 1, 0);
+}
+
void IllusionsEngine_Duckman::cursorControlRoutine(Control *control, uint32 deltaTime) {
control->_actor->_seqCodeValue1 = 100 * deltaTime;
- // TODO
+ if (control->_actor->_flags & 1) {
+ switch (_cursor._gameState) {
+ case 2:
+ updateGameState2();
+ break;
+ case 3:
+ // TODO updateGameState3(cursorControl);
+ break;
+ case 4:
+ // TODO ShellMgr_update(cursorControl);
+ break;
+ }
+ }
}
void IllusionsEngine_Duckman::startScriptThreadSimple(uint32 threadId, uint32 callingThreadId) {
@@ -437,4 +584,225 @@ uint32 IllusionsEngine_Duckman::getObjectActorTypeId(uint32 objectId) {
return _scriptResource->getObjectActorTypeId(objectId);
}
+Common::Point IllusionsEngine_Duckman::convertMousePos(Common::Point mousePos) {
+ Common::Point screenOffsPt = _camera->getScreenOffset();
+ mousePos.x += screenOffsPt.x;
+ mousePos.y += screenOffsPt.y;
+ return mousePos;
+}
+
+void IllusionsEngine_Duckman::startCursorSequence() {
+ // NOTE Calls to startCursorSequence were put after calls to setCursorActorIndex
+ // to make the cursor switch more immediate. In the original these calls are swapped.
+ if (_cursor._actorIndex == 7)
+ _cursor._control->startSequenceActor(_cursor._sequenceId2, 2, 0);
+ else
+ _cursor._control->startSequenceActor(_cursor._sequenceId1, 2, 0);
+}
+
+int IllusionsEngine_Duckman::getCursorActorIndex() {
+ int result = _cursor._actorIndex;
+ do {
+ ++result;
+ if (result > 13)
+ result = 1;
+ } while (!_cursor._field14[result - 1]);
+ return result;
+}
+
+void IllusionsEngine_Duckman::updateGameState2() {
+ Common::Point cursorPos = _input->getCursorPosition();
+ Common::Point convMousePos = convertMousePos(cursorPos);
+ int trackCursorIndex = -1;
+ bool foundOverlapped;
+ Control *overlappedControl;
+
+ _cursor._control->_actor->_position = cursorPos;
+
+ foundOverlapped = _controls->getOverlappedObject(_cursor._control, convMousePos, &overlappedControl, 0);
+
+ if (cursorPos.y < 8 && !_camera->isAtPanLimit(1)) {
+ trackCursorIndex = 10;
+ } else if (cursorPos.y >= 192 && !_camera->isAtPanLimit(2)) {
+ trackCursorIndex = 11;
+ } else if (cursorPos.x < 8 && !_camera->isAtPanLimit(3)) {
+ trackCursorIndex = 12;
+ } else if (cursorPos.x >= 312 && !_camera->isAtPanLimit(4)) {
+ trackCursorIndex = 13;
+ } else if (_cursor._actorIndex == 10 || _cursor._actorIndex == 11 || _cursor._actorIndex == 12 || _cursor._actorIndex == 13) {
+ _cursor._actorIndex = _cursor._savedActorIndex;
+ if (_cursor._currOverlappedControl)
+ setCursorActorIndex(_cursor._actorIndex, 2, 0);
+ else
+ setCursorActorIndex(_cursor._actorIndex, 1, 0);
+ startCursorSequence();
+ }
+
+ if (trackCursorIndex >= 0) {
+ if (_cursor._actorIndex != 10 && _cursor._actorIndex != 11 && _cursor._actorIndex != 12 && _cursor._actorIndex != 13 && _cursor._actorIndex != 3)
+ _cursor._savedActorIndex = _cursor._actorIndex;
+ if (_cursor._actorIndex != trackCursorIndex) {
+ _cursor._actorIndex = trackCursorIndex;
+ setCursorActorIndex(_cursor._actorIndex, 1, 0);
+ startCursorSequence();
+ }
+ _cursor._currOverlappedControl = 0;
+ foundOverlapped = false;
+ }
+
+ if (foundOverlapped) {
+ if (_cursor._currOverlappedControl != overlappedControl) {
+ int cursorValue2 = 0;
+ if (overlappedControl->_flags & 2) {
+ if (_cursor._actorIndex != 3) {
+ _cursor._savedActorIndex = _cursor._actorIndex;
+ _cursor._actorIndex = 3;
+ }
+ if (overlappedControl->_flags & 0x40)
+ cursorValue2 = 1;
+ } else if (_cursor._actorIndex == 3) {
+ _cursor._actorIndex = _cursor._savedActorIndex;
+ }
+ setCursorActorIndex(_cursor._actorIndex, 2, cursorValue2);
+ startCursorSequence();
+ _cursor._currOverlappedControl = overlappedControl;
+ }
+ } else if (_cursor._currOverlappedControl) {
+ if (_cursor._actorIndex == 3)
+ _cursor._actorIndex = _cursor._savedActorIndex;
+ setCursorActorIndex(_cursor._actorIndex, 1, 0);
+ startCursorSequence();
+ _cursor._currOverlappedControl = 0;
+ }
+
+ if (_input->pollButton(1)) {
+ if (_cursor._currOverlappedControl) {
+ runTriggerCause(_cursor._actorIndex, _cursor._objectId, _cursor._currOverlappedControl->_objectId);
+ } else {
+ _cursor._position = convertMousePos(_cursor._control->_actor->_position);
+ // TODO clipMousePos(&_cursor._position);
+ if (_cursor._actorIndex == 10 || _cursor._actorIndex == 11 || _cursor._actorIndex == 12 || _cursor._actorIndex == 13)
+ runTriggerCause(1, _cursor._objectId, 0x40003);
+ else
+ runTriggerCause(_cursor._actorIndex, _cursor._objectId, 0x40003);
+ }
+ } else if (_input->pollButton(2)) {
+ if (_cursor._actorIndex != 3 && _cursor._actorIndex != 10 && _cursor._actorIndex != 11 && _cursor._actorIndex != 12 && _cursor._actorIndex != 13) {
+ int newActorIndex = getCursorActorIndex();
+ debug("newActorIndex = %d", newActorIndex);
+ if (newActorIndex != _cursor._actorIndex) {
+ _cursor._actorIndex = newActorIndex;
+ if (_cursor._currOverlappedControl)
+ setCursorActorIndex(_cursor._actorIndex, 2, 0);
+ else
+ setCursorActorIndex(_cursor._actorIndex, 1, 0);
+ startCursorSequence();
+ }
+ }
+ } else if (_input->pollButton(8)) {
+ if (_cursor._field14[0] == 1) {
+ runTriggerCause(1, 0, _scriptResource->getField6C());
+ } else if (_cursor._field14[1] == 1) {
+ runTriggerCause(2, 0, _scriptResource->getField6C());
+ }
+ }
+
+}
+
+void IllusionsEngine_Duckman::playSoundEffect(int index) {
+ // TODO
+}
+
+bool IllusionsEngine_Duckman::getTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &outThreadId) {
+ ProgInfo *progInfo = _scriptResource->getProgInfo(getCurrentScene() & 0xFFFF);
+ bool found =
+ progInfo->findTriggerCause(verbId, objectId2, objectId, outThreadId) ||
+ progInfo->findTriggerCause(verbId, objectId2, 0x40001, outThreadId);
+ if (!found) {
+ progInfo = _scriptResource->getProgInfo(3);
+ found =
+ progInfo->findTriggerCause(verbId, objectId2, objectId, outThreadId) ||
+ progInfo->findTriggerCause(verbId, objectId2, 0x40001, outThreadId);
+ }
+ return found;
+}
+
+uint32 IllusionsEngine_Duckman::runTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId) {
+ // TODO
+ debug("runTriggerCause(%08X, %08X, %08X)", verbId, objectId2, objectId);
+ uint32 triggerThreadId;
+
+ if (!getTriggerCause(verbId, objectId2, objectId, triggerThreadId))
+ return 0;
+
+ bool flag = false;
+ if (_scriptResource->_properties.get(0x000E003C)) {
+ if (verbId == 7 && objectId == 0x40003 ) {
+ playSoundEffect(7);
+ flag = true;
+ } else if (objectId == 0x40003 ) {
+ playSoundEffect(14);
+ flag = true;
+ } else if (verbId == 3 ) {
+ playSoundEffect(16);
+ flag = true;
+ } else if (verbId == 2 ) {
+ flag = true;
+ }
+ }
+
+ if (!flag) {
+ if (objectId == 0x40003) {
+ playSoundEffect(14);
+ } else if ((verbId == 1 || verbId == 2) && _scriptResource->getField6C() == objectId) {
+ playSoundEffect(15);
+ } else if (verbId == 7 && _scriptResource->getField6C() == objectId) {
+ playSoundEffect(15);
+ } else if (verbId == 1) {
+ playSoundEffect(1);
+ } else if (verbId == 2) {
+ playSoundEffect(2);
+ } else if (verbId == 3) {
+ playSoundEffect(3);
+ } else if (verbId == 4 || verbId == 7) {
+ playSoundEffect(4);
+ } else if (verbId == 9) {
+ playSoundEffect(5);
+ }
+ }
+
+ uint32 tempThreadId = newTempThreadId();
+ debug(2, "Starting cause thread %08X", tempThreadId);
+ CauseThread_Duckman *causeThread = new CauseThread_Duckman(this, tempThreadId, 0, 0,
+ triggerThreadId);
+ _threads->startThread(causeThread);
+
+ return tempThreadId;
+}
+
+// Special code
+
+typedef Common::Functor1Mem<OpCall&, void, IllusionsEngine_Duckman> SpecialCodeFunctionDM;
+#define SPECIAL(id, func) _specialCodeMap[id] = new SpecialCodeFunctionDM(this, &IllusionsEngine_Duckman::func);
+
+void IllusionsEngine_Duckman::initSpecialCode() {
+ SPECIAL(0x00160002, spcSetCursorHandMode);
+}
+
+void IllusionsEngine_Duckman::runSpecialCode(uint32 specialCodeId, OpCall &opCall) {
+ SpecialCodeMapIterator it = _specialCodeMap.find(specialCodeId);
+ if (it != _specialCodeMap.end()) {
+ (*(*it)._value)(opCall);
+ } else {
+ debug("IllusionsEngine_Duckman::runSpecialCode() Unimplemented special code %08X", specialCodeId);
+ notifyThreadId(opCall._threadId);
+ }
+}
+
+void IllusionsEngine_Duckman::spcSetCursorHandMode(OpCall &opCall) {
+ ARG_BYTE(mode);
+ setCursorHandMode(mode);
+ notifyThreadId(opCall._threadId);
+}
+
} // End of namespace Illusions
diff --git a/engines/illusions/illusions_duckman.h b/engines/illusions/illusions_duckman.h
index f70156af88..375407fe09 100644
--- a/engines/illusions/illusions_duckman.h
+++ b/engines/illusions/illusions_duckman.h
@@ -32,6 +32,31 @@ namespace Illusions {
class Dictionary;
class ScriptStack;
+struct Cursor_Duckman {
+ int _gameState;
+ Control *_control;
+ Common::Point _position;
+ uint32 _objectId;
+ int _actorIndex;
+ int _savedActorIndex;
+ bool _field14[14];
+ Control *_currOverlappedControl;
+ uint32 _sequenceId1;
+ uint32 _sequenceId2;
+ uint32 _notifyThreadId30;
+ int16 *_op113_choiceOfsPtr;
+ int _op113_objectNumCtr;
+ uint _overlappedObjectNum;
+ uint32 _field3C;
+ uint32 _field40;
+};
+
+struct OpCall;
+
+typedef Common::Functor1<OpCall&, void> SpecialCodeFunction;
+typedef Common::HashMap<uint32, SpecialCodeFunction*> SpecialCodeMap;
+typedef SpecialCodeMap::iterator SpecialCodeMapIterator;
+
class IllusionsEngine_Duckman : public IllusionsEngine {
public:
IllusionsEngine_Duckman(OSystem *syst, const IllusionsGameDescription *gd);
@@ -55,6 +80,12 @@ public:
uint _activeScenesCount;
uint32 _activeScenes[6];
+ Cursor_Duckman _cursor;
+
+ SpecialCodeMap _specialCodeMap;
+
+ void setDefaultTextCoords();
+
void loadSpecialCode(uint32 resId);
void unloadSpecialCode(uint32 resId);
void notifyThreadId(uint32 &threadId);
@@ -70,6 +101,11 @@ public:
void setCursorControl(Control *control);
void showCursor();
void hideCursor();
+ void initCursor();
+ void setCursorActorIndex(int actorIndex, int a, int b);
+ void enableCursorVerb(int verbNum);
+ void disableCursorVerb(int verbNum);
+ void setCursorHandMode(int mode);
void cursorControlRoutine(Control *control, uint32 deltaTime);
void startScriptThreadSimple(uint32 threadId, uint32 callingThreadId);
@@ -104,6 +140,19 @@ public:
uint32 getObjectActorTypeId(uint32 objectId);
+ Common::Point convertMousePos(Common::Point mousePos);
+ void startCursorSequence();
+ int getCursorActorIndex();
+ void updateGameState2();
+ void playSoundEffect(int index);
+ bool getTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &outThreadId);
+ uint32 runTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId);
+
+ // Special code
+ void initSpecialCode();
+ void runSpecialCode(uint32 specialCodeId, OpCall &opCall);
+ void spcSetCursorHandMode(OpCall &opCall);
+
};
} // End of namespace Illusions
diff --git a/engines/illusions/module.mk b/engines/illusions/module.mk
index 4341732657..f0688d35ad 100644
--- a/engines/illusions/module.mk
+++ b/engines/illusions/module.mk
@@ -10,6 +10,7 @@ MODULE_OBJS := \
bbdou/bbdou_inventory.o \
bbdou/bbdou_specialcode.o \
camera.o \
+ causethread_duckman.o \
cursor.o \
detection.o \
dictionary.o \
@@ -23,6 +24,7 @@ MODULE_OBJS := \
midiresource.o \
resourcesystem.o \
screen.o \
+ screentext.o \
scriptman.o \
scriptopcodes.o \
scriptopcodes_bbdou.o \
@@ -35,6 +37,7 @@ MODULE_OBJS := \
talkresource.o \
talkthread.o \
talkthread_duckman.o \
+ textdrawer.o \
thread.o \
time.o \
timerthread.o \
diff --git a/engines/illusions/screen.cpp b/engines/illusions/screen.cpp
index 0eb78321a9..f4b6982ab8 100644
--- a/engines/illusions/screen.cpp
+++ b/engines/illusions/screen.cpp
@@ -22,6 +22,7 @@
#include "illusions/illusions.h"
#include "illusions/screen.h"
+#include "illusions/fontresource.h"
#include "engines/util.h"
#include "graphics/palette.h"
@@ -315,6 +316,14 @@ void Screen::setPalette(byte *colors, uint start, uint count) {
_needRefreshPalette = true;
}
+void Screen::setPaletteEntry(int16 index, byte r, byte g, byte b) {
+ byte colors[4];
+ colors[0] = r;
+ colors[1] = g;
+ colors[2] = b;
+ setPalette(colors, index, 1);
+}
+
void Screen::getPalette(byte *colors) {
byte *srcPal = _mainPalette;
for (uint i = 0; i < 256; ++i) {
@@ -333,6 +342,26 @@ void Screen::updatePalette() {
}
}
+void Screen::drawText(FontResource *font, Graphics::Surface *surface, int16 x, int16 y, uint16 *text, uint count) {
+ for (uint i = 0; i < count; ++i)
+ x += font->_widthC + drawChar(font, surface, x, y, *text++);
+}
+
+int16 Screen::drawChar(FontResource *font, Graphics::Surface *surface, int16 x, int16 y, uint16 c) {
+ const CharInfo *charInfo = font->getCharInfo(c);
+ const int16 charWidth = charInfo->_width;
+ byte *dst = (byte*)surface->getBasePtr(x, y);
+ byte *pixels = charInfo->_pixels;
+ for (int16 yc = 0; yc < font->_charHeight; ++yc) {
+ for (int16 xc = 0; xc < charWidth; ++xc)
+ if (pixels[xc])
+ dst[xc] = pixels[xc];
+ dst += surface->pitch;
+ pixels += charWidth;
+ }
+ return charWidth;
+}
+
void Screen::setSystemPalette(byte *palette) {
g_system->getPaletteManager()->setPalette(palette, 0, 256);
}
diff --git a/engines/illusions/screen.h b/engines/illusions/screen.h
index 5bd5eb79ce..91750cfba5 100644
--- a/engines/illusions/screen.h
+++ b/engines/illusions/screen.h
@@ -31,7 +31,7 @@
namespace Illusions {
class IllusionsEngine;
-class Screen;
+class FontResource;
struct SpriteDecompressQueueItem {
byte *_drawFlags;
@@ -112,8 +112,11 @@ public:
void decompressSprite(SpriteDecompressQueueItem *item);
void drawSurface(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags);
void setPalette(byte *colors, uint start, uint count);
+ void setPaletteEntry(int16 index, byte r, byte g, byte b);
void getPalette(byte *colors);
void updatePalette();
+ void drawText(FontResource *font, Graphics::Surface *surface, int16 x, int16 y, uint16 *text, uint count);
+ int16 drawChar(FontResource *font, Graphics::Surface *surface, int16 x, int16 y, uint16 c);
int16 getScreenWidth() const { return _backSurface->w; }
int16 getScreenHeight() const { return _backSurface->h; }
public:
diff --git a/engines/illusions/screentext.cpp b/engines/illusions/screentext.cpp
new file mode 100644
index 0000000000..684ab5a426
--- /dev/null
+++ b/engines/illusions/screentext.cpp
@@ -0,0 +1,171 @@
+/* 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/screentext.h"
+#include "illusions/dictionary.h"
+#include "illusions/fontresource.h"
+#include "illusions/screen.h"
+#include "illusions/textdrawer.h"
+#include "engines/util.h"
+#include "graphics/palette.h"
+
+namespace Illusions {
+
+ScreenText::ScreenText(IllusionsEngine *vm)
+ : _vm(vm), _surface(0) {
+}
+
+ScreenText::~ScreenText() {
+}
+
+void ScreenText::getTextInfoDimensions(WidthHeight &textInfoDimensions) {
+ textInfoDimensions = _dimensions;
+}
+
+void ScreenText::setTextInfoPosition(Common::Point position) {
+ _position = position;
+ clipTextInfoPosition(_position);
+}
+
+void ScreenText::updateTextInfoPosition(Common::Point position) {
+ WidthHeight dimensions;
+ getTextInfoDimensions(dimensions);
+ position.x = position.x - dimensions._width / 2;
+ position.y = position.y - dimensions._height / 2;
+ setTextInfoPosition(position);
+}
+
+void ScreenText::clipTextInfoPosition(Common::Point &position) {
+ // TODO Set min/max for BBDOU
+ if (position.x < 2)
+ position.x = 2;
+ else if (position.x + _dimensions._width > 318)
+ position.x = 318 - _dimensions._width;
+ if (position.y < 2)
+ position.y = 2;
+ else if (position.y + _dimensions._height > 198)
+ position.y = 198 - _dimensions._height;
+}
+
+bool ScreenText::refreshScreenText(FontResource *font, WidthHeight dimensions, Common::Point offsPt,
+ uint16 *text, uint textFlags, uint16 color2, uint16 color1, uint16 *&outTextPtr) {
+ TextDrawer textDrawer;
+ bool done = textDrawer.wrapText(font, text, &dimensions, offsPt, textFlags, outTextPtr);
+ _surface = _vm->_screen->allocSurface(dimensions._width, dimensions._height);
+ _dimensions = dimensions;
+ textDrawer.drawText(_vm->_screen, _surface, color2, color1);
+ return done;
+}
+
+bool ScreenText::insertText(uint16 *text, uint32 fontId, WidthHeight dimensions, Common::Point offsPt, uint flags,
+ uint16 color2, uint16 color1, byte colorR, byte colorG, byte colorB, uint16 *&outTextPtr) {
+
+ if (!_screenTexts.empty()) {
+ ScreenTextEntry *screenText = _screenTexts.back();
+ screenText->_info._position = _position;
+ freeTextSurface();
+ }
+
+ ScreenTextEntry *screenText = new ScreenTextEntry();
+ screenText->_info._fontId = fontId;
+ screenText->_info._dimensions = dimensions;
+ screenText->_info._offsPt = offsPt;
+ screenText->_info._flags = 0;
+ if (flags & 8)
+ screenText->_info._flags |= 8;
+ if (flags & 0x10)
+ screenText->_info._flags |= 0x10;
+ if (flags & 1)
+ screenText->_info._flags |= 1;
+ else
+ screenText->_info._flags |= 2;
+ screenText->_info._color2 = color2;
+ screenText->_info._color1 = color1;
+ screenText->_info._colorR = colorR;
+ screenText->_info._colorG = colorG;
+ screenText->_info._colorB = colorB;
+ _screenTexts.push_back(screenText);
+
+ FontResource *font = _vm->_dict->findFont(screenText->_info._fontId);
+ bool done = refreshScreenText(font, screenText->_info._dimensions, screenText->_info._offsPt,
+ text, screenText->_info._flags, screenText->_info._color2, screenText->_info._color1,
+ outTextPtr);
+ _vm->_screen->setPaletteEntry(font->getColorIndex(), screenText->_info._colorR, screenText->_info._colorG, screenText->_info._colorB);
+
+ uint16 *textPart = screenText->_text;
+ while (text != outTextPtr)
+ *textPart++ = *text++;
+ *textPart = 0;
+
+ updateTextInfoPosition(Common::Point(160, 100));
+
+ return done;
+}
+
+void ScreenText::removeText() {
+ freeTextSurface();
+
+ if (!_screenTexts.empty()) {
+ ScreenTextEntry *screenText = _screenTexts.back();
+ delete screenText;
+ _screenTexts.pop_back();
+ }
+
+ if (!_screenTexts.empty()) {
+ ScreenTextEntry *screenText = _screenTexts.back();
+ if (screenText->_info._fontId) {
+ uint16 *outTextPtr;
+ FontResource *font = _vm->_dict->findFont(screenText->_info._fontId);
+ refreshScreenText(font, screenText->_info._dimensions, screenText->_info._offsPt,
+ screenText->_text, screenText->_info._flags, screenText->_info._color2, screenText->_info._color1,
+ outTextPtr);
+ _vm->_screen->setPaletteEntry(font->getColorIndex(), screenText->_info._colorR, screenText->_info._colorG, screenText->_info._colorB);
+ setTextInfoPosition(screenText->_info._position);
+ }
+ }
+
+}
+
+void ScreenText::clearText() {
+
+ if (!_screenTexts.empty()) {
+ ScreenTextEntry *screenText = _screenTexts.back();
+ screenText->_info._position = _position;
+ freeTextSurface();
+ }
+
+ ScreenTextEntry *screenText = new ScreenTextEntry();
+ screenText->_info._fontId = 0;
+ _screenTexts.push_back(screenText);
+
+}
+
+void ScreenText::freeTextSurface() {
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ _surface = 0;
+ }
+}
+
+} // End of namespace Illusions
diff --git a/engines/illusions/screentext.h b/engines/illusions/screentext.h
new file mode 100644
index 0000000000..4340224bdb
--- /dev/null
+++ b/engines/illusions/screentext.h
@@ -0,0 +1,77 @@
+/* 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_SCREENTEXT_H
+#define ILLUSIONS_SCREENTEXT_H
+
+#include "illusions/graphics.h"
+#include "common/list.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+namespace Illusions {
+
+class IllusionsEngine;
+class FontResource;
+
+struct ScreenTextInfo {
+ Common::Point _position;
+ WidthHeight _dimensions;
+ Common::Point _offsPt;
+ uint32 _fontId;
+ uint16 _color2;
+ uint16 _color1;
+ byte _colorR, _colorG, _colorB;
+ uint _flags;
+};
+
+struct ScreenTextEntry {
+ ScreenTextInfo _info;
+ uint16 _text[1024];
+};
+
+class ScreenText {
+public:
+ ScreenText(IllusionsEngine *vm);
+ ~ScreenText();
+ void getTextInfoDimensions(WidthHeight &textInfoDimensions);
+ void setTextInfoPosition(Common::Point position);
+ void updateTextInfoPosition(Common::Point position);
+ void clipTextInfoPosition(Common::Point &position);
+ bool refreshScreenText(FontResource *font, WidthHeight dimensions, Common::Point offsPt,
+ uint16 *text, uint textFlags, uint16 color2, uint16 color1, uint16 *&outTextPtr);
+ bool insertText(uint16 *text, uint32 fontId, WidthHeight dimensions, Common::Point offsPt, uint flags,
+ uint16 color2, uint16 color1, byte colorR, byte colorG, byte colorB, uint16 *&outTextPtr);
+ void removeText();
+ void clearText();
+public:
+ IllusionsEngine *_vm;
+ Common::Point _position;
+ WidthHeight _dimensions;
+ Graphics::Surface *_surface;
+ Common::List<ScreenTextEntry*> _screenTexts;
+ void freeTextSurface();
+};
+
+} // End of namespace Illusions
+
+#endif // ILLUSIONS_SCREENTEXT_H
diff --git a/engines/illusions/scriptopcodes.h b/engines/illusions/scriptopcodes.h
index 1020e618a2..cf20380008 100644
--- a/engines/illusions/scriptopcodes.h
+++ b/engines/illusions/scriptopcodes.h
@@ -61,6 +61,7 @@ protected:
// Convenience macros
#define ARG_SKIP(x) opCall.skip(x);
+#define ARG_BYTE(name) byte name = opCall.readByte(); debug(0, "ARG_BYTE(" #name " = %d)", name);
#define ARG_INT16(name) int16 name = opCall.readSint16(); debug(0, "ARG_INT16(" #name " = %d)", name);
#define ARG_UINT32(name) uint32 name = opCall.readUint32(); debug(0, "ARG_UINT32(" #name " = %08X)", name);
diff --git a/engines/illusions/scriptopcodes_duckman.cpp b/engines/illusions/scriptopcodes_duckman.cpp
index ffe4ac0689..f7e96765be 100644
--- a/engines/illusions/scriptopcodes_duckman.cpp
+++ b/engines/illusions/scriptopcodes_duckman.cpp
@@ -63,14 +63,25 @@ void ScriptOpcodes_Duckman::initOpcodes() {
OPCODE(7, opStartTimerThread);
OPCODE(9, opNotifyThread);
OPCODE(10, opSuspendThread);
+ OPCODE(16, opLoadResource);
+ OPCODE(17, opUnloadResource);
OPCODE(18, opEnterScene18);
OPCODE(20, opChangeScene);
+ OPCODE(22, opStartModalScene);
+ OPCODE(23, opExitModalScene);
OPCODE(24, opEnterScene24);
OPCODE(25, opLeaveScene24);
+ OPCODE(34, opPanToObject);
OPCODE(38, opStartFade);
OPCODE(39, opSetDisplay);
+ OPCODE(40, opSetCameraBounds);
+ OPCODE(48, opSetProperty);
OPCODE(49, opPlaceActor);
+ OPCODE(50, opFaceActor);
+ OPCODE(51, opFaceActorToObject);
OPCODE(52, opStartSequenceActor);
+ OPCODE(54, opStartMoveActor);
+ OPCODE(55, opStartMoveActorToObject);
OPCODE(56, opStartTalkThread);
OPCODE(57, opAppearActor);
OPCODE(58, opDisappearActor);
@@ -102,22 +113,14 @@ void ScriptOpcodes_Duckman::initOpcodes() {
OPCODE(8, opStartTempScriptThread);
OPCODE(14, opSetThreadSceneId);
OPCODE(15, opEndTalkThreads);
- OPCODE(17, opUnloadResource);
OPCODE(20, opEnterScene);
- OPCODE(26, opStartModalScene);
- OPCODE(27, opExitModalScene);
OPCODE(30, opEnterCloseUpScene);
OPCODE(31, opExitCloseUpScene);
OPCODE(32, opPanCenterObject);
- OPCODE(34, opPanToObject);
OPCODE(35, opPanToNamedPoint);
OPCODE(36, opPanToPoint);
OPCODE(37, opPanStop);
OPCODE(43, opClearBlockCounter);
- OPCODE(45, opSetProperty);
- OPCODE(47, opFaceActor);
- OPCODE(48, opFaceActorToObject);
- OPCODE(51, opStartMoveActor);
OPCODE(53, opSetActorToNamedPoint);
OPCODE(63, opSetSelectSfx);
OPCODE(64, opSetMoveSfx);
@@ -206,13 +209,32 @@ void ScriptOpcodes_Duckman::opSuspendThread(ScriptThread *scriptThread, OpCall &
_vm->_threads->suspendTimerThreads(threadId);
}
+void ScriptOpcodes_Duckman::opLoadResource(ScriptThread *scriptThread, OpCall &opCall) {
+ ARG_SKIP(2);
+ ARG_UINT32(resourceId);
+ // NOTE Skipped checking for stalled resources
+ uint32 sceneId = _vm->getCurrentScene();
+ _vm->_resSys->loadResource(resourceId, sceneId, opCall._threadId);
+ _vm->notifyThreadId(opCall._threadId);
+}
+
+void ScriptOpcodes_Duckman::opUnloadResource(ScriptThread *scriptThread, OpCall &opCall) {
+ ARG_SKIP(2);
+ ARG_UINT32(resourceId);
+ // NOTE Skipped checking for stalled resources
+ _vm->_resSys->unloadResourceById(resourceId);
+}
+
void ScriptOpcodes_Duckman::opEnterScene18(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
ARG_UINT32(sceneId);
_vm->enterScene(sceneId, 0);
}
-static uint dsceneId = 0x00010008, dthreadId = 0x00020029;
+//static uint dsceneId = 0, dthreadId = 0;
+static uint dsceneId = 0x00010008, dthreadId = 0x00020029;//Beginning in Jac
+//static uint dsceneId = 0x00010012, dthreadId = 0x0002009D;//Paramount
+//static uint dsceneId = 0x00010039, dthreadId = 0x00020089;//Map
void ScriptOpcodes_Duckman::opChangeScene(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
@@ -234,6 +256,30 @@ void ScriptOpcodes_Duckman::opChangeScene(ScriptThread *scriptThread, OpCall &op
}
}
+void ScriptOpcodes_Duckman::opStartModalScene(ScriptThread *scriptThread, OpCall &opCall) {
+ ARG_SKIP(2);
+ ARG_UINT32(sceneId);
+ ARG_UINT32(threadId);
+ _vm->_input->discardButtons(0xFFFF);
+ _vm->enterPause(_vm->getCurrentScene(), opCall._callerThreadId);
+ _vm->_talkItems->pauseByTag(_vm->getCurrentScene());
+ _vm->enterScene(sceneId, threadId);
+ opCall._result = kTSSuspend;
+}
+
+void ScriptOpcodes_Duckman::opExitModalScene(ScriptThread *scriptThread, OpCall &opCall) {
+ _vm->_input->discardButtons(0xFFFF);
+ if (_vm->_scriptResource->_properties.get(0x000E0027)) {
+ // TODO _vm->startScriptThread2(0x10002, 0x20001, 0);
+ opCall._result = kTSTerminate;
+ } else {
+ _vm->dumpCurrSceneFiles(_vm->getCurrentScene(), opCall._callerThreadId);
+ _vm->exitScene();
+ _vm->leavePause(_vm->getCurrentScene(), opCall._callerThreadId);
+ _vm->_talkItems->unpauseByTag(_vm->getCurrentScene());
+ }
+}
+
void ScriptOpcodes_Duckman::opEnterScene24(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
ARG_UINT32(sceneId);
@@ -249,6 +295,14 @@ void ScriptOpcodes_Duckman::opLeaveScene24(ScriptThread *scriptThread, OpCall &o
_vm->leavePause(_vm->getCurrentScene(), opCall._callerThreadId);
}
+void ScriptOpcodes_Duckman::opPanToObject(ScriptThread *scriptThread, OpCall &opCall) {
+ ARG_INT16(speed);
+ ARG_UINT32(objectId);
+ Control *control = _vm->_dict->getObjectControl(objectId);
+ Common::Point pos = control->getActorPosition();
+ _vm->_camera->panToPoint(pos, speed, opCall._threadId);
+}
+
void ScriptOpcodes_Duckman::opStartFade(ScriptThread *scriptThread, OpCall &opCall) {
ARG_INT16(arg1);
ARG_INT16(arg2);
@@ -266,6 +320,20 @@ void ScriptOpcodes_Duckman::opSetDisplay(ScriptThread *scriptThread, OpCall &opC
_vm->_screen->setDisplayOn(flag != 0);
}
+void ScriptOpcodes_Duckman::opSetCameraBounds(ScriptThread *scriptThread, OpCall &opCall) {
+ ARG_INT16(x1);
+ ARG_INT16(y1);
+ ARG_INT16(x2);
+ ARG_INT16(y2);
+ _vm->_camera->setBounds(Common::Point(x1, y1), Common::Point(x2, y2));
+}
+
+void ScriptOpcodes_Duckman::opSetProperty(ScriptThread *scriptThread, OpCall &opCall) {
+ ARG_INT16(value);
+ ARG_UINT32(propertyId);
+ _vm->_scriptResource->_properties.set(propertyId, value != 0);
+}
+
void ScriptOpcodes_Duckman::opPlaceActor(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
ARG_UINT32(objectId);
@@ -276,6 +344,26 @@ void ScriptOpcodes_Duckman::opPlaceActor(ScriptThread *scriptThread, OpCall &opC
_vm->_controls->placeActor(actorTypeId, pos, sequenceId, objectId, opCall._threadId);
}
+void ScriptOpcodes_Duckman::opFaceActor(ScriptThread *scriptThread, OpCall &opCall) {
+ ARG_INT16(facing);
+ ARG_UINT32(objectId);
+ Control *control = _vm->_dict->getObjectControl(objectId);
+ control->faceActor(facing);
+}
+
+void ScriptOpcodes_Duckman::opFaceActorToObject(ScriptThread *scriptThread, OpCall &opCall) {
+ ARG_SKIP(2);
+ ARG_UINT32(objectId1);
+ ARG_UINT32(objectId2);
+ Control *control1 = _vm->_dict->getObjectControl(objectId1);
+ Control *control2 = _vm->_dict->getObjectControl(objectId2);
+ Common::Point pos1 = control1->getActorPosition();
+ Common::Point pos2 = control2->getActorPosition();
+ uint facing;
+ if (_vm->calcPointDirection(pos1, pos2, facing))
+ control1->faceActor(facing);
+}
+
void ScriptOpcodes_Duckman::opStartSequenceActor(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
ARG_UINT32(objectId);
@@ -285,6 +373,37 @@ void ScriptOpcodes_Duckman::opStartSequenceActor(ScriptThread *scriptThread, OpC
control->startSequenceActor(sequenceId, 2, opCall._threadId);
}
+void ScriptOpcodes_Duckman::opStartMoveActor(ScriptThread *scriptThread, OpCall &opCall) {
+ ARG_SKIP(2);
+ ARG_UINT32(objectId);
+ ARG_UINT32(sequenceId);
+ ARG_UINT32(namedPointId);
+ // NOTE Skipped checking for stalled sequence, not sure if needed
+ Control *control = _vm->_dict->getObjectControl(objectId);
+ Common::Point pos = _vm->getNamedPointPosition(namedPointId);
+ control->startMoveActor(sequenceId, pos, opCall._callerThreadId, opCall._threadId);
+}
+
+void ScriptOpcodes_Duckman::opStartMoveActorToObject(ScriptThread *scriptThread, OpCall &opCall) {
+ ARG_SKIP(2);
+ ARG_UINT32(objectId1);
+ ARG_UINT32(objectId2);
+ ARG_UINT32(sequenceId);
+ Control *control1 = _vm->_dict->getObjectControl(objectId1);
+ Common::Point pos;
+ if (objectId2 == 0x40003) {
+ pos = _vm->_cursor._position;
+ } else {
+ Control *control2 = _vm->_dict->getObjectControl(objectId2);
+ pos = control2->_feetPt;
+ if (control2->_actor) {
+ pos.x += control2->_actor->_position.x;
+ pos.y += control2->_actor->_position.y;
+ }
+ }
+ control1->startMoveActor(sequenceId, pos, opCall._callerThreadId, opCall._threadId);
+}
+
void ScriptOpcodes_Duckman::opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
ARG_UINT32(objectId);
@@ -351,7 +470,7 @@ void ScriptOpcodes_Duckman::opPlayVideo(ScriptThread *scriptThread, OpCall &opCa
void ScriptOpcodes_Duckman::opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
ARG_UINT32(specialCodeId);
-//TODO _vm->_specialCode->run(specialCodeId, opCall);
+ _vm->runSpecialCode(specialCodeId, opCall);
//DEBUG Resume calling thread, later done by the special code
_vm->notifyThreadId(opCall._threadId);
}
@@ -514,21 +633,6 @@ void ScriptOpcodes_Duckman::opEndTalkThreads(ScriptThread *scriptThread, OpCall
_vm->_threads->endTalkThreads();
}
-void ScriptOpcodes_Duckman::opLoadResource(ScriptThread *scriptThread, OpCall &opCall) {
- ARG_SKIP(2);
- ARG_UINT32(resourceId);
- // NOTE Skipped checking for stalled resources
- uint32 sceneId = _vm->getCurrentScene();
- _vm->_resSys->loadResource(resourceId, sceneId, opCall._threadId);
-}
-
-void ScriptOpcodes_Duckman::opUnloadResource(ScriptThread *scriptThread, OpCall &opCall) {
- ARG_SKIP(2);
- ARG_UINT32(resourceId);
- // NOTE Skipped checking for stalled resources
- _vm->_resSys->unloadResourceById(resourceId);
-}
-
void ScriptOpcodes_Duckman::opEnterScene(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
ARG_UINT32(sceneId);
@@ -542,28 +646,6 @@ void ScriptOpcodes_Duckman::opEnterScene(ScriptThread *scriptThread, OpCall &opC
opCall._result = kTSTerminate;
}
-void ScriptOpcodes_Duckman::opStartModalScene(ScriptThread *scriptThread, OpCall &opCall) {
- ARG_SKIP(2);
- ARG_UINT32(sceneId);
- ARG_UINT32(threadId);
- // NOTE Skipped checking for stalled resources
- _vm->_input->discardButtons(0xFFFF);
- _vm->enterPause(opCall._callerThreadId);
- _vm->_talkItems->pauseByTag(_vm->getCurrentScene());
- _vm->enterScene(sceneId, opCall._callerThreadId);
- _vm->startScriptThread(threadId, 0,
- scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10);
- opCall._result = kTSSuspend;
-}
-
-void ScriptOpcodes_Duckman::opExitModalScene(ScriptThread *scriptThread, OpCall &opCall) {
- // NOTE Skipped checking for stalled resources
- _vm->_input->discardButtons(0xFFFF);
- _vm->exitScene(opCall._callerThreadId);
- _vm->leavePause(opCall._callerThreadId);
- _vm->_talkItems->unpauseByTag(_vm->getCurrentScene());
-}
-
void ScriptOpcodes_Duckman::opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
ARG_UINT32(sceneId);
@@ -585,14 +667,6 @@ void ScriptOpcodes_Duckman::opPanCenterObject(ScriptThread *scriptThread, OpCall
_vm->_camera->panCenterObject(objectId, speed);
}
-void ScriptOpcodes_Duckman::opPanToObject(ScriptThread *scriptThread, OpCall &opCall) {
- ARG_INT16(speed);
- ARG_UINT32(objectId);
- Control *control = _vm->_dict->getObjectControl(objectId);
- Common::Point pos = control->getActorPosition();
- _vm->_camera->panToPoint(pos, speed, opCall._threadId);
-}
-
void ScriptOpcodes_Duckman::opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) {
ARG_INT16(speed);
ARG_UINT32(namedPointId);
@@ -616,43 +690,6 @@ void ScriptOpcodes_Duckman::opClearBlockCounter(ScriptThread *scriptThread, OpCa
_vm->_scriptResource->_blockCounters.set(index, 0);
}
-void ScriptOpcodes_Duckman::opSetProperty(ScriptThread *scriptThread, OpCall &opCall) {
- ARG_INT16(value);
- ARG_UINT32(propertyId);
- _vm->_scriptResource->_properties.set(propertyId, value != 0);
-}
-
-void ScriptOpcodes_Duckman::opFaceActor(ScriptThread *scriptThread, OpCall &opCall) {
- ARG_INT16(facing);
- ARG_UINT32(objectId);
- Control *control = _vm->_dict->getObjectControl(objectId);
- control->faceActor(facing);
-}
-
-void ScriptOpcodes_Duckman::opFaceActorToObject(ScriptThread *scriptThread, OpCall &opCall) {
- ARG_SKIP(2);
- ARG_UINT32(objectId1);
- ARG_UINT32(objectId2);
- Control *control1 = _vm->_dict->getObjectControl(objectId1);
- Control *control2 = _vm->_dict->getObjectControl(objectId2);
- Common::Point pos1 = control1->getActorPosition();
- Common::Point pos2 = control2->getActorPosition();
- uint facing;
- if (_vm->calcPointDirection(pos1, pos2, facing))
- control1->faceActor(facing);
-}
-
-void ScriptOpcodes_Duckman::opStartMoveActor(ScriptThread *scriptThread, OpCall &opCall) {
- ARG_SKIP(2);
- ARG_UINT32(objectId);
- ARG_UINT32(sequenceId);
- ARG_UINT32(namedPointId);
- // NOTE Skipped checking for stalled sequence, not sure if needed
- Control *control = _vm->_dict->getObjectControl(objectId);
- Common::Point pos = _vm->getNamedPointPosition(namedPointId);
- control->startMoveActor(sequenceId, pos, opCall._callerThreadId, opCall._threadId);
-}
-
void ScriptOpcodes_Duckman::opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
ARG_UINT32(objectId);
diff --git a/engines/illusions/scriptopcodes_duckman.h b/engines/illusions/scriptopcodes_duckman.h
index a533d7dfbc..2a30c584f3 100644
--- a/engines/illusions/scriptopcodes_duckman.h
+++ b/engines/illusions/scriptopcodes_duckman.h
@@ -49,15 +49,26 @@ protected:
void opStartScriptThread(ScriptThread *scriptThread, OpCall &opCall);
void opNotifyThread(ScriptThread *scriptThread, OpCall &opCall);
void opSuspendThread(ScriptThread *scriptThread, OpCall &opCall);
+ void opLoadResource(ScriptThread *scriptThread, OpCall &opCall);
+ void opUnloadResource(ScriptThread *scriptThread, OpCall &opCall);
void opStartTimerThread(ScriptThread *scriptThread, OpCall &opCall);
void opEnterScene18(ScriptThread *scriptThread, OpCall &opCall);
void opChangeScene(ScriptThread *scriptThread, OpCall &opCall);
+ void opStartModalScene(ScriptThread *scriptThread, OpCall &opCall);
+ void opExitModalScene(ScriptThread *scriptThread, OpCall &opCall);
void opEnterScene24(ScriptThread *scriptThread, OpCall &opCall);
void opLeaveScene24(ScriptThread *scriptThread, OpCall &opCall);
+ void opPanToObject(ScriptThread *scriptThread, OpCall &opCall);
void opStartFade(ScriptThread *scriptThread, OpCall &opCall);
- void opSetDisplay(ScriptThread *scriptThread, OpCall &opCall);
+ void opSetDisplay(ScriptThread *scriptThread, OpCall &opCall);
+ void opSetCameraBounds(ScriptThread *scriptThread, OpCall &opCall);
+ void opSetProperty(ScriptThread *scriptThread, OpCall &opCall);
void opPlaceActor(ScriptThread *scriptThread, OpCall &opCall);
+ void opFaceActor(ScriptThread *scriptThread, OpCall &opCall);
+ void opFaceActorToObject(ScriptThread *scriptThread, OpCall &opCall);
void opStartSequenceActor(ScriptThread *scriptThread, OpCall &opCall);
+ void opStartMoveActor(ScriptThread *scriptThread, OpCall &opCall);
+ void opStartMoveActorToObject(ScriptThread *scriptThread, OpCall &opCall);
void opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall);
void opAppearActor(ScriptThread *scriptThread, OpCall &opCall);
void opDisappearActor(ScriptThread *scriptThread, OpCall &opCall);
@@ -89,23 +100,14 @@ protected:
void opStartTempScriptThread(ScriptThread *scriptThread, OpCall &opCall);
void opSetThreadSceneId(ScriptThread *scriptThread, OpCall &opCall);
void opEndTalkThreads(ScriptThread *scriptThread, OpCall &opCall);
- void opLoadResource(ScriptThread *scriptThread, OpCall &opCall);
- void opUnloadResource(ScriptThread *scriptThread, OpCall &opCall);
void opEnterScene(ScriptThread *scriptThread, OpCall &opCall);
- void opStartModalScene(ScriptThread *scriptThread, OpCall &opCall);
- void opExitModalScene(ScriptThread *scriptThread, OpCall &opCall);
void opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
void opExitCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
void opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall);
- void opPanToObject(ScriptThread *scriptThread, OpCall &opCall);
void opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall);
void opPanToPoint(ScriptThread *scriptThread, OpCall &opCall);
void opPanStop(ScriptThread *scriptThread, OpCall &opCall);
void opClearBlockCounter(ScriptThread *scriptThread, OpCall &opCall);
- void opSetProperty(ScriptThread *scriptThread, OpCall &opCall);
- void opFaceActor(ScriptThread *scriptThread, OpCall &opCall);
- void opFaceActorToObject(ScriptThread *scriptThread, OpCall &opCall);
- void opStartMoveActor(ScriptThread *scriptThread, OpCall &opCall);
void opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall);
void opSetSelectSfx(ScriptThread *scriptThread, OpCall &opCall);
void opSetMoveSfx(ScriptThread *scriptThread, OpCall &opCall);
diff --git a/engines/illusions/scriptresource.cpp b/engines/illusions/scriptresource.cpp
index fb8260f4f2..90658ca165 100644
--- a/engines/illusions/scriptresource.cpp
+++ b/engines/illusions/scriptresource.cpp
@@ -33,7 +33,7 @@ void ScriptResourceLoader::load(Resource *resource) {
ScriptResource *scriptResource = new ScriptResource();
scriptResource->load(resource);
-
+
_vm->_scriptResource = scriptResource;
}
@@ -311,6 +311,9 @@ void ScriptResource::load(Resource *resource) {
}
}
+ stream.seek(0x6C);
+ _field6C = stream.readUint32LE();
+
if (resource->_gameId == kGameIdDuckman)
fixupProgInfosDuckman();
diff --git a/engines/illusions/scriptresource.h b/engines/illusions/scriptresource.h
index f33ac10a41..6452c7c4c5 100644
--- a/engines/illusions/scriptresource.h
+++ b/engines/illusions/scriptresource.h
@@ -114,6 +114,7 @@ public:
byte *getCode(uint32 codeOffs);
ProgInfo *getProgInfo(uint32 index);
uint32 getObjectActorTypeId(uint32 objectId);
+ uint32 getField6C() const { return _field6C; }
public:
byte *_data;
uint32 _dataSize;
@@ -127,6 +128,7 @@ public:
uint32 _soundIds[27];
uint _objectMapCount;
uint32 *_objectMap;
+ uint32 _field6C;
void fixupProgInfosDuckman();
};
diff --git a/engines/illusions/talkthread_duckman.cpp b/engines/illusions/talkthread_duckman.cpp
index 46c11c88b6..fe666a3a29 100644
--- a/engines/illusions/talkthread_duckman.cpp
+++ b/engines/illusions/talkthread_duckman.cpp
@@ -25,6 +25,7 @@
#include "illusions/actor.h"
#include "illusions/dictionary.h"
#include "illusions/input.h"
+#include "illusions/screentext.h"
#include "illusions/scriptman.h"
#include "illusions/talkresource.h"
#include "illusions/time.h"
@@ -109,7 +110,7 @@ int TalkThread_Duckman::onUpdate() {
_status = 4;
// Fallthrough to status 4
- case 4:
+ case 4:
if (!(_flags & 8) ) {
uint32 actorTypeId = _vm->getObjectActorTypeId(_objectId);
// TODO getActorTypeColor(actorTypeId, &_colorR, &_colorG, &_colorB);
@@ -141,7 +142,7 @@ int TalkThread_Duckman::onUpdate() {
if (!(_flags & 4) && !_vm->isVoicePlaying())
_flags |= 4;
if (!(_flags & 8) && isTimerExpired(_textStartTime, _textEndTime)) {
- // TODO _vm->removeText();
+ _vm->_screenText->removeText();
if (_entryText && *_entryText) {
refreshText();
_vm->_input->discardButtons(0x20);
@@ -159,7 +160,7 @@ int TalkThread_Duckman::onUpdate() {
}
if (_objectId && _vm->_input->pollButton(0x20)) {
if (!(_flags & 8)) {
- // TODO largeObj_removeText();
+ _vm->_screenText->removeText();
if (_entryText && *_entryText)
refreshText();
else
@@ -178,13 +179,7 @@ int TalkThread_Duckman::onUpdate() {
}
}
}
- /*
- debug("8: %d", (_flags & 8) != 0);
- debug("4: %d", (_flags & 4) != 0);
- debug("2: %d", (_flags & 2) != 0);
- */
if ((_flags & 8) && (_flags & 2) && (_flags & 4)) {
-debug("TALK DONE");
_vm->_input->discardButtons(0x20);
return kTSTerminate;
}
@@ -226,7 +221,7 @@ void TalkThread_Duckman::onTerminated() {
if (!(_flags & 4))
_vm->stopVoice();
if (!(_flags & 8)) {
- // TODO largeObj_removeText();
+ _vm->_screenText->removeText();
}
if (!(_flags & 2)) {
Control *control = _vm->_dict->getObjectControl(_objectId);
@@ -291,16 +286,17 @@ static char *debugW2I(byte *wstr) {
}
int TalkThread_Duckman::insertText() {
- int charCount = 100;
debug("%08X %08X [%s]", _threadId, _talkId, debugW2I(_currEntryText));
- _entryText = 0;
- // TODO _vm->getDimensions1(&dimensions);
- // TODO _vm->insertText(_currEntryText, 0x00120001, dimensions, 0, 2, 0, 0, _colorR, _colorG, _colorB, 0, &outTextPtr);
- // TODO _vm->charCount = (char *)outTextPtr - (char *)text;
- // TODO _entryText = outTextPtr;
- // TODO _vm->getPoint1(&pt);
- // TODO _vm->updateTextInfoPosition(pt);
- return charCount >> 1;
+ WidthHeight dimensions;
+ _vm->getDefaultTextDimensions(dimensions);
+ uint16 *outTextPtr;
+ _vm->_screenText->insertText((uint16*)_currEntryText, 0x120001, dimensions, Common::Point(0, 0), 2, 0, 0, _colorR, _colorG, _colorB, outTextPtr);
+ _entryText = (byte*)outTextPtr;
+ Common::Point pt;
+ _vm->getDefaultTextPosition(pt);
+ _vm->_screenText->updateTextInfoPosition(pt);
+ int charCount = (_entryText - _currEntryText) / 2;
+ return charCount;
}
TalkEntry *TalkThread_Duckman::getTalkResourceEntry(uint32 talkId) {
diff --git a/engines/illusions/textdrawer.cpp b/engines/illusions/textdrawer.cpp
new file mode 100644
index 0000000000..d3f9379aa9
--- /dev/null
+++ b/engines/illusions/textdrawer.cpp
@@ -0,0 +1,195 @@
+/* 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/textdrawer.h"
+#include "illusions/screen.h"
+
+namespace Illusions {
+
+bool TextDrawer::wrapText(FontResource *font, uint16 *text, WidthHeight *dimensions, Common::Point offsPt,
+ uint textFlags, uint16 *&outTextPtr) {
+ _font = font;
+ _text = text;
+ _dimensions = dimensions;
+ _offsPt = offsPt;
+ _textFlags = textFlags;
+ // TODO Calc max width/height using textFlags (border, shadow)
+ _textLines.clear();
+ bool done = wrapTextIntern(0, 0, dimensions->_width, dimensions->_height, outTextPtr);
+ // TODO Adjust text dimensions
+ return done;
+}
+
+void TextDrawer::drawText(Screen *screen, Graphics::Surface *surface, uint16 color2, uint16 color1) {
+ // TODO Fill box, draw borders and shadow if flags are set
+ for (Common::Array<TextLine>::iterator it = _textLines.begin(); it != _textLines.end(); ++it) {
+ const TextLine &textLine = *it;
+ if (textLine._text)
+ screen->drawText(_font, surface, textLine._x, textLine._y, textLine._text, textLine._length);
+#if 0
+ for (int16 linePos = 0; linePos < textLine._length; ++linePos) {
+ const uint16 c = textLine._text[linePos];
+ debugN("%c", c);
+ }
+ debug(" ");
+#endif
+ }
+}
+
+bool TextDrawer::wrapTextIntern(int16 x, int16 y, int16 maxWidth, int16 maxHeight, uint16 *&outTextPtr) {
+
+ bool lineBreak = false;
+ bool done = false;
+ bool hasChar13 = textHasChar(13);
+
+ uint16 *lineStartText = _text;
+ uint16 *currText = _text;
+ outTextPtr = _text;
+
+ int16 textPosY = y;
+ int16 currLineWidth = 0, currLineLen = 0;
+ int16 currWordWidth = 0, currWordLen = 0;
+ int16 maxLineWidth = 0;
+ int16 spaceWidth = getSpaceWidth();
+
+ while (*currText && !done) {
+
+ currWordWidth = 0;
+ currWordLen = 0;
+ do {
+ currWordWidth += getCharWidth(*currText);
+ ++currText;
+ ++currWordLen;
+ } while (*currText != 32 && *(currText - 1) != 32 && !hasChar13 && *currText != 13 && *currText);
+
+ if (currWordWidth - _font->_widthC > maxWidth) {
+ while (currWordWidth + currLineWidth - _font->_widthC > maxWidth) {
+ --currText;
+ --currWordLen;
+ currWordWidth -= getCharWidth(*currText);
+ }
+ lineBreak = true;
+ }
+
+ if (!lineBreak && currWordWidth + currLineWidth - _font->_widthC > maxWidth) {
+ lineBreak = true;
+ } else {
+ currLineWidth += currWordWidth;
+ currLineLen += currWordLen;
+ if (*currText == 0 || *currText == 13)
+ lineBreak = true;
+ if (lineBreak) {
+ currWordLen = 0;
+ currWordWidth = 0;
+ }
+ }
+
+ while (lineBreak) {
+
+ currLineWidth -= _font->_widthC;
+
+ if (textPosY + _font->_charHeight <= maxHeight) {
+ int16 textPosX;
+
+ if (_textFlags & 2) {
+ textPosX = (_dimensions->_width - currLineWidth) / 2;
+ maxLineWidth = _dimensions->_width;
+ } else {
+ textPosX = x;
+ }
+
+ _textLines.push_back(TextLine(lineStartText, currLineLen, textPosX, textPosY));
+
+ if (*currText == 13) {
+ ++currText;
+ if (*currText == 10)
+ ++currText;
+ while (*currText == 13) {
+ ++currText;
+ if (*currText == 10)
+ ++currText;
+ _textLines.push_back(TextLine());
+ textPosY += _font->_lineIncr + _font->_charHeight;
+ }
+ lineStartText = currText;
+ } else {
+ lineStartText = currText - currWordLen;
+ if (*lineStartText == 32) {
+ ++lineStartText;
+ --currWordLen;
+ currWordWidth -= spaceWidth;
+ }
+ }
+
+ outTextPtr = lineStartText;
+
+ if (maxLineWidth < currLineWidth)
+ maxLineWidth = currLineWidth;
+
+ currLineWidth = currWordWidth;
+ currLineLen = currWordLen;
+ currWordWidth = 0;
+ currWordLen = 0;
+ textPosY += _font->_charHeight + _font->_lineIncr;
+ if (*currText || !currLineLen)
+ lineBreak = false;
+
+ } else {
+ lineBreak = false;
+ done = true;
+ }
+ }
+
+ }
+
+ _dimensions->_width = maxLineWidth;
+ _dimensions->_height = textPosY - _font->_lineIncr;
+
+ return !done;
+}
+
+bool TextDrawer::textHasChar(uint16 c) {
+ // TODO
+ return false;
+}
+
+int16 TextDrawer::getSpaceWidth() {
+ return getCharWidth(32);
+}
+
+int16 TextDrawer::getCharWidth(uint16 c) {
+ return _font->getCharInfo(c)->_width + _font->_widthC;
+}
+
+// TODO
+/*
+int16 offsX = (int16)(offsPt.x * 0.75);
+int16 offsY = (int16)(offsPt.y * 1.5);
+*/
+/*
+if (_surface)
+ drawChar(textPosX, textPosY, c);
+textPosX += getCharWidth(c);
+*/
+
+} // End of namespace Illusions
diff --git a/engines/illusions/textdrawer.h b/engines/illusions/textdrawer.h
new file mode 100644
index 0000000000..a5f6102d28
--- /dev/null
+++ b/engines/illusions/textdrawer.h
@@ -0,0 +1,68 @@
+/* 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_TEXTDRAWER_H
+#define ILLUSIONS_TEXTDRAWER_H
+
+#include "illusions/graphics.h"
+#include "illusions/fontresource.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+namespace Illusions {
+
+class IllusionsEngine;
+
+struct TextLine {
+ uint16 *_text;
+ int16 _length;
+ int16 _x, _y;
+ TextLine() : _text(0) {}
+ TextLine(uint16 *text, int16 length, int16 x, int16 y)
+ : _text(text), _length(length), _x(x), _y(y) {}
+};
+
+class TextDrawer {
+public:
+ bool wrapText(FontResource *font, uint16 *text, WidthHeight *dimensions, Common::Point offsPt,
+ uint textFlags, uint16 *&outTextPtr);
+ void drawText(Screen *screen, Graphics::Surface *surface, uint16 color2, uint16 color1);
+protected:
+ FontResource *_font;
+ uint16 *_text;
+ WidthHeight *_dimensions;
+ Common::Point _offsPt;
+ uint _textFlags;
+ Graphics::Surface *_surface;
+
+ Common::Array<TextLine> _textLines;
+
+ bool textHasChar(uint16 c);
+ int16 getSpaceWidth();
+ int16 getCharWidth(uint16 c);
+ bool wrapTextIntern(int16 x, int16 y, int16 maxWidth, int16 maxHeight, uint16 *&outTextPtr);
+};
+
+} // End of namespace Illusions
+
+#endif // ILLUSIONS_TALKRESOURCE_H
diff --git a/engines/illusions/thread.h b/engines/illusions/thread.h
index e9a9ec3f3f..3a335a27bf 100644
--- a/engines/illusions/thread.h
+++ b/engines/illusions/thread.h
@@ -34,7 +34,8 @@ enum ThreadType {
kTTTimerThread = 2,
kTTTalkThread = 3,
kTTAbortableThread = 4,
- kTTSpecialThread = 5
+ kTTSpecialThread = 5,
+ kTTCauseThread = 6
};
enum ThreadStatus {