diff options
author | johndoe123 | 2014-04-07 12:58:26 +0200 |
---|---|---|
committer | Eugene Sandulenko | 2018-07-20 06:43:33 +0000 |
commit | 3f15233f78a264e45ce74ecd2db9ed3119b1b654 (patch) | |
tree | 821bda821f8b1d0813e271d682c5c42b59103c59 | |
parent | 6ba5570de52344da602cf02fb83725b468e3d8c5 (diff) | |
download | scummvm-rg350-3f15233f78a264e45ce74ecd2db9ed3119b1b654.tar.gz scummvm-rg350-3f15233f78a264e45ce74ecd2db9ed3119b1b654.tar.bz2 scummvm-rg350-3f15233f78a264e45ce74ecd2db9ed3119b1b654.zip |
ILLUSIONS: Refactor code in preparation for the Duckman engine
31 files changed, 1746 insertions, 1501 deletions
diff --git a/engines/illusions/abortablethread.cpp b/engines/illusions/abortablethread.cpp index 493b81ebd8..5f46ca8423 100644 --- a/engines/illusions/abortablethread.cpp +++ b/engines/illusions/abortablethread.cpp @@ -35,7 +35,7 @@ AbortableThread::AbortableThread(IllusionsEngine *vm, uint32 threadId, uint32 ca : Thread(vm, threadId, callingThreadId, notifyFlags), _scriptThreadId(scriptThreadId), _scriptCodeIp(scriptCodeIp), _status(1) { _type = kTTAbortableThread; - _tag = _vm->_scriptMan->_activeScenes.getCurrentScene(); + _tag = _vm->getCurrentScene(); _vm->_input->discardButtons(8); } @@ -43,9 +43,9 @@ int AbortableThread::onUpdate() { if (_status != 1 || _pauseCtr < 0) return kTSTerminate; if (_vm->_input->pollButton(8)) { - _vm->_scriptMan->_threads->killThread(_scriptThreadId); + _vm->_threads->killThread(_scriptThreadId); ++_pauseCtr; - _vm->_scriptMan->startTempScriptThread(_scriptCodeIp, _threadId, 0, 0, 0); + _vm->startTempScriptThread(_scriptCodeIp, _threadId, 0, 0, 0); _status = 2; return kTSSuspend; } diff --git a/engines/illusions/actor.cpp b/engines/illusions/actor.cpp index 97c8dc0e61..1d9aae0c46 100644 --- a/engines/illusions/actor.cpp +++ b/engines/illusions/actor.cpp @@ -215,7 +215,7 @@ Control::Control(IllusionsEngine *vm) _position.y = 0; _actorTypeId = 0; _actor = 0; - _tag = _vm->_scriptMan->_activeScenes.getCurrentScene(); + _tag = _vm->getCurrentScene(); } Control::~Control() { @@ -574,7 +574,7 @@ void Control::startTalkActor(uint32 sequenceId, byte *entryTblPtr, uint32 thread subControl->_actor->_notifyThreadId2 = threadId; subControl->_actor->_entryTblPtr = entryTblPtr; subControl->_actor->_flags |= 0x80; - Thread *thread = _vm->_scriptMan->_threads->findThread(threadId); + Thread *thread = _vm->_threads->findThread(threadId); thread->sendMessage(kMsgClearSequenceId2, 0); } } @@ -680,7 +680,7 @@ void Control::stopSubSequence(int linkIndex) { _actor->_notifyThreadId2 = 0; } if (notifyThreadId2) { - Thread *talkThread = _vm->_scriptMan->_threads->findThread(notifyThreadId2); + Thread *talkThread = _vm->_threads->findThread(notifyThreadId2); talkThread->sendMessage(kMsgClearSequenceId2, 0); } } diff --git a/engines/illusions/bbdou/bbdou_bubble.cpp b/engines/illusions/bbdou/bbdou_bubble.cpp index cc6019c835..7ccd0ea52c 100644 --- a/engines/illusions/bbdou/bbdou_bubble.cpp +++ b/engines/illusions/bbdou/bbdou_bubble.cpp @@ -20,7 +20,7 @@ * */ -#include "illusions/illusions.h" +#include "illusions/illusions_bbdou.h" #include "illusions/bbdou/bbdou_bubble.h" #include "illusions/actor.h" #include "illusions/camera.h" @@ -29,7 +29,7 @@ namespace Illusions { -BbdouBubble::BbdouBubble(IllusionsEngine *vm, BbdouSpecialCode *bbdou) +BbdouBubble::BbdouBubble(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou) : _vm(vm), _bbdou(bbdou) { } diff --git a/engines/illusions/bbdou/bbdou_bubble.h b/engines/illusions/bbdou/bbdou_bubble.h index 2426c9e1b8..fcf5f51512 100644 --- a/engines/illusions/bbdou/bbdou_bubble.h +++ b/engines/illusions/bbdou/bbdou_bubble.h @@ -28,7 +28,7 @@ namespace Illusions { -class IllusionsEngine; +class IllusionsEngine_BBDOU; class BbdouSpecialCode; class Control; @@ -54,7 +54,7 @@ struct Item141C { class BbdouBubble { public: - BbdouBubble(IllusionsEngine *vm, BbdouSpecialCode *bbdou); + BbdouBubble(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou); ~BbdouBubble(); void init(); void addItem0(uint32 sequenceId1, uint32 sequenceId2, uint32 progResKeywordId, @@ -64,7 +64,7 @@ public: void setup(int16 minCount, Common::Point pt1, Common::Point pt2, uint32 progResKeywordId); uint32 addItem(uint positionIndex, uint32 sequenceId); protected: - IllusionsEngine *_vm; + IllusionsEngine_BBDOU *_vm; BbdouSpecialCode *_bbdou; Common::Array<Item0> _item0s; Item0 *_currItem0; diff --git a/engines/illusions/bbdou/bbdou_cursor.cpp b/engines/illusions/bbdou/bbdou_cursor.cpp index 4aca265f6d..c158472f0c 100644 --- a/engines/illusions/bbdou/bbdou_cursor.cpp +++ b/engines/illusions/bbdou/bbdou_cursor.cpp @@ -20,7 +20,7 @@ * */ -#include "illusions/illusions.h" +#include "illusions/illusions_bbdou.h" #include "illusions/bbdou/bbdou_cursor.h" #include "illusions/bbdou/bbdou_specialcode.h" #include "illusions/actor.h" @@ -33,7 +33,7 @@ namespace Illusions { // NOTE It's assumed there's only one game cursor object // The original stores the _data inside the actor, here it's inside the Cursor class. -BbdouCursor::BbdouCursor(IllusionsEngine *vm, BbdouSpecialCode *bbdou) +BbdouCursor::BbdouCursor(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou) : _vm(vm), _bbdou(bbdou) { } diff --git a/engines/illusions/bbdou/bbdou_cursor.h b/engines/illusions/bbdou/bbdou_cursor.h index 43918e88a8..7b42e4f307 100644 --- a/engines/illusions/bbdou/bbdou_cursor.h +++ b/engines/illusions/bbdou/bbdou_cursor.h @@ -27,7 +27,7 @@ namespace Illusions { -class IllusionsEngine; +class IllusionsEngine_BBDOU; class BbdouSpecialCode; class Control; struct Item10; @@ -85,7 +85,7 @@ const uint kMaxCursorSequences = 100; class BbdouCursor { public: - BbdouCursor(IllusionsEngine *vm, BbdouSpecialCode *bbdou); + BbdouCursor(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou); ~BbdouCursor(); void init(uint32 objectId, uint32 progResKeywordId); void enable(uint32 objectId); @@ -104,7 +104,7 @@ public: uint calcTrackingCursorIndex(uint trackingFlags); bool getTrackingCursorSequenceId(Control *control, uint32 &outSequenceId); public: - IllusionsEngine *_vm; + IllusionsEngine_BBDOU *_vm; BbdouSpecialCode *_bbdou; Control *_control; CursorData _data; diff --git a/engines/illusions/bbdou/bbdou_inventory.cpp b/engines/illusions/bbdou/bbdou_inventory.cpp index 26265a706d..c2ffd99e3e 100644 --- a/engines/illusions/bbdou/bbdou_inventory.cpp +++ b/engines/illusions/bbdou/bbdou_inventory.cpp @@ -20,7 +20,7 @@ * */ -#include "illusions/illusions.h" +#include "illusions/illusions_bbdou.h" #include "illusions/bbdou/bbdou_inventory.h" #include "illusions/bbdou/bbdou_cursor.h" #include "illusions/bbdou/bbdou_specialcode.h" @@ -49,7 +49,7 @@ InventorySlot::InventorySlot(uint32 namedPointId) // InventoryBag -InventoryBag::InventoryBag(IllusionsEngine *vm, uint32 sceneId) +InventoryBag::InventoryBag(IllusionsEngine_BBDOU *vm, uint32 sceneId) : _vm(vm), _sceneId(sceneId), _isActive(false), _fieldA(0) { } @@ -116,7 +116,7 @@ InventorySlot *InventoryBag::findClosestSlot(Common::Point putPos, int index) { // BbdouInventory -BbdouInventory::BbdouInventory(IllusionsEngine *vm, BbdouSpecialCode *bbdou) +BbdouInventory::BbdouInventory(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou) : _vm(vm), _bbdou(bbdou) { } diff --git a/engines/illusions/bbdou/bbdou_inventory.h b/engines/illusions/bbdou/bbdou_inventory.h index e4ee28fc08..27843478e9 100644 --- a/engines/illusions/bbdou/bbdou_inventory.h +++ b/engines/illusions/bbdou/bbdou_inventory.h @@ -29,7 +29,7 @@ namespace Illusions { -class IllusionsEngine; +class IllusionsEngine_BBDOU; class BbdouSpecialCode; class Control; class TriggerFunction; @@ -53,7 +53,7 @@ struct InventorySlot { class InventoryBag { public: - InventoryBag(IllusionsEngine *vm, uint32 sceneId); + InventoryBag(IllusionsEngine_BBDOU *vm, uint32 sceneId); void registerInventorySlot(uint32 namedPointId); bool addInventoryItem(InventoryItem *inventoryItem, InventorySlot *inventorySlot); void removeInventoryItem(InventoryItem *inventoryItem); @@ -64,7 +64,7 @@ protected: public: typedef Common::Array<InventorySlot*> InventorySlots; typedef InventorySlots::iterator InventorySlotsIterator; - IllusionsEngine *_vm; + IllusionsEngine_BBDOU *_vm; uint32 _sceneId; InventorySlots _inventorySlots; bool _isActive; @@ -73,7 +73,7 @@ public: class BbdouInventory { public: - BbdouInventory(IllusionsEngine *vm, BbdouSpecialCode *bbdou); + BbdouInventory(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou); void registerInventoryBag(uint32 sceneId); void registerInventoryItem(uint32 objectId, uint32 sequenceId); void registerInventorySlot(uint32 namedPointId); @@ -92,7 +92,7 @@ public: protected: typedef Common::Array<InventoryItem*> InventoryItems; typedef InventoryItems::iterator InventoryItemsIterator; - IllusionsEngine *_vm; + IllusionsEngine_BBDOU *_vm; BbdouSpecialCode *_bbdou; Common::Array<InventoryBag*> _inventoryBags; InventoryItems _inventoryItems; diff --git a/engines/illusions/bbdou/bbdou_specialcode.cpp b/engines/illusions/bbdou/bbdou_specialcode.cpp index f4c23bb97a..8011b3eb5d 100644 --- a/engines/illusions/bbdou/bbdou_specialcode.cpp +++ b/engines/illusions/bbdou/bbdou_specialcode.cpp @@ -20,7 +20,7 @@ * */ -#include "illusions/illusions.h" +#include "illusions/illusions_bbdou.h" #include "illusions/bbdou/bbdou_specialcode.h" #include "illusions/bbdou/bbdou_bubble.h" #include "illusions/bbdou/bbdou_inventory.h" @@ -50,7 +50,7 @@ static const Struct10 kStruct10s[] = { {0x1B000C, 0, 0, 0}, }; -CauseThread::CauseThread(IllusionsEngine *vm, uint32 threadId, uint32 callingThreadId, +CauseThread::CauseThread(IllusionsEngine_BBDOU *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), @@ -70,8 +70,8 @@ void CauseThread::onTerminated() { // BbdouSpecialCode -BbdouSpecialCode::BbdouSpecialCode(IllusionsEngine *vm) - : SpecialCode(vm) { +BbdouSpecialCode::BbdouSpecialCode(IllusionsEngine_BBDOU *vm) + : _vm(vm) { _bubble = new BbdouBubble(_vm, this); _cursor = new BbdouCursor(_vm, this); _inventory = new BbdouInventory(_vm, this); @@ -121,11 +121,6 @@ void BbdouSpecialCode::run(uint32 specialCodeId, OpCall &opCall) { // Special codes -// Convenience macros -#define ARG_SKIP(x) opCall.skip(x); -#define ARG_INT16(name) int16 name = opCall.readSint16(); debug(1, "ARG_INT16(" #name " = %d)", name); -#define ARG_UINT32(name) uint32 name = opCall.readUint32(); debug(1, "ARG_UINT32(" #name " = %08X)", name); - void BbdouSpecialCode::spcInitCursor(OpCall &opCall) { ARG_UINT32(objectId); ARG_UINT32(progResKeywordId); @@ -226,7 +221,7 @@ void BbdouSpecialCode::spcRemoveInventoryItem(OpCall &opCall) { void BbdouSpecialCode::spcHasInventoryItem(OpCall &opCall) { ARG_UINT32(objectId); - _vm->_scriptMan->_stack.push(_inventory->hasInventoryItem(objectId) ? 1 : 0); + _vm->_stack->push(_inventory->hasInventoryItem(objectId) ? 1 : 0); debug("_inventory->hasInventoryItem(%08X) = %d", objectId, _inventory->hasInventoryItem(objectId)); } @@ -237,7 +232,7 @@ void BbdouSpecialCode::spcCloseInventory(OpCall &opCall) { void BbdouSpecialCode::spcIsCursorHoldingObjectId(OpCall &opCall) { ARG_UINT32(cursorObjectId); ARG_UINT32(objectId); - _vm->_scriptMan->_stack.push(isHoldingObjectId(objectId) ? 1 : 0); + _vm->_stack->push(isHoldingObjectId(objectId) ? 1 : 0); _vm->notifyThreadId(opCall._threadId); } @@ -613,7 +608,7 @@ bool BbdouSpecialCode::runCause(Control *cursorControl, CursorData &cursorData, uint32 threadId = startCauseThread(cursorControl->_objectId, _vm->getCurrentScene(), outVerbId, outObjectId2, outObjectId); if (cursorData._field90) { - _vm->_scriptMan->_threads->killThread(cursorData._causeThreadId2); + _vm->_threads->killThread(cursorData._causeThreadId2); cursorData._field90 = 0; } @@ -627,11 +622,11 @@ bool BbdouSpecialCode::runCause(Control *cursorControl, CursorData &cursorData, } uint32 BbdouSpecialCode::startCauseThread(uint32 cursorObjectId, uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { - uint32 tempThreadId = _vm->_scriptMan->newTempThreadId(); + uint32 tempThreadId = _vm->newTempThreadId(); debug(3, "Starting cause thread %08X...", tempThreadId); CauseThread *causeThread = new CauseThread(_vm, tempThreadId, 0, this, cursorObjectId, sceneId, verbId, objectId2, objectId); - _vm->_scriptMan->_threads->startThread(causeThread); + _vm->_threads->startThread(causeThread); causeThread->suspend(); return tempThreadId; } diff --git a/engines/illusions/bbdou/bbdou_specialcode.h b/engines/illusions/bbdou/bbdou_specialcode.h index f272193bd7..b9080c9810 100644 --- a/engines/illusions/bbdou/bbdou_specialcode.h +++ b/engines/illusions/bbdou/bbdou_specialcode.h @@ -29,7 +29,7 @@ namespace Illusions { -class IllusionsEngine; +class IllusionsEngine_BBDOU; class BbdouBubble; class BbdouCursor; class BbdouInventory; @@ -49,7 +49,7 @@ struct Struct10 { class CauseThread : public Thread { public: - CauseThread(IllusionsEngine *vm, uint32 threadId, uint32 callingThreadId, + CauseThread(IllusionsEngine_BBDOU *vm, uint32 threadId, uint32 callingThreadId, BbdouSpecialCode *bbdou, uint32 cursorObjectId, uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); virtual void onNotify(); @@ -65,13 +65,14 @@ public: class BbdouSpecialCode : public SpecialCode { public: - BbdouSpecialCode(IllusionsEngine *vm); + BbdouSpecialCode(IllusionsEngine_BBDOU *vm); virtual ~BbdouSpecialCode(); virtual void init(); virtual void run(uint32 specialCodeId, OpCall &opCall); public: typedef Common::HashMap<uint32, SpecialCodeFunction*> Map; typedef Map::iterator MapIterator; + IllusionsEngine_BBDOU *_vm; Map _map; BbdouCursor *_cursor; BbdouBubble *_bubble; diff --git a/engines/illusions/detection.cpp b/engines/illusions/detection.cpp index 88d63b4714..c42909c57e 100644 --- a/engines/illusions/detection.cpp +++ b/engines/illusions/detection.cpp @@ -21,6 +21,7 @@ */ #include "illusions/illusions.h" +#include "illusions/illusions_bbdou.h" #include "common/config-manager.h" #include "engines/advancedDetector.h" @@ -37,18 +38,26 @@ static const PlainGameDescriptor illusionsGames[] = { namespace Illusions { -static const ADGameDescription gameDescriptions[] = { +struct IllusionsGameDescription { + ADGameDescription desc; + int gameId; +}; + +static const IllusionsGameDescription gameDescriptions[] = { { - "bbdou", - 0, - AD_ENTRY1s("000D0001.scr", "d0c846d5dccc5607a482c7dcbdf06973", 601980), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - GUIO0() + { + "bbdou", + 0, + AD_ENTRY1s("000D0001.scr", "d0c846d5dccc5607a482c7dcbdf06973", 601980), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO0() + }, + kGameIdBBDOU }, - AD_TABLE_END_MARKER + {AD_TABLE_END_MARKER, 0} }; } // End of namespace Illusions @@ -60,7 +69,7 @@ static const char * const directoryGlobs[] = { class IllusionsMetaEngine : public AdvancedMetaEngine { public: - IllusionsMetaEngine() : AdvancedMetaEngine(Illusions::gameDescriptions, sizeof(ADGameDescription), illusionsGames) { + IllusionsMetaEngine() : AdvancedMetaEngine(Illusions::gameDescriptions, sizeof(Illusions::IllusionsGameDescription), illusionsGames) { _singleid = "illusions"; _maxScanDepth = 2; _directoryGlobs = directoryGlobs; @@ -88,13 +97,13 @@ bool IllusionsMetaEngine::hasFeature(MetaEngineFeature f) const { return false; /* - (f == kSupportsListSaves) || - (f == kSupportsDeleteSave) || - (f == kSupportsLoadingDuringStartup) || - (f == kSavesSupportMetaInfo) || - (f == kSavesSupportThumbnail) || - (f == kSavesSupportCreationDate); - */ + (f == kSupportsListSaves) || + (f == kSupportsDeleteSave) || + (f == kSupportsLoadingDuringStartup) || + (f == kSavesSupportMetaInfo) || + (f == kSavesSupportThumbnail) || + (f == kSavesSupportCreationDate); + */ } #if 0 @@ -159,8 +168,16 @@ SaveStateDescriptor IllusionsMetaEngine::querySaveMetaInfos(const char *target, #endif bool IllusionsMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { - if (desc) { - *engine = new Illusions::IllusionsEngine(syst, desc); + const Illusions::IllusionsGameDescription *gd = (const Illusions::IllusionsGameDescription *)desc; + if (gd) { + switch (gd->gameId) { + case Illusions::kGameIdBBDOU: + *engine = new Illusions::IllusionsEngine_BBDOU(syst, desc); + break; + default: + error("Unknown game id"); + break; + } } return desc != 0; } diff --git a/engines/illusions/illusions.cpp b/engines/illusions/illusions.cpp index a024b8da94..60d9b5bd6a 100644 --- a/engines/illusions/illusions.cpp +++ b/engines/illusions/illusions.cpp @@ -41,6 +41,8 @@ #include "illusions/time.h" #include "illusions/updatefunctions.h" +#include "illusions/talkthread.h" + #include "audio/audiostream.h" #include "common/config-manager.h" #include "common/debug-channels.h" @@ -71,102 +73,6 @@ IllusionsEngine::~IllusionsEngine() { } -Common::Error IllusionsEngine::run() { - - // Init search paths - const Common::FSNode gameDataDir(ConfMan.get("path")); - SearchMan.addSubDirectoryMatching(gameDataDir, "music"); - SearchMan.addSubDirectoryMatching(gameDataDir, "resource"); - SearchMan.addSubDirectoryMatching(gameDataDir, "resrem"); - SearchMan.addSubDirectoryMatching(gameDataDir, "savegame"); - SearchMan.addSubDirectoryMatching(gameDataDir, "sfx"); - SearchMan.addSubDirectoryMatching(gameDataDir, "video"); - SearchMan.addSubDirectoryMatching(gameDataDir, "voice"); - - Graphics::PixelFormat pixelFormat16(2, 5, 6, 5, 0, 11, 5, 0, 0); - initGraphics(640, 480, true, &pixelFormat16); - - _dict = new Dictionary(); - - _resSys = new ResourceSystem(); - _resSys->addResourceLoader(0x00060000, new ActorResourceLoader(this)); - _resSys->addResourceLoader(0x00080000, new SoundGroupResourceLoader(this)); - _resSys->addResourceLoader(0x000D0000, new ScriptResourceLoader(this)); - _resSys->addResourceLoader(0x000F0000, new TalkResourceLoader(this)); - _resSys->addResourceLoader(0x00100000, new ActorResourceLoader(this)); - _resSys->addResourceLoader(0x00110000, new BackgroundResourceLoader(this)); - _resSys->addResourceLoader(0x00120000, new FontResourceLoader(this)); - _resSys->addResourceLoader(0x00170000, new SpecialCodeLoader(this)); - - _screen = new Screen(this); - _input = new Input(); - _scriptMan = new ScriptMan(this); - _actorItems = new ActorItems(this); - _backgroundItems = new BackgroundItems(this); - _camera = new Camera(this); - _controls = new Controls(this); - _cursor = new Cursor(this); - _talkItems = new TalkItems(this); - _triggerFunctions = new TriggerFunctions(); - - // TODO Move to own class - _resGetCtr = 0; - _unpauseControlActorFlag = false; - _lastUpdateTime = 0; - -#if 1 - // Actor/graphics/script test - - /* TODO 0x0010000B LinkIndex 0x00060AAB 0x00060556 - */ - - _scriptMan->_globalSceneId = 0x00010003; - - _resSys->loadResource(0x000D0001, 0, 0); - - _scriptMan->startScriptThread(0x00020004, 0, 0, 0, 0); - _scriptMan->_doScriptThreadInit = true; - - while (!shouldQuit()) { - _scriptMan->_threads->updateThreads(); - updateActors(); - updateSequences(); - updateGraphics(); - _screen->updateSprites(); - _system->updateScreen(); - updateEvents(); - _system->delayMillis(10); - } -#endif - - delete _triggerFunctions; - delete _talkItems; - delete _cursor; - delete _controls; - delete _camera; - delete _backgroundItems; - delete _actorItems; - delete _scriptMan; - delete _input; - delete _screen; - delete _resSys; - delete _dict; - - debug("Ok"); - - return Common::kNoError; -} - -bool IllusionsEngine::hasFeature(EngineFeature f) const { - return - false; - /* - (f == kSupportsRTL) || - (f == kSupportsLoadingDuringRuntime) || - (f == kSupportsSavingDuringRuntime); - */ -} - void IllusionsEngine::updateEvents() { Common::Event event; while (_eventMan->pollEvent(event)) { @@ -182,20 +88,12 @@ void IllusionsEngine::updateEvents() { } Common::Point *IllusionsEngine::getObjectActorPositionPtr(uint32 objectId) { - Control *control = _dict->getObjectControl(objectId); + Control *control = getObjectControl(objectId); if (control && control->_actor) return &control->_actor->_position; return 0; } -void IllusionsEngine::notifyThreadId(uint32 &threadId) { - if (threadId) { - uint32 tempThreadId = threadId; - threadId = 0; - _scriptMan->_threads->notifyId(tempThreadId); - } -} - uint32 IllusionsEngine::getElapsedUpdateTime() { uint32 result = 0; uint32 currTime = getCurrentTime(); @@ -301,54 +199,11 @@ int IllusionsEngine::getRandom(int max) { return _random->getRandomNumber(max - 1); } -bool IllusionsEngine::causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { - uint32 codeOffs; - bool r = - _triggerFunctions->find(sceneId, verbId, objectId2, objectId) || - _scriptMan->findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs); - debug(3, "causeIsDeclared() sceneId: %08X; verbId: %08X; objectId2: %08X; objectId: %08X -> %d", - sceneId, verbId, objectId2, objectId, r); - return r; -} - -void IllusionsEngine::causeDeclare(uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) { - _triggerFunctions->add(getCurrentScene(), verbId, objectId2, objectId, callback); -} - -uint32 IllusionsEngine::causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId) { - uint32 codeOffs; - uint32 causeThreadId = 0; - TriggerFunction *triggerFunction = _triggerFunctions->find(sceneId, verbId, objectId2, objectId); - if (triggerFunction) { - triggerFunction->run(callingThreadId); - } else if (_scriptMan->findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs)) { - //debug("Run cause at %08X", codeOffs); - causeThreadId = _scriptMan->startTempScriptThread(_scriptMan->_scriptResource->getCode(codeOffs), - callingThreadId, verbId, objectId2, objectId); - } - return causeThreadId; -} - int IllusionsEngine::convertPanXCoord(int16 x) { // TODO return 0; } -Common::Point IllusionsEngine::getNamedPointPosition(uint32 namedPointId) { - Common::Point pt; - if (_backgroundItems->findActiveBackgroundNamedPoint(namedPointId, pt) || - _actorItems->findNamedPoint(namedPointId, pt) || - _controls->findNamedPoint(namedPointId, pt)) - return pt; - // TODO - //debug("getNamedPointPosition(%08X) UNKNOWN", namedPointId); - return Common::Point(0, 0); -} - -uint32 IllusionsEngine::getPriorityFromBase(int16 priority) { - return 32000000 * priority; -} - bool IllusionsEngine::calcPointDirection(Common::Point &srcPt, Common::Point &dstPt, uint &facing) { facing = 0; uint xd = 0, yd = 0; @@ -413,8 +268,30 @@ bool IllusionsEngine::isVoicePlaying() { return false; } -uint32 IllusionsEngine::getCurrentScene() { - return _scriptMan->_activeScenes.getCurrentScene(); +void IllusionsEngine::setCurrFontId(uint32 fontId) { + _fontId = fontId; +} + +bool IllusionsEngine::checkActiveTalkThreads() { + return _threads->isActiveThread(kMsgQueryTalkThreadActive); +} + +uint32 IllusionsEngine::clipTextDuration(uint32 duration) { + switch (_field8) { + case 2: + if (duration == 0) + duration = 240; + break; + case 3: + if (duration < _fieldA) + duration = _fieldA; + break; + case 4: + if (duration > _fieldA) + duration = _fieldA; + break; + } + return duration; } } // End of namespace Illusions diff --git a/engines/illusions/illusions.h b/engines/illusions/illusions.h index 08a9f760ef..a9b8555c50 100644 --- a/engines/illusions/illusions.h +++ b/engines/illusions/illusions.h @@ -62,25 +62,23 @@ class Dictionary; class FramesList; class Input; class Screen; +class ScriptOpcodes; class ScriptResource; -class ScriptMan; class Sequence; class SpecialCode; class TalkItems; -class TriggerFunctions; -class TriggerFunction; +class ThreadList; -typedef Common::Functor2<TriggerFunction*, uint32, void> TriggerFunctionCallback; +enum { + kGameIdBBDOU = 1, + kGameIdDuckman = 2 +}; class IllusionsEngine : public Engine { -protected: - Common::Error run(); - virtual bool hasFeature(EngineFeature f) const; public: IllusionsEngine(OSystem *syst, const ADGameDescription *gd); ~IllusionsEngine(); const Common::String getTargetName() { return _targetName; } - private: const ADGameDescription *_gameDescription; Graphics::PixelFormat _pixelFormat; @@ -93,51 +91,61 @@ public: Screen *_screen; Input *_input; - ScriptMan *_scriptMan; ActorItems *_actorItems; BackgroundItems *_backgroundItems; Camera *_camera; Controls *_controls; - Cursor *_cursor; TalkItems *_talkItems; + ScriptOpcodes *_scriptOpcodes; SpecialCode *_specialCode; - TriggerFunctions *_triggerFunctions; + ThreadList *_threads; + Cursor *_cursor; + + ScriptResource *_scriptResource; int _resGetCtr; uint32 _resGetTime; bool _unpauseControlActorFlag; uint32 _lastUpdateTime; + uint32 _fontId; + int _field8; + uint32 _fieldA, _fieldE; + + int16 _menuChoiceOfs; + Common::Point *getObjectActorPositionPtr(uint32 objectId); - - void notifyThreadId(uint32 &threadId); - uint32 getElapsedUpdateTime(); int updateActors(); int updateSequences(); int updateGraphics(); int getRandom(int max); - - // TODO Move to ScriptMan? - bool causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); - void causeDeclare(uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback); - uint32 causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId); - int convertPanXCoord(int16 x); - Common::Point getNamedPointPosition(uint32 namedPointId); - uint32 getPriorityFromBase(int16 priority); bool calcPointDirection(Common::Point &srcPt, Common::Point &dstPt, uint &facing); - void playVideo(uint32 videoId, uint32 objectId, uint32 value, uint32 threadId); - bool isSoundActive(); bool cueVoice(byte *voiceName); bool isVoiceCued(); void startVoice(int volume, int panX); void stopVoice(); bool isVoicePlaying(); + + void setCurrFontId(uint32 fontId); + bool checkActiveTalkThreads(); + uint32 clipTextDuration(uint32 duration); - uint32 getCurrentScene(); + virtual void loadSpecialCode(uint32 resId) = 0; + virtual void unloadSpecialCode(uint32 resId) = 0; + virtual void notifyThreadId(uint32 &threadId) = 0; + virtual Control *getObjectControl(uint32 objectId) = 0; + virtual Common::Point getNamedPointPosition(uint32 namedPointId) = 0; + virtual uint32 getPriorityFromBase(int16 priority) = 0; + virtual uint32 getPrevScene() = 0; + virtual uint32 getCurrentScene() = 0; + + virtual void startScriptThreadSimple(uint32 threadId, uint32 callingThreadId) = 0; + virtual uint32 startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId, + uint32 value8, uint32 valueC, uint32 value10) = 0; #if 0 diff --git a/engines/illusions/illusions_bbdou.cpp b/engines/illusions/illusions_bbdou.cpp new file mode 100644 index 0000000000..76d476aa50 --- /dev/null +++ b/engines/illusions/illusions_bbdou.cpp @@ -0,0 +1,516 @@ +/* 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_bbdou.h" +#include "illusions/actor.h" +#include "illusions/actorresource.h" +#include "illusions/backgroundresource.h" +#include "illusions/camera.h" +#include "illusions/cursor.h" +#include "illusions/dictionary.h" +#include "illusions/fontresource.h" +#include "illusions/graphics.h" +#include "illusions/input.h" +#include "illusions/resourcesystem.h" +#include "illusions/screen.h" +#include "illusions/scriptopcodes_bbdou.h" +#include "illusions/scriptresource.h" +#include "illusions/scriptman.h" +#include "illusions/soundresource.h" +#include "illusions/specialcode.h" +#include "illusions/bbdou/bbdou_specialcode.h" +#include "illusions/talkresource.h" +#include "illusions/thread.h" +#include "illusions/time.h" +#include "illusions/updatefunctions.h" + +#include "illusions/abortablethread.h" +#include "illusions/scriptthread.h" +#include "illusions/talkthread.h" +#include "illusions/timerthread.h" + +#include "audio/audiostream.h" +#include "common/config-manager.h" +#include "common/debug-channels.h" +#include "common/error.h" +#include "common/fs.h" +#include "common/timer.h" +#include "engines/util.h" +#include "graphics/cursorman.h" +#include "graphics/font.h" +#include "graphics/fontman.h" +#include "graphics/palette.h" +#include "graphics/surface.h" + +namespace Illusions { + +// TriggerFunction + +TriggerFunction::TriggerFunction(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) + : _sceneId(sceneId), _verbId(verbId), _objectId2(objectId2), _objectId(objectId), _callback(callback) { +} + +TriggerFunction::~TriggerFunction() { + delete _callback; +} + +void TriggerFunction::run(uint32 callingThreadId) { + (*_callback)(this, callingThreadId); +} + +// TriggerFunctions + +void TriggerFunctions::add(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) { + ItemsIterator it = findInternal(sceneId, verbId, objectId2, objectId); + if (it != _triggerFunctions.end()) { + delete *it; + _triggerFunctions.erase(it); + } + _triggerFunctions.push_back(new TriggerFunction(sceneId, verbId, objectId2, objectId, callback)); +} + +TriggerFunction *TriggerFunctions::find(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { + ItemsIterator it = findInternal(sceneId, verbId, objectId2, objectId); + if (it != _triggerFunctions.end()) + return (*it); + return 0; +} + +void TriggerFunctions::removeBySceneId(uint32 sceneId) { + ItemsIterator it = _triggerFunctions.begin(); + while (it != _triggerFunctions.end()) { + if ((*it)->_sceneId == sceneId) { + delete *it; + it = _triggerFunctions.erase(it); + } else + ++it; + } +} + +TriggerFunctions::ItemsIterator TriggerFunctions::findInternal(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { + ItemsIterator it = _triggerFunctions.begin(); + for (; it != _triggerFunctions.end(); ++it) { + TriggerFunction *triggerFunction = *it; + if (triggerFunction->_sceneId == sceneId && triggerFunction->_verbId == verbId && + triggerFunction->_objectId2 == objectId2 && triggerFunction->_objectId == objectId) + break; + } + return it; +} + +// ActiveScenes + +ActiveScenes::ActiveScenes() { + clear(); +} + +void ActiveScenes::clear() { + _stack.clear(); +} + +void ActiveScenes::push(uint32 sceneId) { + ActiveScene activeScene; + activeScene._sceneId = sceneId; + activeScene._pauseCtr = 0; + _stack.push(activeScene); +} + +void ActiveScenes::pop() { + _stack.pop(); +} + +void ActiveScenes::pauseActiveScene() { + ++_stack.top()._pauseCtr; +} + +void ActiveScenes::unpauseActiveScene() { + --_stack.top()._pauseCtr; +} + +uint ActiveScenes::getActiveScenesCount() { + return _stack.size(); +} + +void ActiveScenes::getActiveSceneInfo(uint index, uint32 *sceneId, int *pauseCtr) { + if (sceneId) + *sceneId = _stack[index - 1]._sceneId; + if (pauseCtr) + *pauseCtr = _stack[index - 1]._pauseCtr; +} + +uint32 ActiveScenes::getCurrentScene() { + if (_stack.size() > 0) + return _stack.top()._sceneId; + return 0; +} + +bool ActiveScenes::isSceneActive(uint32 sceneId) { + for (uint i = 0; i < _stack.size(); ++i) + if (_stack[i]._sceneId == sceneId && _stack[i]._pauseCtr <= 0) + return true; + return false; +} + +// IllusionsEngine_BBDOU + +IllusionsEngine_BBDOU::IllusionsEngine_BBDOU(OSystem *syst, const ADGameDescription *gd) + : IllusionsEngine(syst, gd) { +} + +Common::Error IllusionsEngine_BBDOU::run() { + + // Init search paths + const Common::FSNode gameDataDir(ConfMan.get("path")); + SearchMan.addSubDirectoryMatching(gameDataDir, "music"); + SearchMan.addSubDirectoryMatching(gameDataDir, "resource"); + SearchMan.addSubDirectoryMatching(gameDataDir, "resrem"); + SearchMan.addSubDirectoryMatching(gameDataDir, "savegame"); + SearchMan.addSubDirectoryMatching(gameDataDir, "sfx"); + SearchMan.addSubDirectoryMatching(gameDataDir, "video"); + SearchMan.addSubDirectoryMatching(gameDataDir, "voice"); + + Graphics::PixelFormat pixelFormat16(2, 5, 6, 5, 0, 11, 5, 0, 0); + initGraphics(640, 480, true, &pixelFormat16); + + _dict = new Dictionary(); + + _resSys = new ResourceSystem(); + _resSys->addResourceLoader(0x00060000, new ActorResourceLoader(this)); + _resSys->addResourceLoader(0x00080000, new SoundGroupResourceLoader(this)); + _resSys->addResourceLoader(0x000D0000, new ScriptResourceLoader(this)); + _resSys->addResourceLoader(0x000F0000, new TalkResourceLoader(this)); + _resSys->addResourceLoader(0x00100000, new ActorResourceLoader(this)); + _resSys->addResourceLoader(0x00110000, new BackgroundResourceLoader(this)); + _resSys->addResourceLoader(0x00120000, new FontResourceLoader(this)); + _resSys->addResourceLoader(0x00170000, new SpecialCodeLoader(this)); + + _screen = new Screen(this); + _input = new Input(); + _scriptMan = new ScriptMan(this); + _actorItems = new ActorItems(this); + _backgroundItems = new BackgroundItems(this); + _camera = new Camera(this); + _controls = new Controls(this); + _cursor = new Cursor(this); + _talkItems = new TalkItems(this); + _triggerFunctions = new TriggerFunctions(); + _threads = new ThreadList(this); + + _scriptOpcodes = new ScriptOpcodes_BBDOU(this); + _stack = new ScriptStack(); + + // TODO Move to own class + _resGetCtr = 0; + _unpauseControlActorFlag = false; + _lastUpdateTime = 0; + + _pauseCtr = 0; + _doScriptThreadInit = false; + _field8 = 1; + _fieldA = 0; + _fieldE = 240; + + _globalSceneId = 0x00010003; + + _resSys->loadResource(0x000D0001, 0, 0); + + startScriptThread(0x00020004, 0, 0, 0, 0); + _doScriptThreadInit = true; + + while (!shouldQuit()) { + _threads->updateThreads(); + updateActors(); + updateSequences(); + updateGraphics(); + _screen->updateSprites(); + _system->updateScreen(); + updateEvents(); + _system->delayMillis(10); + } + + delete _stack; + delete _scriptOpcodes; + + delete _threads; + delete _triggerFunctions; + delete _talkItems; + delete _cursor; + delete _controls; + delete _camera; + delete _backgroundItems; + delete _actorItems; + delete _scriptMan; + delete _input; + delete _screen; + delete _resSys; + delete _dict; + + debug("Ok"); + + return Common::kNoError; +} + +bool IllusionsEngine_BBDOU::hasFeature(EngineFeature f) const { + return + false; + /* + (f == kSupportsRTL) || + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime); + */ +} + +bool IllusionsEngine_BBDOU::causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { + uint32 codeOffs; + bool r = + _triggerFunctions->find(sceneId, verbId, objectId2, objectId) || + findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs); + debug(3, "causeIsDeclared() sceneId: %08X; verbId: %08X; objectId2: %08X; objectId: %08X -> %d", + sceneId, verbId, objectId2, objectId, r); + return r; +} + +void IllusionsEngine_BBDOU::causeDeclare(uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) { + _triggerFunctions->add(getCurrentScene(), verbId, objectId2, objectId, callback); +} + +uint32 IllusionsEngine_BBDOU::causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId) { + uint32 codeOffs; + uint32 causeThreadId = 0; + TriggerFunction *triggerFunction = _triggerFunctions->find(sceneId, verbId, objectId2, objectId); + if (triggerFunction) { + triggerFunction->run(callingThreadId); + } else if (findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs)) { + //debug("Run cause at %08X", codeOffs); + causeThreadId = startTempScriptThread(_scriptResource->getCode(codeOffs), + callingThreadId, verbId, objectId2, objectId); + } + return causeThreadId; +} + +void IllusionsEngine_BBDOU::loadSpecialCode(uint32 resId) { + _specialCode = new BbdouSpecialCode(this); + _specialCode->init(); +} + +void IllusionsEngine_BBDOU::unloadSpecialCode(uint32 resId) { + delete _specialCode; + _specialCode = 0; +} + +void IllusionsEngine_BBDOU::notifyThreadId(uint32 &threadId) { + if (threadId) { + uint32 tempThreadId = threadId; + threadId = 0; + _threads->notifyId(tempThreadId); + } +} + +Control *IllusionsEngine_BBDOU::getObjectControl(uint32 objectId) { + return _dict->getObjectControl(objectId); +} + +Common::Point IllusionsEngine_BBDOU::getNamedPointPosition(uint32 namedPointId) { + Common::Point pt; + if (_backgroundItems->findActiveBackgroundNamedPoint(namedPointId, pt) || + _actorItems->findNamedPoint(namedPointId, pt) || + _controls->findNamedPoint(namedPointId, pt)) + return pt; + // TODO + //debug("getNamedPointPosition(%08X) UNKNOWN", namedPointId); + return Common::Point(0, 0); +} + +uint32 IllusionsEngine_BBDOU::getPriorityFromBase(int16 priority) { + return 32000000 * priority; +} + +uint32 IllusionsEngine_BBDOU::getCurrentScene() { + return _activeScenes.getCurrentScene(); +} + +uint32 IllusionsEngine_BBDOU::getPrevScene() { + return _prevSceneId; +} + +void IllusionsEngine_BBDOU::startScriptThreadSimple(uint32 threadId, uint32 callingThreadId) { + startScriptThread(threadId, callingThreadId, 0, 0, 0); +} + +void IllusionsEngine_BBDOU::startScriptThread(uint32 threadId, uint32 callingThreadId, + uint32 value8, uint32 valueC, uint32 value10) { + debug(2, "Starting script thread %08X", threadId); + byte *scriptCodeIp = _scriptResource->getThreadCode(threadId); + newScriptThread(threadId, callingThreadId, 0, scriptCodeIp, value8, valueC, value10); +} + +void IllusionsEngine_BBDOU::startAnonScriptThread(int32 threadId, uint32 callingThreadId, + uint32 value8, uint32 valueC, uint32 value10) { + debug(2, "Starting anonymous script thread %08X", threadId); + uint32 tempThreadId = newTempThreadId(); + byte *scriptCodeIp = _scriptResource->getThreadCode(threadId); + scriptCodeIp = _scriptResource->getThreadCode(threadId); + newScriptThread(tempThreadId, callingThreadId, 0, scriptCodeIp, value8, valueC, value10); +} + +uint32 IllusionsEngine_BBDOU::startAbortableTimerThread(uint32 duration, uint32 threadId) { + return newTimerThread(duration, threadId, true); +} + +uint32 IllusionsEngine_BBDOU::startTimerThread(uint32 duration, uint32 threadId) { + return newTimerThread(duration, threadId, false); +} + +uint32 IllusionsEngine_BBDOU::startAbortableThread(byte *scriptCodeIp1, byte *scriptCodeIp2, uint32 callingThreadId) { + uint32 tempThreadId = newTempThreadId(); + debug(2, "Starting abortable thread %08X", tempThreadId); + uint32 scriptThreadId = startTempScriptThread(scriptCodeIp1, tempThreadId, 0, 0, 0); + AbortableThread *abortableThread = new AbortableThread(this, tempThreadId, callingThreadId, 0, + scriptThreadId, scriptCodeIp2); + _threads->startThread(abortableThread); + return tempThreadId; +} + +uint32 IllusionsEngine_BBDOU::startTalkThread(int16 duration, uint32 objectId, uint32 talkId, uint32 sequenceId1, + uint32 sequenceId2, uint32 namedPointId, uint32 callingThreadId) { + debug(2, "Starting talk thread"); + uint32 tempThreadId = newTempThreadId(); + _threads->endTalkThreadsNoNotify(); + TalkThread *talkThread = new TalkThread(this, tempThreadId, callingThreadId, 0, + duration, objectId, talkId, sequenceId1, sequenceId2, namedPointId); + _threads->startThread(talkThread); + return tempThreadId; +} + +uint32 IllusionsEngine_BBDOU::startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId, + uint32 value8, uint32 valueC, uint32 value10) { + uint32 tempThreadId = newTempThreadId(); + debug(2, "Starting temp script thread %08X", tempThreadId); + newScriptThread(tempThreadId, callingThreadId, 0, scriptCodeIp, value8, valueC, value10); + return tempThreadId; +} + +void IllusionsEngine_BBDOU::newScriptThread(uint32 threadId, uint32 callingThreadId, uint notifyFlags, + byte *scriptCodeIp, uint32 value8, uint32 valueC, uint32 value10) { + ScriptThread *scriptThread = new ScriptThread(this, threadId, callingThreadId, notifyFlags, + scriptCodeIp, value8, valueC, value10); + _threads->startThread(scriptThread); + if (_pauseCtr > 0) + scriptThread->pause(); + if (_doScriptThreadInit) { + int updateResult = kTSRun; + while (scriptThread->_pauseCtr <= 0 && updateResult != kTSTerminate && updateResult != kTSYield) + updateResult = scriptThread->update(); + } +} + +uint32 IllusionsEngine_BBDOU::newTimerThread(uint32 duration, uint32 callingThreadId, bool isAbortable) { + uint32 tempThreadId = newTempThreadId(); + TimerThread *timerThread = new TimerThread(this, tempThreadId, callingThreadId, 0, + duration, isAbortable); + _threads->startThread(timerThread); + return tempThreadId; +} + +uint32 IllusionsEngine_BBDOU::newTempThreadId() { + uint32 threadId = _nextTempThreadId + 2 * _scriptResource->_codeCount; + if (threadId > 65535) { + _nextTempThreadId = 0; + threadId = 2 * _scriptResource->_codeCount; + } + ++_nextTempThreadId; + return 0x00020000 | threadId; +} + +bool IllusionsEngine_BBDOU::enterScene(uint32 sceneId, uint32 threadId) { + ProgInfo *progInfo = _scriptResource->getProgInfo(sceneId & 0xFFFF); + if (!progInfo) { + dumpActiveScenes(_globalSceneId, threadId); + sceneId = _theSceneId; + } + _activeScenes.push(sceneId); + return progInfo != 0; +} + +void IllusionsEngine_BBDOU::exitScene(uint32 threadId) { + uint32 sceneId = _activeScenes.getCurrentScene(); + // TODO krnfileDump(sceneId); + // TODO UpdateFunctions_disableByTag__TODO_maybe(sceneId); + _threads->terminateThreadsByTag(sceneId, threadId); + _controls->destroyControlsByTag(sceneId); + _triggerFunctions->removeBySceneId(sceneId); + _resSys->unloadResourcesByTag(sceneId); + _activeScenes.pop(); +} + +void IllusionsEngine_BBDOU::enterPause(uint32 threadId) { + uint32 sceneId = _activeScenes.getCurrentScene(); + _camera->pushCameraMode(); + _threads->suspendThreadsByTag(sceneId, threadId); + _controls->pauseControlsByTag(sceneId); + _actorItems->pauseByTag(sceneId); + _backgroundItems->pauseByTag(sceneId); + _activeScenes.pauseActiveScene(); +} + +void IllusionsEngine_BBDOU::leavePause(uint32 threadId) { + uint32 sceneId = _activeScenes.getCurrentScene(); + _backgroundItems->unpauseByTag(sceneId); + _actorItems->unpauseByTag(sceneId); + _controls->unpauseControlsByTag(sceneId); + _threads->notifyThreadsByTag(sceneId, threadId); + _camera->popCameraMode(); + _activeScenes.unpauseActiveScene(); +} + +void IllusionsEngine_BBDOU::dumpActiveScenes(uint32 sceneId, uint32 threadId) { + uint activeScenesCount = _activeScenes.getActiveScenesCount(); + while (activeScenesCount > 0) { + uint32 activeSceneId; + _activeScenes.getActiveSceneInfo(activeScenesCount, &activeSceneId, 0); + if (activeSceneId == sceneId) + break; + exitScene(threadId); + --activeScenesCount; + } + _camera->clearCameraModeStack(); +} + +void IllusionsEngine_BBDOU::setSceneIdThreadId(uint32 theSceneId, uint32 theThreadId) { + _theSceneId = theSceneId; + _theThreadId = theThreadId; +} + +bool IllusionsEngine_BBDOU::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 IllusionsEngine_BBDOU::reset() { + _scriptResource->_blockCounters.clear(); + _scriptResource->_properties.clear(); + // TODO script_sub_417FF0(1, 0); +} + +} // End of namespace Illusions diff --git a/engines/illusions/illusions_bbdou.h b/engines/illusions/illusions_bbdou.h new file mode 100644 index 0000000000..cd6d8d7d31 --- /dev/null +++ b/engines/illusions/illusions_bbdou.h @@ -0,0 +1,150 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ILLUSIONS_ILLUSIONS_BBDOU_H +#define ILLUSIONS_ILLUSIONS_BBDOU_H + +#include "illusions/illusions.h" +#include "common/algorithm.h" +#include "common/stack.h" + +namespace Illusions { + +class Dictionary; +class ScriptMan; +class ScriptStack; +class TriggerFunctions; +class TriggerFunction; + +typedef Common::Functor2<TriggerFunction*, uint32, void> TriggerFunctionCallback; + +struct TriggerFunction { + uint32 _sceneId; + uint32 _verbId; + uint32 _objectId2; + uint32 _objectId; + TriggerFunctionCallback *_callback; + TriggerFunction(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback); + ~TriggerFunction(); + void run(uint32 callingThreadId); +}; + +class TriggerFunctions { +public: + void add(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback); + TriggerFunction *find(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); + void removeBySceneId(uint32 sceneId); +public: + typedef Common::List<TriggerFunction*> Items; + typedef Items::iterator ItemsIterator; + Items _triggerFunctions; + ItemsIterator findInternal(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); +}; + +struct ActiveScene { + uint32 _sceneId; + int _pauseCtr; +}; + +class ActiveScenes { +public: + ActiveScenes(); + void clear(); + void push(uint32 sceneId); + void pop(); + void pauseActiveScene(); + void unpauseActiveScene(); + uint getActiveScenesCount(); + void getActiveSceneInfo(uint index, uint32 *sceneId, int *pauseCtr); + uint32 getCurrentScene(); + bool isSceneActive(uint32 sceneId); +protected: + Common::FixedStack<ActiveScene, 16> _stack; +}; + +class IllusionsEngine_BBDOU : public IllusionsEngine { +public: + IllusionsEngine_BBDOU(OSystem *syst, const ADGameDescription *gd); +protected: + virtual Common::Error run(); + virtual bool hasFeature(EngineFeature f) const; +public: + ScriptMan *_scriptMan; + TriggerFunctions *_triggerFunctions; + + ActiveScenes _activeScenes; + uint32 _prevSceneId; + uint32 _theSceneId; + uint32 _theThreadId; + uint32 _globalSceneId; + + int _pauseCtr; + ScriptStack *_stack; + bool _doScriptThreadInit; + + uint32 _nextTempThreadId; + + bool causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); + void causeDeclare(uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback); + uint32 causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId); + + void loadSpecialCode(uint32 resId); + void unloadSpecialCode(uint32 resId); + void notifyThreadId(uint32 &threadId); + Control *getObjectControl(uint32 objectId); + Common::Point getNamedPointPosition(uint32 namedPointId); + uint32 getPriorityFromBase(int16 priority); + uint32 getPrevScene(); + uint32 getCurrentScene(); + + void startScriptThreadSimple(uint32 threadId, uint32 callingThreadId); + void startScriptThread(uint32 threadId, uint32 callingThreadId, + uint32 value8, uint32 valueC, uint32 value10); + void startAnonScriptThread(int32 threadId, uint32 callingThreadId, + uint32 value8, uint32 valueC, uint32 value10); + uint32 startAbortableTimerThread(uint32 duration, uint32 threadId); + uint32 startTimerThread(uint32 duration, uint32 threadId); + uint32 startAbortableThread(byte *scriptCodeIp1, byte *scriptCodeIp2, uint32 callingThreadId); + uint32 startTalkThread(int16 duration, uint32 objectId, uint32 talkId, uint32 sequenceId1, + uint32 sequenceId2, uint32 namedPointId, uint32 callingThreadId); + uint32 startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId, + uint32 value8, uint32 valueC, uint32 value10); + void newScriptThread(uint32 threadId, uint32 callingThreadId, uint notifyFlags, + byte *scriptCodeIp, uint32 value8, uint32 valueC, uint32 value10); + uint32 newTimerThread(uint32 duration, uint32 callingThreadId, bool isAbortable); + uint32 newTempThreadId(); + + bool enterScene(uint32 sceneId, uint32 threadId); + void exitScene(uint32 threadId); + void enterPause(uint32 threadId); + void leavePause(uint32 threadId); + void dumpActiveScenes(uint32 sceneId, uint32 threadId); + + void setSceneIdThreadId(uint32 theSceneId, uint32 theThreadId); + bool findTriggerCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs); + void reset(); + +}; + +} // End of namespace Illusions + +#endif // ILLUSIONS_ILLUSIONS_H diff --git a/engines/illusions/module.mk b/engines/illusions/module.mk index c4fe62b896..63bf8260e8 100644 --- a/engines/illusions/module.mk +++ b/engines/illusions/module.mk @@ -1,7 +1,7 @@ MODULE := engines/illusions MODULE_OBJS := \ - abortablethread.o \ + abortablethread.o \ actor.o \ actorresource.o \ backgroundresource.o \ @@ -17,11 +17,13 @@ MODULE_OBJS := \ fontresource.o \ graphics.o \ illusions.o \ + illusions_bbdou.o \ input.o \ resourcesystem.o \ screen.o \ scriptman.o \ scriptopcodes.o \ + scriptopcodes_bbdou.o \ scriptresource.o \ scriptthread.o \ sequenceopcodes.o \ diff --git a/engines/illusions/screen.cpp b/engines/illusions/screen.cpp index de2efae4e9..9e03a40bd9 100644 --- a/engines/illusions/screen.cpp +++ b/engines/illusions/screen.cpp @@ -161,17 +161,7 @@ bool SpriteDrawQueue::draw(SpriteDrawQueueItem *item) { if (!calcItemRect(item, srcRect, dstRect)) return true; - if (item->_scale == 100) { - if (item->_flags & 1) - _screen->drawSurface10(dstRect.left, dstRect.top, item->_surface, srcRect, _screen->getColorKey2()); - else - _screen->drawSurface11(dstRect.left, dstRect.top, item->_surface, srcRect); - } else { - if (item->_flags & 1) - _screen->drawSurface20(dstRect, item->_surface, srcRect, _screen->getColorKey2()); - else - _screen->drawSurface21(dstRect, item->_surface, srcRect); - } + _screen->drawSurface(dstRect, item->_surface, srcRect, item->_scale, item->_flags); if (item->_drawFlags) *item->_drawFlags &= ~4; @@ -346,6 +336,20 @@ void Screen::updateSprites() { g_system->copyRectToScreen((byte*)_backSurface->getBasePtr(0, 0), _backSurface->pitch, 0, 0, _backSurface->w, _backSurface->h); } +void Screen::drawSurface(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags) { + if (scale == 100) { + if (flags & 1) + drawSurface10(dstRect.left, dstRect.top, surface, srcRect, _colorKey2); + else + drawSurface11(dstRect.left, dstRect.top, surface, srcRect); + } else { + if (flags & 1) + drawSurface20(dstRect, surface, srcRect, _colorKey2); + else + drawSurface21(dstRect, surface, srcRect); + } +} + void Screen::drawSurface10(int16 destX, int16 destY, Graphics::Surface *surface, Common::Rect &srcRect, uint16 colorKey) { // Unscaled // TODO diff --git a/engines/illusions/screen.h b/engines/illusions/screen.h index 6332f7887f..cfeaba63bc 100644 --- a/engines/illusions/screen.h +++ b/engines/illusions/screen.h @@ -106,6 +106,7 @@ public: void setDisplayOn(bool isOn); uint16 getColorKey2(); void updateSprites(); + void drawSurface(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, int16 scale, uint32 flags); void drawSurface10(int16 destX, int16 destY, Graphics::Surface *surface, Common::Rect &srcRect, uint16 colorKey); void drawSurface11(int16 destX, int16 destY, Graphics::Surface *surface, Common::Rect &srcRect); void drawSurface20(Common::Rect &dstRect, Graphics::Surface *surface, Common::Rect &srcRect, uint16 colorKey); diff --git a/engines/illusions/scriptman.cpp b/engines/illusions/scriptman.cpp index c438def393..ef4f462250 100644 --- a/engines/illusions/scriptman.cpp +++ b/engines/illusions/scriptman.cpp @@ -22,123 +22,12 @@ #include "illusions/illusions.h" #include "illusions/scriptman.h" -#include "illusions/abortablethread.h" #include "illusions/actor.h" #include "illusions/camera.h" -#include "illusions/scriptthread.h" #include "illusions/scriptopcodes.h" -#include "illusions/talkthread.h" -#include "illusions/timerthread.h" namespace Illusions { -// ActiveScenes - -ActiveScenes::ActiveScenes() { - clear(); -} - -void ActiveScenes::clear() { - _stack.clear(); -} - -void ActiveScenes::push(uint32 sceneId) { - ActiveScene activeScene; - activeScene._sceneId = sceneId; - activeScene._pauseCtr = 0; - _stack.push(activeScene); -} - -void ActiveScenes::pop() { - _stack.pop(); -} - -void ActiveScenes::pauseActiveScene() { - ++_stack.top()._pauseCtr; -} - -void ActiveScenes::unpauseActiveScene() { - --_stack.top()._pauseCtr; -} - -uint ActiveScenes::getActiveScenesCount() { - return _stack.size(); -} - -void ActiveScenes::getActiveSceneInfo(uint index, uint32 *sceneId, int *pauseCtr) { - if (sceneId) - *sceneId = _stack[index - 1]._sceneId; - if (pauseCtr) - *pauseCtr = _stack[index - 1]._pauseCtr; -} - -uint32 ActiveScenes::getCurrentScene() { - if (_stack.size() > 0) - return _stack.top()._sceneId; - return 0; -} - -bool ActiveScenes::isSceneActive(uint32 sceneId) { - for (uint i = 0; i < _stack.size(); ++i) - if (_stack[i]._sceneId == sceneId && _stack[i]._pauseCtr <= 0) - return true; - return false; -} - -// TriggerFunction - -TriggerFunction::TriggerFunction(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) - : _sceneId(sceneId), _verbId(verbId), _objectId2(objectId2), _objectId(objectId), _callback(callback) { -} - -TriggerFunction::~TriggerFunction() { - delete _callback; -} - -void TriggerFunction::run(uint32 callingThreadId) { - (*_callback)(this, callingThreadId); -} - -// TriggerFunctions - -void TriggerFunctions::add(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) { - ItemsIterator it = findInternal(sceneId, verbId, objectId2, objectId); - if (it != _triggerFunctions.end()) { - delete *it; - _triggerFunctions.erase(it); - } - _triggerFunctions.push_back(new TriggerFunction(sceneId, verbId, objectId2, objectId, callback)); -} - -TriggerFunction *TriggerFunctions::find(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { - ItemsIterator it = findInternal(sceneId, verbId, objectId2, objectId); - if (it != _triggerFunctions.end()) - return (*it); - return 0; -} - -void TriggerFunctions::removeBySceneId(uint32 sceneId) { - ItemsIterator it = _triggerFunctions.begin(); - while (it != _triggerFunctions.end()) { - if ((*it)->_sceneId == sceneId) { - delete *it; - it = _triggerFunctions.erase(it); - } else - ++it; - } -} - -TriggerFunctions::ItemsIterator TriggerFunctions::findInternal(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) { - ItemsIterator it = _triggerFunctions.begin(); - for (; it != _triggerFunctions.end(); ++it) { - TriggerFunction *triggerFunction = *it; - if (triggerFunction->_sceneId == sceneId && triggerFunction->_verbId == verbId && - triggerFunction->_objectId2 == objectId2 && triggerFunction->_objectId == objectId) - break; - } - return it; -} - // ScriptStack ScriptStack::ScriptStack() { @@ -180,201 +69,11 @@ int16 *ScriptStack::topPtr() { // ScriptMan -ScriptMan::ScriptMan(IllusionsEngine *vm) - : _vm(vm), _pauseCtr(0), _doScriptThreadInit(false) { - _threads = new ThreadList(vm); - _scriptOpcodes = new ScriptOpcodes(vm); - _field8 = 1; - _fieldA = 0; - _fieldE = 240; +ScriptMan::ScriptMan(IllusionsEngine_BBDOU *vm) + : _vm(vm) { } ScriptMan::~ScriptMan() { - delete _threads; - delete _scriptOpcodes; -} - -void ScriptMan::setSceneIdThreadId(uint32 theSceneId, uint32 theThreadId) { - _theSceneId = theSceneId; - _theThreadId = theThreadId; -} - -void ScriptMan::startScriptThread(uint32 threadId, uint32 callingThreadId, - uint32 value8, uint32 valueC, uint32 value10) { - debug(2, "Starting script thread %08X", threadId); - byte *scriptCodeIp = _scriptResource->getThreadCode(threadId); - newScriptThread(threadId, callingThreadId, 0, scriptCodeIp, value8, valueC, value10); -} - -void ScriptMan::startAnonScriptThread(int32 threadId, uint32 callingThreadId, - uint32 value8, uint32 valueC, uint32 value10) { - debug(2, "Starting anonymous script thread %08X", threadId); - uint32 tempThreadId = newTempThreadId(); - byte *scriptCodeIp = _scriptResource->getThreadCode(threadId); - scriptCodeIp = _scriptResource->getThreadCode(threadId); - newScriptThread(tempThreadId, callingThreadId, 0, scriptCodeIp, value8, valueC, value10); -} - -uint32 ScriptMan::startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId, - uint32 value8, uint32 valueC, uint32 value10) { - uint32 tempThreadId = newTempThreadId(); - debug(2, "Starting temp script thread %08X", tempThreadId); - newScriptThread(tempThreadId, callingThreadId, 0, scriptCodeIp, value8, valueC, value10); - return tempThreadId; -} - -uint32 ScriptMan::startAbortableTimerThread(uint32 duration, uint32 threadId) { - return newTimerThread(duration, threadId, true); -} - -uint32 ScriptMan::startTimerThread(uint32 duration, uint32 threadId) { - return newTimerThread(duration, threadId, false); -} - -uint32 ScriptMan::startAbortableThread(byte *scriptCodeIp1, byte *scriptCodeIp2, uint32 callingThreadId) { - uint32 tempThreadId = newTempThreadId(); - debug(2, "Starting abortable thread %08X", tempThreadId); - uint32 scriptThreadId = startTempScriptThread(scriptCodeIp1, tempThreadId, 0, 0, 0); - AbortableThread *abortableThread = new AbortableThread(_vm, tempThreadId, callingThreadId, 0, - scriptThreadId, scriptCodeIp2); - _threads->startThread(abortableThread); - return tempThreadId; -} - -uint32 ScriptMan::startTalkThread(int16 duration, uint32 objectId, uint32 talkId, uint32 sequenceId1, - uint32 sequenceId2, uint32 namedPointId, uint32 callingThreadId) { - debug(2, "Starting talk thread"); - uint32 tempThreadId = newTempThreadId(); - _threads->endTalkThreadsNoNotify(); - TalkThread *talkThread = new TalkThread(_vm, tempThreadId, callingThreadId, 0, - duration, objectId, talkId, sequenceId1, sequenceId2, namedPointId); - _threads->startThread(talkThread); - 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; -} - -bool ScriptMan::checkActiveTalkThreads() { - return _threads->isActiveThread(kMsgQueryTalkThreadActive); -} - -uint32 ScriptMan::clipTextDuration(uint32 duration) { - switch (_field8) { - case 2: - if (duration == 0) - duration = 240; - break; - case 3: - if (duration < _fieldA) - duration = _fieldA; - break; - case 4: - if (duration > _fieldA) - duration = _fieldA; - break; - } - return duration; -} - -void ScriptMan::reset() { - _scriptResource->_blockCounters.clear(); - _scriptResource->_properties.clear(); - // TODO script_sub_417FF0(1, 0); -} - -bool ScriptMan::enterScene(uint32 sceneId, uint32 threadId) { - ProgInfo *progInfo = _scriptResource->getProgInfo(sceneId & 0xFFFF); - if (!progInfo) { - // TODO dumpActiveScenes(_globalSceneId, threadId); - sceneId = _theSceneId; - } - _activeScenes.push(sceneId); - return progInfo != 0; -} - -void ScriptMan::exitScene(uint32 threadId) { - uint32 sceneId = _activeScenes.getCurrentScene(); - // TODO krnfileDump(sceneId); - // TODO UpdateFunctions_disableByTag__TODO_maybe(sceneId); - _threads->terminateThreadsByTag(sceneId, threadId); - _vm->_controls->destroyControlsByTag(sceneId); - _vm->_triggerFunctions->removeBySceneId(sceneId); - _vm->_resSys->unloadResourcesByTag(sceneId); - _activeScenes.pop(); -} - -void ScriptMan::enterPause(uint32 threadId) { - uint32 sceneId = _activeScenes.getCurrentScene(); - _vm->_camera->pushCameraMode(); - _threads->suspendThreadsByTag(sceneId, threadId); - _vm->_controls->pauseControlsByTag(sceneId); - _vm->_actorItems->pauseByTag(sceneId); - _vm->_backgroundItems->pauseByTag(sceneId); - _activeScenes.pauseActiveScene(); -} - -void ScriptMan::leavePause(uint32 threadId) { - uint32 sceneId = _activeScenes.getCurrentScene(); - _vm->_backgroundItems->unpauseByTag(sceneId); - _vm->_actorItems->unpauseByTag(sceneId); - _vm->_controls->unpauseControlsByTag(sceneId); - _threads->notifyThreadsByTag(sceneId, threadId); - _vm->_camera->popCameraMode(); - _activeScenes.unpauseActiveScene(); -} - -void ScriptMan::dumpActiveScenes(uint32 sceneId, uint32 threadId) { - uint activeScenesCount = _activeScenes.getActiveScenesCount(); - while (activeScenesCount > 0) { - uint32 activeSceneId; - _activeScenes.getActiveSceneInfo(activeScenesCount, &activeSceneId, 0); - if (activeSceneId == sceneId) - break; - exitScene(threadId); - --activeScenesCount; - } - _vm->_camera->clearCameraModeStack(); -} - -void ScriptMan::newScriptThread(uint32 threadId, uint32 callingThreadId, uint notifyFlags, - byte *scriptCodeIp, uint32 value8, uint32 valueC, uint32 value10) { - ScriptThread *scriptThread = new ScriptThread(_vm, threadId, callingThreadId, notifyFlags, - scriptCodeIp, value8, valueC, value10); - _threads->startThread(scriptThread); - if (_pauseCtr > 0) - scriptThread->pause(); - if (_doScriptThreadInit) { - int updateResult = kTSRun; - while (scriptThread->_pauseCtr <= 0 && updateResult != kTSTerminate && updateResult != kTSYield) - updateResult = scriptThread->update(); - } -} - -uint32 ScriptMan::newTimerThread(uint32 duration, uint32 callingThreadId, bool isAbortable) { - uint32 tempThreadId = newTempThreadId(); - TimerThread *timerThread = new TimerThread(_vm, tempThreadId, callingThreadId, 0, - duration, isAbortable); - _threads->startThread(timerThread); - return tempThreadId; -} - -uint32 ScriptMan::newTempThreadId() { - uint32 threadId = _nextTempThreadId + 2 * _scriptResource->_codeCount; - if (threadId > 65535) { - _nextTempThreadId = 0; - threadId = 2 * _scriptResource->_codeCount; - } - ++_nextTempThreadId; - return 0x00020000 | threadId; } } // End of namespace Illusions diff --git a/engines/illusions/scriptman.h b/engines/illusions/scriptman.h index 6ea28c8272..d296d807bd 100644 --- a/engines/illusions/scriptman.h +++ b/engines/illusions/scriptman.h @@ -23,7 +23,7 @@ #ifndef ILLUSIONS_SCRIPTMAN_H #define ILLUSIONS_SCRIPTMAN_H -#include "illusions/illusions.h" +#include "illusions/illusions_bbdou.h" #include "illusions/scriptresource.h" #include "illusions/thread.h" #include "common/algorithm.h" @@ -31,54 +31,7 @@ namespace Illusions { -class IllusionsEngine; -class ScriptOpcodes; - -struct ActiveScene { - uint32 _sceneId; - int _pauseCtr; -}; - -class ActiveScenes { -public: - ActiveScenes(); - void clear(); - void push(uint32 sceneId); - void pop(); - void pauseActiveScene(); - void unpauseActiveScene(); - uint getActiveScenesCount(); - void getActiveSceneInfo(uint index, uint32 *sceneId, int *pauseCtr); - uint32 getCurrentScene(); - bool isSceneActive(uint32 sceneId); -protected: - Common::FixedStack<ActiveScene, 16> _stack; -}; - -struct TriggerFunction; - -struct TriggerFunction { - uint32 _sceneId; - uint32 _verbId; - uint32 _objectId2; - uint32 _objectId; - TriggerFunctionCallback *_callback; - TriggerFunction(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback); - ~TriggerFunction(); - void run(uint32 callingThreadId); -}; - -class TriggerFunctions { -public: - void add(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback); - TriggerFunction *find(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); - void removeBySceneId(uint32 sceneId); -public: - typedef Common::List<TriggerFunction*> Items; - typedef Items::iterator ItemsIterator; - Items _triggerFunctions; - ItemsIterator findInternal(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId); -}; +class IllusionsEngine_BBDOU; class ScriptStack { public: @@ -95,63 +48,12 @@ protected: class ScriptMan { public: - ScriptMan(IllusionsEngine *vm); + ScriptMan(IllusionsEngine_BBDOU *vm); ~ScriptMan(); - void setSceneIdThreadId(uint32 theSceneId, uint32 theThreadId); - void startScriptThread(uint32 threadId, uint32 callingThreadId, - uint32 value8, uint32 valueC, uint32 value10); - void startAnonScriptThread(int32 threadId, uint32 callingThreadId, - uint32 value8, uint32 valueC, uint32 value10); - uint32 startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId, - uint32 value8, uint32 valueC, uint32 value10); - uint32 startAbortableTimerThread(uint32 duration, uint32 threadId); - uint32 startTimerThread(uint32 duration, uint32 threadId); - 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); - void reset(); - bool enterScene(uint32 sceneId, uint32 threadId); - void exitScene(uint32 threadId); - void enterPause(uint32 threadId); - void leavePause(uint32 threadId); - void dumpActiveScenes(uint32 sceneId, uint32 threadId); public: - IllusionsEngine *_vm; - ScriptResource *_scriptResource; - - ActiveScenes _activeScenes; - ScriptStack _stack; - - int _pauseCtr; - - uint32 _theSceneId; - uint32 _theThreadId; - uint32 _globalSceneId; - bool _doScriptThreadInit; - uint32 _nextTempThreadId; + IllusionsEngine_BBDOU *_vm; - uint32 _fontId; - int _field8; - uint32 _fieldA, _fieldE; - - uint32 _prevSceneId; - - ThreadList *_threads; - ScriptOpcodes *_scriptOpcodes; - - uint32 _callerThreadId; - int16 _menuChoiceOfs; - - void newScriptThread(uint32 threadId, uint32 callingThreadId, uint notifyFlags, - byte *scriptCodeIp, uint32 value8, uint32 valueC, uint32 value10); - uint32 newTimerThread(uint32 duration, uint32 callingThreadId, bool isAbortable); - uint32 newTempThreadId(); - }; } // End of namespace Illusions diff --git a/engines/illusions/scriptopcodes.cpp b/engines/illusions/scriptopcodes.cpp index a551bdfcae..c8817f6aca 100644 --- a/engines/illusions/scriptopcodes.cpp +++ b/engines/illusions/scriptopcodes.cpp @@ -22,16 +22,7 @@ #include "illusions/illusions.h" #include "illusions/scriptopcodes.h" -#include "illusions/actor.h" -#include "illusions/camera.h" -#include "illusions/dictionary.h" -#include "illusions/input.h" -#include "illusions/screen.h" -#include "illusions/scriptman.h" -#include "illusions/scriptresource.h" #include "illusions/scriptthread.h" -#include "illusions/specialcode.h" -#include "illusions/talkresource.h" namespace Illusions { @@ -75,733 +66,4 @@ void ScriptOpcodes::execOpcode(ScriptThread *scriptThread, OpCall &opCall) { (*_opcodes[opCall._op])(scriptThread, opCall); } -typedef Common::Functor2Mem<ScriptThread*, OpCall&, void, ScriptOpcodes> ScriptOpcodeI; -#define OPCODE(op, func) \ - _opcodes[op] = new ScriptOpcodeI(this, &ScriptOpcodes::func); \ - _opcodeNames[op] = #func; - -void ScriptOpcodes::initOpcodes() { - // First clear everything - for (uint i = 0; i < 256; ++i) - _opcodes[i] = 0; - // Register opcodes - OPCODE(2, opSuspend); - OPCODE(3, opYield); - OPCODE(4, opTerminate); - OPCODE(5, opJump); - OPCODE(6, opStartScriptThread); - OPCODE(8, opStartTempScriptThread); - OPCODE(9, opStartTimerThread); - OPCODE(14, opSetThreadSceneId); - OPCODE(15, opEndTalkThreads); - OPCODE(16, opLoadResource); - OPCODE(17, opUnloadResource); - OPCODE(20, opEnterScene); - OPCODE(25, opChangeScene); - 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(39, opSetDisplay); - OPCODE(42, opIncBlockCounter); - OPCODE(43, opClearBlockCounter); - OPCODE(45, opSetProperty); - OPCODE(46, opPlaceActor); - OPCODE(47, opFaceActor); - OPCODE(48, opFaceActorToObject); - OPCODE(49, opStartSequenceActor); - OPCODE(51, opStartMoveActor); - OPCODE(53, opSetActorToNamedPoint); - OPCODE(56, opStartTalkThread); - OPCODE(57, opAppearActor); - OPCODE(58, opDisappearActor); - OPCODE(60, opActivateObject); - OPCODE(61, opDeactivateObject); - OPCODE(62, opSetDefaultSequence); - OPCODE(63, opSetSelectSfx); - OPCODE(64, opSetMoveSfx); - OPCODE(65, opSetDenySfx); - OPCODE(66, opSetAdjustUpSfx); - OPCODE(67, opSetAdjustDnSfx); - OPCODE(71, opStartSound); - OPCODE(74, opStopSound); - OPCODE(75, opStartMusic); - OPCODE(76, opStopMusic); - OPCODE(78, opStackPushRandom); - OPCODE(79, opIfLte); - OPCODE(80, opAddMenuChoice); - OPCODE(81, opDisplayMenu); - OPCODE(82, opSwitchMenuChoice); - OPCODE(84, opResetGame); - OPCODE(87, opDeactivateButton); - OPCODE(88, opActivateButton); - OPCODE(103, opJumpIf); - OPCODE(104, opIsPrevSceneId); - OPCODE(105, opIsCurrentSceneId); - OPCODE(106, opIsActiveSceneId); - OPCODE(107, opNot); - OPCODE(108, opAnd); - OPCODE(109, opOr); - OPCODE(110, opGetProperty); - OPCODE(111, opCompareBlockCounter); - OPCODE(126, opDebug126); - OPCODE(144, opPlayVideo); - OPCODE(146, opStackPop); - OPCODE(147, opStackDup); - OPCODE(148, opLoadSpecialCodeModule); - OPCODE(150, opRunSpecialCode); - OPCODE(160, opStopActor); - OPCODE(161, opSetActorUsePan); - OPCODE(168, opStartAbortableThread); - OPCODE(169, opKillThread); - OPCODE(175, opSetSceneIdThreadId); - OPCODE(176, opStackPush0); - OPCODE(177, opSetFontId); - OPCODE(178, opAddMenuKey); - OPCODE(179, opChangeSceneAll); -} - -#undef OPCODE - -void ScriptOpcodes::freeOpcodes() { - for (uint i = 0; i < 256; ++i) - delete _opcodes[i]; -} - -// Opcodes - -// Convenience macros -#define ARG_SKIP(x) opCall.skip(x); -#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); - -void ScriptOpcodes::opSuspend(ScriptThread *scriptThread, OpCall &opCall) { - opCall._result = kTSSuspend; -} - -void ScriptOpcodes::opYield(ScriptThread *scriptThread, OpCall &opCall) { - opCall._result = kTSYield; -} - -void ScriptOpcodes::opTerminate(ScriptThread *scriptThread, OpCall &opCall) { - opCall._result = kTSTerminate; -} - -void ScriptOpcodes::opJump(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(jumpOffs); - opCall._deltaOfs += jumpOffs; -} - -void ScriptOpcodes::opStartScriptThread(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(threadId); - _vm->_scriptMan->startScriptThread(threadId, opCall._threadId, - scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10); -} - -void ScriptOpcodes::opStartTempScriptThread(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(codeOffs); - _vm->_scriptMan->startTempScriptThread(opCall._code + codeOffs, - opCall._threadId, scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10); -} - -void ScriptOpcodes::opStartTimerThread(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(isAbortable); - ARG_INT16(duration); - ARG_INT16(maxDuration); - if (maxDuration) - duration += _vm->getRandom(maxDuration); - -duration = 1;//DEBUG Speeds up things - - if (isAbortable) - _vm->_scriptMan->startAbortableTimerThread(duration, opCall._threadId); - else - _vm->_scriptMan->startTimerThread(duration, opCall._threadId); -} - -void ScriptOpcodes::opSetThreadSceneId(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(sceneId); - _vm->_scriptMan->_threads->setThreadSceneId(opCall._callerThreadId, sceneId); -} - -void ScriptOpcodes::opEndTalkThreads(ScriptThread *scriptThread, OpCall &opCall) { - _vm->_scriptMan->_threads->endTalkThreads(); -} - -void ScriptOpcodes::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::opUnloadResource(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(resourceId); - // NOTE Skipped checking for stalled resources - _vm->_resSys->unloadResourceById(resourceId); -} - -void ScriptOpcodes::opEnterScene(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(sceneId); - uint scenesCount = _vm->_scriptMan->_activeScenes.getActiveScenesCount(); - if (scenesCount > 0) { - uint32 currSceneId; - _vm->_scriptMan->_activeScenes.getActiveSceneInfo(scenesCount, &currSceneId, 0); - // TODO krnfileDump(currSceneId); - } - if (!_vm->_scriptMan->enterScene(sceneId, opCall._callerThreadId)) - opCall._result = kTSTerminate; -} - -//DEBUG Scenes -//uint32 dsceneId = 0x00010031, dthreadId = 0x00020036;//MAP -//uint32 dsceneId = 0x00010028, dthreadId = 0x000202A1; -//uint32 dsceneId = 0x00010007, dthreadId = 0x0002000C;//Auditorium -//uint32 dsceneId = 0x0001000B, dthreadId = 0x00020010; -//uint32 dsceneId = 0x00010013, dthreadId = 0x00020018;//Therapist -//uint32 dsceneId = 0x00010016, dthreadId = 0x0002001B;//Dorms ext -//uint32 dsceneId = 0x00010017, dthreadId = 0x0002001C;//Dorms int -//uint32 dsceneId = 0x0001000D, dthreadId = 0x00020012;//Food minigame -//uint32 dsceneId = 0x00010067, dthreadId = 0x0002022A; -//uint32 dsceneId = 0x0001000C, dthreadId = 0x00020011;//Cafeteria -uint32 dsceneId = 0x0001000B, dthreadId = 0x00020010; - -void ScriptOpcodes::opChangeScene(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(sceneId); - ARG_UINT32(threadId); - - if (dsceneId) { - sceneId = dsceneId; - threadId = dthreadId; - dsceneId = 0; - } - - // NOTE Skipped checking for stalled resources - _vm->_input->discardButtons(0xFFFF); - _vm->_scriptMan->_prevSceneId = _vm->getCurrentScene(); - _vm->_scriptMan->exitScene(opCall._callerThreadId); - _vm->_scriptMan->enterScene(sceneId, opCall._callerThreadId); - // TODO _vm->_gameStates->writeStates(_vm->_scriptMan->_prevSceneId, sceneId, threadId); - _vm->_scriptMan->startAnonScriptThread(threadId, 0, - scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10); -} - -void ScriptOpcodes::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->_scriptMan->enterPause(opCall._callerThreadId); - _vm->_talkItems->pauseByTag(_vm->getCurrentScene()); - _vm->_scriptMan->enterScene(sceneId, opCall._callerThreadId); - _vm->_scriptMan->startScriptThread(threadId, 0, - scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10); - opCall._result = kTSSuspend; -} - -void ScriptOpcodes::opExitModalScene(ScriptThread *scriptThread, OpCall &opCall) { - // NOTE Skipped checking for stalled resources - _vm->_input->discardButtons(0xFFFF); - _vm->_scriptMan->exitScene(opCall._callerThreadId); - _vm->_scriptMan->leavePause(opCall._callerThreadId); - _vm->_talkItems->unpauseByTag(_vm->getCurrentScene()); -} - -void ScriptOpcodes::opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(sceneId); - // NOTE Skipped checking for stalled resources - _vm->_input->discardButtons(0xFFFF); - _vm->_scriptMan->enterPause(opCall._callerThreadId); - _vm->_scriptMan->enterScene(sceneId, opCall._callerThreadId); -} - -void ScriptOpcodes::opExitCloseUpScene(ScriptThread *scriptThread, OpCall &opCall) { - _vm->_scriptMan->exitScene(opCall._callerThreadId); - _vm->_scriptMan->leavePause(opCall._callerThreadId); - opCall._result = kTSYield; -} - -void ScriptOpcodes::opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(speed); - ARG_UINT32(objectId); - _vm->_camera->panCenterObject(objectId, speed); -} - -void ScriptOpcodes::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::opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(speed); - ARG_UINT32(namedPointId); - Common::Point pos = _vm->getNamedPointPosition(namedPointId); - _vm->_camera->panToPoint(pos, speed, opCall._threadId); -} - -void ScriptOpcodes::opPanToPoint(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(speed); - ARG_INT16(x); - ARG_INT16(y); - _vm->_camera->panToPoint(Common::Point(x, y), speed, opCall._threadId); -} - -void ScriptOpcodes::opPanStop(ScriptThread *scriptThread, OpCall &opCall) { - _vm->_camera->stopPan(); -} - -void ScriptOpcodes::opSetDisplay(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(flag); - _vm->_screen->setDisplayOn(flag != 0); -} - -void ScriptOpcodes::opIncBlockCounter(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(index); - byte value = _vm->_scriptMan->_scriptResource->_blockCounters.get(index) + 1; - if (value <= 63) - _vm->_scriptMan->_scriptResource->_blockCounters.set(index, value); -} - -void ScriptOpcodes::opClearBlockCounter(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(index); - _vm->_scriptMan->_scriptResource->_blockCounters.set(index, 0); -} - -void ScriptOpcodes::opSetProperty(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(value); - ARG_UINT32(propertyId); - _vm->_scriptMan->_scriptResource->_properties.set(propertyId, value != 0); -} - -void ScriptOpcodes::opPlaceActor(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(objectId); - ARG_UINT32(actorTypeId); - ARG_UINT32(sequenceId); - ARG_UINT32(namedPointId); - Common::Point pos = _vm->getNamedPointPosition(namedPointId); - _vm->_controls->placeActor(actorTypeId, pos, sequenceId, objectId, opCall._threadId); -} - -void ScriptOpcodes::opFaceActor(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(facing); - ARG_UINT32(objectId); - Control *control = _vm->_dict->getObjectControl(objectId); - control->faceActor(facing); -} - -void ScriptOpcodes::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::opStartSequenceActor(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(objectId); - ARG_UINT32(sequenceId); - // NOTE Skipped checking for stalled sequence, not sure if needed - Control *control = _vm->_dict->getObjectControl(objectId); - control->startSequenceActor(sequenceId, 2, opCall._threadId); -} - -void ScriptOpcodes::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::opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(objectId); - ARG_UINT32(namedPointId); - Control *control = _vm->_dict->getObjectControl(objectId); - Common::Point pos = _vm->getNamedPointPosition(namedPointId); - control->stopActor(); - control->setActorPosition(pos); -} - -void ScriptOpcodes::opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(duration); - ARG_UINT32(objectId); - ARG_UINT32(talkId); - ARG_UINT32(sequenceId1); - ARG_UINT32(sequenceId2); - ARG_UINT32(namedPointId); - _vm->_scriptMan->startTalkThread(duration, objectId, talkId, sequenceId1, sequenceId2, namedPointId, opCall._threadId); -} - -void ScriptOpcodes::opAppearActor(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(objectId); - Control *control = _vm->_dict->getObjectControl(objectId); - if (!control) { - Common::Point pos = _vm->getNamedPointPosition(0x70023); - _vm->_controls->placeActor(0x50001, pos, 0x60001, objectId, 0); - control = _vm->_dict->getObjectControl(objectId); - control->startSequenceActor(0x60001, 2, 0); - } - control->appearActor(); -} - -void ScriptOpcodes::opDisappearActor(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(objectId); - Control *control = _vm->_dict->getObjectControl(objectId); - control->disappearActor(); -} - -void ScriptOpcodes::opActivateObject(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(objectId); - Control *control = _vm->_dict->getObjectControl(objectId); - if (control) - control->activateObject(); -} - -void ScriptOpcodes::opDeactivateObject(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(objectId); - Control *control = _vm->_dict->getObjectControl(objectId); - control->deactivateObject(); -} - -void ScriptOpcodes::opSetDefaultSequence(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(objectId); - ARG_UINT32(defaultSequenceId); - ARG_UINT32(sequenceId); - Control *control = _vm->_dict->getObjectControl(objectId); - control->_actor->_defaultSequences.set(sequenceId, defaultSequenceId); -} - -void ScriptOpcodes::opSetSelectSfx(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(soundEffectId); - // TODO _vm->setSelectSfx(soundEffectId); -} - -void ScriptOpcodes::opSetMoveSfx(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(soundEffectId); - // TODO _vm->setMoveSfx(soundEffectId); -} - -void ScriptOpcodes::opSetDenySfx(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(soundEffectId); - // TODO _vm->setDenySfx(soundEffectId); -} - -void ScriptOpcodes::opSetAdjustUpSfx(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(soundEffectId); - // TODO _vm->setAdjustUpSfx(soundEffectId); -} - -void ScriptOpcodes::opSetAdjustDnSfx(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(soundEffectId); - // TODO _vm->setAdjustDnSfx(soundEffectId); -} - -void ScriptOpcodes::opStartSound(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_INT16(volume); - ARG_INT16(pan); - ARG_UINT32(soundEffectId); - // TODO _vm->startSound(soundEffectId, volume, pan); -} -void ScriptOpcodes::opStopSound(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(soundEffectId); - // TODO _vm->stopSound(soundEffectId); -} - -void ScriptOpcodes::opStartMusic(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_INT16(volume); - ARG_INT16(pan); - ARG_UINT32(musicId); - ARG_UINT32(type); - // TODO _vm->playMusic(musicId, type, volume, pan); -} - -void ScriptOpcodes::opStopMusic(ScriptThread *scriptThread, OpCall &opCall) { - // TODO _vm->stopMusic(); -} - -void ScriptOpcodes::opStackPushRandom(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(maxValue); - _vm->_scriptMan->_stack.push(_vm->getRandom(maxValue) + 1); -} - -void ScriptOpcodes::opIfLte(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_INT16(rvalue); - ARG_INT16(elseJumpOffs); - int16 lvalue = _vm->_scriptMan->_stack.pop(); - if (!(lvalue <= rvalue)) - opCall._deltaOfs += elseJumpOffs; -} - -void ScriptOpcodes::opAddMenuChoice(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_INT16(jumpOffs); - ARG_INT16(endMarker); - _vm->_scriptMan->_stack.push(endMarker); - _vm->_scriptMan->_stack.push(jumpOffs); -} - -void ScriptOpcodes::opDisplayMenu(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(unk1); - ARG_UINT32(menuId); - ARG_UINT32(unk2); - // TODO _vm->_shellMgr->displayMenu(_vm->_scriptMan->_stack.topPtr(), &_vm->_scriptMan->_menuChoiceOfs, menuId, unk1, unk2, opCall._callerThreadId); - // Remove menu choices from the stack - do { - _vm->_scriptMan->_stack.pop(); - } while (_vm->_scriptMan->_stack.pop() == 0); - - //DEBUG Resume calling thread, later done by the video player - _vm->notifyThreadId(opCall._callerThreadId); - -} - -void ScriptOpcodes::opSwitchMenuChoice(ScriptThread *scriptThread, OpCall &opCall) { -_vm->_scriptMan->_menuChoiceOfs = 88; // DEBUG Chose "Start game" - - opCall._deltaOfs += _vm->_scriptMan->_menuChoiceOfs; -} - -void ScriptOpcodes::opResetGame(ScriptThread *scriptThread, OpCall &opCall) { - _vm->_scriptMan->_threads->terminateThreads(opCall._callerThreadId); - _vm->_scriptMan->reset(); - _vm->_input->activateButton(0xFFFF); - // TODO _vm->stopMusic(); - // TODO _vm->_gameStates->clear(); -} - -void ScriptOpcodes::opDeactivateButton(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(button) - _vm->_input->deactivateButton(button); -} - -void ScriptOpcodes::opActivateButton(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(button) - _vm->_input->activateButton(button); -} - -void ScriptOpcodes::opJumpIf(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(jumpOffs); - int16 value = _vm->_scriptMan->_stack.pop(); - if (value == 0) - opCall._deltaOfs += jumpOffs; -} - -void ScriptOpcodes::opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(sceneId); - _vm->_scriptMan->_stack.push(_vm->_scriptMan->_prevSceneId == sceneId ? 1 : 0); -} - -void ScriptOpcodes::opIsCurrentSceneId(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(sceneId); - _vm->_scriptMan->_stack.push(_vm->getCurrentScene() == sceneId ? 1 : 0); -} - -void ScriptOpcodes::opIsActiveSceneId(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(sceneId); - _vm->_scriptMan->_stack.push(_vm->_scriptMan->_activeScenes.isSceneActive(sceneId) ? 1 : 0); -} - -void ScriptOpcodes::opNot(ScriptThread *scriptThread, OpCall &opCall) { - int16 value = _vm->_scriptMan->_stack.pop(); - _vm->_scriptMan->_stack.push(value != 0 ? 0 : 1); -} - -void ScriptOpcodes::opAnd(ScriptThread *scriptThread, OpCall &opCall) { - int16 value1 = _vm->_scriptMan->_stack.pop(); - int16 value2 = _vm->_scriptMan->_stack.pop(); - _vm->_scriptMan->_stack.push(value1 & value2); -} - -void ScriptOpcodes::opOr(ScriptThread *scriptThread, OpCall &opCall) { - int16 value1 = _vm->_scriptMan->_stack.pop(); - int16 value2 = _vm->_scriptMan->_stack.pop(); - _vm->_scriptMan->_stack.push(value1 | value2); -} - -void ScriptOpcodes::opGetProperty(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(propertyId) - bool value = _vm->_scriptMan->_scriptResource->_properties.get(propertyId); - _vm->_scriptMan->_stack.push(value ? 1 : 0); -} - -void ScriptOpcodes::opCompareBlockCounter(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(index); - ARG_INT16(compareOp); - ARG_INT16(rvalue); - int16 lvalue = _vm->_scriptMan->_scriptResource->_blockCounters.get(index); - bool compareResult = false; - switch (compareOp) { - case 1: - compareResult = lvalue == rvalue; - break; - case 2: - compareResult = lvalue != rvalue; - break; - case 3: - compareResult = lvalue < rvalue; - break; - case 4: - compareResult = lvalue > rvalue; - break; - case 5: - compareResult = lvalue >= rvalue; - break; - case 6: - compareResult = lvalue <= rvalue; - break; - } - _vm->_scriptMan->_stack.push(compareResult ? 1 : 0); -} - -void ScriptOpcodes::opDebug126(ScriptThread *scriptThread, OpCall &opCall) { - // NOTE Prints some debug text - debug(1, "[DBG] %s", (char*)opCall._code); -} - -void ScriptOpcodes::opPlayVideo(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(objectId); - ARG_UINT32(videoId); - ARG_UINT32(priority); - // TODO _vm->playVideo(videoId, objectId, value, opCall._threadId); - - //DEBUG Resume calling thread, later done by the video player - _vm->notifyThreadId(opCall._callerThreadId); - -} - -void ScriptOpcodes::opStackPop(ScriptThread *scriptThread, OpCall &opCall) { - _vm->_scriptMan->_stack.pop(); -} - -void ScriptOpcodes::opStackDup(ScriptThread *scriptThread, OpCall &opCall) { - int16 value = _vm->_scriptMan->_stack.peek(); - _vm->_scriptMan->_stack.push(value); -} - -void ScriptOpcodes::opLoadSpecialCodeModule(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(specialCodeModuleId); - _vm->_resSys->loadResource(specialCodeModuleId, 0, 0); -} - -void ScriptOpcodes::opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(specialCodeId); - _vm->_scriptMan->_callerThreadId = opCall._callerThreadId; - _vm->_specialCode->run(specialCodeId, opCall); - _vm->_scriptMan->_callerThreadId = 0; -} - -void ScriptOpcodes::opStopActor(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(objectId); - Control *control = _vm->_dict->getObjectControl(objectId); - control->stopActor(); -} - -void ScriptOpcodes::opSetActorUsePan(ScriptThread *scriptThread, OpCall &opCall) { - ARG_INT16(usePan) - ARG_UINT32(objectId); - Control *control = _vm->_dict->getObjectControl(objectId); - control->setActorUsePan(usePan); -} - -void ScriptOpcodes::opStartAbortableThread(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_INT16(codeOffs); - ARG_INT16(skipOffs); - _vm->_scriptMan->startAbortableThread(opCall._code + codeOffs, - opCall._code + skipOffs, opCall._threadId); -} - -void ScriptOpcodes::opKillThread(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(threadId); - _vm->_scriptMan->_threads->killThread(threadId); -} - -void ScriptOpcodes::opSetSceneIdThreadId(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(sceneId); - ARG_UINT32(threadId); - _vm->_scriptMan->setSceneIdThreadId(sceneId, threadId); -} - -void ScriptOpcodes::opStackPush0(ScriptThread *scriptThread, OpCall &opCall) { - _vm->_scriptMan->_stack.push(0); -} - -void ScriptOpcodes::opSetFontId(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(fontId); - _vm->_scriptMan->setCurrFontId(fontId); -} - -void ScriptOpcodes::opAddMenuKey(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(key); - ARG_UINT32(threadId); - // TODO _vm->addMenuKey(key, threadId); -} - -void ScriptOpcodes::opChangeSceneAll(ScriptThread *scriptThread, OpCall &opCall) { - ARG_SKIP(2); - ARG_UINT32(sceneId); - ARG_UINT32(threadId); - // NOTE Skipped checking for stalled resources - _vm->_input->discardButtons(0xFFFF); - _vm->_scriptMan->_prevSceneId = _vm->getCurrentScene(); - _vm->_scriptMan->dumpActiveScenes(_vm->_scriptMan->_globalSceneId, opCall._callerThreadId); - _vm->_scriptMan->enterScene(sceneId, opCall._callerThreadId); - // TODO _vm->_gameStates->writeStates(_vm->_scriptMan->_prevSceneId, sceneId, threadId); - _vm->_scriptMan->startAnonScriptThread(threadId, 0, - scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10); -} - } // End of namespace Illusions diff --git a/engines/illusions/scriptopcodes.h b/engines/illusions/scriptopcodes.h index 4fc6cd68b5..1020e618a2 100644 --- a/engines/illusions/scriptopcodes.h +++ b/engines/illusions/scriptopcodes.h @@ -49,98 +49,21 @@ typedef Common::Functor2<ScriptThread*, OpCall&, void> ScriptOpcode; class ScriptOpcodes { public: ScriptOpcodes(IllusionsEngine *vm); - ~ScriptOpcodes(); + virtual ~ScriptOpcodes(); void execOpcode(ScriptThread *scriptThread, OpCall &opCall); protected: IllusionsEngine *_vm; ScriptOpcode *_opcodes[256]; Common::String _opcodeNames[256]; - void initOpcodes(); - void freeOpcodes(); - - // Opcodes - void opSuspend(ScriptThread *scriptThread, OpCall &opCall); - void opYield(ScriptThread *scriptThread, OpCall &opCall); - void opTerminate(ScriptThread *scriptThread, OpCall &opCall); - void opJump(ScriptThread *scriptThread, OpCall &opCall); - void opStartScriptThread(ScriptThread *scriptThread, OpCall &opCall); - void opStartTempScriptThread(ScriptThread *scriptThread, OpCall &opCall); - void opStartTimerThread(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 opChangeScene(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 opSetDisplay(ScriptThread *scriptThread, OpCall &opCall); - void opIncBlockCounter(ScriptThread *scriptThread, OpCall &opCall); - void opClearBlockCounter(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 opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall); - void opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall); - void opAppearActor(ScriptThread *scriptThread, OpCall &opCall); - void opDisappearActor(ScriptThread *scriptThread, OpCall &opCall); - void opActivateObject(ScriptThread *scriptThread, OpCall &opCall); - void opDeactivateObject(ScriptThread *scriptThread, OpCall &opCall); - void opSetDefaultSequence(ScriptThread *scriptThread, OpCall &opCall); - void opSetSelectSfx(ScriptThread *scriptThread, OpCall &opCall); - void opSetMoveSfx(ScriptThread *scriptThread, OpCall &opCall); - void opSetDenySfx(ScriptThread *scriptThread, OpCall &opCall); - void opSetAdjustUpSfx(ScriptThread *scriptThread, OpCall &opCall); - void opSetAdjustDnSfx(ScriptThread *scriptThread, OpCall &opCall); - void opStartSound(ScriptThread *scriptThread, OpCall &opCall); - void opStopSound(ScriptThread *scriptThread, OpCall &opCall); - void opStartMusic(ScriptThread *scriptThread, OpCall &opCall); - void opStopMusic(ScriptThread *scriptThread, OpCall &opCall); - void opStackPushRandom(ScriptThread *scriptThread, OpCall &opCall); - void opIfLte(ScriptThread *scriptThread, OpCall &opCall); - void opAddMenuChoice(ScriptThread *scriptThread, OpCall &opCall); - void opDisplayMenu(ScriptThread *scriptThread, OpCall &opCall); - void opSwitchMenuChoice(ScriptThread *scriptThread, OpCall &opCall); - void opResetGame(ScriptThread *scriptThread, OpCall &opCall); - void opDeactivateButton(ScriptThread *scriptThread, OpCall &opCall); - void opActivateButton(ScriptThread *scriptThread, OpCall &opCall); - void opJumpIf(ScriptThread *scriptThread, OpCall &opCall); - void opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall); - void opIsCurrentSceneId(ScriptThread *scriptThread, OpCall &opCall); - void opIsActiveSceneId(ScriptThread *scriptThread, OpCall &opCall); - void opNot(ScriptThread *scriptThread, OpCall &opCall); - void opAnd(ScriptThread *scriptThread, OpCall &opCall); - void opOr(ScriptThread *scriptThread, OpCall &opCall); - void opGetProperty(ScriptThread *scriptThread, OpCall &opCall); - void opCompareBlockCounter(ScriptThread *scriptThread, OpCall &opCall); - void opDebug126(ScriptThread *scriptThread, OpCall &opCall); - void opPlayVideo(ScriptThread *scriptThread, OpCall &opCall); - void opStackPop(ScriptThread *scriptThread, OpCall &opCall); - void opStackDup(ScriptThread *scriptThread, OpCall &opCall); - void opLoadSpecialCodeModule(ScriptThread *scriptThread, OpCall &opCall); - void opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall); - void opStopActor(ScriptThread *scriptThread, OpCall &opCall); - void opSetActorUsePan(ScriptThread *scriptThread, OpCall &opCall); - void opStartAbortableThread(ScriptThread *scriptThread, OpCall &opCall); - void opKillThread(ScriptThread *scriptThread, OpCall &opCall); - void opSetSceneIdThreadId(ScriptThread *scriptThread, OpCall &opCall); - void opStackPush0(ScriptThread *scriptThread, OpCall &opCall); - void opSetFontId(ScriptThread *scriptThread, OpCall &opCall); - void opAddMenuKey(ScriptThread *scriptThread, OpCall &opCall); - void opChangeSceneAll(ScriptThread *scriptThread, OpCall &opCall); - + virtual void initOpcodes() {} + virtual void freeOpcodes() {} }; +// Convenience macros +#define ARG_SKIP(x) opCall.skip(x); +#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); + } // End of namespace Illusions #endif // ILLUSIONS_SCRIPTOPCODES_H diff --git a/engines/illusions/scriptopcodes_bbdou.cpp b/engines/illusions/scriptopcodes_bbdou.cpp new file mode 100644 index 0000000000..f63a2216b9 --- /dev/null +++ b/engines/illusions/scriptopcodes_bbdou.cpp @@ -0,0 +1,771 @@ +/* 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/scriptopcodes_bbdou.h" +#include "illusions/actor.h" +#include "illusions/camera.h" +#include "illusions/dictionary.h" +#include "illusions/input.h" +#include "illusions/screen.h" +#include "illusions/scriptman.h" +#include "illusions/scriptresource.h" +#include "illusions/scriptthread.h" +#include "illusions/specialcode.h" +#include "illusions/talkresource.h" + +namespace Illusions { + +// ScriptOpcodes_BBDOU + +ScriptOpcodes_BBDOU::ScriptOpcodes_BBDOU(IllusionsEngine_BBDOU *vm) + : ScriptOpcodes(vm), _vm(vm) { + initOpcodes(); +} + +ScriptOpcodes_BBDOU::~ScriptOpcodes_BBDOU() { + freeOpcodes(); +} + +typedef Common::Functor2Mem<ScriptThread*, OpCall&, void, ScriptOpcodes_BBDOU> ScriptOpcodeI; +#define OPCODE(op, func) \ + _opcodes[op] = new ScriptOpcodeI(this, &ScriptOpcodes_BBDOU::func); \ + _opcodeNames[op] = #func; + +void ScriptOpcodes_BBDOU::initOpcodes() { + // First clear everything + for (uint i = 0; i < 256; ++i) + _opcodes[i] = 0; + // Register opcodes + OPCODE(2, opSuspend); + OPCODE(3, opYield); + OPCODE(4, opTerminate); + OPCODE(5, opJump); + OPCODE(6, opStartScriptThread); + OPCODE(8, opStartTempScriptThread); + OPCODE(9, opStartTimerThread); + OPCODE(14, opSetThreadSceneId); + OPCODE(15, opEndTalkThreads); + OPCODE(16, opLoadResource); + OPCODE(17, opUnloadResource); + OPCODE(20, opEnterScene); + OPCODE(25, opChangeScene); + 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(39, opSetDisplay); + OPCODE(42, opIncBlockCounter); + OPCODE(43, opClearBlockCounter); + OPCODE(45, opSetProperty); + OPCODE(46, opPlaceActor); + OPCODE(47, opFaceActor); + OPCODE(48, opFaceActorToObject); + OPCODE(49, opStartSequenceActor); + OPCODE(51, opStartMoveActor); + OPCODE(53, opSetActorToNamedPoint); + OPCODE(56, opStartTalkThread); + OPCODE(57, opAppearActor); + OPCODE(58, opDisappearActor); + OPCODE(60, opActivateObject); + OPCODE(61, opDeactivateObject); + OPCODE(62, opSetDefaultSequence); + OPCODE(63, opSetSelectSfx); + OPCODE(64, opSetMoveSfx); + OPCODE(65, opSetDenySfx); + OPCODE(66, opSetAdjustUpSfx); + OPCODE(67, opSetAdjustDnSfx); + OPCODE(71, opStartSound); + OPCODE(74, opStopSound); + OPCODE(75, opStartMusic); + OPCODE(76, opStopMusic); + OPCODE(78, opStackPushRandom); + OPCODE(79, opIfLte); + OPCODE(80, opAddMenuChoice); + OPCODE(81, opDisplayMenu); + OPCODE(82, opSwitchMenuChoice); + OPCODE(84, opResetGame); + OPCODE(87, opDeactivateButton); + OPCODE(88, opActivateButton); + OPCODE(103, opJumpIf); + OPCODE(104, opIsPrevSceneId); + OPCODE(105, opIsCurrentSceneId); + OPCODE(106, opIsActiveSceneId); + OPCODE(107, opNot); + OPCODE(108, opAnd); + OPCODE(109, opOr); + OPCODE(110, opGetProperty); + OPCODE(111, opCompareBlockCounter); + OPCODE(126, opDebug126); + OPCODE(144, opPlayVideo); + OPCODE(146, opStackPop); + OPCODE(147, opStackDup); + OPCODE(148, opLoadSpecialCodeModule); + OPCODE(150, opRunSpecialCode); + OPCODE(160, opStopActor); + OPCODE(161, opSetActorUsePan); + OPCODE(168, opStartAbortableThread); + OPCODE(169, opKillThread); + OPCODE(175, opSetSceneIdThreadId); + OPCODE(176, opStackPush0); + OPCODE(177, opSetFontId); + OPCODE(178, opAddMenuKey); + OPCODE(179, opChangeSceneAll); +} + +#undef OPCODE + +void ScriptOpcodes_BBDOU::freeOpcodes() { + for (uint i = 0; i < 256; ++i) + delete _opcodes[i]; +} + +// Opcodes + +void ScriptOpcodes_BBDOU::opSuspend(ScriptThread *scriptThread, OpCall &opCall) { + opCall._result = kTSSuspend; +} + +void ScriptOpcodes_BBDOU::opYield(ScriptThread *scriptThread, OpCall &opCall) { + opCall._result = kTSYield; +} + +void ScriptOpcodes_BBDOU::opTerminate(ScriptThread *scriptThread, OpCall &opCall) { + opCall._result = kTSTerminate; +} + +void ScriptOpcodes_BBDOU::opJump(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(jumpOffs); + opCall._deltaOfs += jumpOffs; +} + +void ScriptOpcodes_BBDOU::opStartScriptThread(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(threadId); + _vm->startScriptThread(threadId, opCall._threadId, + scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10); +} + +void ScriptOpcodes_BBDOU::opStartTempScriptThread(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(codeOffs); + _vm->startTempScriptThread(opCall._code + codeOffs, + opCall._threadId, scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10); +} + +void ScriptOpcodes_BBDOU::opStartTimerThread(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(isAbortable); + ARG_INT16(duration); + ARG_INT16(maxDuration); + if (maxDuration) + duration += _vm->getRandom(maxDuration); + +duration = 1;//DEBUG Speeds up things + + if (isAbortable) + _vm->startAbortableTimerThread(duration, opCall._threadId); + else + _vm->startTimerThread(duration, opCall._threadId); +} + +void ScriptOpcodes_BBDOU::opSetThreadSceneId(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(sceneId); + _vm->_threads->setThreadSceneId(opCall._callerThreadId, sceneId); +} + +void ScriptOpcodes_BBDOU::opEndTalkThreads(ScriptThread *scriptThread, OpCall &opCall) { + _vm->_threads->endTalkThreads(); +} + +void ScriptOpcodes_BBDOU::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_BBDOU::opUnloadResource(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(resourceId); + // NOTE Skipped checking for stalled resources + _vm->_resSys->unloadResourceById(resourceId); +} + +void ScriptOpcodes_BBDOU::opEnterScene(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(sceneId); + uint scenesCount = _vm->_activeScenes.getActiveScenesCount(); + if (scenesCount > 0) { + uint32 currSceneId; + _vm->_activeScenes.getActiveSceneInfo(scenesCount, &currSceneId, 0); + // TODO krnfileDump(currSceneId); + } + if (!_vm->enterScene(sceneId, opCall._callerThreadId)) + opCall._result = kTSTerminate; +} + +//DEBUG Scenes +//uint32 dsceneId = 0x00010031, dthreadId = 0x00020036;//MAP +//uint32 dsceneId = 0x00010028, dthreadId = 0x000202A1; +//uint32 dsceneId = 0x00010007, dthreadId = 0x0002000C;//Auditorium +//uint32 dsceneId = 0x0001000B, dthreadId = 0x00020010; +//uint32 dsceneId = 0x00010013, dthreadId = 0x00020018;//Therapist +//uint32 dsceneId = 0x00010016, dthreadId = 0x0002001B;//Dorms ext +//uint32 dsceneId = 0x00010017, dthreadId = 0x0002001C;//Dorms int +//uint32 dsceneId = 0x0001000D, dthreadId = 0x00020012;//Food minigame +//uint32 dsceneId = 0x00010067, dthreadId = 0x0002022A; +//uint32 dsceneId = 0x0001000C, dthreadId = 0x00020011;//Cafeteria +uint32 dsceneId = 0x0001000B, dthreadId = 0x00020010; + +void ScriptOpcodes_BBDOU::opChangeScene(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(sceneId); + ARG_UINT32(threadId); + + if (dsceneId) { + sceneId = dsceneId; + threadId = dthreadId; + dsceneId = 0; + } + + // NOTE Skipped checking for stalled resources + _vm->_input->discardButtons(0xFFFF); + _vm->_prevSceneId = _vm->getCurrentScene(); + _vm->exitScene(opCall._callerThreadId); + _vm->enterScene(sceneId, opCall._callerThreadId); + // TODO _vm->_gameStates->writeStates(_vm->_prevSceneId, sceneId, threadId); + _vm->startAnonScriptThread(threadId, 0, + scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10); +} + +void ScriptOpcodes_BBDOU::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_BBDOU::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_BBDOU::opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(sceneId); + // NOTE Skipped checking for stalled resources + _vm->_input->discardButtons(0xFFFF); + _vm->enterPause(opCall._callerThreadId); + _vm->enterScene(sceneId, opCall._callerThreadId); +} + +void ScriptOpcodes_BBDOU::opExitCloseUpScene(ScriptThread *scriptThread, OpCall &opCall) { + _vm->exitScene(opCall._callerThreadId); + _vm->leavePause(opCall._callerThreadId); + opCall._result = kTSYield; +} + +void ScriptOpcodes_BBDOU::opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(speed); + ARG_UINT32(objectId); + _vm->_camera->panCenterObject(objectId, speed); +} + +void ScriptOpcodes_BBDOU::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_BBDOU::opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(speed); + ARG_UINT32(namedPointId); + Common::Point pos = _vm->getNamedPointPosition(namedPointId); + _vm->_camera->panToPoint(pos, speed, opCall._threadId); +} + +void ScriptOpcodes_BBDOU::opPanToPoint(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(speed); + ARG_INT16(x); + ARG_INT16(y); + _vm->_camera->panToPoint(Common::Point(x, y), speed, opCall._threadId); +} + +void ScriptOpcodes_BBDOU::opPanStop(ScriptThread *scriptThread, OpCall &opCall) { + _vm->_camera->stopPan(); +} + +void ScriptOpcodes_BBDOU::opSetDisplay(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(flag); + _vm->_screen->setDisplayOn(flag != 0); +} + +void ScriptOpcodes_BBDOU::opIncBlockCounter(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(index); + byte value = _vm->_scriptResource->_blockCounters.get(index) + 1; + if (value <= 63) + _vm->_scriptResource->_blockCounters.set(index, value); +} + +void ScriptOpcodes_BBDOU::opClearBlockCounter(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(index); + _vm->_scriptResource->_blockCounters.set(index, 0); +} + +void ScriptOpcodes_BBDOU::opSetProperty(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(value); + ARG_UINT32(propertyId); + _vm->_scriptResource->_properties.set(propertyId, value != 0); +} + +void ScriptOpcodes_BBDOU::opPlaceActor(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(objectId); + ARG_UINT32(actorTypeId); + ARG_UINT32(sequenceId); + ARG_UINT32(namedPointId); + Common::Point pos = _vm->getNamedPointPosition(namedPointId); + _vm->_controls->placeActor(actorTypeId, pos, sequenceId, objectId, opCall._threadId); +} + +void ScriptOpcodes_BBDOU::opFaceActor(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(facing); + ARG_UINT32(objectId); + Control *control = _vm->_dict->getObjectControl(objectId); + control->faceActor(facing); +} + +void ScriptOpcodes_BBDOU::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_BBDOU::opStartSequenceActor(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(objectId); + ARG_UINT32(sequenceId); + // NOTE Skipped checking for stalled sequence, not sure if needed + Control *control = _vm->_dict->getObjectControl(objectId); + control->startSequenceActor(sequenceId, 2, opCall._threadId); +} + +void ScriptOpcodes_BBDOU::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_BBDOU::opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(objectId); + ARG_UINT32(namedPointId); + Control *control = _vm->_dict->getObjectControl(objectId); + Common::Point pos = _vm->getNamedPointPosition(namedPointId); + control->stopActor(); + control->setActorPosition(pos); +} + +void ScriptOpcodes_BBDOU::opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(duration); + ARG_UINT32(objectId); + ARG_UINT32(talkId); + ARG_UINT32(sequenceId1); + ARG_UINT32(sequenceId2); + ARG_UINT32(namedPointId); + _vm->startTalkThread(duration, objectId, talkId, sequenceId1, sequenceId2, namedPointId, opCall._threadId); +} + +void ScriptOpcodes_BBDOU::opAppearActor(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(objectId); + Control *control = _vm->_dict->getObjectControl(objectId); + if (!control) { + Common::Point pos = _vm->getNamedPointPosition(0x70023); + _vm->_controls->placeActor(0x50001, pos, 0x60001, objectId, 0); + control = _vm->_dict->getObjectControl(objectId); + control->startSequenceActor(0x60001, 2, 0); + } + control->appearActor(); +} + +void ScriptOpcodes_BBDOU::opDisappearActor(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(objectId); + Control *control = _vm->_dict->getObjectControl(objectId); + control->disappearActor(); +} + +void ScriptOpcodes_BBDOU::opActivateObject(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(objectId); + Control *control = _vm->_dict->getObjectControl(objectId); + if (control) + control->activateObject(); +} + +void ScriptOpcodes_BBDOU::opDeactivateObject(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(objectId); + Control *control = _vm->_dict->getObjectControl(objectId); + control->deactivateObject(); +} + +void ScriptOpcodes_BBDOU::opSetDefaultSequence(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(objectId); + ARG_UINT32(defaultSequenceId); + ARG_UINT32(sequenceId); + Control *control = _vm->_dict->getObjectControl(objectId); + control->_actor->_defaultSequences.set(sequenceId, defaultSequenceId); +} + +void ScriptOpcodes_BBDOU::opSetSelectSfx(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(soundEffectId); + // TODO _vm->setSelectSfx(soundEffectId); +} + +void ScriptOpcodes_BBDOU::opSetMoveSfx(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(soundEffectId); + // TODO _vm->setMoveSfx(soundEffectId); +} + +void ScriptOpcodes_BBDOU::opSetDenySfx(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(soundEffectId); + // TODO _vm->setDenySfx(soundEffectId); +} + +void ScriptOpcodes_BBDOU::opSetAdjustUpSfx(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(soundEffectId); + // TODO _vm->setAdjustUpSfx(soundEffectId); +} + +void ScriptOpcodes_BBDOU::opSetAdjustDnSfx(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(soundEffectId); + // TODO _vm->setAdjustDnSfx(soundEffectId); +} + +void ScriptOpcodes_BBDOU::opStartSound(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_INT16(volume); + ARG_INT16(pan); + ARG_UINT32(soundEffectId); + // TODO _vm->startSound(soundEffectId, volume, pan); +} +void ScriptOpcodes_BBDOU::opStopSound(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(soundEffectId); + // TODO _vm->stopSound(soundEffectId); +} + +void ScriptOpcodes_BBDOU::opStartMusic(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_INT16(volume); + ARG_INT16(pan); + ARG_UINT32(musicId); + ARG_UINT32(type); + // TODO _vm->playMusic(musicId, type, volume, pan); +} + +void ScriptOpcodes_BBDOU::opStopMusic(ScriptThread *scriptThread, OpCall &opCall) { + // TODO _vm->stopMusic(); +} + +void ScriptOpcodes_BBDOU::opStackPushRandom(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(maxValue); + _vm->_stack->push(_vm->getRandom(maxValue) + 1); +} + +void ScriptOpcodes_BBDOU::opIfLte(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_INT16(rvalue); + ARG_INT16(elseJumpOffs); + int16 lvalue = _vm->_stack->pop(); + if (!(lvalue <= rvalue)) + opCall._deltaOfs += elseJumpOffs; +} + +void ScriptOpcodes_BBDOU::opAddMenuChoice(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_INT16(jumpOffs); + ARG_INT16(endMarker); + _vm->_stack->push(endMarker); + _vm->_stack->push(jumpOffs); +} + +void ScriptOpcodes_BBDOU::opDisplayMenu(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(unk1); + ARG_UINT32(menuId); + ARG_UINT32(unk2); + // TODO _vm->_shellMgr->displayMenu(_vm->_stack->topPtr(), &_vm->_menuChoiceOfs, menuId, unk1, unk2, opCall._callerThreadId); + // Remove menu choices from the stack + do { + _vm->_stack->pop(); + } while (_vm->_stack->pop() == 0); + + //DEBUG Resume calling thread, later done by the video player + _vm->notifyThreadId(opCall._callerThreadId); + +} + +void ScriptOpcodes_BBDOU::opSwitchMenuChoice(ScriptThread *scriptThread, OpCall &opCall) { +_vm->_menuChoiceOfs = 88; // DEBUG Chose "Start game" + + opCall._deltaOfs += _vm->_menuChoiceOfs; +} + +void ScriptOpcodes_BBDOU::opResetGame(ScriptThread *scriptThread, OpCall &opCall) { + _vm->_threads->terminateThreads(opCall._callerThreadId); + _vm->reset(); + _vm->_input->activateButton(0xFFFF); + // TODO _vm->stopMusic(); + // TODO _vm->_gameStates->clear(); +} + +void ScriptOpcodes_BBDOU::opDeactivateButton(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(button) + _vm->_input->deactivateButton(button); +} + +void ScriptOpcodes_BBDOU::opActivateButton(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(button) + _vm->_input->activateButton(button); +} + +void ScriptOpcodes_BBDOU::opJumpIf(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(jumpOffs); + int16 value = _vm->_stack->pop(); + if (value == 0) + opCall._deltaOfs += jumpOffs; +} + +void ScriptOpcodes_BBDOU::opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(sceneId); + _vm->_stack->push(_vm->_prevSceneId == sceneId ? 1 : 0); +} + +void ScriptOpcodes_BBDOU::opIsCurrentSceneId(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(sceneId); + _vm->_stack->push(_vm->getCurrentScene() == sceneId ? 1 : 0); +} + +void ScriptOpcodes_BBDOU::opIsActiveSceneId(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(sceneId); + _vm->_stack->push(_vm->_activeScenes.isSceneActive(sceneId) ? 1 : 0); +} + +void ScriptOpcodes_BBDOU::opNot(ScriptThread *scriptThread, OpCall &opCall) { + int16 value = _vm->_stack->pop(); + _vm->_stack->push(value != 0 ? 0 : 1); +} + +void ScriptOpcodes_BBDOU::opAnd(ScriptThread *scriptThread, OpCall &opCall) { + int16 value1 = _vm->_stack->pop(); + int16 value2 = _vm->_stack->pop(); + _vm->_stack->push(value1 & value2); +} + +void ScriptOpcodes_BBDOU::opOr(ScriptThread *scriptThread, OpCall &opCall) { + int16 value1 = _vm->_stack->pop(); + int16 value2 = _vm->_stack->pop(); + _vm->_stack->push(value1 | value2); +} + +void ScriptOpcodes_BBDOU::opGetProperty(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(propertyId) + bool value = _vm->_scriptResource->_properties.get(propertyId); + _vm->_stack->push(value ? 1 : 0); +} + +void ScriptOpcodes_BBDOU::opCompareBlockCounter(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(index); + ARG_INT16(compareOp); + ARG_INT16(rvalue); + int16 lvalue = _vm->_scriptResource->_blockCounters.get(index); + bool compareResult = false; + switch (compareOp) { + case 1: + compareResult = lvalue == rvalue; + break; + case 2: + compareResult = lvalue != rvalue; + break; + case 3: + compareResult = lvalue < rvalue; + break; + case 4: + compareResult = lvalue > rvalue; + break; + case 5: + compareResult = lvalue >= rvalue; + break; + case 6: + compareResult = lvalue <= rvalue; + break; + } + _vm->_stack->push(compareResult ? 1 : 0); +} + +void ScriptOpcodes_BBDOU::opDebug126(ScriptThread *scriptThread, OpCall &opCall) { + // NOTE Prints some debug text + debug(1, "[DBG] %s", (char*)opCall._code); +} + +void ScriptOpcodes_BBDOU::opPlayVideo(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(objectId); + ARG_UINT32(videoId); + ARG_UINT32(priority); + // TODO _vm->playVideo(videoId, objectId, value, opCall._threadId); + + //DEBUG Resume calling thread, later done by the video player + _vm->notifyThreadId(opCall._callerThreadId); + +} + +void ScriptOpcodes_BBDOU::opStackPop(ScriptThread *scriptThread, OpCall &opCall) { + _vm->_stack->pop(); +} + +void ScriptOpcodes_BBDOU::opStackDup(ScriptThread *scriptThread, OpCall &opCall) { + int16 value = _vm->_stack->peek(); + _vm->_stack->push(value); +} + +void ScriptOpcodes_BBDOU::opLoadSpecialCodeModule(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(specialCodeModuleId); + _vm->_resSys->loadResource(specialCodeModuleId, 0, 0); +} + +void ScriptOpcodes_BBDOU::opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(specialCodeId); + _vm->_specialCode->run(specialCodeId, opCall); +} + +void ScriptOpcodes_BBDOU::opStopActor(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(objectId); + Control *control = _vm->_dict->getObjectControl(objectId); + control->stopActor(); +} + +void ScriptOpcodes_BBDOU::opSetActorUsePan(ScriptThread *scriptThread, OpCall &opCall) { + ARG_INT16(usePan) + ARG_UINT32(objectId); + Control *control = _vm->_dict->getObjectControl(objectId); + control->setActorUsePan(usePan); +} + +void ScriptOpcodes_BBDOU::opStartAbortableThread(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_INT16(codeOffs); + ARG_INT16(skipOffs); + _vm->startAbortableThread(opCall._code + codeOffs, + opCall._code + skipOffs, opCall._threadId); +} + +void ScriptOpcodes_BBDOU::opKillThread(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(threadId); + _vm->_threads->killThread(threadId); +} + +void ScriptOpcodes_BBDOU::opSetSceneIdThreadId(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(sceneId); + ARG_UINT32(threadId); + _vm->setSceneIdThreadId(sceneId, threadId); +} + +void ScriptOpcodes_BBDOU::opStackPush0(ScriptThread *scriptThread, OpCall &opCall) { + _vm->_stack->push(0); +} + +void ScriptOpcodes_BBDOU::opSetFontId(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(fontId); + _vm->setCurrFontId(fontId); +} + +void ScriptOpcodes_BBDOU::opAddMenuKey(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(key); + ARG_UINT32(threadId); + // TODO _vm->addMenuKey(key, threadId); +} + +void ScriptOpcodes_BBDOU::opChangeSceneAll(ScriptThread *scriptThread, OpCall &opCall) { + ARG_SKIP(2); + ARG_UINT32(sceneId); + ARG_UINT32(threadId); + // NOTE Skipped checking for stalled resources + _vm->_input->discardButtons(0xFFFF); + _vm->_prevSceneId = _vm->getCurrentScene(); + _vm->dumpActiveScenes(_vm->_globalSceneId, opCall._callerThreadId); + _vm->enterScene(sceneId, opCall._callerThreadId); + // TODO _vm->_gameStates->writeStates(_vm->_prevSceneId, sceneId, threadId); + _vm->startAnonScriptThread(threadId, 0, + scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10); +} + +} // End of namespace Illusions diff --git a/engines/illusions/scriptopcodes_bbdou.h b/engines/illusions/scriptopcodes_bbdou.h new file mode 100644 index 0000000000..28c798710b --- /dev/null +++ b/engines/illusions/scriptopcodes_bbdou.h @@ -0,0 +1,128 @@ +/* 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_SCRIPTOPCODES_BBDOU_H +#define ILLUSIONS_SCRIPTOPCODES_BBDOU_H + +#include "illusions/scriptopcodes.h" +#include "common/func.h" + +namespace Illusions { + +class IllusionsEngine_BBDOU; +class ScriptThread; + +class ScriptOpcodes_BBDOU : public ScriptOpcodes { +public: + ScriptOpcodes_BBDOU(IllusionsEngine_BBDOU *vm); + ~ScriptOpcodes_BBDOU(); + void initOpcodes(); + void freeOpcodes(); +protected: + IllusionsEngine_BBDOU *_vm; + + // Opcodes + void opSuspend(ScriptThread *scriptThread, OpCall &opCall); + void opYield(ScriptThread *scriptThread, OpCall &opCall); + void opTerminate(ScriptThread *scriptThread, OpCall &opCall); + void opJump(ScriptThread *scriptThread, OpCall &opCall); + void opStartScriptThread(ScriptThread *scriptThread, OpCall &opCall); + void opStartTempScriptThread(ScriptThread *scriptThread, OpCall &opCall); + void opStartTimerThread(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 opChangeScene(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 opSetDisplay(ScriptThread *scriptThread, OpCall &opCall); + void opIncBlockCounter(ScriptThread *scriptThread, OpCall &opCall); + void opClearBlockCounter(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 opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall); + void opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall); + void opAppearActor(ScriptThread *scriptThread, OpCall &opCall); + void opDisappearActor(ScriptThread *scriptThread, OpCall &opCall); + void opActivateObject(ScriptThread *scriptThread, OpCall &opCall); + void opDeactivateObject(ScriptThread *scriptThread, OpCall &opCall); + void opSetDefaultSequence(ScriptThread *scriptThread, OpCall &opCall); + void opSetSelectSfx(ScriptThread *scriptThread, OpCall &opCall); + void opSetMoveSfx(ScriptThread *scriptThread, OpCall &opCall); + void opSetDenySfx(ScriptThread *scriptThread, OpCall &opCall); + void opSetAdjustUpSfx(ScriptThread *scriptThread, OpCall &opCall); + void opSetAdjustDnSfx(ScriptThread *scriptThread, OpCall &opCall); + void opStartSound(ScriptThread *scriptThread, OpCall &opCall); + void opStopSound(ScriptThread *scriptThread, OpCall &opCall); + void opStartMusic(ScriptThread *scriptThread, OpCall &opCall); + void opStopMusic(ScriptThread *scriptThread, OpCall &opCall); + void opStackPushRandom(ScriptThread *scriptThread, OpCall &opCall); + void opIfLte(ScriptThread *scriptThread, OpCall &opCall); + void opAddMenuChoice(ScriptThread *scriptThread, OpCall &opCall); + void opDisplayMenu(ScriptThread *scriptThread, OpCall &opCall); + void opSwitchMenuChoice(ScriptThread *scriptThread, OpCall &opCall); + void opResetGame(ScriptThread *scriptThread, OpCall &opCall); + void opDeactivateButton(ScriptThread *scriptThread, OpCall &opCall); + void opActivateButton(ScriptThread *scriptThread, OpCall &opCall); + void opJumpIf(ScriptThread *scriptThread, OpCall &opCall); + void opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall); + void opIsCurrentSceneId(ScriptThread *scriptThread, OpCall &opCall); + void opIsActiveSceneId(ScriptThread *scriptThread, OpCall &opCall); + void opNot(ScriptThread *scriptThread, OpCall &opCall); + void opAnd(ScriptThread *scriptThread, OpCall &opCall); + void opOr(ScriptThread *scriptThread, OpCall &opCall); + void opGetProperty(ScriptThread *scriptThread, OpCall &opCall); + void opCompareBlockCounter(ScriptThread *scriptThread, OpCall &opCall); + void opDebug126(ScriptThread *scriptThread, OpCall &opCall); + void opPlayVideo(ScriptThread *scriptThread, OpCall &opCall); + void opStackPop(ScriptThread *scriptThread, OpCall &opCall); + void opStackDup(ScriptThread *scriptThread, OpCall &opCall); + void opLoadSpecialCodeModule(ScriptThread *scriptThread, OpCall &opCall); + void opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall); + void opStopActor(ScriptThread *scriptThread, OpCall &opCall); + void opSetActorUsePan(ScriptThread *scriptThread, OpCall &opCall); + void opStartAbortableThread(ScriptThread *scriptThread, OpCall &opCall); + void opKillThread(ScriptThread *scriptThread, OpCall &opCall); + void opSetSceneIdThreadId(ScriptThread *scriptThread, OpCall &opCall); + void opStackPush0(ScriptThread *scriptThread, OpCall &opCall); + void opSetFontId(ScriptThread *scriptThread, OpCall &opCall); + void opAddMenuKey(ScriptThread *scriptThread, OpCall &opCall); + void opChangeSceneAll(ScriptThread *scriptThread, OpCall &opCall); + +}; + +} // End of namespace Illusions + +#endif // ILLUSIONS_SCRIPTOPCODES_H diff --git a/engines/illusions/scriptresource.cpp b/engines/illusions/scriptresource.cpp index 9c4f171c0b..715039e7d5 100644 --- a/engines/illusions/scriptresource.cpp +++ b/engines/illusions/scriptresource.cpp @@ -34,7 +34,7 @@ void ScriptResourceLoader::load(Resource *resource) { ScriptResource *scriptResource = new ScriptResource(); scriptResource->load(resource->_data, resource->_dataSize); - _vm->_scriptMan->_scriptResource = scriptResource; + _vm->_scriptResource = scriptResource; } diff --git a/engines/illusions/scriptthread.cpp b/engines/illusions/scriptthread.cpp index 6f6d3a0709..78fb8b86ab 100644 --- a/engines/illusions/scriptthread.cpp +++ b/engines/illusions/scriptthread.cpp @@ -34,7 +34,7 @@ ScriptThread::ScriptThread(IllusionsEngine *vm, uint32 threadId, uint32 callingT : Thread(vm, threadId, callingThreadId, notifyFlags), _scriptCodeIp(scriptCodeIp), _value8(value8), _valueC(valueC), _value10(value10), _sequenceStalled(0) { _type = kTTScriptThread; - _tag = _vm->_scriptMan->_activeScenes.getCurrentScene(); + _tag = _vm->getCurrentScene(); } int ScriptThread::onUpdate() { @@ -56,8 +56,7 @@ int ScriptThread::onUpdate() { } void ScriptThread::execOpcode(OpCall &opCall) { - // TODO Clean this up - _vm->_scriptMan->_scriptOpcodes->execOpcode(this, opCall); + _vm->_scriptOpcodes->execOpcode(this, opCall); } } // End of namespace Illusions diff --git a/engines/illusions/sequenceopcodes.cpp b/engines/illusions/sequenceopcodes.cpp index 818b6816a1..f020423a1a 100644 --- a/engines/illusions/sequenceopcodes.cpp +++ b/engines/illusions/sequenceopcodes.cpp @@ -99,11 +99,6 @@ void SequenceOpcodes::freeOpcodes() { // Opcodes -// Convenience macros -#define ARG_SKIP(x) opCall.skip(x); -#define ARG_INT16(name) int16 name = opCall.readSint16(); debug(1, "ARG_INT16(" #name " = %d)", name); -#define ARG_UINT32(name) uint32 name = opCall.readUint32(); debug(1, "ARG_UINT32(" #name " = %08X)", name); - void SequenceOpcodes::opYield(Control *control, OpCall &opCall) { opCall._result = 2; } @@ -138,7 +133,7 @@ void SequenceOpcodes::opEndSequence(Control *control, OpCall &opCall) { control->_actor->_frames = 0; control->_actor->_frameIndex = 0; control->_actor->_newFrameIndex = 0; - // TODO _vm->_resSys->unloadResourceById(control->_actor->_sequenceId); + _vm->_resSys->unloadResourceById(control->_actor->_sequenceId); } _vm->notifyThreadId(control->_actor->_notifyThreadId1); opCall._result = 1; @@ -321,7 +316,7 @@ void SequenceOpcodes::opStopSound(Control *control, OpCall &opCall) { void SequenceOpcodes::opStartScriptThread(Control *control, OpCall &opCall) { ARG_SKIP(2); ARG_UINT32(threadId); - _vm->_scriptMan->startScriptThread(threadId, 0, 0, 0, 0); + _vm->startScriptThreadSimple(threadId, 0); } void SequenceOpcodes::opPlaceSubActor(Control *control, OpCall &opCall) { diff --git a/engines/illusions/specialcode.cpp b/engines/illusions/specialcode.cpp index a412462d26..37286574a9 100644 --- a/engines/illusions/specialcode.cpp +++ b/engines/illusions/specialcode.cpp @@ -30,14 +30,12 @@ namespace Illusions { void SpecialCodeLoader::load(Resource *resource) { debug("SpecialCodeLoader::load() Loading special code %08X...", resource->_resId); - _vm->_specialCode = new BbdouSpecialCode(_vm); - _vm->_specialCode->init(); + _vm->loadSpecialCode(resource->_resId); } void SpecialCodeLoader::unload(Resource *resource) { debug("SpecialCodeLoader::unload() Unloading special code %08X...", resource->_resId); - delete _vm->_specialCode; - _vm->_specialCode = 0; + _vm->unloadSpecialCode(resource->_resId); } void SpecialCodeLoader::buildFilename(Resource *resource) { diff --git a/engines/illusions/specialcode.h b/engines/illusions/specialcode.h index e3ecc8d7c1..9a69b389b3 100644 --- a/engines/illusions/specialcode.h +++ b/engines/illusions/specialcode.h @@ -44,12 +44,9 @@ protected: class SpecialCode { public: - SpecialCode(IllusionsEngine *vm) : _vm(vm) {} virtual ~SpecialCode() {} virtual void init() = 0; virtual void run(uint32 specialCodeId, OpCall &opCall) = 0; -protected: - IllusionsEngine *_vm; }; } // End of namespace Illusions diff --git a/engines/illusions/talkthread.cpp b/engines/illusions/talkthread.cpp index 10ff05df7d..d74dddeea2 100644 --- a/engines/illusions/talkthread.cpp +++ b/engines/illusions/talkthread.cpp @@ -52,16 +52,16 @@ TalkThread::TalkThread(IllusionsEngine *vm, uint32 threadId, uint32 callingThrea if (duration) _status = 1; - else if (_vm->_scriptMan->checkActiveTalkThreads()) + else if (_vm->checkActiveTalkThreads()) _status = 2; else _status = 3; _flags = 0x0E; - _durationMult = _vm->_scriptMan->clipTextDuration(_vm->_scriptMan->_fieldE); + _durationMult = _vm->clipTextDuration(_vm->_fieldE); _textDuration = _durationMult; - _defDurationMult = _vm->_scriptMan->clipTextDuration(240); + _defDurationMult = _vm->clipTextDuration(240); _textStartTime = 0; _textEndTime = 0; _textDurationElapsed = 0; @@ -74,7 +74,7 @@ TalkThread::TalkThread(IllusionsEngine *vm, uint32 threadId, uint32 callingThrea _entryTblPtr = 0; if (callingThreadId) { - Thread *callingThread = _vm->_scriptMan->_threads->findThread(callingThreadId); + Thread *callingThread = _vm->_threads->findThread(callingThreadId); if (callingThread) _tag = callingThread->_tag; } @@ -90,7 +90,7 @@ int TalkThread::onUpdate() { case 1: if (isTimerExpired(_voiceStartTime, _voiceEndTime)) { - if (_vm->_scriptMan->checkActiveTalkThreads()) + if (_vm->checkActiveTalkThreads()) _status = 2; else _status = 3; @@ -98,7 +98,7 @@ int TalkThread::onUpdate() { return kTSYield; case 2: - if (_vm->_scriptMan->checkActiveTalkThreads()) + if (_vm->checkActiveTalkThreads()) return kTSYield; _status = 3; // Fallthrough to status 3 @@ -312,7 +312,7 @@ int TalkThread::insertText() { _entryText = 0; // TODO _vm->getDimensions1(&dimensions); - // TODO _vm->insertText(_currEntryText, _vm->_scriptMan->currFontId, dimensions, 0, 2, 0, 0, 0, 0, 0, 0, &outTextPtr); + // TODO _vm->insertText(_currEntryText, _vm->_currFontId, dimensions, 0, 2, 0, 0, 0, 0, 0, 0, &outTextPtr); // TODO _vm->charCount = (char *)outTextPtr - (char *)text; // TODO _entryText = outTextPtr; // TODO _vm->getPoint1(&pt); diff --git a/engines/illusions/timerthread.cpp b/engines/illusions/timerthread.cpp index bf9c32fbdb..8cd5ea2e1c 100644 --- a/engines/illusions/timerthread.cpp +++ b/engines/illusions/timerthread.cpp @@ -38,7 +38,7 @@ TimerThread::TimerThread(IllusionsEngine *vm, uint32 threadId, uint32 callingThr _endTime = _startTime + _duration; if (callingThreadId) { - Thread *callingThread = _vm->_scriptMan->_threads->findThread(callingThreadId); + Thread *callingThread = _vm->_threads->findThread(callingThreadId); if (callingThread) _tag = callingThread->_tag; } |