[Scummvm-git-logs] scummvm master -> 3e88827c4cea00dcc9f0fe90fc4a173c2b821b41

yinsimei roseline.yin at gmail.com
Tue May 29 23:10:17 CEST 2018


This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
b6c2dc385a SLUDGE: Split out function.h/cpp for upcoming refactoring
0548765479 SLUDGE: Objectify FatalMsgManager
1ec5ef3e4d SLUDGE: Move resource names to ResourceManager
dc320b86bc SLUDGE: Create constructor of Variable instead of initVarNew
87e58a9b7e SLUDGE: Split runSludge() to runAllFunctions() and handleSaveLoad()
3e88827c4c SLUDGE: Move function/variable load/save functions to related files


Commit: b6c2dc385a2eb186026266c6eb015920b443cf81
    https://github.com/scummvm/scummvm/commit/b6c2dc385a2eb186026266c6eb015920b443cf81
Author: Simei Yin (roseline.yin at gmail.com)
Date: 2018-05-29T22:37:10+02:00

Commit Message:
SLUDGE: Split out function.h/cpp for upcoming refactoring

Changed paths:
  A engines/sludge/function.cpp
  A engines/sludge/function.h
    engines/sludge/builtin.cpp
    engines/sludge/builtin.h
    engines/sludge/csludge.h
    engines/sludge/event.cpp
    engines/sludge/loadsave.cpp
    engines/sludge/main_loop.cpp
    engines/sludge/module.mk
    engines/sludge/people.cpp
    engines/sludge/people.h
    engines/sludge/sludger.cpp
    engines/sludge/sludger.h


diff --git a/engines/sludge/builtin.cpp b/engines/sludge/builtin.cpp
index 8646dd4..0d1d940 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 b2274c2..b7fa8b8 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 435a220..cf0d6aa 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 b553702..d6afe2f 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 0000000..8aa69f0
--- /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 0000000..ead2adf
--- /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 8706f7f..2d29645 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 10f54d4..ee0bae1 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 a083ec4..d904e6c 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 3624950..658954a 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 2d19a14..db22d19 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 8bbf76e..cab0342 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 2351cb9..8efdfa6 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


Commit: 0548765479b69f2aaaf153e6370ed262a80c1d2d
    https://github.com/scummvm/scummvm/commit/0548765479b69f2aaaf153e6370ed262a80c1d2d
Author: Simei Yin (roseline.yin at gmail.com)
Date: 2018-05-29T22:37:10+02:00

Commit Message:
SLUDGE: Objectify FatalMsgManager

Changed paths:
    engines/sludge/newfatal.cpp
    engines/sludge/newfatal.h
    engines/sludge/sludge.cpp
    engines/sludge/sludge.h


diff --git a/engines/sludge/newfatal.cpp b/engines/sludge/newfatal.cpp
index edd4a88..820b497 100644
--- a/engines/sludge/newfatal.cpp
+++ b/engines/sludge/newfatal.cpp
@@ -24,74 +24,88 @@
 
 #include "sludge/allfiles.h"
 #include "sludge/errors.h"
+#include "sludge/newfatal.h"
 #include "sludge/sludge.h"
 #include "sludge/sound.h"
 #include "sludge/version.h"
 
-namespace Sludge {
+namespace Common {
+DECLARE_SINGLETON(Sludge::FatalMsgManager);
+}
 
-const char emergencyMemoryMessage[] = "Out of memory displaying error message!";
+namespace Sludge {
 
 extern int numResourceNames /* = 0*/;
 extern Common::String *allResourceNames /*= ""*/;
 
-int resourceForFatal = -1;
+int inFatal(const Common::String &str) {
+	g_sludge->_soundMan->killSoundStuff();
+	error("%s", str.c_str());
+	return true;
+}
 
-const Common::String resourceNameFromNum(int i) {
-	if (i == -1)
-		return NULL;
-	if (numResourceNames == 0)
-		return "RESOURCE";
-	if (i < numResourceNames)
-		return allResourceNames[i];
-	return "Unknown resource";
+FatalMsgManager::FatalMsgManager() {
+	reset();
 }
 
-bool hasFatal() {
-	if (!g_sludge->fatalMessage.empty())
-		return true;
-	return false;
+FatalMsgManager::~FatalMsgManager() {
 }
 
-int inFatal(const Common::String &str) {
-	g_sludge->_soundMan->killSoundStuff();
-	error("%s", str.c_str());
-	return true;
+void FatalMsgManager::reset() {
+	_fatalMessage = "";
+	_fatalInfo = "Initialisation error! Something went wrong before we even got started!";
+	_resourceForFatal = -1;
 }
 
-int checkNew(const void *mem) {
-	if (mem == NULL) {
-		inFatal(ERROR_OUT_OF_MEMORY);
-		return 0;
-	}
-	return 1;
+bool FatalMsgManager::hasFatal() {
+	if (!_fatalMessage.empty())
+		return true;
+	return false;
 }
 
-void setFatalInfo(const Common::String &userFunc, const Common::String &BIF) {
-	g_sludge->fatalInfo = "Currently in this sub: " + userFunc + "\nCalling: " + BIF;
-	debugC(0, kSludgeDebugFatal, "%s", g_sludge->fatalInfo.c_str());
+void FatalMsgManager::setFatalInfo(const Common::String &userFunc, const Common::String &BIF) {
+	_fatalInfo = "Currently in this sub: " + userFunc + "\nCalling: " + BIF;
+	debugC(0, kSludgeDebugFatal, "%s", _fatalInfo.c_str());
 }
 
-void setResourceForFatal(int n) {
-	resourceForFatal = n;
+void FatalMsgManager::setResourceForFatal(int n) {
+	_resourceForFatal = n;
 }
 
-int fatal(const Common::String &str1) {
-	if (numResourceNames && resourceForFatal != -1) {
-		Common::String r = resourceNameFromNum(resourceForFatal);
-		Common::String newStr = g_sludge->fatalInfo + "\nResource: " + r + "\n\n" + str1;
+int FatalMsgManager::fatal(const Common::String &str1) {
+	if (numResourceNames && _resourceForFatal != -1) {
+		Common::String r = resourceNameFromNum(_resourceForFatal);
+		Common::String newStr = _fatalInfo + "\nResource: " + r + "\n\n" + str1;
 		inFatal(newStr);
 	} else {
-		Common::String newStr = g_sludge->fatalInfo + "\n\n" + str1;
+		Common::String newStr = _fatalInfo + "\n\n" + str1;
 		inFatal(newStr);
 	}
 	return 0;
 }
 
+int checkNew(const void *mem) {
+	if (mem == NULL) {
+		inFatal(ERROR_OUT_OF_MEMORY);
+		return 0;
+	}
+	return 1;
+}
+
 int fatal(const Common::String &str1, const Common::String &str2) {
 	Common::String newStr = str1 + " " + str2;
 	fatal(newStr);
 	return 0;
 }
 
+const Common::String resourceNameFromNum(int i) {
+	if (i == -1)
+		return NULL;
+	if (numResourceNames == 0)
+		return "RESOURCE";
+	if (i < numResourceNames)
+		return allResourceNames[i];
+	return "Unknown resource";
+}
+
 } // End of namespace Sludge
diff --git a/engines/sludge/newfatal.h b/engines/sludge/newfatal.h
index fc91110..08a26db 100644
--- a/engines/sludge/newfatal.h
+++ b/engines/sludge/newfatal.h
@@ -23,18 +23,49 @@
 #define SLUDGE_NEWFATAL_H
 
 #include "common/str.h"
+#include "common/singleton.h"
 
 #include "sludge/errors.h"
 
 namespace Sludge {
 
-bool hasFatal();
+class FatalMsgManager : public Common::Singleton<Sludge::FatalMsgManager>{
+public:
+	FatalMsgManager();
+	~FatalMsgManager();
+
+	void reset();
+
+	bool hasFatal();
+	int fatal(const Common::String &str);
+	void setFatalInfo(const Common::String &userFunc, const Common::String &BIF);
+	void setResourceForFatal(int n);
+
+private:
+	Common::String _fatalMessage;
+	Common::String _fatalInfo;
+
+	int _resourceForFatal;
+};
+
+inline bool hasFatal() {
+	return FatalMsgManager::instance().hasFatal();
+}
+
+inline int fatal(const Common::String &str) {
+	return FatalMsgManager::instance().fatal(str);
+}
+
+inline void setFatalInfo(const Common::String &userFunc, const Common::String &BIF) {
+	FatalMsgManager::instance().setFatalInfo(userFunc, BIF);
+}
+
+inline void setResourceForFatal(int n) {
+	FatalMsgManager::instance().setResourceForFatal(n);
+}
 
-int fatal(const Common::String &str);
-int fatal(const Common::String &str1, const Common::String &str2);
 int checkNew(const void *mem);
-void setFatalInfo(const Common::String &userFunc, const Common::String &BIF);
-void setResourceForFatal(int n);
+int fatal(const Common::String &str1, const Common::String &str2);
 const Common::String resourceNameFromNum(int i);
 
 } // End of namespace Sludge
diff --git a/engines/sludge/sludge.cpp b/engines/sludge/sludge.cpp
index a864a61..821539d 100644
--- a/engines/sludge/sludge.cpp
+++ b/engines/sludge/sludge.cpp
@@ -30,12 +30,13 @@
 #include "sludge/fonttext.h"
 #include "sludge/floor.h"
 #include "sludge/graphics.h"
+#include "sludge/main_loop.h"
+#include "sludge/newfatal.h"
 #include "sludge/people.h"
 #include "sludge/region.h"
 #include "sludge/sludge.h"
 #include "sludge/sound.h"
 #include "sludge/speech.h"
-#include "sludge/main_loop.h"
 
 namespace Sludge {
 
@@ -71,11 +72,9 @@ SludgeEngine::SludgeEngine(OSystem *syst, const SludgeGameDescription *gameDesc)
 	launchNext = "";
 	loadNow = "";
 	gamePath = "";
-	bundleFolder = "";
-	fatalMessage = "";
-	fatalInfo = "Initialisation error! Something went wrong before we even got started!";
 
 	// Init managers
+	_fatalMan = new FatalMsgManager();
 	_peopleMan = new PeopleManager(this);
 	_resMan = new ResourceManager();
 	_languageMan = new LanguageManager();
@@ -134,6 +133,8 @@ SludgeEngine::~SludgeEngine() {
 	_peopleMan = nullptr;
 	delete _floorMan;
 	_floorMan = nullptr;
+	delete _fatalMan;
+	_fatalMan = nullptr;
 }
 
 Common::Error SludgeEngine::run() {
diff --git a/engines/sludge/sludge.h b/engines/sludge/sludge.h
index 6a0848a..692af64 100644
--- a/engines/sludge/sludge.h
+++ b/engines/sludge/sludge.h
@@ -40,6 +40,7 @@ extern SludgeEngine *g_sludge;
 
 class CursorManager;
 class EventManager;
+class FatalMsgManager;
 class FloorManager;
 class GraphicsManager;
 class PeopleManager;
@@ -74,9 +75,6 @@ public:
 	Common::String launchNext;
 	Common::String loadNow;
 	Common::String gamePath;
-	Common::String bundleFolder;
-	Common::String fatalMessage;
-	Common::String fatalInfo;
 
 	// timer
 	Timer _timer;
@@ -94,6 +92,7 @@ public:
 	RegionManager *_regionMan;
 	PeopleManager *_peopleMan;
 	FloorManager *_floorMan;
+	FatalMsgManager *_fatalMan;
 
 	SludgeEngine(OSystem *syst, const SludgeGameDescription *gameDesc);
 	virtual ~SludgeEngine();


Commit: 1ec5ef3e4df9ee3606bb4b3092fcf0d6f515563e
    https://github.com/scummvm/scummvm/commit/1ec5ef3e4df9ee3606bb4b3092fcf0d6f515563e
Author: Simei Yin (roseline.yin at gmail.com)
Date: 2018-05-29T22:37:10+02:00

Commit Message:
SLUDGE: Move resource names to ResourceManager

Changed paths:
    engines/sludge/fileset.cpp
    engines/sludge/fileset.h
    engines/sludge/newfatal.cpp
    engines/sludge/newfatal.h
    engines/sludge/sludger.cpp
    engines/sludge/variable.cpp


diff --git a/engines/sludge/fileset.cpp b/engines/sludge/fileset.cpp
index fcdec32..c9c3e7a 100644
--- a/engines/sludge/fileset.cpp
+++ b/engines/sludge/fileset.cpp
@@ -48,12 +48,14 @@ void ResourceManager::init() {
 	_startOfSubIndex = 0;
 	_startOfObjectIndex = 0;
 	_startIndex = 0;
+	_allResourceNames.clear();
 }
 void ResourceManager::kill() {
 	if (_bigDataFile) {
 		delete _bigDataFile;
 		_bigDataFile = nullptr;
 	}
+	_allResourceNames.clear();
 }
 
 bool ResourceManager::openSubSlice(int num) {
@@ -216,6 +218,31 @@ void ResourceManager::finishAccess() {
 	_sliceBusy = false;
 }
 
+void ResourceManager::readResourceNames(Common::SeekableReadStream *readStream) {
+	int numResourceNames = readStream->readUint16BE();
+	debugC(2, kSludgeDebugDataLoad, "numResourceNames %i", numResourceNames);
+	_allResourceNames.reserve(numResourceNames);
+
+	for (int fn = 0; fn < numResourceNames; fn++) {
+		_allResourceNames[fn].clear();
+		_allResourceNames[fn] = readString(readStream);
+		debugC(2, kSludgeDebugDataLoad, "Resource %i: %s", fn, _allResourceNames[fn].c_str());
+	}
+}
+
+const Common::String ResourceManager::resourceNameFromNum(int i) {
+	if (i == -1)
+		return "";
+
+	if (_allResourceNames.empty())
+		return "RESOURCE";
+
+	if (i < (int)_allResourceNames.size())
+		return _allResourceNames[i];
+
+	return "Unknown resource";
+}
+
 void ResourceManager::setData(Common::File *fp) {
 	_bigDataFile = fp;
 	_startIndex = fp->pos();
diff --git a/engines/sludge/fileset.h b/engines/sludge/fileset.h
index 83200ce..fb6a696 100644
--- a/engines/sludge/fileset.h
+++ b/engines/sludge/fileset.h
@@ -44,15 +44,23 @@ public:
 	bool openObjectSlice(int num);
 	Common::String getNumberedString(int value);
 
+	// Access control flag
 	bool startAccess();
 	void finishAccess();
 
+	// Resource names
+	void readResourceNames(Common::SeekableReadStream *readStream);
+	const Common::String resourceNameFromNum(int i);
+	bool hasResourceNames() { return !_allResourceNames.empty(); }
+
 private:
 	bool _sliceBusy;
 	Common::File *_bigDataFile;
 	uint32 _startOfDataIndex, _startOfTextIndex, _startOfSubIndex, _startOfObjectIndex;
 	int32 _startIndex;
 
+	Common::Array<Common::String> _allResourceNames;
+
 private:
 	static uint32 _cp1250ToUTF32[128];
 	Common::String convertString(const Common::String &s);
diff --git a/engines/sludge/newfatal.cpp b/engines/sludge/newfatal.cpp
index 820b497..a5069ae 100644
--- a/engines/sludge/newfatal.cpp
+++ b/engines/sludge/newfatal.cpp
@@ -24,6 +24,7 @@
 
 #include "sludge/allfiles.h"
 #include "sludge/errors.h"
+#include "sludge/fileset.h"
 #include "sludge/newfatal.h"
 #include "sludge/sludge.h"
 #include "sludge/sound.h"
@@ -35,9 +36,6 @@ DECLARE_SINGLETON(Sludge::FatalMsgManager);
 
 namespace Sludge {
 
-extern int numResourceNames /* = 0*/;
-extern Common::String *allResourceNames /*= ""*/;
-
 int inFatal(const Common::String &str) {
 	g_sludge->_soundMan->killSoundStuff();
 	error("%s", str.c_str());
@@ -73,8 +71,9 @@ void FatalMsgManager::setResourceForFatal(int n) {
 }
 
 int FatalMsgManager::fatal(const Common::String &str1) {
-	if (numResourceNames && _resourceForFatal != -1) {
-		Common::String r = resourceNameFromNum(_resourceForFatal);
+	ResourceManager *resMan = g_sludge->_resMan;
+	if (resMan->hasResourceNames() && _resourceForFatal != -1) {
+		Common::String r = resMan->resourceNameFromNum(_resourceForFatal);
 		Common::String newStr = _fatalInfo + "\nResource: " + r + "\n\n" + str1;
 		inFatal(newStr);
 	} else {
@@ -98,14 +97,4 @@ int fatal(const Common::String &str1, const Common::String &str2) {
 	return 0;
 }
 
-const Common::String resourceNameFromNum(int i) {
-	if (i == -1)
-		return NULL;
-	if (numResourceNames == 0)
-		return "RESOURCE";
-	if (i < numResourceNames)
-		return allResourceNames[i];
-	return "Unknown resource";
-}
-
 } // End of namespace Sludge
diff --git a/engines/sludge/newfatal.h b/engines/sludge/newfatal.h
index 08a26db..81ca4b7 100644
--- a/engines/sludge/newfatal.h
+++ b/engines/sludge/newfatal.h
@@ -66,7 +66,6 @@ inline void setResourceForFatal(int n) {
 
 int checkNew(const void *mem);
 int fatal(const Common::String &str1, const Common::String &str2);
-const Common::String resourceNameFromNum(int i);
 
 } // End of namespace Sludge
 
diff --git a/engines/sludge/sludger.cpp b/engines/sludge/sludger.cpp
index cab0342..f297ff1 100644
--- a/engines/sludge/sludger.cpp
+++ b/engines/sludge/sludger.cpp
@@ -60,8 +60,6 @@ extern Common::String *allBIFNames;
 extern int numUserFunc;
 extern Common::String *allUserFunc;
 
-int numResourceNames = 0;
-Common::String *allResourceNames = NULL;
 int selectedLanguage = 0;
 
 int gameVersion;
@@ -206,19 +204,9 @@ bool initSludge(const Common::String &filename) {
 			allUserFunc[fn].clear();
 			allUserFunc[fn] = readString(fp);
 		}
+
 		if (gameVersion >= VERSION(1, 3)) {
-			numResourceNames = fp->readUint16BE();
-			debugC(2, kSludgeDebugDataLoad, "numResourceNames %i",
-					numResourceNames);
-			allResourceNames = new Common::String[numResourceNames];
-			if (!checkNew(allResourceNames))
-				return false;
-
-			for (int fn = 0; fn < numResourceNames; fn++) {
-				allResourceNames[fn].clear();
-				allResourceNames[fn] = readString(fp);
-				debugC(2, kSludgeDebugDataLoad, "Resource %i: %s", fn, allResourceNames[fn].c_str());
-			}
+			g_sludge->_resMan->readResourceNames(fp);
 		}
 	}
 
diff --git a/engines/sludge/variable.cpp b/engines/sludge/variable.cpp
index 5537377..8ed2297 100644
--- a/engines/sludge/variable.cpp
+++ b/engines/sludge/variable.cpp
@@ -303,7 +303,7 @@ Common::String getTextFromAnyVar(const Variable &from) {
 		}
 
 		case SVT_FILE: {
-			return resourceNameFromNum(from.varData.intValue);
+			return g_sludge->_resMan->resourceNameFromNum(from.varData.intValue);
 		}
 
 		case SVT_OBJTYPE: {


Commit: dc320b86bc0da7026bfd650be6a8450684b54fa9
    https://github.com/scummvm/scummvm/commit/dc320b86bc0da7026bfd650be6a8450684b54fa9
Author: Simei Yin (roseline.yin at gmail.com)
Date: 2018-05-29T22:37:10+02:00

Commit Message:
SLUDGE: Create constructor of Variable instead of initVarNew

Changed paths:
    engines/sludge/event.cpp
    engines/sludge/function.cpp
    engines/sludge/sludger.cpp
    engines/sludge/variable.cpp
    engines/sludge/variable.h


diff --git a/engines/sludge/event.cpp b/engines/sludge/event.cpp
index d6afe2f..acccd7f 100644
--- a/engines/sludge/event.cpp
+++ b/engines/sludge/event.cpp
@@ -182,7 +182,6 @@ bool EventManager::handleInput() {
 		if (!checkNew(tempStack))
 			return false;
 
-		initVarNew(tempStack->thisVar);
 		ScreenRegion *overRegion = _vm->_regionMan->getOverRegion();
 		if (overRegion) {
 			setVariable(tempStack->thisVar, SVT_OBJTYPE, overRegion->thisType->objectNum);
@@ -321,7 +320,6 @@ bool EventManager::handleInput() {
 			VariableStack *tempStack = new VariableStack;
 			if (!checkNew(tempStack))
 				return false;
-			initVarNew(tempStack->thisVar);
 			makeTextVar(tempStack->thisVar, tempString);
 			tempStack->next = nullptr;
 			if (!startNewFunctionNum(_currentEvents->func[kSpace], 1, nullptr, tempStack))
diff --git a/engines/sludge/function.cpp b/engines/sludge/function.cpp
index 8aa69f0..98f7bf7 100644
--- a/engines/sludge/function.cpp
+++ b/engines/sludge/function.cpp
@@ -661,9 +661,6 @@ bool loadFunctionCode(LoadedFunction *newFunc) {
 	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;
 }
@@ -700,7 +697,6 @@ int startNewFunctionNum(uint funcNum, uint numParamsExpected,
 	newFunc->freezerLevel = 0;
 	newFunc->runThisLine = 0;
 	newFunc->isSpeech = 0;
-	initVarNew(newFunc->reg);
 
 	restartFunction(newFunc);
 	return 1;
diff --git a/engines/sludge/sludger.cpp b/engines/sludge/sludger.cpp
index f297ff1..f9dedf2 100644
--- a/engines/sludge/sludger.cpp
+++ b/engines/sludge/sludger.cpp
@@ -177,7 +177,6 @@ void killSludge() {
 bool initSludge(const Common::String &filename) {
 	initSludge();
 
-	int a = 0;
 	Common::File *fp = openAndVerify(filename, 'G', 'E', ERROR_BAD_HEADER, gameVersion);
 	if (!fp)
 		return false;
@@ -276,8 +275,6 @@ bool initSludge(const Common::String &filename) {
 	globalVars = new Variable[numGlobals];
 	if (!checkNew(globalVars))
 		return false;
-	for (a = 0; a < numGlobals; a++)
-		initVarNew(globalVars[a]);
 
 	// Get language selected by user
 	g_sludge->_resMan->setData(fp);
diff --git a/engines/sludge/variable.cpp b/engines/sludge/variable.cpp
index 8ed2297..a663599 100644
--- a/engines/sludge/variable.cpp
+++ b/engines/sludge/variable.cpp
@@ -408,9 +408,6 @@ bool makeFastArraySize(Variable &to, int size) {
 	to.varData.fastArray->fastVariables = new Variable[size];
 	if (!checkNew(to.varData.fastArray->fastVariables))
 		return false;
-	for (int i = 0; i < size; i++) {
-		initVarNew(to.varData.fastArray->fastVariables[i]);
-	}
 	to.varData.fastArray->size = size;
 	to.varData.fastArray->timesUsed = 1;
 	return true;
diff --git a/engines/sludge/variable.h b/engines/sludge/variable.h
index a3cc57d..27bf71a 100644
--- a/engines/sludge/variable.h
+++ b/engines/sludge/variable.h
@@ -68,6 +68,11 @@ union VariableData {
 struct Variable {
 	VariableType varType;
 	VariableData varData;
+
+	Variable() {
+		varType = SVT_NULL;
+		varData.intValue = 0;
+	}
 };
 
 struct VariableStack {
@@ -75,10 +80,6 @@ struct VariableStack {
 	VariableStack *next;
 };
 
-// Initialisation
-
-#define initVarNew(thisVar)     thisVar.varType = SVT_NULL
-
 // Setting variables
 
 void setVariable(Variable &thisVar, VariableType vT, int value);
@@ -94,7 +95,6 @@ char *createCString(const Common::String &s);
 // Misc.
 
 void unlinkVar(Variable &thisVar);
-Common::String getNumberedString(int value);
 Common::String getTextFromAnyVar(const Variable &from);
 struct Persona *getCostumeFromVar(Variable &thisVar);
 struct PersonaAnimation  *getAnimationFromVar(Variable &thisVar);


Commit: 87e58a9b7e26986c8d396d836a97ad01a5f74c52
    https://github.com/scummvm/scummvm/commit/87e58a9b7e26986c8d396d836a97ad01a5f74c52
Author: Simei Yin (roseline.yin at gmail.com)
Date: 2018-05-29T22:37:10+02:00

Commit Message:
SLUDGE: Split runSludge() to runAllFunctions() and handleSaveLoad()

Changed paths:
    engines/sludge/function.cpp
    engines/sludge/function.h
    engines/sludge/loadsave.cpp
    engines/sludge/loadsave.h
    engines/sludge/main_loop.cpp


diff --git a/engines/sludge/function.cpp b/engines/sludge/function.cpp
index 98f7bf7..6905c38 100644
--- a/engines/sludge/function.cpp
+++ b/engines/sludge/function.cpp
@@ -702,7 +702,7 @@ int startNewFunctionNum(uint funcNum, uint numParamsExpected,
 	return 1;
 }
 
-bool runSludge() {
+bool runAllFunctions() {
 
 	LoadedFunction *thisFunction = allRunningFunctions;
 	LoadedFunction *nextFunction;
@@ -732,17 +732,6 @@ bool runSludge() {
 		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;
 }
 
diff --git a/engines/sludge/function.h b/engines/sludge/function.h
index ead2adf..6980d6b 100644
--- a/engines/sludge/function.h
+++ b/engines/sludge/function.h
@@ -50,8 +50,7 @@ struct LoadedFunction {
 	byte freezerLevel;
 };
 
-bool runSludge();
-
+bool runAllFunctions();
 int startNewFunctionNum(uint, uint, LoadedFunction *, VariableStack*&, bool = true);
 void restartFunction(LoadedFunction *fun);
 bool loadFunctionCode(LoadedFunction *newFunc);
diff --git a/engines/sludge/loadsave.cpp b/engines/sludge/loadsave.cpp
index 2d29645..923c171 100644
--- a/engines/sludge/loadsave.cpp
+++ b/engines/sludge/loadsave.cpp
@@ -56,6 +56,7 @@ namespace Sludge {
 // From elsewhere
 //----------------------------------------------------------------------
 
+extern LoadedFunction *saverFunc;					// In function.cpp
 extern LoadedFunction *allRunningFunctions;         // In sludger.cpp
 extern const char *typeName[];                      // In variable.cpp
 extern int numGlobals;                              // In sludger.cpp
@@ -336,6 +337,20 @@ LoadedFunction *loadFunction(Common::SeekableReadStream *stream) {
 // Save everything
 //----------------------------------------------------------------------
 
+bool handleSaveLoad() {
+	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;
+}
+
 bool saveGame(const Common::String &fname) {
 	Common::OutSaveFile *fp = g_system->getSavefileManager()->openForSaving(fname);
 
diff --git a/engines/sludge/loadsave.h b/engines/sludge/loadsave.h
index 269fadb..54e0577 100644
--- a/engines/sludge/loadsave.h
+++ b/engines/sludge/loadsave.h
@@ -28,6 +28,8 @@ struct LoadedFunction;
 struct Variable;
 struct VariableStack;
 
+bool handleSaveLoad();
+
 bool saveGame(const Common::String &fname);
 bool loadGame(const Common::String &fname);
 
diff --git a/engines/sludge/main_loop.cpp b/engines/sludge/main_loop.cpp
index ee0bae1..8f6e1f9 100644
--- a/engines/sludge/main_loop.cpp
+++ b/engines/sludge/main_loop.cpp
@@ -31,6 +31,7 @@
 #include "sludge/function.h"
 #include "sludge/graphics.h"
 #include "sludge/language.h"
+#include "sludge/loadsave.h"
 #include "sludge/newfatal.h"
 #include "sludge/objtypes.h"
 #include "sludge/people.h"
@@ -63,7 +64,8 @@ int main_loop(Common::String filename) {
 		g_sludge->_evtMan->checkInput();
 		g_sludge->_peopleMan->walkAllPeople();
 		if (g_sludge->_evtMan->handleInput()) {
-			runSludge();
+			runAllFunctions();
+			handleSaveLoad();
 		}
 		sludgeDisplay();
 		g_sludge->_soundMan->handleSoundLists();


Commit: 3e88827c4cea00dcc9f0fe90fc4a173c2b821b41
    https://github.com/scummvm/scummvm/commit/3e88827c4cea00dcc9f0fe90fc4a173c2b821b41
Author: Simei Yin (roseline.yin at gmail.com)
Date: 2018-05-29T22:59:52+02:00

Commit Message:
SLUDGE: Move function/variable load/save functions to related files

Changed paths:
    engines/sludge/function.cpp
    engines/sludge/function.h
    engines/sludge/loadsave.cpp
    engines/sludge/loadsave.h
    engines/sludge/variable.cpp
    engines/sludge/variable.h


diff --git a/engines/sludge/function.cpp b/engines/sludge/function.cpp
index 6905c38..0a7a344 100644
--- a/engines/sludge/function.cpp
+++ b/engines/sludge/function.cpp
@@ -735,4 +735,66 @@ bool runAllFunctions() {
 	return true;
 }
 
+void saveFunction(LoadedFunction *fun, Common::WriteStream *stream) {
+	int a;
+	stream->writeUint16BE(fun->originalNumber);
+	if (fun->calledBy) {
+		stream->writeByte(1);
+		saveFunction(fun->calledBy, stream);
+	} else {
+		stream->writeByte(0);
+	}
+	stream->writeUint32LE(fun->timeLeft);
+	stream->writeUint16BE(fun->runThisLine);
+	stream->writeByte(fun->cancelMe);
+	stream->writeByte(fun->returnSomething);
+	stream->writeByte(fun->isSpeech);
+	saveVariable(&(fun->reg), stream);
+
+	if (fun->freezerLevel) {
+		fatal(ERROR_GAME_SAVE_FROZEN);
+	}
+	saveStack(fun->stack, stream);
+	for (a = 0; a < fun->numLocals; a++) {
+		saveVariable(&(fun->localVars[a]), stream);
+	}
+}
+
+LoadedFunction *loadFunction(Common::SeekableReadStream *stream) {
+	int a;
+
+	// Reserve memory...
+
+	LoadedFunction *buildFunc = new LoadedFunction;
+	if (!checkNew(buildFunc))
+		return NULL;
+
+	// See what it was called by and load if we need to...
+
+	buildFunc->originalNumber = stream->readUint16BE();
+	buildFunc->calledBy = NULL;
+	if (stream->readByte()) {
+		buildFunc->calledBy = loadFunction(stream);
+		if (!buildFunc->calledBy)
+			return NULL;
+	}
+
+	buildFunc->timeLeft = stream->readUint32LE();
+	buildFunc->runThisLine = stream->readUint16BE();
+	buildFunc->freezerLevel = 0;
+	buildFunc->cancelMe = stream->readByte();
+	buildFunc->returnSomething = stream->readByte();
+	buildFunc->isSpeech = stream->readByte();
+	loadVariable(&(buildFunc->reg), stream);
+	loadFunctionCode(buildFunc);
+
+	buildFunc->stack = loadStack(stream, NULL);
+
+	for (a = 0; a < buildFunc->numLocals; a++) {
+		loadVariable(&(buildFunc->localVars[a]), stream);
+	}
+
+	return buildFunc;
+}
+
 } // End of namespace Sludge
diff --git a/engines/sludge/function.h b/engines/sludge/function.h
index 6980d6b..005760a 100644
--- a/engines/sludge/function.h
+++ b/engines/sludge/function.h
@@ -65,6 +65,9 @@ void completeTimers();
 void killSpeechTimers();
 int cancelAFunction(int funcNum, LoadedFunction *myself, bool &killedMyself);
 
+LoadedFunction *loadFunction(Common::SeekableReadStream *stream);
+void saveFunction(LoadedFunction *fun, Common::WriteStream *stream);
+
 } // End of namespace Sludge
 
 #endif
diff --git a/engines/sludge/loadsave.cpp b/engines/sludge/loadsave.cpp
index 923c171..4a78b83 100644
--- a/engines/sludge/loadsave.cpp
+++ b/engines/sludge/loadsave.cpp
@@ -58,282 +58,12 @@ namespace Sludge {
 
 extern LoadedFunction *saverFunc;					// In function.cpp
 extern LoadedFunction *allRunningFunctions;         // In sludger.cpp
-extern const char *typeName[];                      // In variable.cpp
 extern int numGlobals;                              // In sludger.cpp
 extern Variable *globalVars;                        // In sludger.cpp
 extern FILETIME fileTime;                           // In sludger.cpp
 extern bool allowAnyFilename;
 
 //----------------------------------------------------------------------
-// Globals (so we know what's saved already and what's a reference
-//----------------------------------------------------------------------
-
-struct stackLibrary {
-	StackHandler *stack;
-	stackLibrary *next;
-};
-
-int stackLibTotal = 0;
-stackLibrary *stackLib = NULL;
-
-//----------------------------------------------------------------------
-// For saving and loading stacks...
-//----------------------------------------------------------------------
-void saveStack(VariableStack *vs, Common::WriteStream *stream) {
-	int elements = 0;
-	int a;
-
-	VariableStack *search = vs;
-	while (search) {
-		elements++;
-		search = search->next;
-	}
-
-	stream->writeUint16BE(elements);
-	search = vs;
-	for (a = 0; a < elements; a++) {
-		saveVariable(&search->thisVar, stream);
-		search = search->next;
-	}
-}
-
-VariableStack *loadStack(Common::SeekableReadStream *stream, VariableStack **last) {
-	int elements = stream->readUint16BE();
-	int a;
-	VariableStack *first = NULL;
-	VariableStack **changeMe = &first;
-
-	for (a = 0; a < elements; a++) {
-		VariableStack *nS = new VariableStack;
-		if (!checkNew(nS))
-			return NULL;
-		loadVariable(&(nS->thisVar), stream);
-		if (last && a == elements - 1) {
-			*last = nS;
-		}
-		nS->next = NULL;
-		(*changeMe) = nS;
-		changeMe = &(nS->next);
-	}
-
-	return first;
-}
-
-bool saveStackRef(StackHandler *vs, Common::WriteStream *stream) {
-	stackLibrary *s = stackLib;
-	int a = 0;
-	while (s) {
-		if (s->stack == vs) {
-			stream->writeByte(1);
-			stream->writeUint16BE(stackLibTotal - a);
-			return true;
-		}
-		s = s->next;
-		a++;
-	}
-	stream->writeByte(0);
-	saveStack(vs->first, stream);
-	s = new stackLibrary;
-	stackLibTotal++;
-	if (!checkNew(s))
-		return false;
-	s->next = stackLib;
-	s->stack = vs;
-	stackLib = s;
-	return true;
-}
-
-void clearStackLib() {
-	stackLibrary *k;
-	while (stackLib) {
-		k = stackLib;
-		stackLib = stackLib->next;
-		delete k;
-	}
-	stackLibTotal = 0;
-}
-
-StackHandler *getStackFromLibrary(int n) {
-	n = stackLibTotal - n;
-	while (n) {
-		stackLib = stackLib->next;
-		n--;
-	}
-	return stackLib->stack;
-}
-
-StackHandler *loadStackRef(Common::SeekableReadStream *stream) {
-	StackHandler *nsh;
-
-	if (stream->readByte()) {    // It's one we've loaded already...
-		nsh = getStackFromLibrary(stream->readUint16BE());
-		nsh->timesUsed++;
-	} else {
-		// Load the new stack
-
-		nsh = new StackHandler;
-		if (!checkNew(nsh))
-			return NULL;
-		nsh->last = NULL;
-		nsh->first = loadStack(stream, &nsh->last);
-		nsh->timesUsed = 1;
-
-		// Add it to the library of loaded stacks
-
-		stackLibrary *s = new stackLibrary;
-		if (!checkNew(s))
-			return NULL;
-		s->stack = nsh;
-		s->next = stackLib;
-		stackLib = s;
-		stackLibTotal++;
-	}
-	return nsh;
-}
-
-//----------------------------------------------------------------------
-// For saving and loading variables...
-//----------------------------------------------------------------------
-bool saveVariable(Variable *from, Common::WriteStream *stream) {
-	stream->writeByte(from->varType);
-	switch (from->varType) {
-		case SVT_INT:
-		case SVT_FUNC:
-		case SVT_BUILT:
-		case SVT_FILE:
-		case SVT_OBJTYPE:
-			stream->writeUint32LE(from->varData.intValue);
-			return true;
-
-		case SVT_STRING:
-			writeString(from->varData.theString, stream);
-			return true;
-
-		case SVT_STACK:
-			return saveStackRef(from->varData.theStack, stream);
-
-		case SVT_COSTUME:
-			from->varData.costumeHandler->save(stream);
-			return false;
-
-		case SVT_ANIM:
-			from->varData.animHandler->save(stream);
-			return false;
-
-		case SVT_NULL:
-			return false;
-
-		default:
-			fatal("Can't save variables of this type:", (from->varType < SVT_NUM_TYPES) ? typeName[from->varType] : "bad ID");
-	}
-	return true;
-}
-
-bool loadVariable(Variable *to, Common::SeekableReadStream *stream) {
-	to->varType = (VariableType)stream->readByte();
-	switch (to->varType) {
-		case SVT_INT:
-		case SVT_FUNC:
-		case SVT_BUILT:
-		case SVT_FILE:
-		case SVT_OBJTYPE:
-			to->varData.intValue = stream->readUint32LE();
-			return true;
-
-		case SVT_STRING:
-			to->varData.theString = createCString(readString(stream));
-			return true;
-
-		case SVT_STACK:
-			to->varData.theStack = loadStackRef(stream);
-			return true;
-
-		case SVT_COSTUME:
-			to->varData.costumeHandler = new Persona;
-			if (!checkNew(to->varData.costumeHandler))
-				return false;
-			to->varData.costumeHandler->load(stream);
-			return true;
-
-		case SVT_ANIM:
-			to->varData.animHandler = new PersonaAnimation;
-			if (!checkNew(to->varData.animHandler))
-				return false;
-			to->varData.animHandler->load(stream);
-			return true;
-
-		default:
-			break;
-	}
-	return true;
-}
-
-//----------------------------------------------------------------------
-// For saving and loading functions
-//----------------------------------------------------------------------
-void saveFunction(LoadedFunction *fun, Common::WriteStream *stream) {
-	int a;
-	stream->writeUint16BE(fun->originalNumber);
-	if (fun->calledBy) {
-		stream->writeByte(1);
-		saveFunction(fun->calledBy, stream);
-	} else {
-		stream->writeByte(0);
-	}
-	stream->writeUint32LE(fun->timeLeft);
-	stream->writeUint16BE(fun->runThisLine);
-	stream->writeByte(fun->cancelMe);
-	stream->writeByte(fun->returnSomething);
-	stream->writeByte(fun->isSpeech);
-	saveVariable(&(fun->reg), stream);
-
-	if (fun->freezerLevel) {
-		fatal(ERROR_GAME_SAVE_FROZEN);
-	}
-	saveStack(fun->stack, stream);
-	for (a = 0; a < fun->numLocals; a++) {
-		saveVariable(&(fun->localVars[a]), stream);
-	}
-}
-
-LoadedFunction *loadFunction(Common::SeekableReadStream *stream) {
-	int a;
-
-	// Reserve memory...
-
-	LoadedFunction *buildFunc = new LoadedFunction;
-	if (!checkNew(buildFunc))
-		return NULL;
-
-	// See what it was called by and load if we need to...
-
-	buildFunc->originalNumber = stream->readUint16BE();
-	buildFunc->calledBy = NULL;
-	if (stream->readByte()) {
-		buildFunc->calledBy = loadFunction(stream);
-		if (!buildFunc->calledBy)
-			return NULL;
-	}
-
-	buildFunc->timeLeft = stream->readUint32LE();
-	buildFunc->runThisLine = stream->readUint16BE();
-	buildFunc->freezerLevel = 0;
-	buildFunc->cancelMe = stream->readByte();
-	buildFunc->returnSomething = stream->readByte();
-	buildFunc->isSpeech = stream->readByte();
-	loadVariable(&(buildFunc->reg), stream);
-	loadFunctionCode(buildFunc);
-
-	buildFunc->stack = loadStack(stream, NULL);
-
-	for (a = 0; a < buildFunc->numLocals; a++) {
-		loadVariable(&(buildFunc->localVars[a]), stream);
-	}
-
-	return buildFunc;
-}
-
-//----------------------------------------------------------------------
 // Save everything
 //----------------------------------------------------------------------
 
diff --git a/engines/sludge/loadsave.h b/engines/sludge/loadsave.h
index 54e0577..4077950 100644
--- a/engines/sludge/loadsave.h
+++ b/engines/sludge/loadsave.h
@@ -24,25 +24,10 @@
 
 namespace Sludge {
 
-struct LoadedFunction;
-struct Variable;
-struct VariableStack;
-
 bool handleSaveLoad();
-
 bool saveGame(const Common::String &fname);
 bool loadGame(const Common::String &fname);
 
-bool saveVariable(Variable *from, Common::WriteStream *stream);
-bool loadVariable(Variable *to, Common::SeekableReadStream *stream);
-
-VariableStack *loadStack(Common::SeekableReadStream *stream, VariableStack **last);
-bool saveStackRef(StackHandler *vs, Common::WriteStream *stream);
-StackHandler *loadStackRef(Common::SeekableReadStream *stream);
-
-LoadedFunction *loadFunction(Common::SeekableReadStream *stream);
-void saveFunction(LoadedFunction *fun, Common::WriteStream *stream);
-
 } // End of namespace Sludge
 
 #endif
diff --git a/engines/sludge/variable.cpp b/engines/sludge/variable.cpp
index a663599..35e1036 100644
--- a/engines/sludge/variable.cpp
+++ b/engines/sludge/variable.cpp
@@ -537,4 +537,208 @@ void trimStack(VariableStack *&stack) {
 	delete killMe;
 }
 
+//----------------------------------------------------------------------
+// Globals (so we know what's saved already and what's a reference
+//----------------------------------------------------------------------
+
+struct stackLibrary {
+	StackHandler *stack;
+	stackLibrary *next;
+};
+
+int stackLibTotal = 0;
+stackLibrary *stackLib = NULL;
+
+//----------------------------------------------------------------------
+// For saving and loading stacks...
+//----------------------------------------------------------------------
+void saveStack(VariableStack *vs, Common::WriteStream *stream) {
+	int elements = 0;
+	int a;
+
+	VariableStack *search = vs;
+	while (search) {
+		elements++;
+		search = search->next;
+	}
+
+	stream->writeUint16BE(elements);
+	search = vs;
+	for (a = 0; a < elements; a++) {
+		saveVariable(&search->thisVar, stream);
+		search = search->next;
+	}
+}
+
+VariableStack *loadStack(Common::SeekableReadStream *stream, VariableStack **last) {
+	int elements = stream->readUint16BE();
+	int a;
+	VariableStack *first = NULL;
+	VariableStack **changeMe = &first;
+
+	for (a = 0; a < elements; a++) {
+		VariableStack *nS = new VariableStack;
+		if (!checkNew(nS))
+			return NULL;
+		loadVariable(&(nS->thisVar), stream);
+		if (last && a == elements - 1) {
+			*last = nS;
+		}
+		nS->next = NULL;
+		(*changeMe) = nS;
+		changeMe = &(nS->next);
+	}
+
+	return first;
+}
+
+bool saveStackRef(StackHandler *vs, Common::WriteStream *stream) {
+	stackLibrary *s = stackLib;
+	int a = 0;
+	while (s) {
+		if (s->stack == vs) {
+			stream->writeByte(1);
+			stream->writeUint16BE(stackLibTotal - a);
+			return true;
+		}
+		s = s->next;
+		a++;
+	}
+	stream->writeByte(0);
+	saveStack(vs->first, stream);
+	s = new stackLibrary;
+	stackLibTotal++;
+	if (!checkNew(s))
+		return false;
+	s->next = stackLib;
+	s->stack = vs;
+	stackLib = s;
+	return true;
+}
+
+void clearStackLib() {
+	stackLibrary *k;
+	while (stackLib) {
+		k = stackLib;
+		stackLib = stackLib->next;
+		delete k;
+	}
+	stackLibTotal = 0;
+}
+
+StackHandler *getStackFromLibrary(int n) {
+	n = stackLibTotal - n;
+	while (n) {
+		stackLib = stackLib->next;
+		n--;
+	}
+	return stackLib->stack;
+}
+
+StackHandler *loadStackRef(Common::SeekableReadStream *stream) {
+	StackHandler *nsh;
+
+	if (stream->readByte()) {    // It's one we've loaded already...
+		nsh = getStackFromLibrary(stream->readUint16BE());
+		nsh->timesUsed++;
+	} else {
+		// Load the new stack
+
+		nsh = new StackHandler;
+		if (!checkNew(nsh))
+			return NULL;
+		nsh->last = NULL;
+		nsh->first = loadStack(stream, &nsh->last);
+		nsh->timesUsed = 1;
+
+		// Add it to the library of loaded stacks
+
+		stackLibrary *s = new stackLibrary;
+		if (!checkNew(s))
+			return NULL;
+		s->stack = nsh;
+		s->next = stackLib;
+		stackLib = s;
+		stackLibTotal++;
+	}
+	return nsh;
+}
+
+//----------------------------------------------------------------------
+// For saving and loading variables...
+//----------------------------------------------------------------------
+bool saveVariable(Variable *from, Common::WriteStream *stream) {
+	stream->writeByte(from->varType);
+	switch (from->varType) {
+		case SVT_INT:
+		case SVT_FUNC:
+		case SVT_BUILT:
+		case SVT_FILE:
+		case SVT_OBJTYPE:
+			stream->writeUint32LE(from->varData.intValue);
+			return true;
+
+		case SVT_STRING:
+			writeString(from->varData.theString, stream);
+			return true;
+
+		case SVT_STACK:
+			return saveStackRef(from->varData.theStack, stream);
+
+		case SVT_COSTUME:
+			from->varData.costumeHandler->save(stream);
+			return false;
+
+		case SVT_ANIM:
+			from->varData.animHandler->save(stream);
+			return false;
+
+		case SVT_NULL:
+			return false;
+
+		default:
+			fatal("Can't save variables of this type:", (from->varType < SVT_NUM_TYPES) ? typeName[from->varType] : "bad ID");
+	}
+	return true;
+}
+
+bool loadVariable(Variable *to, Common::SeekableReadStream *stream) {
+	to->varType = (VariableType)stream->readByte();
+	switch (to->varType) {
+		case SVT_INT:
+		case SVT_FUNC:
+		case SVT_BUILT:
+		case SVT_FILE:
+		case SVT_OBJTYPE:
+			to->varData.intValue = stream->readUint32LE();
+			return true;
+
+		case SVT_STRING:
+			to->varData.theString = createCString(readString(stream));
+			return true;
+
+		case SVT_STACK:
+			to->varData.theStack = loadStackRef(stream);
+			return true;
+
+		case SVT_COSTUME:
+			to->varData.costumeHandler = new Persona;
+			if (!checkNew(to->varData.costumeHandler))
+				return false;
+			to->varData.costumeHandler->load(stream);
+			return true;
+
+		case SVT_ANIM:
+			to->varData.animHandler = new PersonaAnimation;
+			if (!checkNew(to->varData.animHandler))
+				return false;
+			to->varData.animHandler->load(stream);
+			return true;
+
+		default:
+			break;
+	}
+	return true;
+}
+
 } // End of namespace Sludge
diff --git a/engines/sludge/variable.h b/engines/sludge/variable.h
index 27bf71a..8f0d394 100644
--- a/engines/sludge/variable.h
+++ b/engines/sludge/variable.h
@@ -119,6 +119,16 @@ bool makeFastArrayFromStack(Variable &to, const StackHandler *stacky);
 bool makeFastArraySize(Variable &to, int size);
 Variable *fastArrayGetByIndex(FastArrayHandler *vS, uint theIndex);
 
+// load & save
+bool saveVariable(Variable *from, Common::WriteStream *stream);
+bool loadVariable(Variable *to, Common::SeekableReadStream *stream);
+
+void saveStack(VariableStack *vs, Common::WriteStream *stream);
+VariableStack *loadStack(Common::SeekableReadStream *stream, VariableStack **last);
+bool saveStackRef(StackHandler *vs, Common::WriteStream *stream);
+StackHandler *loadStackRef(Common::SeekableReadStream *stream);
+void clearStackLib();
+
 } // End of namespace Sludge
 
 #endif





More information about the Scummvm-git-logs mailing list