aboutsummaryrefslogtreecommitdiff
path: root/engines/sludge
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sludge')
-rw-r--r--engines/sludge/builtin.cpp3
-rw-r--r--engines/sludge/builtin.h2
-rw-r--r--engines/sludge/csludge.h2
-rw-r--r--engines/sludge/event.cpp1
-rw-r--r--engines/sludge/function.cpp753
-rw-r--r--engines/sludge/function.h71
-rw-r--r--engines/sludge/loadsave.cpp1
-rw-r--r--engines/sludge/main_loop.cpp1
-rw-r--r--engines/sludge/module.mk1
-rw-r--r--engines/sludge/people.cpp1
-rw-r--r--engines/sludge/people.h2
-rw-r--r--engines/sludge/sludger.cpp737
-rw-r--r--engines/sludge/sludger.h41
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