From 41bd7cd94b6c26ea06da5a2f3f0aefdf4adc5c90 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 11 Apr 2009 21:38:41 +0000 Subject: SAGA: changed _threadList back to a list of ScriptThread objs, instead of ptrs to instances. svn-id: r39944 --- engines/saga/events.cpp | 19 +++----- engines/saga/script.cpp | 6 +-- engines/saga/script.h | 54 +++++++++++++++++----- engines/saga/sfuncs.cpp | 9 ++-- engines/saga/sthread.cpp | 115 +++++++++++++++++++++++------------------------ 5 files changed, 110 insertions(+), 93 deletions(-) diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp index 2e0cb9f09a..cce8464653 100644 --- a/engines/saga/events.cpp +++ b/engines/saga/events.cpp @@ -273,7 +273,6 @@ int Events::handleImmediate(Event *event) { } int Events::handleOneShot(Event *event) { - ScriptThread *sthread; Rect rect; @@ -478,24 +477,20 @@ int Events::handleOneShot(Event *event) { case kScriptEvent: switch (event->op) { case kEventExecBlocking: - case kEventExecNonBlocking: + case kEventExecNonBlocking: { debug(6, "Exec module number %ld script entry number %ld", event->param, event->param2); - sthread = _vm->_script->createThread(event->param, event->param2); - if (sthread == NULL) { - _vm->_console->DebugPrintf("Thread creation failed.\n"); - break; - } - - sthread->_threadVars[kThreadVarAction] = event->param3; - sthread->_threadVars[kThreadVarObject] = event->param4; - sthread->_threadVars[kThreadVarWithObject] = event->param5; - sthread->_threadVars[kThreadVarActor] = event->param6; + ScriptThread &sthread = _vm->_script->createThread(event->param, event->param2); + sthread._threadVars[kThreadVarAction] = event->param3; + sthread._threadVars[kThreadVarObject] = event->param4; + sthread._threadVars[kThreadVarWithObject] = event->param5; + sthread._threadVars[kThreadVarActor] = event->param6; if (event->op == kEventExecBlocking) _vm->_script->completeThread(); break; + } case kEventThreadWake: _vm->_script->wakeUpThreads(event->param); break; diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp index 1cc85b05c2..7a7e15c249 100644 --- a/engines/saga/script.cpp +++ b/engines/saga/script.cpp @@ -220,11 +220,7 @@ Script::Script(SagaEngine *vm) : _vm(vm) { // Shut down script module gracefully; free all allocated module resources Script::~Script() { - ScriptThreadList::iterator threadIterator = _threadList.begin(); - while (threadIterator != _threadList.end()) { - delete *threadIterator; - threadIterator = _threadList.erase(threadIterator); - } + } // Script opcodes diff --git a/engines/saga/script.h b/engines/saga/script.h index fd4a4df0f3..85eb92b96c 100644 --- a/engines/saga/script.h +++ b/engines/saga/script.h @@ -42,7 +42,6 @@ namespace Saga { #define ITE_SCRIPT_FUNCTION_MAX 78 #define IHNM_SCRIPT_FUNCTION_MAX 105 -#define DEFAULT_THREAD_STACK_SIZE 256 enum AddressTypes { kAddressCommon = 0, // offset from global variables @@ -169,8 +168,7 @@ struct ModuleData { class ScriptThread { public: - uint16 *_stackBuf; - uint16 _stackSize; // stack size in uint16 + int16 *_stackBuf; uint16 _stackTopIndex; uint16 _frameIndex; @@ -196,6 +194,10 @@ public: int32 _frameWait; + enum { + THREAD_STACK_SIZE = 256 + }; + public: byte *baseAddress(byte addrMode) { switch (addrMode) { @@ -215,25 +217,25 @@ public: } int16 stackTop() { - return (int16)_stackBuf[_stackTopIndex]; + return _stackBuf[_stackTopIndex]; } uint pushedSize() { - return _stackSize - _stackTopIndex - 2; + return THREAD_STACK_SIZE - _stackTopIndex - 2; } void push(int16 value) { if (_stackTopIndex <= 0) { error("ScriptThread::push() stack overflow"); } - _stackBuf[--_stackTopIndex] = (uint16)value; + _stackBuf[--_stackTopIndex] = value; } int16 pop() { - if (_stackTopIndex >= _stackSize) { + if (_stackTopIndex >= THREAD_STACK_SIZE) { error("ScriptThread::pop() stack underflow"); } - return (int16)_stackBuf[_stackTopIndex++]; + return _stackBuf[_stackTopIndex++]; } @@ -260,14 +262,42 @@ public: ScriptThread() { memset(this, 0xFE, sizeof(*this)); - _stackBuf = NULL; + _flags = kTFlagNone; + _stackBuf = 0; + } + + // copy constructor + ScriptThread(const ScriptThread& s) { + memcpy(this, &s, sizeof(*this)); + + // Verify that s doesn't have a non-zero _stackBuf, for else + // we would have to clone that buffer, too, which we currently + // don't do. This case should never occur anyway, though (at + // least as long as the thread handling code does not change). + assert(!_stackBuf); } + + // assignment operator + ScriptThread& operator=(const ScriptThread &s) { + if (this == &s) + return *this; + + free(_stackBuf); + memcpy(this, &s, sizeof(*this)); + + // Verify that s doesn't have a non-zero _stackBuf, for else + // we would have to clone that buffer, too, which we currently + // don't do. This case should never occur anyway, though (at + // least as long as the thread handling code does not change). + assert(!_stackBuf); + } + ~ScriptThread() { free(_stackBuf); } }; -typedef Common::List ScriptThreadList; +typedef Common::List ScriptThreadList; #define SCRIPTOP_PARAMS ScriptThread *thread, MemoryReadStream *scriptS, bool &stopParsing, bool &breakOut #define SCRIPTFUNC_PARAMS ScriptThread *thread, int nArgs, bool &disContinue @@ -381,7 +411,7 @@ public: VoiceLUT _globalVoiceLUT; public: - ScriptThread *createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber); + ScriptThread &createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber); int executeThread(ScriptThread *thread, int entrypointNumber); void executeThreads(uint msec); void completeThread(void); @@ -397,7 +427,7 @@ protected: void loadModuleBase(ModuleData &module, const byte *resourcePointer, size_t resourceLength); // runThread returns true if we should break running of other threads - bool runThread(ScriptThread *thread); + bool runThread(ScriptThread &thread); void setThreadEntrypoint(ScriptThread *thread, int entrypointNumber); public: diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp index 3010fb696d..4c44aa2bdd 100644 --- a/engines/saga/sfuncs.cpp +++ b/engines/saga/sfuncs.cpp @@ -394,15 +394,14 @@ void Script::sfPreDialog(SCRIPTFUNC_PARAMS) { // Script function #13 (0x0D) void Script::sfKillActorThreads(SCRIPTFUNC_PARAMS) { - ScriptThread *anotherThread; ScriptThreadList::iterator threadIterator; int16 actorId = thread->pop(); for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) { - anotherThread = *threadIterator; - if ((anotherThread != thread) && (anotherThread->_threadVars[kThreadVarActor] == actorId)) { - anotherThread->_flags &= ~kTFlagWaiting; - anotherThread->_flags |= kTFlagAborted; + ScriptThread &anotherThread = *threadIterator; + if ((&anotherThread != thread) && (anotherThread._threadVars[kThreadVarActor] == actorId)) { + anotherThread._flags &= ~kTFlagWaiting; + anotherThread._flags |= kTFlagAborted; } } } diff --git a/engines/saga/sthread.cpp b/engines/saga/sthread.cpp index b6b0df9cc9..5edd40ac16 100644 --- a/engines/saga/sthread.cpp +++ b/engines/saga/sthread.cpp @@ -37,42 +37,40 @@ namespace Saga { -ScriptThread *Script::createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber) { - ScriptThread *newThread = new ScriptThread(); - +ScriptThread &Script::createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber) { loadModule(scriptModuleNumber); if (_modules[scriptModuleNumber].entryPointsCount <= scriptEntryPointNumber) { error("Script::createThread wrong scriptEntryPointNumber"); } - newThread->_flags = kTFlagNone; - newThread->_stackSize = DEFAULT_THREAD_STACK_SIZE; - newThread->_stackBuf = (uint16 *)malloc(newThread->_stackSize * sizeof(uint16)); - newThread->_stackTopIndex = newThread->_stackSize - 2; - newThread->_instructionOffset = _modules[scriptModuleNumber].entryPoints[scriptEntryPointNumber].offset; - newThread->_commonBase = _commonBuffer; - newThread->_staticBase = _commonBuffer + _modules[scriptModuleNumber].staticOffset; - newThread->_moduleBase = _modules[scriptModuleNumber].moduleBase; - newThread->_moduleBaseSize = _modules[scriptModuleNumber].moduleBaseSize; - newThread->_strings = &_modules[scriptModuleNumber].strings; + ScriptThread newThread; + newThread._instructionOffset = _modules[scriptModuleNumber].entryPoints[scriptEntryPointNumber].offset; + newThread._commonBase = _commonBuffer; + newThread._staticBase = _commonBuffer + _modules[scriptModuleNumber].staticOffset; + newThread._moduleBase = _modules[scriptModuleNumber].moduleBase; + newThread._moduleBaseSize = _modules[scriptModuleNumber].moduleBaseSize; + newThread._strings = &_modules[scriptModuleNumber].strings; if (_vm->getGameId() == GID_IHNM) - newThread->_voiceLUT = &_globalVoiceLUT; + newThread._voiceLUT = &_globalVoiceLUT; else - newThread->_voiceLUT = &_modules[scriptModuleNumber].voiceLUT; + newThread._voiceLUT = &_modules[scriptModuleNumber].voiceLUT; _threadList.push_front(newThread); - return newThread; + ScriptThread &tmp = *_threadList.begin(); + tmp._stackBuf = (int16 *)malloc(ScriptThread::THREAD_STACK_SIZE * sizeof(int16)); + tmp._stackTopIndex = ScriptThread::THREAD_STACK_SIZE - 2; + return tmp; } void Script::wakeUpActorThread(int waitType, void *threadObj) { ScriptThreadList::iterator threadIterator; for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) { - ScriptThread *thread = *threadIterator; - if ((thread->_flags & kTFlagWaiting) && (thread->_waitType == waitType) && (thread->_threadObj == threadObj)) { - thread->_flags &= ~kTFlagWaiting; + ScriptThread &thread = *threadIterator; + if ((thread._flags & kTFlagWaiting) && (thread._waitType == waitType) && (thread._threadObj == threadObj)) { + thread._flags &= ~kTFlagWaiting; } } } @@ -81,9 +79,9 @@ void Script::wakeUpThreads(int waitType) { ScriptThreadList::iterator threadIterator; for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) { - ScriptThread *thread = *threadIterator; - if ((thread->_flags & kTFlagWaiting) && (thread->_waitType == waitType)) { - thread->_flags &= ~kTFlagWaiting; + ScriptThread &thread = *threadIterator; + if ((thread._flags & kTFlagWaiting) && (thread._waitType == waitType)) { + thread._flags &= ~kTFlagWaiting; } } } @@ -92,10 +90,10 @@ void Script::wakeUpThreadsDelayed(int waitType, int sleepTime) { ScriptThreadList::iterator threadIterator; for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) { - ScriptThread *thread = *threadIterator; - if ((thread->_flags & kTFlagWaiting) && (thread->_waitType == waitType)) { - thread->_waitType = kWaitTypeDelay; - thread->_sleepTime = sleepTime; + ScriptThread &thread = *threadIterator; + if ((thread._flags & kTFlagWaiting) && (thread._waitType == waitType)) { + thread._waitType = kWaitTypeDelay; + thread._sleepTime = sleepTime; } } } @@ -110,55 +108,54 @@ void Script::executeThreads(uint msec) { threadIterator = _threadList.begin(); while (threadIterator != _threadList.end()) { - ScriptThread *thread = *threadIterator; + ScriptThread &thread = *threadIterator; - if (thread->_flags & (kTFlagFinished | kTFlagAborted)) { - if (thread->_flags & kTFlagFinished) + if (thread._flags & (kTFlagFinished | kTFlagAborted)) { + if (thread._flags & kTFlagFinished) setPointerVerb(); if (_vm->getGameId() == GID_IHNM) { - thread->_flags &= ~kTFlagFinished; - thread->_flags |= kTFlagAborted; + thread._flags &= ~kTFlagFinished; + thread._flags |= kTFlagAborted; ++threadIterator; } else { - delete *threadIterator; threadIterator = _threadList.erase(threadIterator); } continue; } - if (thread->_flags & kTFlagWaiting) { + if (thread._flags & kTFlagWaiting) { - switch (thread->_waitType) { + switch (thread._waitType) { case kWaitTypeDelay: - if (thread->_sleepTime < msec) { - thread->_sleepTime = 0; + if (thread._sleepTime < msec) { + thread._sleepTime = 0; } else { - thread->_sleepTime -= msec; + thread._sleepTime -= msec; } - if (thread->_sleepTime == 0) - thread->_flags &= ~kTFlagWaiting; + if (thread._sleepTime == 0) + thread._flags &= ~kTFlagWaiting; break; case kWaitTypeWalk: { ActorData *actor; - actor = (ActorData *)thread->_threadObj; + actor = (ActorData *)thread._threadObj; if (actor->_currentAction == kActionWait) { - thread->_flags &= ~kTFlagWaiting; + thread._flags &= ~kTFlagWaiting; } } break; case kWaitTypeWaitFrames: // IHNM - if (thread->_frameWait < _vm->_frameCount) - thread->_flags &= ~kTFlagWaiting; + if (thread._frameWait < _vm->_frameCount) + thread._flags &= ~kTFlagWaiting; break; } } - if (!(thread->_flags & kTFlagWaiting)) { + if (!(thread._flags & kTFlagWaiting)) { if (runThread(thread)) { break; } @@ -175,8 +172,8 @@ void Script::abortAllThreads(void) { threadIterator = _threadList.begin(); while (threadIterator != _threadList.end()) { - ScriptThread *thread = *threadIterator; - thread->_flags |= kTFlagAborted; + ScriptThread &thread = *threadIterator; + thread._flags |= kTFlagAborted; ++threadIterator; } executeThreads(0); @@ -189,44 +186,44 @@ void Script::completeThread(void) { executeThreads(0); } -bool Script::runThread(ScriptThread *thread) { +bool Script::runThread(ScriptThread &thread) { uint16 savedInstructionOffset; bool stopParsing = false; bool breakOut = false; int operandChar; - MemoryReadStream scriptS(thread->_moduleBase, thread->_moduleBaseSize); + MemoryReadStream scriptS(thread._moduleBase, thread._moduleBaseSize); - scriptS.seek(thread->_instructionOffset); + scriptS.seek(thread._instructionOffset); for (uint instructionCount = 0; instructionCount < STHREAD_TIMESLICE; instructionCount++) { - if (thread->_flags & (kTFlagAsleep)) + if (thread._flags & (kTFlagAsleep)) break; - savedInstructionOffset = thread->_instructionOffset; + savedInstructionOffset = thread._instructionOffset; operandChar = scriptS.readByte(); - debug(8, "Executing thread offset: %u (%x) stack: %d", thread->_instructionOffset, operandChar, thread->pushedSize()); + debug(8, "Executing thread offset: %u (%x) stack: %d", thread._instructionOffset, operandChar, thread.pushedSize()); stopParsing = false; debug(4, "Calling op %s", this->_scriptOpsList[operandChar].scriptOpName); - (this->*_scriptOpsList[operandChar].scriptOp)(thread, &scriptS, stopParsing, breakOut); + (this->*_scriptOpsList[operandChar].scriptOp)(&thread, &scriptS, stopParsing, breakOut); if (stopParsing) return breakOut; - if (thread->_flags & (kTFlagFinished | kTFlagAborted)) { - error("Wrong flags %d in thread", thread->_flags); + if (thread._flags & (kTFlagFinished | kTFlagAborted)) { + error("Wrong flags %d in thread", thread._flags); } // Set instruction offset only if a previous instruction didn't branch - if (savedInstructionOffset == thread->_instructionOffset) { - thread->_instructionOffset = scriptS.pos(); + if (savedInstructionOffset == thread._instructionOffset) { + thread._instructionOffset = scriptS.pos(); } else { - if (thread->_instructionOffset >= scriptS.size()) { + if (thread._instructionOffset >= scriptS.size()) { error("Script::runThread() Out of range script execution"); } - scriptS.seek(thread->_instructionOffset); + scriptS.seek(thread._instructionOffset); } if (breakOut) -- cgit v1.2.3