Initial commit
This commit is contained in:
813
engines/sludge/variable.cpp
Normal file
813
engines/sludge/variable.cpp
Normal file
@@ -0,0 +1,813 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "engines/metaengine.h"
|
||||
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/moreio.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/objtypes.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sprbanks.h"
|
||||
#include "sludge/variable.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
const char *typeName[] = { "undefined", "number", "user function", "string",
|
||||
"built-in function", "file", "stack", "object type", "animation",
|
||||
"costume", "fast array" };
|
||||
|
||||
void Variable::unlinkVar() {
|
||||
switch (varType) {
|
||||
case SVT_STRING:
|
||||
delete []varData.theString;
|
||||
varData.theString = NULL;
|
||||
break;
|
||||
|
||||
case SVT_STACK:
|
||||
varData.theStack->timesUsed--;
|
||||
if (varData.theStack->timesUsed <= 0) {
|
||||
while (varData.theStack->first)
|
||||
trimStack(varData.theStack->first);
|
||||
delete varData.theStack;
|
||||
varData.theStack = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case SVT_FASTARRAY:
|
||||
varData.fastArray->timesUsed--;
|
||||
if (varData.theStack->timesUsed <= 0) {
|
||||
delete varData.fastArray->fastVariables;
|
||||
delete[] varData.fastArray;
|
||||
varData.fastArray = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case SVT_ANIM:
|
||||
if (varData.animHandler) {
|
||||
delete varData.animHandler;
|
||||
varData.animHandler = nullptr;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Variable::setVariable(VariableType vT, int value) {
|
||||
unlinkVar();
|
||||
varType = vT;
|
||||
varData.intValue = value;
|
||||
}
|
||||
|
||||
void Variable::makeAnimationVariable(PersonaAnimation *i) {
|
||||
unlinkVar();
|
||||
varType = SVT_ANIM;
|
||||
varData.animHandler = i;
|
||||
}
|
||||
|
||||
PersonaAnimation *Variable::getAnimationFromVar() {
|
||||
if (varType == SVT_ANIM)
|
||||
return new PersonaAnimation(varData.animHandler);
|
||||
|
||||
if (varType == SVT_INT && varData.intValue == 0)
|
||||
return new PersonaAnimation();
|
||||
|
||||
fatal("Expecting an animation variable; found Variable of type", typeName[varType]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Variable::makeCostumeVariable(Persona *i) {
|
||||
unlinkVar();
|
||||
varType = SVT_COSTUME;
|
||||
varData.costumeHandler = i;
|
||||
}
|
||||
|
||||
Persona *Variable::getCostumeFromVar() {
|
||||
Persona *p = NULL;
|
||||
|
||||
switch (varType) {
|
||||
case SVT_ANIM:
|
||||
p = new Persona;
|
||||
if (!checkNew(p))
|
||||
return NULL;
|
||||
p->numDirections = 1;
|
||||
p->animation = new PersonaAnimation *[3];
|
||||
if (!checkNew(p->animation))
|
||||
return NULL;
|
||||
|
||||
for (int iii = 0; iii < 3; iii++)
|
||||
p->animation[iii] = new PersonaAnimation(varData.animHandler);
|
||||
|
||||
break;
|
||||
|
||||
case SVT_COSTUME:
|
||||
return varData.costumeHandler;
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Expecting an animation variable; found Variable of type", typeName[varType]);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void Variable::debugPrint() {
|
||||
switch (varType) {
|
||||
case SVT_NULL:
|
||||
debugN("SVT_NULL() ");
|
||||
break;
|
||||
case SVT_INT:
|
||||
debugN("SVT_INT(%d) ", varData.intValue);
|
||||
break;
|
||||
case SVT_STRING:
|
||||
debugN("SVT_STRING(\"%s\") ", Common::toPrintable(varData.theString).c_str());
|
||||
break;
|
||||
case SVT_BUILT:
|
||||
debugN("SVT_BUILT(%d) ", varData.intValue);
|
||||
break;
|
||||
case SVT_STACK:
|
||||
debugN("SVT_STACK(");
|
||||
varData.theStack->debugPrint();
|
||||
debugN(") ");
|
||||
break;
|
||||
case SVT_FUNC:
|
||||
debugN("SVT_FUNC(%d) ", varData.intValue);
|
||||
break;
|
||||
case SVT_FILE:
|
||||
debugN("SVT_FILE(\"%s\") ", g_sludge->_resMan->resourceNameFromNum(varData.intValue).c_str());
|
||||
break;
|
||||
case SVT_ANIM:
|
||||
debugN("SVT_ANIM(Frames: %d, ID: %d) ", varData.animHandler->numFrames, varData.animHandler->numFrames ? varData.animHandler->theSprites->ID : -1337);
|
||||
break;
|
||||
case SVT_OBJTYPE:
|
||||
debugN("SVT_OBJTYPE(%d) ", varData.intValue);
|
||||
break;
|
||||
case SVT_COSTUME:
|
||||
debugN("SVT_COSTUME(numDirections: %d) ", varData.costumeHandler->numDirections);
|
||||
break;
|
||||
case SVT_FASTARRAY:
|
||||
debugN("FASTARRAY(");
|
||||
varData.fastArray->debugPrint();
|
||||
debugN(") ");
|
||||
break;
|
||||
default :
|
||||
debugN("<UNK %d> ", varType);
|
||||
}
|
||||
}
|
||||
|
||||
int StackHandler::getStackSize() const {
|
||||
int r = 0;
|
||||
VariableStack *a = first;
|
||||
while (a) {
|
||||
r++;
|
||||
a = a->next;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int stringCompareToIgnoreCase(const Common::String &s1, const Common::String &s2) {
|
||||
return s1.compareToIgnoreCase(s2) > 0;
|
||||
}
|
||||
|
||||
bool StackHandler::getSavedGamesStack(const Common::String &ext) {
|
||||
// Make pattern
|
||||
//uint len = realExtension.size();
|
||||
|
||||
// Get all saved files
|
||||
SaveStateList sa = g_sludge->getMetaEngine()->listSaves(g_sludge->getTargetName().c_str());
|
||||
Common::StringArray realNames;
|
||||
|
||||
g_sludge->_saveNameToSlot.clear();
|
||||
|
||||
for (auto &savestate : sa) {
|
||||
Common::String name = savestate.getDescription();
|
||||
realNames.push_back(name);
|
||||
g_sludge->_saveNameToSlot[name] = savestate.getSaveSlot();
|
||||
}
|
||||
|
||||
Common::sort(realNames.begin(), realNames.end(), stringCompareToIgnoreCase);
|
||||
|
||||
|
||||
// Save file names to stacks
|
||||
Variable newName;
|
||||
newName.varType = SVT_NULL;
|
||||
|
||||
for (Common::StringArray::iterator it = realNames.begin(); it != realNames.end(); ++it) {
|
||||
newName.makeTextVar((*it));
|
||||
if (!addVarToStack(newName, first))
|
||||
return false;
|
||||
if (last == NULL)
|
||||
last = first;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StackHandler::debugPrint() {
|
||||
VariableStack *a = first;
|
||||
|
||||
debugN("{");
|
||||
|
||||
while (a) {
|
||||
a->thisVar.debugPrint();
|
||||
a = a->next;
|
||||
}
|
||||
|
||||
debugN("}");
|
||||
}
|
||||
|
||||
bool Variable::copyStack(const Variable &from) {
|
||||
varType = SVT_STACK;
|
||||
varData.theStack = new StackHandler;
|
||||
if (!checkNew(varData.theStack))
|
||||
return false;
|
||||
varData.theStack->first = NULL;
|
||||
varData.theStack->last = NULL;
|
||||
varData.theStack->timesUsed = 1;
|
||||
VariableStack *a = from.varData.theStack->first;
|
||||
|
||||
while (a) {
|
||||
addVarToStack(a->thisVar, varData.theStack->first);
|
||||
if (varData.theStack->last == NULL) {
|
||||
varData.theStack->last = varData.theStack->first;
|
||||
}
|
||||
a = a->next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Variable::addVariablesInSecond(const Variable &other) {
|
||||
if (other.varType == SVT_INT && varType == SVT_INT) {
|
||||
varData.intValue += other.varData.intValue;
|
||||
} else {
|
||||
Common::String string1 = other.getTextFromAnyVar();
|
||||
Common::String string2 = getTextFromAnyVar();
|
||||
|
||||
unlinkVar();
|
||||
varData.theString = createCString(string1 + string2);
|
||||
varType = SVT_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
int Variable::compareVars(const Variable &other) const {
|
||||
int re = 0;
|
||||
if (other.varType == varType) {
|
||||
switch (other.varType) {
|
||||
case SVT_NULL:
|
||||
re = 1;
|
||||
break;
|
||||
|
||||
case SVT_COSTUME:
|
||||
re = (other.varData.costumeHandler == varData.costumeHandler);
|
||||
break;
|
||||
|
||||
case SVT_ANIM:
|
||||
re = (other.varData.animHandler == varData.animHandler);
|
||||
break;
|
||||
|
||||
case SVT_STRING:
|
||||
re = (strcmp(other.varData.theString, varData.theString) == 0);
|
||||
break;
|
||||
|
||||
case SVT_STACK:
|
||||
re = (other.varData.theStack == varData.theStack);
|
||||
break;
|
||||
|
||||
default:
|
||||
re = (other.varData.intValue == varData.intValue);
|
||||
}
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
void Variable::compareVariablesInSecond(const Variable &other) {
|
||||
setVariable(SVT_INT, compareVars(other));
|
||||
}
|
||||
|
||||
void Variable::makeTextVar(const Common::String &txt) {
|
||||
unlinkVar();
|
||||
varType = SVT_STRING;
|
||||
varData.theString = createCString(txt);
|
||||
}
|
||||
|
||||
bool Variable::loadStringToVar(int value) {
|
||||
makeTextVar(g_sludge->_resMan->getNumberedString(value));
|
||||
return (bool)(varData.theString != NULL);
|
||||
}
|
||||
|
||||
Common::String Variable::getTextFromAnyVar(bool skipLoad) const {
|
||||
switch (varType) {
|
||||
case SVT_STRING:
|
||||
return varData.theString;
|
||||
|
||||
case SVT_FASTARRAY: {
|
||||
Common::String builder = "FAST:";
|
||||
Common::String builder2 = "";
|
||||
Common::String grabText = "";
|
||||
|
||||
for (int i = 0; i < varData.fastArray->size; i++) {
|
||||
builder2 = builder + " ";
|
||||
grabText = varData.fastArray->fastVariables[i].getTextFromAnyVar(skipLoad);
|
||||
builder.clear();
|
||||
builder = builder2 + grabText;
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
case SVT_STACK: {
|
||||
Common::String builder = "ARRAY:";
|
||||
Common::String builder2 = "";
|
||||
Common::String grabText = "";
|
||||
|
||||
VariableStack *stacky = varData.theStack->first;
|
||||
|
||||
while (stacky) {
|
||||
builder2 = builder + " ";
|
||||
grabText = stacky->thisVar.getTextFromAnyVar(skipLoad);
|
||||
builder.clear();
|
||||
builder = builder2 + grabText;
|
||||
stacky = stacky->next;
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
case SVT_INT: {
|
||||
Common::String buff = Common::String::format("%i", varData.intValue);
|
||||
return buff;
|
||||
}
|
||||
|
||||
case SVT_FILE: {
|
||||
return g_sludge->_resMan->resourceNameFromNum(varData.intValue);
|
||||
}
|
||||
|
||||
case SVT_OBJTYPE: {
|
||||
ObjectType *thisType = g_sludge->_objMan->findObjectType(varData.intValue, skipLoad);
|
||||
if (thisType)
|
||||
return thisType->screenName;
|
||||
else
|
||||
return Common::String::format("<unloaded id %d>", varData.intValue);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return typeName[varType];
|
||||
}
|
||||
|
||||
bool Variable::getBoolean() const {
|
||||
switch (varType) {
|
||||
case SVT_NULL:
|
||||
return false;
|
||||
|
||||
case SVT_INT:
|
||||
return (bool)(varData.intValue != 0);
|
||||
|
||||
case SVT_STACK:
|
||||
return (bool)(varData.theStack->first != NULL);
|
||||
|
||||
case SVT_STRING:
|
||||
return (bool)(varData.theString[0] != 0);
|
||||
|
||||
case SVT_FASTARRAY:
|
||||
return (bool)(varData.fastArray->size != 0);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Variable::copyMain(const Variable &from) {
|
||||
varType = from.varType;
|
||||
switch (varType) {
|
||||
case SVT_INT:
|
||||
case SVT_FUNC:
|
||||
case SVT_BUILT:
|
||||
case SVT_FILE:
|
||||
case SVT_OBJTYPE:
|
||||
varData.intValue = from.varData.intValue;
|
||||
return true;
|
||||
|
||||
case SVT_FASTARRAY:
|
||||
varData.fastArray = from.varData.fastArray;
|
||||
varData.fastArray->timesUsed++;
|
||||
return true;
|
||||
|
||||
case SVT_STRING:
|
||||
varData.theString = createCString(from.varData.theString);
|
||||
return varData.theString ? true : false;
|
||||
|
||||
case SVT_STACK:
|
||||
varData.theStack = from.varData.theStack;
|
||||
varData.theStack->timesUsed++;
|
||||
return true;
|
||||
|
||||
case SVT_COSTUME:
|
||||
varData.costumeHandler = from.varData.costumeHandler;
|
||||
return true;
|
||||
|
||||
case SVT_ANIM:
|
||||
varData.animHandler = new PersonaAnimation(from.varData.animHandler);
|
||||
return true;
|
||||
|
||||
case SVT_NULL:
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fatal("Unknown value type");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Variable::copyFrom(const Variable &from) {
|
||||
unlinkVar();
|
||||
return copyMain(from);
|
||||
}
|
||||
|
||||
Variable *FastArrayHandler::fastArrayGetByIndex(uint theIndex) {
|
||||
if ((int)theIndex >= size)
|
||||
return NULL;
|
||||
return &fastVariables[theIndex];
|
||||
}
|
||||
|
||||
void FastArrayHandler::debugPrint() {
|
||||
debugN("[");
|
||||
for (int i = 0; i < size; i++)
|
||||
fastVariables[i].debugPrint();
|
||||
|
||||
debugN("]");
|
||||
}
|
||||
|
||||
bool Variable::makeFastArraySize(int size) {
|
||||
if (size < 0)
|
||||
return fatal("Can't create a fast array with a negative number of elements!");
|
||||
unlinkVar();
|
||||
varType = SVT_FASTARRAY;
|
||||
varData.fastArray = new FastArrayHandler;
|
||||
if (!checkNew(varData.fastArray))
|
||||
return false;
|
||||
varData.fastArray->fastVariables = new Variable[size];
|
||||
if (!checkNew(varData.fastArray->fastVariables))
|
||||
return false;
|
||||
varData.fastArray->size = size;
|
||||
varData.fastArray->timesUsed = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Variable::makeFastArrayFromStack(const StackHandler *stacky) {
|
||||
int size = stacky->getStackSize();
|
||||
if (!makeFastArraySize(size))
|
||||
return false;
|
||||
|
||||
// Now let's fill up the new array
|
||||
|
||||
VariableStack *allV = stacky->first;
|
||||
size = 0;
|
||||
while (allV) {
|
||||
varData.fastArray->fastVariables[size].copyMain(allV->thisVar);
|
||||
size++;
|
||||
allV = allV->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addVarToStack(const Variable &va, VariableStack *&thisStack) {
|
||||
VariableStack *newStack = new VariableStack;
|
||||
if (!checkNew(newStack))
|
||||
return false;
|
||||
|
||||
if (!newStack->thisVar.copyMain(va))
|
||||
return false;
|
||||
newStack->next = thisStack;
|
||||
thisStack = newStack;
|
||||
debugC(2, kSludgeDebugStackMachine, "Variable %s was added to stack", va.getTextFromAnyVar(true).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addVarToStackQuick(Variable &va, VariableStack *&thisStack) {
|
||||
VariableStack *newStack = new VariableStack;
|
||||
if (!checkNew(newStack))
|
||||
return false;
|
||||
|
||||
// if (! copyMain (va, newStack -> thisVar)) return false;
|
||||
|
||||
memcpy(&(newStack->thisVar), &va, sizeof(Variable));
|
||||
va.varType = SVT_NULL;
|
||||
|
||||
newStack->next = thisStack;
|
||||
thisStack = newStack;
|
||||
debugC(2, kSludgeDebugStackMachine, "Variable %s was added to stack quick", va.getTextFromAnyVar(true).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VariableStack::stackSetByIndex(uint theIndex, const Variable &va) {
|
||||
VariableStack *vS = this;
|
||||
while (theIndex--) {
|
||||
vS = vS->next;
|
||||
if (!vS)
|
||||
return fatal("Index past end of stack.");
|
||||
}
|
||||
return vS->thisVar.copyFrom(va);
|
||||
}
|
||||
|
||||
Variable *VariableStack::stackGetByIndex(uint theIndex) {
|
||||
VariableStack *vS = this;
|
||||
while (theIndex--) {
|
||||
vS = vS->next;
|
||||
if (!vS) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return &(vS->thisVar);
|
||||
}
|
||||
|
||||
int deleteVarFromStack(const Variable &va, VariableStack *&thisStack, bool allOfEm) {
|
||||
VariableStack **huntVar = &thisStack;
|
||||
VariableStack *killMe;
|
||||
int reply = 0;
|
||||
|
||||
while (*huntVar) {
|
||||
if (va.compareVars((*huntVar)->thisVar)) {
|
||||
killMe = *huntVar;
|
||||
*huntVar = killMe->next;
|
||||
killMe->thisVar.unlinkVar();
|
||||
delete killMe;
|
||||
if (!allOfEm)
|
||||
return 1;
|
||||
reply++;
|
||||
} else {
|
||||
huntVar = &((*huntVar)->next);
|
||||
}
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
// Would be a LOT better just to keep this up to date in the above function... ah well
|
||||
VariableStack *VariableStack::stackFindLast() {
|
||||
VariableStack *hunt = this;
|
||||
while (hunt->next)
|
||||
hunt = hunt->next;
|
||||
|
||||
return hunt;
|
||||
}
|
||||
|
||||
bool Variable::getValueType(int &toHere, VariableType vT) const {
|
||||
if (varType != vT) {
|
||||
Common::String e1 = "Can only perform specified operation on a value which is of type ";
|
||||
e1 += typeName[vT];
|
||||
Common::String e2 = "... value supplied was of type ";
|
||||
e2 += typeName[varType];
|
||||
fatal(e1, e2);
|
||||
|
||||
return false;
|
||||
}
|
||||
toHere = varData.intValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
void trimStack(VariableStack *&stack) {
|
||||
VariableStack *killMe = stack;
|
||||
stack = stack->next;
|
||||
|
||||
debugC(2, kSludgeDebugStackMachine, "Variable %s was removed from stack", killMe->thisVar.getTextFromAnyVar(true).c_str());
|
||||
|
||||
// When calling this, we've ALWAYS checked that stack != NULL
|
||||
killMe->thisVar.unlinkVar();
|
||||
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++) {
|
||||
search->thisVar.save(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;
|
||||
nS->thisVar.load(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 Variable::save(Common::WriteStream *stream) {
|
||||
stream->writeByte(varType);
|
||||
switch (varType) {
|
||||
case SVT_INT:
|
||||
case SVT_FUNC:
|
||||
case SVT_BUILT:
|
||||
case SVT_FILE:
|
||||
case SVT_OBJTYPE:
|
||||
stream->writeUint32LE(varData.intValue);
|
||||
return true;
|
||||
|
||||
case SVT_STRING:
|
||||
writeString(varData.theString, stream);
|
||||
return true;
|
||||
|
||||
case SVT_STACK:
|
||||
return saveStackRef(varData.theStack, stream);
|
||||
|
||||
case SVT_COSTUME:
|
||||
varData.costumeHandler->save(stream);
|
||||
return false;
|
||||
|
||||
case SVT_ANIM:
|
||||
varData.animHandler->save(stream);
|
||||
return false;
|
||||
|
||||
case SVT_NULL:
|
||||
return false;
|
||||
|
||||
default:
|
||||
fatal("Can't save variables of this type:", (varType < SVT_NUM_TYPES - 1) ? typeName[varType] : "bad ID");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Variable::load(Common::SeekableReadStream *stream) {
|
||||
varType = (VariableType)stream->readByte();
|
||||
switch (varType) {
|
||||
case SVT_INT:
|
||||
case SVT_FUNC:
|
||||
case SVT_BUILT:
|
||||
case SVT_FILE:
|
||||
case SVT_OBJTYPE:
|
||||
varData.intValue = stream->readUint32LE();
|
||||
return true;
|
||||
|
||||
case SVT_STRING:
|
||||
varData.theString = createCString(readString(stream));
|
||||
return true;
|
||||
|
||||
case SVT_STACK:
|
||||
varData.theStack = loadStackRef(stream);
|
||||
return true;
|
||||
|
||||
case SVT_COSTUME:
|
||||
varData.costumeHandler = new Persona;
|
||||
if (!checkNew(varData.costumeHandler))
|
||||
return false;
|
||||
varData.costumeHandler->load(stream);
|
||||
return true;
|
||||
|
||||
case SVT_ANIM:
|
||||
varData.animHandler = new PersonaAnimation;
|
||||
if (!checkNew(varData.animHandler))
|
||||
return false;
|
||||
varData.animHandler->load(stream);
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
Reference in New Issue
Block a user