aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/saga/events.cpp19
-rw-r--r--engines/saga/script.cpp6
-rw-r--r--engines/saga/script.h54
-rw-r--r--engines/saga/sfuncs.cpp9
-rw-r--r--engines/saga/sthread.cpp115
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<ScriptThread*> ScriptThreadList;
+typedef Common::List<ScriptThread> 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)