diff options
Diffstat (limited to 'engines/sludge')
-rw-r--r-- | engines/sludge/builtin.cpp | 3 | ||||
-rw-r--r-- | engines/sludge/builtin.h | 2 | ||||
-rw-r--r-- | engines/sludge/csludge.h | 2 | ||||
-rw-r--r-- | engines/sludge/event.cpp | 1 | ||||
-rw-r--r-- | engines/sludge/function.cpp | 753 | ||||
-rw-r--r-- | engines/sludge/function.h | 71 | ||||
-rw-r--r-- | engines/sludge/loadsave.cpp | 1 | ||||
-rw-r--r-- | engines/sludge/main_loop.cpp | 1 | ||||
-rw-r--r-- | engines/sludge/module.mk | 1 | ||||
-rw-r--r-- | engines/sludge/people.cpp | 1 | ||||
-rw-r--r-- | engines/sludge/people.h | 2 | ||||
-rw-r--r-- | engines/sludge/sludger.cpp | 737 | ||||
-rw-r--r-- | engines/sludge/sludger.h | 41 |
13 files changed, 848 insertions, 768 deletions
diff --git a/engines/sludge/builtin.cpp b/engines/sludge/builtin.cpp index 8646dd46a3..0d1d940259 100644 --- a/engines/sludge/builtin.cpp +++ b/engines/sludge/builtin.cpp @@ -32,6 +32,7 @@ #include "sludge/floor.h" #include "sludge/fonttext.h" #include "sludge/freeze.h" +#include "sludge/function.h" #include "sludge/graphics.h" #include "sludge/language.h" #include "sludge/loadsave.h" @@ -86,7 +87,7 @@ bool failSecurityCheck(const Common::String &fn) { return false; } -LoadedFunction *saverFunc; +extern LoadedFunction *saverFunc; typedef BuiltReturn (*builtInSludgeFunc)(int numParams, LoadedFunction *fun); struct builtInFunctionData { diff --git a/engines/sludge/builtin.h b/engines/sludge/builtin.h index b2274c22e9..b7fa8b86ef 100644 --- a/engines/sludge/builtin.h +++ b/engines/sludge/builtin.h @@ -23,6 +23,8 @@ #ifndef SLUDGE_BUILTIN_H #define SLUDGE_BUILTIN_H +#include "sludge/allfiles.h" + namespace Sludge { struct LoadedFunction; diff --git a/engines/sludge/csludge.h b/engines/sludge/csludge.h index 435a220a2d..cf0d6aaf43 100644 --- a/engines/sludge/csludge.h +++ b/engines/sludge/csludge.h @@ -25,7 +25,7 @@ namespace Sludge { -enum sludgeCommand { +enum SludgeCommand { SLU_UNKNOWN, SLU_RETURN, SLU_BRANCH, diff --git a/engines/sludge/event.cpp b/engines/sludge/event.cpp index b553702710..d6afe2f5b9 100644 --- a/engines/sludge/event.cpp +++ b/engines/sludge/event.cpp @@ -25,6 +25,7 @@ #include "sludge/event.h" #include "sludge/freeze.h" +#include "sludge/function.h" #include "sludge/graphics.h" #include "sludge/newfatal.h" #include "sludge/region.h" diff --git a/engines/sludge/function.cpp b/engines/sludge/function.cpp new file mode 100644 index 0000000000..8aa69f07c4 --- /dev/null +++ b/engines/sludge/function.cpp @@ -0,0 +1,753 @@ +/* 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 "sludge/builtin.h" +#include "sludge/function.h" +#include "sludge/loadsave.h" +#include "sludge/newfatal.h" +#include "sludge/people.h" +#include "sludge/sludge.h" +#include "sludge/sound.h" +#include "sludge/speech.h" + +namespace Sludge { + +int numBIFNames = 0; +Common::String *allBIFNames = NULL; +int numUserFunc = 0; +Common::String *allUserFunc = NULL; + +LoadedFunction *saverFunc; +LoadedFunction *allRunningFunctions = NULL; +VariableStack *noStack = NULL; +Variable *globalVars = NULL; + +const char *sludgeText[] = { "?????", "RETURN", "BRANCH", "BR_ZERO", + "SET_GLOBAL", "SET_LOCAL", "LOAD_GLOBAL", "LOAD_LOCAL", "PLUS", "MINUS", + "MULT", "DIVIDE", "AND", "OR", "EQUALS", "NOT_EQ", "MODULUS", + "LOAD_VALUE", "LOAD_BUILT", "LOAD_FUNC", "CALLIT", "LOAD_STRING", + "LOAD_FILE", "LOAD_OBJTYPE", "NOT", "LOAD_NULL", "STACK_PUSH", + "LESSTHAN", "MORETHAN", "NEGATIVE", "U", "LESS_EQUAL", "MORE_EQUAL", + "INC_LOCAL", "DEC_LOCAL", "INC_GLOBAL", "DEC_GLOBAL", "INDEXSET", + "INDEXGET", "INC_INDEX", "DEC_INDEX", "QUICK_PUSH" }; + +void pauseFunction(LoadedFunction *fun) { + LoadedFunction **huntAndDestroy = &allRunningFunctions; + while (*huntAndDestroy) { + if (fun == *huntAndDestroy) { + (*huntAndDestroy) = (*huntAndDestroy)->next; + fun->next = NULL; + } else { + huntAndDestroy = &(*huntAndDestroy)->next; + } + } +} + +void restartFunction(LoadedFunction *fun) { + fun->next = allRunningFunctions; + allRunningFunctions = fun; +} + +void killSpeechTimers() { + LoadedFunction *thisFunction = allRunningFunctions; + + while (thisFunction) { + if (thisFunction->freezerLevel == 0 && thisFunction->isSpeech + && thisFunction->timeLeft) { + thisFunction->timeLeft = 0; + thisFunction->isSpeech = false; + } + thisFunction = thisFunction->next; + } + + g_sludge->_speechMan->kill(); +} + +void completeTimers() { + LoadedFunction *thisFunction = allRunningFunctions; + + while (thisFunction) { + if (thisFunction->freezerLevel == 0) + thisFunction->timeLeft = 0; + thisFunction = thisFunction->next; + } +} + +void finishFunction(LoadedFunction *fun) { + int a; + + pauseFunction(fun); + if (fun->stack) + fatal(ERROR_NON_EMPTY_STACK); + delete[] fun->compiledLines; + for (a = 0; a < fun->numLocals; a++) + unlinkVar(fun->localVars[a]); + delete[] fun->localVars; + unlinkVar(fun->reg); + delete fun; + fun = NULL; +} + +void abortFunction(LoadedFunction *fun) { + int a; + + pauseFunction(fun); + while (fun->stack) + trimStack(fun->stack); + delete []fun->compiledLines; + for (a = 0; a < fun->numLocals; a++) + unlinkVar(fun->localVars[a]); + delete []fun->localVars; + unlinkVar(fun->reg); + if (fun->calledBy) + abortFunction(fun->calledBy); + delete fun; + fun = NULL; +} + +int cancelAFunction(int funcNum, LoadedFunction *myself, bool &killedMyself) { + int n = 0; + killedMyself = false; + + LoadedFunction *fun = allRunningFunctions; + while (fun) { + if (fun->originalNumber == funcNum) { + fun->cancelMe = true; + n++; + if (fun == myself) + killedMyself = true; + } + fun = fun->next; + } + return n; +} + +void freezeSubs() { + LoadedFunction *thisFunction = allRunningFunctions; + + while (thisFunction) { + if (thisFunction->unfreezable) { + //msgBox ("SLUDGE debugging bollocks!", "Trying to freeze an unfreezable function!"); + } else { + thisFunction->freezerLevel++; + } + thisFunction = thisFunction->next; + } +} + +void unfreezeSubs() { + LoadedFunction *thisFunction = allRunningFunctions; + + while (thisFunction) { + if (thisFunction->freezerLevel) + thisFunction->freezerLevel--; + thisFunction = thisFunction->next; + } +} + +bool continueFunction(LoadedFunction *fun) { + bool keepLooping = true; + bool advanceNow; + uint param; + SludgeCommand com; + + if (fun->cancelMe) { + abortFunction(fun); + return true; + } + + while (keepLooping) { + advanceNow = true; + debugC(1, kSludgeDebugStackMachine, "Executing command line %i : ", fun->runThisLine); + param = fun->compiledLines[fun->runThisLine].param; + com = fun->compiledLines[fun->runThisLine].theCommand; + + if (numBIFNames) { + setFatalInfo((fun->originalNumber < numUserFunc) ? allUserFunc[fun->originalNumber] : "Unknown user function", (com < numSludgeCommands) ? sludgeText[com] : ERROR_UNKNOWN_MCODE); + } + + switch (com) { + case SLU_RETURN: + if (fun->calledBy) { + LoadedFunction *returnTo = fun->calledBy; + if (fun->returnSomething) + copyVariable(fun->reg, returnTo->reg); + finishFunction(fun); + fun = returnTo; + restartFunction(fun); + } else { + finishFunction(fun); + advanceNow = false; // So we don't do anything else with "fun" + keepLooping = false; // So we drop out of the loop + } + break; + + case SLU_CALLIT: + switch (fun->reg.varType) { + case SVT_FUNC: + pauseFunction(fun); + if (numBIFNames) + setFatalInfo( + (fun->originalNumber < numUserFunc) ? + allUserFunc[fun->originalNumber] : + "Unknown user function", + (fun->reg.varData.intValue < numUserFunc) ? + allUserFunc[fun->reg.varData.intValue] : + "Unknown user function"); + + if (!startNewFunctionNum(fun->reg.varData.intValue, param, fun, + fun->stack)) + return false; + fun = allRunningFunctions; + advanceNow = false; // So we don't do anything else with "fun" + break; + + case SVT_BUILT: { + debugC(1, kSludgeDebugStackMachine, "Built-in init value: %i", + fun->reg.varData.intValue); + BuiltReturn br = callBuiltIn(fun->reg.varData.intValue, param, + fun); + + switch (br) { + case BR_ERROR: + return fatal( + "Unknown error. This shouldn't happen. Please notify the SLUDGE developers."); + + case BR_PAUSE: + pauseFunction(fun); + // fall through + + case BR_KEEP_AND_PAUSE: + keepLooping = false; + break; + + case BR_ALREADY_GONE: + keepLooping = false; + advanceNow = false; + break; + + case BR_CALLAFUNC: { + int i = fun->reg.varData.intValue; + setVariable(fun->reg, SVT_INT, 1); + pauseFunction(fun); + if (numBIFNames) + setFatalInfo( + (fun->originalNumber < numUserFunc) ? + allUserFunc[fun->originalNumber] : + "Unknown user function", + (i < numUserFunc) ? + allUserFunc[i] : + "Unknown user function"); + if (!startNewFunctionNum(i, 0, fun, noStack, false)) + return false; + fun = allRunningFunctions; + advanceNow = false; // So we don't do anything else with "fun" + } + break; + + default: + break; + } + } + break; + + default: + return fatal(ERROR_CALL_NONFUNCTION); + } + break; + + // These all grab things and shove 'em into the register + + case SLU_LOAD_NULL: + setVariable(fun->reg, SVT_NULL, 0); + break; + + case SLU_LOAD_FILE: + setVariable(fun->reg, SVT_FILE, param); + break; + + case SLU_LOAD_VALUE: + setVariable(fun->reg, SVT_INT, param); + break; + + case SLU_LOAD_LOCAL: + if (!copyVariable(fun->localVars[param], fun->reg)) + return false; + break; + + case SLU_AND: + setVariable(fun->reg, SVT_INT, + getBoolean(fun->reg) && getBoolean(fun->stack->thisVar)); + trimStack(fun->stack); + break; + + case SLU_OR: + setVariable(fun->reg, SVT_INT, + getBoolean(fun->reg) || getBoolean(fun->stack->thisVar)); + trimStack(fun->stack); + break; + + case SLU_LOAD_FUNC: + setVariable(fun->reg, SVT_FUNC, param); + break; + + case SLU_LOAD_BUILT: + setVariable(fun->reg, SVT_BUILT, param); + break; + + case SLU_LOAD_OBJTYPE: + setVariable(fun->reg, SVT_OBJTYPE, param); + break; + + case SLU_UNREG: + break; + + case SLU_LOAD_STRING: + if (!loadStringToVar(fun->reg, param)) { + return false; + } + break; + + case SLU_INDEXGET: + case SLU_INCREMENT_INDEX: + case SLU_DECREMENT_INDEX: + switch (fun->stack->thisVar.varType) { + case SVT_NULL: + if (com == SLU_INDEXGET) { + setVariable(fun->reg, SVT_NULL, 0); + trimStack(fun->stack); + } else { + return fatal(ERROR_INCDEC_UNKNOWN); + } + break; + + case SVT_FASTARRAY: + case SVT_STACK: + if (fun->stack->thisVar.varData.theStack->first == NULL) { + return fatal(ERROR_INDEX_EMPTY); + } else { + int ii; + if (!getValueType(ii, SVT_INT, fun->reg)) + return false; + Variable *grab = + (fun->stack->thisVar.varType == SVT_FASTARRAY) ? + fastArrayGetByIndex( + fun->stack->thisVar.varData.fastArray, + ii) : + stackGetByIndex( + fun->stack->thisVar.varData.theStack->first, + ii); + + trimStack(fun->stack); + + if (!grab) { + setVariable(fun->reg, SVT_NULL, 0); + } else { + int kk; + switch (com) { + case SLU_INCREMENT_INDEX: + if (!getValueType(kk, SVT_INT, *grab)) + return false; + setVariable(fun->reg, SVT_INT, kk); + grab->varData.intValue = kk + 1; + break; + + case SLU_DECREMENT_INDEX: + if (!getValueType(kk, SVT_INT, *grab)) + return false; + setVariable(fun->reg, SVT_INT, kk); + grab->varData.intValue = kk - 1; + break; + + default: + if (!copyVariable(*grab, fun->reg)) + return false; + } + } + } + break; + + default: + return fatal(ERROR_INDEX_NONSTACK); + } + break; + + case SLU_INDEXSET: + switch (fun->stack->thisVar.varType) { + case SVT_STACK: + if (fun->stack->thisVar.varData.theStack->first == NULL) { + return fatal(ERROR_INDEX_EMPTY); + } else { + int ii; + if (!getValueType(ii, SVT_INT, fun->reg)) + return false; + if (!stackSetByIndex( + fun->stack->thisVar.varData.theStack->first, ii, + fun->stack->next->thisVar)) { + return false; + } + trimStack(fun->stack); + trimStack(fun->stack); + } + break; + + case SVT_FASTARRAY: { + int ii; + if (!getValueType(ii, SVT_INT, fun->reg)) + return false; + Variable *v = fastArrayGetByIndex( + fun->stack->thisVar.varData.fastArray, ii); + if (v == NULL) + return fatal("Not within bounds of fast array."); + if (!copyVariable(fun->stack->next->thisVar, *v)) + return false; + trimStack(fun->stack); + trimStack(fun->stack); + } + break; + + default: + return fatal(ERROR_INDEX_NONSTACK); + } + break; + + // What can we do with the register? Well, we can copy it into a local + // variable, a global or onto the stack... + + case SLU_INCREMENT_LOCAL: { + int ii; + if (!getValueType(ii, SVT_INT, fun->localVars[param])) + return false; + setVariable(fun->reg, SVT_INT, ii); + setVariable(fun->localVars[param], SVT_INT, ii + 1); + } + break; + + case SLU_INCREMENT_GLOBAL: { + int ii; + if (!getValueType(ii, SVT_INT, globalVars[param])) + return false; + setVariable(fun->reg, SVT_INT, ii); + setVariable(globalVars[param], SVT_INT, ii + 1); + } + break; + + case SLU_DECREMENT_LOCAL: { + int ii; + if (!getValueType(ii, SVT_INT, fun->localVars[param])) + return false; + setVariable(fun->reg, SVT_INT, ii); + setVariable(fun->localVars[param], SVT_INT, ii - 1); + } + break; + + case SLU_DECREMENT_GLOBAL: { + int ii; + if (!getValueType(ii, SVT_INT, globalVars[param])) + return false; + setVariable(fun->reg, SVT_INT, ii); + setVariable(globalVars[param], SVT_INT, ii - 1); + } + break; + + case SLU_SET_LOCAL: + if (!copyVariable(fun->reg, fun->localVars[param])) + return false; + break; + + case SLU_SET_GLOBAL: +// newDebug (" Copying TO global variable", param); +// newDebug (" Global type at the moment", globalVars[param].varType); + if (!copyVariable(fun->reg, globalVars[param])) + return false; +// newDebug (" New type", globalVars[param].varType); + break; + + case SLU_LOAD_GLOBAL: +// newDebug (" Copying FROM global variable", param); +// newDebug (" Global type at the moment", globalVars[param].varType); + if (!copyVariable(globalVars[param], fun->reg)) + return false; + break; + + case SLU_STACK_PUSH: + if (!addVarToStack(fun->reg, fun->stack)) + return false; + break; + + case SLU_QUICK_PUSH: + if (!addVarToStackQuick(fun->reg, fun->stack)) + return false; + break; + + case SLU_NOT: + setVariable(fun->reg, SVT_INT, !getBoolean(fun->reg)); + break; + + case SLU_BR_ZERO: + if (!getBoolean(fun->reg)) { + advanceNow = false; + fun->runThisLine = param; + } + break; + + case SLU_BRANCH: + advanceNow = false; + fun->runThisLine = param; + break; + + case SLU_NEGATIVE: { + int i; + if (!getValueType(i, SVT_INT, fun->reg)) + return false; + setVariable(fun->reg, SVT_INT, -i); + } + break; + + // All these things rely on there being somet' on the stack + + case SLU_MULT: + case SLU_PLUS: + case SLU_MINUS: + case SLU_MODULUS: + case SLU_DIVIDE: + case SLU_EQUALS: + case SLU_NOT_EQ: + case SLU_LESSTHAN: + case SLU_MORETHAN: + case SLU_LESS_EQUAL: + case SLU_MORE_EQUAL: + if (fun->stack) { + int firstValue, secondValue; + + switch (com) { + case SLU_PLUS: + addVariablesInSecond(fun->stack->thisVar, fun->reg); + trimStack(fun->stack); + break; + + case SLU_EQUALS: + compareVariablesInSecond(fun->stack->thisVar, fun->reg); + trimStack(fun->stack); + break; + + case SLU_NOT_EQ: + compareVariablesInSecond(fun->stack->thisVar, fun->reg); + trimStack(fun->stack); + fun->reg.varData.intValue = !fun->reg.varData.intValue; + break; + + default: + if (!getValueType(firstValue, SVT_INT, fun->stack->thisVar)) + return false; + if (!getValueType(secondValue, SVT_INT, fun->reg)) + return false; + trimStack(fun->stack); + + switch (com) { + case SLU_MULT: + setVariable(fun->reg, SVT_INT, + firstValue * secondValue); + break; + + case SLU_MINUS: + setVariable(fun->reg, SVT_INT, + firstValue - secondValue); + break; + + case SLU_MODULUS: + setVariable(fun->reg, SVT_INT, + firstValue % secondValue); + break; + + case SLU_DIVIDE: + setVariable(fun->reg, SVT_INT, + firstValue / secondValue); + break; + + case SLU_LESSTHAN: + setVariable(fun->reg, SVT_INT, + firstValue < secondValue); + break; + + case SLU_MORETHAN: + setVariable(fun->reg, SVT_INT, + firstValue > secondValue); + break; + + case SLU_LESS_EQUAL: + setVariable(fun->reg, SVT_INT, + firstValue <= secondValue); + break; + + case SLU_MORE_EQUAL: + setVariable(fun->reg, SVT_INT, + firstValue >= secondValue); + break; + + default: + break; + } + } + } else { + return fatal(ERROR_NOSTACK); + } + break; + + default: + return fatal(ERROR_UNKNOWN_CODE); + } + + if (advanceNow) + fun->runThisLine++; + + } + return true; +} + +void killAllFunctions() { + while (allRunningFunctions) + finishFunction(allRunningFunctions); +} + +bool loadFunctionCode(LoadedFunction *newFunc) { + uint numLines, numLinesRead; + + if (!g_sludge->_resMan->openSubSlice(newFunc->originalNumber)) + return false; + + debugC(3, kSludgeDebugDataLoad, "Load function code"); + + Common::SeekableReadStream *readStream = g_sludge->_resMan->getData(); + newFunc->unfreezable = readStream->readByte(); + numLines = readStream->readUint16BE(); + debugC(3, kSludgeDebugDataLoad, "numLines: %i", numLines); + newFunc->numArgs = readStream->readUint16BE(); + debugC(3, kSludgeDebugDataLoad, "numArgs: %i", newFunc->numArgs); + newFunc->numLocals = readStream->readUint16BE(); + debugC(3, kSludgeDebugDataLoad, "numLocals: %i", newFunc->numLocals); + newFunc->compiledLines = new LineOfCode[numLines]; + if (!checkNew(newFunc->compiledLines)) + return false; + + for (numLinesRead = 0; numLinesRead < numLines; numLinesRead++) { + newFunc->compiledLines[numLinesRead].theCommand = (SludgeCommand)readStream->readByte(); + newFunc->compiledLines[numLinesRead].param = readStream->readUint16BE(); + debugC(3, kSludgeDebugDataLoad, "command line %i: %i", numLinesRead, + newFunc->compiledLines[numLinesRead].theCommand); + } + g_sludge->_resMan->finishAccess(); + + // Now we need to reserve memory for the local variables + newFunc->localVars = new Variable[newFunc->numLocals]; + if (!checkNew(newFunc->localVars)) + return false; + for (int a = 0; a < newFunc->numLocals; a++) { + initVarNew(newFunc->localVars[a]); + } + + return true; +} + +int startNewFunctionNum(uint funcNum, uint numParamsExpected, + LoadedFunction *calledBy, VariableStack *&vStack, bool returnSommet) { + LoadedFunction *newFunc = new LoadedFunction; + checkNew(newFunc); + newFunc->originalNumber = funcNum; + + loadFunctionCode(newFunc); + + if (newFunc->numArgs != (int) numParamsExpected) + return fatal("Wrong number of parameters!"); + if (newFunc->numArgs > newFunc->numLocals) + return fatal("More arguments than local Variable space!"); + + // Now, lets copy the parameters from the calling function's stack... + + while (numParamsExpected) { + numParamsExpected--; + if (vStack == NULL) + return fatal( + "Corrupted file!The stack's empty and there were still parameters expected"); + copyVariable(vStack->thisVar, newFunc->localVars[numParamsExpected]); + trimStack(vStack); + } + + newFunc->cancelMe = false; + newFunc->timeLeft = 0; + newFunc->returnSomething = returnSommet; + newFunc->calledBy = calledBy; + newFunc->stack = NULL; + newFunc->freezerLevel = 0; + newFunc->runThisLine = 0; + newFunc->isSpeech = 0; + initVarNew(newFunc->reg); + + restartFunction(newFunc); + return 1; +} + +bool runSludge() { + + LoadedFunction *thisFunction = allRunningFunctions; + LoadedFunction *nextFunction; + + while (thisFunction) { + nextFunction = thisFunction->next; + + if (!thisFunction->freezerLevel) { + if (thisFunction->timeLeft) { + if (thisFunction->timeLeft < 0) { + if (!g_sludge->_soundMan->stillPlayingSound( + g_sludge->_speechMan->getLastSpeechSound())) { + thisFunction->timeLeft = 0; + } + } else if (!--(thisFunction->timeLeft)) { + } + } else { + if (thisFunction->isSpeech) { + thisFunction->isSpeech = false; + g_sludge->_speechMan->kill(); + } + if (!continueFunction(thisFunction)) + return false; + } + } + + thisFunction = nextFunction; + } + + if (!g_sludge->loadNow.empty()) { + if (g_sludge->loadNow[0] == ':') { + saveGame(g_sludge->loadNow.c_str() + 1); + setVariable(saverFunc->reg, SVT_INT, 1); + } else { + if (!loadGame(g_sludge->loadNow)) + return false; + } + g_sludge->loadNow.clear(); + } + + return true; +} + +} // End of namespace Sludge diff --git a/engines/sludge/function.h b/engines/sludge/function.h new file mode 100644 index 0000000000..ead2adfa0a --- /dev/null +++ b/engines/sludge/function.h @@ -0,0 +1,71 @@ +/* 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 SLUDGE_FUNCTION_H +#define SLUDGE_FUNCTION_H + +#include "sludge/allfiles.h" +#include "sludge/csludge.h" +#include "sludge/variable.h" + +namespace Sludge { + +struct Variable; +struct VariableStack; + +struct LineOfCode { + SludgeCommand theCommand; + int32 param; +}; + +struct LoadedFunction { + int originalNumber; + LineOfCode *compiledLines; + int numLocals, timeLeft, numArgs; + Variable *localVars; + VariableStack *stack; + Variable reg; + uint runThisLine; + LoadedFunction *calledBy; + LoadedFunction *next; + bool returnSomething, isSpeech, unfreezable, cancelMe; + byte freezerLevel; +}; + +bool runSludge(); + +int startNewFunctionNum(uint, uint, LoadedFunction *, VariableStack*&, bool = true); +void restartFunction(LoadedFunction *fun); +bool loadFunctionCode(LoadedFunction *newFunc); +void killAllFunctions(); + +void finishFunction(LoadedFunction *fun); +void abortFunction(LoadedFunction *fun); + +void freezeSubs(); +void unfreezeSubs(); +void completeTimers(); +void killSpeechTimers(); +int cancelAFunction(int funcNum, LoadedFunction *myself, bool &killedMyself); + +} // End of namespace Sludge + +#endif diff --git a/engines/sludge/loadsave.cpp b/engines/sludge/loadsave.cpp index 8706f7f0a4..2d29645acd 100644 --- a/engines/sludge/loadsave.cpp +++ b/engines/sludge/loadsave.cpp @@ -29,6 +29,7 @@ #include "sludge/event.h" #include "sludge/floor.h" #include "sludge/fonttext.h" +#include "sludge/function.h" #include "sludge/graphics.h" #include "sludge/language.h" #include "sludge/loadsave.h" diff --git a/engines/sludge/main_loop.cpp b/engines/sludge/main_loop.cpp index 10f54d4e71..ee0bae1d1d 100644 --- a/engines/sludge/main_loop.cpp +++ b/engines/sludge/main_loop.cpp @@ -28,6 +28,7 @@ #include "sludge/backdrop.h" #include "sludge/event.h" #include "sludge/floor.h" +#include "sludge/function.h" #include "sludge/graphics.h" #include "sludge/language.h" #include "sludge/newfatal.h" diff --git a/engines/sludge/module.mk b/engines/sludge/module.mk index a083ec4a95..d904e6c4c3 100644 --- a/engines/sludge/module.mk +++ b/engines/sludge/module.mk @@ -12,6 +12,7 @@ MODULE_OBJS := \ floor.o \ freeze.o \ fonttext.o \ + function.o \ graphics.o \ hsi.o \ imgloader.o \ diff --git a/engines/sludge/people.cpp b/engines/sludge/people.cpp index 36249501bd..658954af69 100644 --- a/engines/sludge/people.cpp +++ b/engines/sludge/people.cpp @@ -22,6 +22,7 @@ #include "sludge/allfiles.h" #include "sludge/floor.h" +#include "sludge/function.h" #include "sludge/graphics.h" #include "sludge/loadsave.h" #include "sludge/moreio.h" diff --git a/engines/sludge/people.h b/engines/sludge/people.h index 2d19a14d73..db22d19ad1 100644 --- a/engines/sludge/people.h +++ b/engines/sludge/people.h @@ -30,6 +30,8 @@ struct FrozenStuffStruct; struct LoadedSpriteBank; struct ScreenRegion; +class SludgeEngine; + struct AnimFrame { int frameNum, howMany; int noise; diff --git a/engines/sludge/sludger.cpp b/engines/sludge/sludger.cpp index 8bbf76e6ef..cab0342c6d 100644 --- a/engines/sludge/sludger.cpp +++ b/engines/sludge/sludger.cpp @@ -32,9 +32,9 @@ #include "sludge/freeze.h" #include "sludge/floor.h" #include "sludge/fileset.h" +#include "sludge/function.h" #include "sludge/graphics.h" #include "sludge/imgloader.h" -#include "sludge/loadsave.h" #include "sludge/language.h" #include "sludge/moreio.h" #include "sludge/newfatal.h" @@ -42,23 +42,24 @@ #include "sludge/people.h" #include "sludge/region.h" #include "sludge/savedata.h" -#include "sludge/statusba.h" -#include "sludge/sprites.h" -#include "sludge/sprbanks.h" -#include "sludge/sound.h" #include "sludge/sludge.h" #include "sludge/sludger.h" +#include "sludge/sound.h" #include "sludge/speech.h" +#include "sludge/sprites.h" +#include "sludge/sprbanks.h" +#include "sludge/statusba.h" #include "sludge/variable.h" #include "sludge/version.h" #include "sludge/zbuffer.h" namespace Sludge { -int numBIFNames = 0; -Common::String *allBIFNames; -int numUserFunc = 0; -Common::String *allUserFunc = NULL; +extern int numBIFNames; +extern Common::String *allBIFNames; +extern int numUserFunc; +extern Common::String *allUserFunc; + int numResourceNames = 0; Common::String *allResourceNames = NULL; int selectedLanguage = 0; @@ -66,28 +67,14 @@ int selectedLanguage = 0; int gameVersion; FILETIME fileTime; -extern LoadedFunction *saverFunc; - -LoadedFunction *allRunningFunctions = NULL; -VariableStack *noStack = NULL; -Variable *globalVars; - int numGlobals = 0; extern Variable *launchResult; -extern int lastFramesPerSecond; +extern Variable *globalVars; +extern VariableStack *noStack; extern bool allowAnyFilename; -const char *sludgeText[] = { "?????", "RETURN", "BRANCH", "BR_ZERO", - "SET_GLOBAL", "SET_LOCAL", "LOAD_GLOBAL", "LOAD_LOCAL", "PLUS", "MINUS", - "MULT", "DIVIDE", "AND", "OR", "EQUALS", "NOT_EQ", "MODULUS", - "LOAD_VALUE", "LOAD_BUILT", "LOAD_FUNC", "CALLIT", "LOAD_STRING", - "LOAD_FILE", "LOAD_OBJTYPE", "NOT", "LOAD_NULL", "STACK_PUSH", - "LESSTHAN", "MORETHAN", "NEGATIVE", "U", "LESS_EQUAL", "MORE_EQUAL", - "INC_LOCAL", "DEC_LOCAL", "INC_GLOBAL", "DEC_GLOBAL", "INDEXSET", - "INDEXGET", "INC_INDEX", "DEC_INDEX", "QUICK_PUSH" }; - Common::File *openAndVerify(const Common::String &filename, char extra1, char extra2, const char *er, int &fileVersion) { Common::File *fp = new Common::File(); @@ -333,704 +320,4 @@ void sludgeDisplay() { g_sludge->_gfxMan->display(); } -void pauseFunction(LoadedFunction *fun) { - LoadedFunction **huntAndDestroy = &allRunningFunctions; - while (*huntAndDestroy) { - if (fun == *huntAndDestroy) { - (*huntAndDestroy) = (*huntAndDestroy)->next; - fun->next = NULL; - } else { - huntAndDestroy = &(*huntAndDestroy)->next; - } - } -} - -void restartFunction(LoadedFunction *fun) { - fun->next = allRunningFunctions; - allRunningFunctions = fun; -} - -void killSpeechTimers() { - LoadedFunction *thisFunction = allRunningFunctions; - - while (thisFunction) { - if (thisFunction->freezerLevel == 0 && thisFunction->isSpeech - && thisFunction->timeLeft) { - thisFunction->timeLeft = 0; - thisFunction->isSpeech = false; - } - thisFunction = thisFunction->next; - } - - g_sludge->_speechMan->kill(); -} - -void completeTimers() { - LoadedFunction *thisFunction = allRunningFunctions; - - while (thisFunction) { - if (thisFunction->freezerLevel == 0) - thisFunction->timeLeft = 0; - thisFunction = thisFunction->next; - } -} - -void finishFunction(LoadedFunction *fun) { - int a; - - pauseFunction(fun); - if (fun->stack) - fatal(ERROR_NON_EMPTY_STACK); - delete[] fun->compiledLines; - for (a = 0; a < fun->numLocals; a++) - unlinkVar(fun->localVars[a]); - delete[] fun->localVars; - unlinkVar(fun->reg); - delete fun; - fun = NULL; -} - -void abortFunction(LoadedFunction *fun) { - int a; - - pauseFunction(fun); - while (fun->stack) - trimStack(fun->stack); - delete []fun->compiledLines; - for (a = 0; a < fun->numLocals; a++) - unlinkVar(fun->localVars[a]); - delete []fun->localVars; - unlinkVar(fun->reg); - if (fun->calledBy) - abortFunction(fun->calledBy); - delete fun; - fun = NULL; -} - -int cancelAFunction(int funcNum, LoadedFunction *myself, bool &killedMyself) { - int n = 0; - killedMyself = false; - - LoadedFunction *fun = allRunningFunctions; - while (fun) { - if (fun->originalNumber == funcNum) { - fun->cancelMe = true; - n++; - if (fun == myself) - killedMyself = true; - } - fun = fun->next; - } - return n; -} - -void freezeSubs() { - LoadedFunction *thisFunction = allRunningFunctions; - - while (thisFunction) { - if (thisFunction->unfreezable) { - //msgBox ("SLUDGE debugging bollocks!", "Trying to freeze an unfreezable function!"); - } else { - thisFunction->freezerLevel++; - } - thisFunction = thisFunction->next; - } -} - -void unfreezeSubs() { - LoadedFunction *thisFunction = allRunningFunctions; - - while (thisFunction) { - if (thisFunction->freezerLevel) - thisFunction->freezerLevel--; - thisFunction = thisFunction->next; - } -} - -bool continueFunction(LoadedFunction *fun) { - bool keepLooping = true; - bool advanceNow; - uint param; - sludgeCommand com; - - if (fun->cancelMe) { - abortFunction(fun); - return true; - } - - while (keepLooping) { - advanceNow = true; - debugC(1, kSludgeDebugStackMachine, "Executing command line %i : ", fun->runThisLine); - param = fun->compiledLines[fun->runThisLine].param; - com = fun->compiledLines[fun->runThisLine].theCommand; - - if (numBIFNames) { - setFatalInfo((fun->originalNumber < numUserFunc) ? allUserFunc[fun->originalNumber] : "Unknown user function", (com < numSludgeCommands) ? sludgeText[com] : ERROR_UNKNOWN_MCODE); - } - - switch (com) { - case SLU_RETURN: - if (fun->calledBy) { - LoadedFunction *returnTo = fun->calledBy; - if (fun->returnSomething) - copyVariable(fun->reg, returnTo->reg); - finishFunction(fun); - fun = returnTo; - restartFunction(fun); - } else { - finishFunction(fun); - advanceNow = false; // So we don't do anything else with "fun" - keepLooping = false; // So we drop out of the loop - } - break; - - case SLU_CALLIT: - switch (fun->reg.varType) { - case SVT_FUNC: - pauseFunction(fun); - if (numBIFNames) - setFatalInfo( - (fun->originalNumber < numUserFunc) ? - allUserFunc[fun->originalNumber] : - "Unknown user function", - (fun->reg.varData.intValue < numUserFunc) ? - allUserFunc[fun->reg.varData.intValue] : - "Unknown user function"); - - if (!startNewFunctionNum(fun->reg.varData.intValue, param, fun, - fun->stack)) - return false; - fun = allRunningFunctions; - advanceNow = false; // So we don't do anything else with "fun" - break; - - case SVT_BUILT: { - debugC(1, kSludgeDebugStackMachine, "Built-in init value: %i", - fun->reg.varData.intValue); - BuiltReturn br = callBuiltIn(fun->reg.varData.intValue, param, - fun); - - switch (br) { - case BR_ERROR: - return fatal( - "Unknown error. This shouldn't happen. Please notify the SLUDGE developers."); - - case BR_PAUSE: - pauseFunction(fun); - // fall through - - case BR_KEEP_AND_PAUSE: - keepLooping = false; - break; - - case BR_ALREADY_GONE: - keepLooping = false; - advanceNow = false; - break; - - case BR_CALLAFUNC: { - int i = fun->reg.varData.intValue; - setVariable(fun->reg, SVT_INT, 1); - pauseFunction(fun); - if (numBIFNames) - setFatalInfo( - (fun->originalNumber < numUserFunc) ? - allUserFunc[fun->originalNumber] : - "Unknown user function", - (i < numUserFunc) ? - allUserFunc[i] : - "Unknown user function"); - if (!startNewFunctionNum(i, 0, fun, noStack, false)) - return false; - fun = allRunningFunctions; - advanceNow = false; // So we don't do anything else with "fun" - } - break; - - default: - break; - } - } - break; - - default: - return fatal(ERROR_CALL_NONFUNCTION); - } - break; - - // These all grab things and shove 'em into the register - - case SLU_LOAD_NULL: - setVariable(fun->reg, SVT_NULL, 0); - break; - - case SLU_LOAD_FILE: - setVariable(fun->reg, SVT_FILE, param); - break; - - case SLU_LOAD_VALUE: - setVariable(fun->reg, SVT_INT, param); - break; - - case SLU_LOAD_LOCAL: - if (!copyVariable(fun->localVars[param], fun->reg)) - return false; - break; - - case SLU_AND: - setVariable(fun->reg, SVT_INT, - getBoolean(fun->reg) && getBoolean(fun->stack->thisVar)); - trimStack(fun->stack); - break; - - case SLU_OR: - setVariable(fun->reg, SVT_INT, - getBoolean(fun->reg) || getBoolean(fun->stack->thisVar)); - trimStack(fun->stack); - break; - - case SLU_LOAD_FUNC: - setVariable(fun->reg, SVT_FUNC, param); - break; - - case SLU_LOAD_BUILT: - setVariable(fun->reg, SVT_BUILT, param); - break; - - case SLU_LOAD_OBJTYPE: - setVariable(fun->reg, SVT_OBJTYPE, param); - break; - - case SLU_UNREG: - break; - - case SLU_LOAD_STRING: - if (!loadStringToVar(fun->reg, param)) { - return false; - } - break; - - case SLU_INDEXGET: - case SLU_INCREMENT_INDEX: - case SLU_DECREMENT_INDEX: - switch (fun->stack->thisVar.varType) { - case SVT_NULL: - if (com == SLU_INDEXGET) { - setVariable(fun->reg, SVT_NULL, 0); - trimStack(fun->stack); - } else { - return fatal(ERROR_INCDEC_UNKNOWN); - } - break; - - case SVT_FASTARRAY: - case SVT_STACK: - if (fun->stack->thisVar.varData.theStack->first == NULL) { - return fatal(ERROR_INDEX_EMPTY); - } else { - int ii; - if (!getValueType(ii, SVT_INT, fun->reg)) - return false; - Variable *grab = - (fun->stack->thisVar.varType == SVT_FASTARRAY) ? - fastArrayGetByIndex( - fun->stack->thisVar.varData.fastArray, - ii) : - stackGetByIndex( - fun->stack->thisVar.varData.theStack->first, - ii); - - trimStack(fun->stack); - - if (!grab) { - setVariable(fun->reg, SVT_NULL, 0); - } else { - int kk; - switch (com) { - case SLU_INCREMENT_INDEX: - if (!getValueType(kk, SVT_INT, *grab)) - return false; - setVariable(fun->reg, SVT_INT, kk); - grab->varData.intValue = kk + 1; - break; - - case SLU_DECREMENT_INDEX: - if (!getValueType(kk, SVT_INT, *grab)) - return false; - setVariable(fun->reg, SVT_INT, kk); - grab->varData.intValue = kk - 1; - break; - - default: - if (!copyVariable(*grab, fun->reg)) - return false; - } - } - } - break; - - default: - return fatal(ERROR_INDEX_NONSTACK); - } - break; - - case SLU_INDEXSET: - switch (fun->stack->thisVar.varType) { - case SVT_STACK: - if (fun->stack->thisVar.varData.theStack->first == NULL) { - return fatal(ERROR_INDEX_EMPTY); - } else { - int ii; - if (!getValueType(ii, SVT_INT, fun->reg)) - return false; - if (!stackSetByIndex( - fun->stack->thisVar.varData.theStack->first, ii, - fun->stack->next->thisVar)) { - return false; - } - trimStack(fun->stack); - trimStack(fun->stack); - } - break; - - case SVT_FASTARRAY: { - int ii; - if (!getValueType(ii, SVT_INT, fun->reg)) - return false; - Variable *v = fastArrayGetByIndex( - fun->stack->thisVar.varData.fastArray, ii); - if (v == NULL) - return fatal("Not within bounds of fast array."); - if (!copyVariable(fun->stack->next->thisVar, *v)) - return false; - trimStack(fun->stack); - trimStack(fun->stack); - } - break; - - default: - return fatal(ERROR_INDEX_NONSTACK); - } - break; - - // What can we do with the register? Well, we can copy it into a local - // variable, a global or onto the stack... - - case SLU_INCREMENT_LOCAL: { - int ii; - if (!getValueType(ii, SVT_INT, fun->localVars[param])) - return false; - setVariable(fun->reg, SVT_INT, ii); - setVariable(fun->localVars[param], SVT_INT, ii + 1); - } - break; - - case SLU_INCREMENT_GLOBAL: { - int ii; - if (!getValueType(ii, SVT_INT, globalVars[param])) - return false; - setVariable(fun->reg, SVT_INT, ii); - setVariable(globalVars[param], SVT_INT, ii + 1); - } - break; - - case SLU_DECREMENT_LOCAL: { - int ii; - if (!getValueType(ii, SVT_INT, fun->localVars[param])) - return false; - setVariable(fun->reg, SVT_INT, ii); - setVariable(fun->localVars[param], SVT_INT, ii - 1); - } - break; - - case SLU_DECREMENT_GLOBAL: { - int ii; - if (!getValueType(ii, SVT_INT, globalVars[param])) - return false; - setVariable(fun->reg, SVT_INT, ii); - setVariable(globalVars[param], SVT_INT, ii - 1); - } - break; - - case SLU_SET_LOCAL: - if (!copyVariable(fun->reg, fun->localVars[param])) - return false; - break; - - case SLU_SET_GLOBAL: -// newDebug (" Copying TO global variable", param); -// newDebug (" Global type at the moment", globalVars[param].varType); - if (!copyVariable(fun->reg, globalVars[param])) - return false; -// newDebug (" New type", globalVars[param].varType); - break; - - case SLU_LOAD_GLOBAL: -// newDebug (" Copying FROM global variable", param); -// newDebug (" Global type at the moment", globalVars[param].varType); - if (!copyVariable(globalVars[param], fun->reg)) - return false; - break; - - case SLU_STACK_PUSH: - if (!addVarToStack(fun->reg, fun->stack)) - return false; - break; - - case SLU_QUICK_PUSH: - if (!addVarToStackQuick(fun->reg, fun->stack)) - return false; - break; - - case SLU_NOT: - setVariable(fun->reg, SVT_INT, !getBoolean(fun->reg)); - break; - - case SLU_BR_ZERO: - if (!getBoolean(fun->reg)) { - advanceNow = false; - fun->runThisLine = param; - } - break; - - case SLU_BRANCH: - advanceNow = false; - fun->runThisLine = param; - break; - - case SLU_NEGATIVE: { - int i; - if (!getValueType(i, SVT_INT, fun->reg)) - return false; - setVariable(fun->reg, SVT_INT, -i); - } - break; - - // All these things rely on there being somet' on the stack - - case SLU_MULT: - case SLU_PLUS: - case SLU_MINUS: - case SLU_MODULUS: - case SLU_DIVIDE: - case SLU_EQUALS: - case SLU_NOT_EQ: - case SLU_LESSTHAN: - case SLU_MORETHAN: - case SLU_LESS_EQUAL: - case SLU_MORE_EQUAL: - if (fun->stack) { - int firstValue, secondValue; - - switch (com) { - case SLU_PLUS: - addVariablesInSecond(fun->stack->thisVar, fun->reg); - trimStack(fun->stack); - break; - - case SLU_EQUALS: - compareVariablesInSecond(fun->stack->thisVar, fun->reg); - trimStack(fun->stack); - break; - - case SLU_NOT_EQ: - compareVariablesInSecond(fun->stack->thisVar, fun->reg); - trimStack(fun->stack); - fun->reg.varData.intValue = !fun->reg.varData.intValue; - break; - - default: - if (!getValueType(firstValue, SVT_INT, fun->stack->thisVar)) - return false; - if (!getValueType(secondValue, SVT_INT, fun->reg)) - return false; - trimStack(fun->stack); - - switch (com) { - case SLU_MULT: - setVariable(fun->reg, SVT_INT, - firstValue * secondValue); - break; - - case SLU_MINUS: - setVariable(fun->reg, SVT_INT, - firstValue - secondValue); - break; - - case SLU_MODULUS: - setVariable(fun->reg, SVT_INT, - firstValue % secondValue); - break; - - case SLU_DIVIDE: - setVariable(fun->reg, SVT_INT, - firstValue / secondValue); - break; - - case SLU_LESSTHAN: - setVariable(fun->reg, SVT_INT, - firstValue < secondValue); - break; - - case SLU_MORETHAN: - setVariable(fun->reg, SVT_INT, - firstValue > secondValue); - break; - - case SLU_LESS_EQUAL: - setVariable(fun->reg, SVT_INT, - firstValue <= secondValue); - break; - - case SLU_MORE_EQUAL: - setVariable(fun->reg, SVT_INT, - firstValue >= secondValue); - break; - - default: - break; - } - } - } else { - return fatal(ERROR_NOSTACK); - } - break; - - default: - return fatal(ERROR_UNKNOWN_CODE); - } - - if (advanceNow) - fun->runThisLine++; - - } - return true; -} - -bool runSludge() { - - LoadedFunction *thisFunction = allRunningFunctions; - LoadedFunction *nextFunction; - - while (thisFunction) { - nextFunction = thisFunction->next; - - if (!thisFunction->freezerLevel) { - if (thisFunction->timeLeft) { - if (thisFunction->timeLeft < 0) { - if (!g_sludge->_soundMan->stillPlayingSound( - g_sludge->_speechMan->getLastSpeechSound())) { - thisFunction->timeLeft = 0; - } - } else if (!--(thisFunction->timeLeft)) { - } - } else { - if (thisFunction->isSpeech) { - thisFunction->isSpeech = false; - g_sludge->_speechMan->kill(); - } - if (!continueFunction(thisFunction)) - return false; - } - } - - thisFunction = nextFunction; - } - - if (!g_sludge->loadNow.empty()) { - if (g_sludge->loadNow[0] == ':') { - saveGame(g_sludge->loadNow.c_str() + 1); - setVariable(saverFunc->reg, SVT_INT, 1); - } else { - if (!loadGame(g_sludge->loadNow)) - return false; - } - g_sludge->loadNow.clear(); - } - - return true; -} - -void killAllFunctions() { - while (allRunningFunctions) - finishFunction(allRunningFunctions); -} - -bool loadFunctionCode(LoadedFunction *newFunc) { - uint numLines, numLinesRead; - - if (!g_sludge->_resMan->openSubSlice(newFunc->originalNumber)) - return false; - - debugC(3, kSludgeDebugDataLoad, "Load function code"); - - Common::SeekableReadStream *readStream = g_sludge->_resMan->getData(); - newFunc->unfreezable = readStream->readByte(); - numLines = readStream->readUint16BE(); - debugC(3, kSludgeDebugDataLoad, "numLines: %i", numLines); - newFunc->numArgs = readStream->readUint16BE(); - debugC(3, kSludgeDebugDataLoad, "numArgs: %i", newFunc->numArgs); - newFunc->numLocals = readStream->readUint16BE(); - debugC(3, kSludgeDebugDataLoad, "numLocals: %i", newFunc->numLocals); - newFunc->compiledLines = new LineOfCode[numLines]; - if (!checkNew(newFunc->compiledLines)) - return false; - - for (numLinesRead = 0; numLinesRead < numLines; numLinesRead++) { - newFunc->compiledLines[numLinesRead].theCommand = (sludgeCommand)readStream->readByte(); - newFunc->compiledLines[numLinesRead].param = readStream->readUint16BE(); - debugC(3, kSludgeDebugDataLoad, "command line %i: %i", numLinesRead, - newFunc->compiledLines[numLinesRead].theCommand); - } - g_sludge->_resMan->finishAccess(); - - // Now we need to reserve memory for the local variables - newFunc->localVars = new Variable[newFunc->numLocals]; - if (!checkNew(newFunc->localVars)) - return false; - for (int a = 0; a < newFunc->numLocals; a++) { - initVarNew(newFunc->localVars[a]); - } - - return true; -} - -int startNewFunctionNum(uint funcNum, uint numParamsExpected, - LoadedFunction *calledBy, VariableStack *&vStack, bool returnSommet) { - LoadedFunction *newFunc = new LoadedFunction; - checkNew(newFunc); - newFunc->originalNumber = funcNum; - - loadFunctionCode(newFunc); - - if (newFunc->numArgs != (int) numParamsExpected) - return fatal("Wrong number of parameters!"); - if (newFunc->numArgs > newFunc->numLocals) - return fatal("More arguments than local Variable space!"); - - // Now, lets copy the parameters from the calling function's stack... - - while (numParamsExpected) { - numParamsExpected--; - if (vStack == NULL) - return fatal( - "Corrupted file!The stack's empty and there were still parameters expected"); - copyVariable(vStack->thisVar, newFunc->localVars[numParamsExpected]); - trimStack(vStack); - } - - newFunc->cancelMe = false; - newFunc->timeLeft = 0; - newFunc->returnSomething = returnSommet; - newFunc->calledBy = calledBy; - newFunc->stack = NULL; - newFunc->freezerLevel = 0; - newFunc->runThisLine = 0; - newFunc->isSpeech = 0; - initVarNew(newFunc->reg); - - restartFunction(newFunc); - return 1; -} - } // End of namespace Sludge diff --git a/engines/sludge/sludger.h b/engines/sludge/sludger.h index 2351cb9057..8efdfa62f2 100644 --- a/engines/sludge/sludger.h +++ b/engines/sludge/sludger.h @@ -22,12 +22,7 @@ #ifndef SLUDGER_H #define SLUDGER_H -#include "common/file.h" - #include "sludge/allfiles.h" -#include "sludge/variable.h" -#include "sludge/csludge.h" -#include "sludge/language.h" namespace Sludge { @@ -36,51 +31,15 @@ typedef struct _FILETIME { uint32 dwHighDateTime; } FILETIME; -struct Variable; -struct VariableStack; - -struct LineOfCode { - sludgeCommand theCommand; - int32 param; -}; - -struct LoadedFunction { - int originalNumber; - LineOfCode *compiledLines; - int numLocals, timeLeft, numArgs; - Variable *localVars; - VariableStack *stack; - Variable reg; - uint runThisLine; - LoadedFunction *calledBy; - LoadedFunction *next; - bool returnSomething, isSpeech, unfreezable, cancelMe; - byte freezerLevel; -}; - bool initSludge(const Common::String &); -bool runSludge(); - void initSludge(); void killSludge(); void displayBase(); void sludgeDisplay(); -int startNewFunctionNum(uint, uint, LoadedFunction *, VariableStack*&, bool = true); -void restartFunction(LoadedFunction *fun); -bool loadFunctionCode(LoadedFunction *newFunc); -void killAllFunctions(); -void finishFunction(LoadedFunction *fun); -void abortFunction(LoadedFunction *fun); Common::File *openAndVerify(const Common::String &filename, char extra1, char extra2, const char *er, int &fileVersion); -void freezeSubs(); -void unfreezeSubs(); -void completeTimers(); -void killSpeechTimers(); -int cancelAFunction(int funcNum, LoadedFunction *myself, bool &killedMyself); - } // End of namespace Sludge #endif |