diff options
-rw-r--r-- | engines/illusions/actor.cpp | 11 | ||||
-rw-r--r-- | engines/illusions/bbdou/bbdou_cursor.cpp | 28 | ||||
-rw-r--r-- | engines/illusions/bbdou/bbdou_cursor.h | 1 | ||||
-rw-r--r-- | engines/illusions/bbdou/bbdou_specialcode.cpp | 161 | ||||
-rw-r--r-- | engines/illusions/bbdou/bbdou_specialcode.h | 27 | ||||
-rw-r--r-- | engines/illusions/illusions.cpp | 25 | ||||
-rw-r--r-- | engines/illusions/illusions.h | 9 | ||||
-rw-r--r-- | engines/illusions/scriptman.cpp | 7 | ||||
-rw-r--r-- | engines/illusions/scriptman.h | 1 | ||||
-rw-r--r-- | engines/illusions/scriptresource.cpp | 27 | ||||
-rw-r--r-- | engines/illusions/scriptresource.h | 4 |
11 files changed, 279 insertions, 22 deletions
diff --git a/engines/illusions/actor.cpp b/engines/illusions/actor.cpp index fbc5958ecc..b2fccb1c89 100644 --- a/engines/illusions/actor.cpp +++ b/engines/illusions/actor.cpp @@ -861,15 +861,14 @@ bool Controls::getOverlappedObject(Control *control, Common::Point pt, Control * (!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); + //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); + //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); + //debug("overlapped() %08X; pauseCtr: %d; flags: %04X", testControl->_objectId, testControl->_pauseCtr, testControl->_flags); foundControl = testControl; foundPriority = testPriority; } @@ -877,8 +876,6 @@ bool Controls::getOverlappedObject(Control *control, Common::Point pt, Control * } } - debug("OVERLAPPED DONE\n"); - if (foundControl) { if (foundControl->_actor && foundControl->_actor->_parentObjectId && (foundControl->_actor->_flags & 0x40)) { uint32 parentObjectId = foundControl->getSubActorParent(); diff --git a/engines/illusions/bbdou/bbdou_cursor.cpp b/engines/illusions/bbdou/bbdou_cursor.cpp index 16cd82ade6..1c4af97a2c 100644 --- a/engines/illusions/bbdou/bbdou_cursor.cpp +++ b/engines/illusions/bbdou/bbdou_cursor.cpp @@ -72,7 +72,7 @@ void BbdouCursor::init(uint32 objectId, uint32 progResKeywordId) { _data._item10._objectIds[1] = 0; _data._item10._index = 0; _data._item10._flag56 = 0; - + clearCursorDataField14(); control->setActorIndexTo1(); @@ -111,8 +111,32 @@ uint32 BbdouCursor::findCursorSequenceId(uint32 objectId) { return 0; } +void BbdouCursor::setStruct8bsValue(uint32 objectId, int value) { + // TODO Clean this up, preliminary + Struct8b *struct8b = 0; + for (uint i = 0; i < 512; ++i) + if (_cursorStruct8bs[i]._objectId == objectId) { + struct8b = &_cursorStruct8bs[i]; + break; + } + if (!struct8b) { + for (uint i = 0; i < 512; ++i) + if (_cursorStruct8bs[i]._objectId == 0) { + struct8b = &_cursorStruct8bs[i]; + break; + } + } + if (value != 11) { + struct8b->_objectId = objectId; + struct8b->_value = value; + } else if (struct8b->_objectId == objectId) { + struct8b->_objectId = 0; + struct8b->_value = 0; + } +} + int BbdouCursor::findStruct8bsValue(uint32 objectId) { - for (uint i = 0; i < kMaxCursorSequences; ++i) + for (uint i = 0; i < 512; ++i) if (_cursorStruct8bs[i]._objectId == objectId) return _cursorStruct8bs[i]._value; return 11; diff --git a/engines/illusions/bbdou/bbdou_cursor.h b/engines/illusions/bbdou/bbdou_cursor.h index 8f02632857..bd3ba3aea3 100644 --- a/engines/illusions/bbdou/bbdou_cursor.h +++ b/engines/illusions/bbdou/bbdou_cursor.h @@ -92,6 +92,7 @@ public: void disable(uint32 objectId); void addCursorSequence(uint32 objectId, uint32 sequenceId); uint32 findCursorSequenceId(uint32 objectId); + void setStruct8bsValue(uint32 objectId, int value); int findStruct8bsValue(uint32 objectId); void saveInfo(); void restoreInfo(); diff --git a/engines/illusions/bbdou/bbdou_specialcode.cpp b/engines/illusions/bbdou/bbdou_specialcode.cpp index e0d29e7265..62b0a7aca1 100644 --- a/engines/illusions/bbdou/bbdou_specialcode.cpp +++ b/engines/illusions/bbdou/bbdou_specialcode.cpp @@ -33,6 +33,24 @@ namespace Illusions { +CauseThread::CauseThread(IllusionsEngine *vm, uint32 threadId, uint32 callingThreadId, + BbdouSpecialCode *bbdou, uint32 cursorObjectId, uint32 sceneId, uint32 verbId, + uint32 objectId2, uint32 objectId) + : Thread(vm, threadId, callingThreadId, 0), _bbdou(bbdou), _cursorObjectId(cursorObjectId), + _sceneId(sceneId), _verbId(verbId), _objectId2(objectId2), _objectId(objectId) { + _type = kTTSpecialThread; +} + +void CauseThread::onNotify() { + _bbdou->_cursor->_data._causeThreadId1 = 0; + terminate(); +} + +void CauseThread::onTerminated() { + _bbdou->_cursor->_data._causeThreadId1 = 0; + _bbdou->_cursor->enable(_cursorObjectId); +} + // BbdouSpecialCode BbdouSpecialCode::BbdouSpecialCode(IllusionsEngine *vm) @@ -125,7 +143,7 @@ void BbdouSpecialCode::spcSetObjectInteractMode(OpCall &opCall) { ARG_SKIP(4); ARG_UINT32(objectId); ARG_INT16(value); - // TODO Cursor_updateStruct8bs(objectId, v3); + _cursor->setStruct8bsValue(objectId, value); _vm->notifyThreadId(opCall._callerThreadId); } @@ -176,19 +194,26 @@ Common::Point BbdouSpecialCode::getBackgroundCursorPos(Common::Point cursorPos) 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 + if (item10->_playSound48) { + int verbNum = item10->_verbId & 0xFFFF; + int verbNumI = verbNum + 1; + while (1) { + if (verbNumI >= 32) + verbNumI = 0; + if (verbNumI++ == verbNum) + break; + if (item10->_verbActive[verbNumI] && testVerbId(verbNumI | 0x1B0000, always0, currOverlappedObjectId)) { + outVerbId = verbNumI | 0x1B0000; + return true; + } + } + } return false; } @@ -221,21 +246,22 @@ void BbdouSpecialCode::cursorInteractControlRoutine(Control *cursorControl, uint if (cursorData._flags & 1) { foundOverlapped = 0; - } else if (_vm->_scriptMan->_activeScenes.getCurrentScene() == 0x1000D) { + } else if (_vm->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) { + debug("overlappedControl: %p", (void*)overlappedControl); if (overlappedControl->_objectId != cursorData._currOverlappedObjectId) { if (cursorData._item10._playSound48) playSoundEffect(4); resetItem10(cursorControl->_objectId, &cursorData._item10); int value = _cursor->findStruct8bsValue(overlappedControl->_objectId); + debug("object value: %d", value); if (!testValueRange(value)) { if (cursorData._mode == 3) _cursor->restoreInfo(); @@ -346,4 +372,119 @@ bool BbdouSpecialCode::updateTrackingCursor(Control *cursorControl) { return false; } +bool BbdouSpecialCode::testVerbId(uint32 verbId, uint32 holdingObjectId, uint32 overlappedObjectId) { + static const uint32 kVerbIdsEE[] = {0x001B0002, 0x001B0001, 0}; + static const uint32 kVerbIdsE9[] = {0x001B0005, 0}; + static const uint32 kVerbIdsE8[] = {0x001B0005, 0x001B0001, 0}; + static const uint32 kVerbIdsHE[] = {0x001B0003, 0x001B0001, 0}; + static const uint32 kVerbIdsH9[] = {0x001B0003, 0}; + static const uint32 kVerbIdsH8[] = {0x001B0003, 0x001B0001, 0}; + + const uint32 *verbIds; + int value = _cursor->findStruct8bsValue(overlappedObjectId); + + if (holdingObjectId) { + if (value == 9) + verbIds = kVerbIdsH9; + else if (value == 9) + verbIds = kVerbIdsH8; + else + verbIds = kVerbIdsHE; + } else { + if (value == 9) + verbIds = kVerbIdsE9; + else if (value == 8) + verbIds = kVerbIdsE8; + else + verbIds = kVerbIdsEE; + } + + for (; *verbIds; ++verbIds) + if (*verbIds == verbId) + return true; + return false; +} + +bool BbdouSpecialCode::getCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, + uint32 &outVerbId, uint32 &outObjectId2, uint32 &outObjectId) { + bool success = false; + objectId2 = verbId != 0x1B0003 ? 0 : objectId2; + if (_vm->causeIsDeclared(sceneId, verbId, objectId2, objectId)) { + outVerbId = verbId; + outObjectId2 = objectId2; + outObjectId = objectId; + success = true; + } else if (objectId2 != 0 && _vm->causeIsDeclared(sceneId, 0x1B0008, 0, objectId)) { + outVerbId = 0x1B0008; + outObjectId2 = 0; + outObjectId = objectId; + success = true; + } else if (_vm->causeIsDeclared(sceneId, verbId, objectId2, 0x40001)) { + outVerbId = verbId; + outObjectId2 = objectId2; + outObjectId = 0x40001; + success = true; + } else if (objectId2 != 0 && _vm->causeIsDeclared(sceneId, 0x1B0008, 0, 0x40001)) { + outVerbId = 0x1B0008; + outObjectId2 = 0; + outObjectId = 0x40001; + success = true; + } + + if (success) { + debug("getCause() -> %08X %08X %08X", outVerbId, outObjectId2, outObjectId); + } + + return success; +} + +bool BbdouSpecialCode::runCause(Control *cursorControl, CursorData &cursorData, + uint32 verbId, uint32 objectId2, uint32 objectId, int soundIndex) { + debug("runCause(%08X, %08X, %08X)", verbId, objectId2, objectId); + uint32 sceneId = _vm->getCurrentScene(); + uint32 outVerbId, outObjectId2, outObjectId; + bool success = false; + + if (getCause(_vm->getCurrentScene(), verbId, objectId2, objectId, outVerbId, outObjectId2, outObjectId)) { + sceneId = _vm->getCurrentScene(); + success = true; + } else if (getCause(0x10003, verbId, objectId2, objectId, outVerbId, outObjectId2, outObjectId)) { + sceneId = 0x10003; + success = true; + } + + debug("runCause() success: %d", success); + + if (!success) + return false; + + + _cursor->hide(cursorControl->_objectId); + + uint32 threadId = startCauseThread(cursorControl->_objectId, _vm->getCurrentScene(), outVerbId, outObjectId2, outObjectId); + + if (cursorData._field90) { + _vm->_scriptMan->_threads->killThread(cursorData._causeThreadId2); + cursorData._field90 = 0; + } + + if (soundIndex) + playSoundEffect(soundIndex); + + cursorData._causeThreadId1 = _vm->causeTrigger(sceneId, outVerbId, outObjectId2, outObjectId, threadId); + cursorData._causeThreadId2 = cursorData._causeThreadId1; + + return true; +} + +uint32 BbdouSpecialCode::startCauseThread(uint32 cursorObjectId, uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { + uint32 tempThreadId = _vm->_scriptMan->newTempThreadId(); + debug("staring cause thread %08X...", tempThreadId); + CauseThread *causeThread = new CauseThread(_vm, tempThreadId, 0, this, + cursorObjectId, sceneId, verbId, objectId2, objectId); + _vm->_scriptMan->_threads->startThread(causeThread); + causeThread->suspend(); + return tempThreadId; +} + } // End of namespace Illusions diff --git a/engines/illusions/bbdou/bbdou_specialcode.h b/engines/illusions/bbdou/bbdou_specialcode.h index 1dda19fa78..61f6b703da 100644 --- a/engines/illusions/bbdou/bbdou_specialcode.h +++ b/engines/illusions/bbdou/bbdou_specialcode.h @@ -24,6 +24,7 @@ #define ILLUSIONS_BBDOU_BBDOU_SPECIALCODE_H #include "illusions/specialcode.h" +#include "illusions/thread.h" #include "common/hashmap.h" namespace Illusions { @@ -36,6 +37,24 @@ struct Item10; typedef Common::Functor1<OpCall&, void> SpecialCodeFunction; +class BbdouSpecialCode; + +class CauseThread : public Thread { +public: + CauseThread(IllusionsEngine *vm, uint32 threadId, uint32 callingThreadId, + BbdouSpecialCode *bbdou, uint32 cursorObjectId, uint32 sceneId, + uint32 verbId, uint32 objectId2, uint32 objectId); + virtual void onNotify(); + virtual void onTerminated(); +public: + BbdouSpecialCode *_bbdou; + uint32 _cursorObjectId; + uint32 _sceneId; + uint32 _verbId; + uint32 _objectId2; + uint32 _objectId; +}; + class BbdouSpecialCode : public SpecialCode { public: BbdouSpecialCode(IllusionsEngine *vm); @@ -63,14 +82,18 @@ protected: 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); + bool testVerbId(uint32 verbId, uint32 holdingObjectId, uint32 overlappedObjectId); + bool getCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, + uint32 &outVerbId, uint32 &outObjectId2, uint32 &outObjectId); + bool runCause(Control *cursorControl, CursorData &cursorData, + uint32 verbId, uint32 objectId2, uint32 objectId, int soundIndex); + uint32 startCauseThread(uint32 cursorObjectId, uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); }; } // End of namespace Illusions diff --git a/engines/illusions/illusions.cpp b/engines/illusions/illusions.cpp index cf40801fff..5f7bb23b79 100644 --- a/engines/illusions/illusions.cpp +++ b/engines/illusions/illusions.cpp @@ -169,6 +169,7 @@ Common::Error IllusionsEngine::run() { #endif _scriptMan->startScriptThread(0x00020004, 0, 0, 0, 0); + _scriptMan->_doScriptThreadInit = true; //_camera->panToPoint(Common::Point(800, 0), 500, 0); @@ -347,6 +348,26 @@ int IllusionsEngine::getRandom(int max) { return _random->getRandomNumber(max - 1); } +bool IllusionsEngine::causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { + uint32 codeOffs; + // TODO Also search for native trigger functions later (findCauseFunc) + bool r = _scriptMan->findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs); + debug("causeIsDeclared() sceneId: %08X; verbId: %08X; objectId2: %08X; objectId: %08X -> %d", + sceneId, verbId, objectId2, objectId, r); + return r; +} + +uint32 IllusionsEngine::causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId) { + uint32 codeOffs; + uint32 causeThreadId = 0; + // TODO Also search for native trigger functions later and run it (findCauseFunc) + if (_scriptMan->findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs)) { + causeThreadId = _scriptMan->startTempScriptThread(_scriptMan->_scriptResource->getCode(codeOffs), + callingThreadId, verbId, objectId2, objectId); + } + return causeThreadId; +} + int IllusionsEngine::convertPanXCoord(int16 x) { // TODO return 0; @@ -389,4 +410,8 @@ bool IllusionsEngine::isVoicePlaying() { return false; } +uint32 IllusionsEngine::getCurrentScene() { + return _scriptMan->_activeScenes.getCurrentScene(); +} + } // End of namespace Illusions diff --git a/engines/illusions/illusions.h b/engines/illusions/illusions.h index e0f27b0abb..71f7a38d2e 100644 --- a/engines/illusions/illusions.h +++ b/engines/illusions/illusions.h @@ -112,6 +112,11 @@ public: int updateSequences(); int updateGraphics(); int getRandom(int max); + + // TODO Move to ScriptMan? + bool causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); + uint32 causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId); + int convertPanXCoord(int16 x); Common::Point getNamedPointPosition(uint32 namedPointId); void playVideo(uint32 videoId, uint32 objectId, uint32 value, uint32 threadId); @@ -121,7 +126,9 @@ public: bool isVoiceCued(); void startVoice(int volume, int panX); void stopVoice(); - bool isVoicePlaying(); + bool isVoicePlaying(); + + uint32 getCurrentScene(); #if 0 diff --git a/engines/illusions/scriptman.cpp b/engines/illusions/scriptman.cpp index de18dee9dc..27e570a605 100644 --- a/engines/illusions/scriptman.cpp +++ b/engines/illusions/scriptman.cpp @@ -198,6 +198,13 @@ uint32 ScriptMan::startTalkThread(int16 duration, uint32 objectId, uint32 talkId return tempThreadId; } +bool ScriptMan::findTriggerCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs) { + ProgInfo *progInfo = _scriptResource->getProgInfo(sceneId & 0xFFFF); + if (progInfo) + return progInfo->findTriggerCause(verbId, objectId2, objectId, codeOffs); + return false; +} + void ScriptMan::setCurrFontId(uint32 fontId) { _fontId = fontId; } diff --git a/engines/illusions/scriptman.h b/engines/illusions/scriptman.h index bd9f2c71d7..adfc365327 100644 --- a/engines/illusions/scriptman.h +++ b/engines/illusions/scriptman.h @@ -83,6 +83,7 @@ public: uint32 startAbortableThread(byte *scriptCodeIp1, byte *scriptCodeIp2, uint32 callingThreadId); uint32 startTalkThread(int16 duration, uint32 objectId, uint32 talkId, uint32 sequenceId1, uint32 sequenceId2, uint32 namedPointId, uint32 callingThreadId); + bool findTriggerCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs); void setCurrFontId(uint32 fontId); bool checkActiveTalkThreads(); uint32 clipTextDuration(uint32 duration); diff --git a/engines/illusions/scriptresource.cpp b/engines/illusions/scriptresource.cpp index 6aa8ec6c9d..9c4f171c0b 100644 --- a/engines/illusions/scriptresource.cpp +++ b/engines/illusions/scriptresource.cpp @@ -144,6 +144,15 @@ void TriggerObject::load(byte *dataStart, Common::SeekableReadStream &stream) { _causes[i].load(stream); } +bool TriggerObject::findTriggerCause(uint32 verbId, uint32 objectId2, uint32 &codeOffs) { + for (uint i = 0; i < _causesCount; ++i) + if (_causes[i]._verbId == verbId && _causes[i]._objectId2 == objectId2) { + codeOffs = _causes[i]._codeOffs; + return true; + } + return false; +} + // ProgInfo ProgInfo::ProgInfo() @@ -186,6 +195,20 @@ void ProgInfo::load(byte *dataStart, Common::SeekableReadStream &stream) { } } +bool ProgInfo::findTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs) { + TriggerObject *triggerObject = findTriggerObject(objectId); + if (triggerObject) + return triggerObject->findTriggerCause(verbId, objectId2, codeOffs); + return false; +} + +TriggerObject *ProgInfo::findTriggerObject(uint32 objectId) { + for (uint i = 0; i < _triggerObjectsCount; ++i) + if (_triggerObjects[i]._objectId == objectId) + return &_triggerObjects[i]; + return 0; +} + // ScriptResource ScriptResource::ScriptResource() @@ -241,6 +264,10 @@ byte *ScriptResource::getThreadCode(uint32 threadId) { return _data + _codeOffsets[(threadId & 0xFFFF) - 1]; } +byte *ScriptResource::getCode(uint32 codeOffs) { + return _data + codeOffs; +} + ProgInfo *ScriptResource::getProgInfo(uint32 index) { if (index > 0 && index <= _progInfosCount) return &_progInfos[index - 1]; diff --git a/engines/illusions/scriptresource.h b/engines/illusions/scriptresource.h index e2df45a34d..5e2da4574d 100644 --- a/engines/illusions/scriptresource.h +++ b/engines/illusions/scriptresource.h @@ -78,6 +78,7 @@ public: TriggerObject(); ~TriggerObject(); void load(byte *dataStart, Common::SeekableReadStream &stream); + bool findTriggerCause(uint32 verbId, uint32 objectId2, uint32 &codeOffs); public: uint32 _objectId; uint _causesCount; @@ -89,12 +90,14 @@ public: ProgInfo(); ~ProgInfo(); void load(byte *dataStart, Common::SeekableReadStream &stream); + bool findTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs); protected: uint16 _id; uint16 _unk; byte *_name; uint _triggerObjectsCount; TriggerObject *_triggerObjects; + TriggerObject *findTriggerObject(uint32 objectId); }; class ScriptResource { @@ -103,6 +106,7 @@ public: ~ScriptResource(); void load(byte *data, uint32 dataSize); byte *getThreadCode(uint32 threadId); + byte *getCode(uint32 codeOffs); ProgInfo *getProgInfo(uint32 index); public: byte *_data; |