diff options
Diffstat (limited to 'engines/sludge/variable.cpp')
-rw-r--r-- | engines/sludge/variable.cpp | 511 |
1 files changed, 351 insertions, 160 deletions
diff --git a/engines/sludge/variable.cpp b/engines/sludge/variable.cpp index 9cbb9f49f8..44381aa97f 100644 --- a/engines/sludge/variable.cpp +++ b/engines/sludge/variable.cpp @@ -38,34 +38,37 @@ const char *typeName[] = { "undefined", "number", "user function", "string", "built-in function", "file", "stack", "object type", "animation", "costume" }; -void unlinkVar(Variable &thisVar) { - switch (thisVar.varType) { +void Variable::unlinkVar() { + switch (varType) { case SVT_STRING: - delete []thisVar.varData.theString; - thisVar.varData.theString = NULL; + delete []varData.theString; + varData.theString = NULL; break; case SVT_STACK: - thisVar.varData.theStack->timesUsed--; - if (thisVar.varData.theStack->timesUsed <= 0) { - while (thisVar.varData.theStack->first) - trimStack(thisVar.varData.theStack->first); - delete thisVar.varData.theStack; - thisVar.varData.theStack = NULL; + 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: - thisVar.varData.fastArray->timesUsed--; - if (thisVar.varData.theStack->timesUsed <= 0) { - delete thisVar.varData.fastArray->fastVariables; - delete[] thisVar.varData.fastArray; - thisVar.varData.fastArray = NULL; + varData.fastArray->timesUsed--; + if (varData.theStack->timesUsed <= 0) { + delete varData.fastArray->fastVariables; + delete[] varData.fastArray; + varData.fastArray = NULL; } break; case SVT_ANIM: - deleteAnim(thisVar.varData.animHandler); + if (varData.animHandler) { + delete varData.animHandler; + varData.animHandler = nullptr; + } break; default: @@ -73,39 +76,39 @@ void unlinkVar(Variable &thisVar) { } } -void setVariable(Variable &thisVar, VariableType vT, int value) { - unlinkVar(thisVar); - thisVar.varType = vT; - thisVar.varData.intValue = value; +void Variable::setVariable(VariableType vT, int value) { + unlinkVar(); + varType = vT; + varData.intValue = value; } -void newAnimationVariable(Variable &thisVar, PersonaAnimation *i) { - unlinkVar(thisVar); - thisVar.varType = SVT_ANIM; - thisVar.varData.animHandler = i; +void Variable::makeAnimationVariable(PersonaAnimation *i) { + unlinkVar(); + varType = SVT_ANIM; + varData.animHandler = i; } -PersonaAnimation *getAnimationFromVar(Variable &thisVar) { - if (thisVar.varType == SVT_ANIM) - return copyAnim(thisVar.varData.animHandler); +PersonaAnimation *Variable::getAnimationFromVar() { + if (varType == SVT_ANIM) + return new PersonaAnimation(varData.animHandler); - if (thisVar.varType == SVT_INT && thisVar.varData.intValue == 0) - return makeNullAnim(); + if (varType == SVT_INT && varData.intValue == 0) + return new PersonaAnimation(); - fatal("Expecting an animation variable; found Variable of type", typeName[thisVar.varType]); + fatal("Expecting an animation variable; found Variable of type", typeName[varType]); return NULL; } -void newCostumeVariable(Variable &thisVar, Persona *i) { - unlinkVar(thisVar); - thisVar.varType = SVT_COSTUME; - thisVar.varData.costumeHandler = i; +void Variable::makeCostumeVariable(Persona *i) { + unlinkVar(); + varType = SVT_COSTUME; + varData.costumeHandler = i; } -Persona *getCostumeFromVar(Variable &thisVar) { +Persona *Variable::getCostumeFromVar() { Persona *p = NULL; - switch (thisVar.varType) { + switch (varType) { case SVT_ANIM: p = new Persona; if (!checkNew(p)) @@ -116,24 +119,24 @@ Persona *getCostumeFromVar(Variable &thisVar) { return NULL; for (int iii = 0; iii < 3; iii++) - p->animation[iii] = copyAnim(thisVar.varData.animHandler); + p->animation[iii] = new PersonaAnimation(varData.animHandler); break; case SVT_COSTUME: - return thisVar.varData.costumeHandler; + return varData.costumeHandler; break; default: - fatal("Expecting an animation variable; found Variable of type", typeName[thisVar.varType]); + fatal("Expecting an animation variable; found Variable of type", typeName[varType]); } return p; } -int stackSize(const StackHandler *me) { +int StackHandler::getStackSize() const { int r = 0; - VariableStack *a = me->first; + VariableStack *a = first; while (a) { r++; a = a->next; @@ -141,8 +144,7 @@ int stackSize(const StackHandler *me) { return r; } -bool getSavedGamesStack(StackHandler *sH, const Common::String &ext) { - +bool StackHandler::getSavedGamesStack(const Common::String &ext) { // Make pattern uint len = ext.size(); Common::String pattern = "*"; @@ -157,30 +159,30 @@ bool getSavedGamesStack(StackHandler *sH, const Common::String &ext) { Common::StringArray::iterator it; for (it = sa.begin(); it != sa.end(); ++it) { (*it).erase((*it).size() - len, len); - makeTextVar(newName, (*it)); - if (!addVarToStack(newName, sH->first)) + newName.makeTextVar((*it)); + if (!addVarToStack(newName, first)) return false; - if (sH->last == NULL) - sH->last = sH->first; + if (last == NULL) + last = first; } return true; } -bool copyStack(const Variable &from, Variable &to) { - to.varType = SVT_STACK; - to.varData.theStack = new StackHandler; - if (!checkNew(to.varData.theStack)) +bool Variable::copyStack(const Variable &from) { + varType = SVT_STACK; + varData.theStack = new StackHandler; + if (!checkNew(varData.theStack)) return false; - to.varData.theStack->first = NULL; - to.varData.theStack->last = NULL; - to.varData.theStack->timesUsed = 1; + varData.theStack->first = NULL; + varData.theStack->last = NULL; + varData.theStack->timesUsed = 1; VariableStack *a = from.varData.theStack->first; while (a) { - addVarToStack(a->thisVar, to.varData.theStack->first); - if (to.varData.theStack->last == NULL) { - to.varData.theStack->last = to.varData.theStack->first; + addVarToStack(a->thisVar, varData.theStack->first); + if (varData.theStack->last == NULL) { + varData.theStack->last = varData.theStack->first; } a = a->next; } @@ -188,89 +190,78 @@ bool copyStack(const Variable &from, Variable &to) { return true; } -void addVariablesInSecond(Variable &var1, Variable &var2) { - if (var1.varType == SVT_INT && var2.varType == SVT_INT) { - var2.varData.intValue += var1.varData.intValue; +void Variable::addVariablesInSecond(const Variable &other) { + if (other.varType == SVT_INT && varType == SVT_INT) { + varData.intValue += other.varData.intValue; } else { - Common::String string1 = getTextFromAnyVar(var1); - Common::String string2 = getTextFromAnyVar(var2); + Common::String string1 = other.getTextFromAnyVar(); + Common::String string2 = getTextFromAnyVar(); - unlinkVar(var2); - var2.varData.theString = createCString(string1 + string2); - var2.varType = SVT_STRING; + unlinkVar(); + varData.theString = createCString(string1 + string2); + varType = SVT_STRING; } } -int compareVars(const Variable &var1, const Variable &var2) { +int Variable::compareVars(const Variable &other) const { int re = 0; - if (var1.varType == var2.varType) { - switch (var1.varType) { + if (other.varType == varType) { + switch (other.varType) { case SVT_NULL: re = 1; break; case SVT_COSTUME: - re = (var1.varData.costumeHandler == var2.varData.costumeHandler); + re = (other.varData.costumeHandler == varData.costumeHandler); break; case SVT_ANIM: - re = (var1.varData.animHandler == var2.varData.animHandler); + re = (other.varData.animHandler == varData.animHandler); break; case SVT_STRING: - re = (strcmp(var1.varData.theString, var2.varData.theString) == 0); + re = (strcmp(other.varData.theString, varData.theString) == 0); break; case SVT_STACK: - re = (var1.varData.theStack == var2.varData.theStack); + re = (other.varData.theStack == varData.theStack); break; default: - re = (var1.varData.intValue == var2.varData.intValue); + re = (other.varData.intValue == varData.intValue); } } return re; } -void compareVariablesInSecond(const Variable &var1, Variable &var2) { - setVariable(var2, SVT_INT, compareVars(var1, var2)); -} - -char *createCString(const Common::String &s) { - uint n = s.size() + 1; - char *res = new char[n]; - if (!checkNew(res)) { - fatal("createCString : Unable to copy String"); - return NULL; - } - memcpy(res, s.c_str(), n); - return res; +void Variable::compareVariablesInSecond(const Variable &other) { + setVariable(SVT_INT, compareVars(other)); } -void makeTextVar(Variable &thisVar, const Common::String &txt) { - unlinkVar(thisVar); - thisVar.varType = SVT_STRING; - thisVar.varData.theString = createCString(txt); +void Variable::makeTextVar(const Common::String &txt) { + unlinkVar(); + varType = SVT_STRING; + varData.theString = createCString(txt); } -bool loadStringToVar(Variable &thisVar, int value) { - makeTextVar(thisVar, g_sludge->_resMan->getNumberedString(value)); - return (bool)(thisVar.varData.theString != NULL); +bool Variable::loadStringToVar(int value) { + makeTextVar(g_sludge->_resMan->getNumberedString(value)); + return (bool)(varData.theString != NULL); } -Common::String getTextFromAnyVar(const Variable &from) { - switch (from.varType) { +Common::String Variable::getTextFromAnyVar() const { + switch (varType) { case SVT_STRING: - return from.varData.theString; + return varData.theString; case SVT_FASTARRAY: { Common::String builder = "FAST:"; Common::String builder2 = ""; Common::String grabText = ""; - for (int i = 0; i < from.varData.fastArray->size; i++) { + for (int i = 0; i < varData.fastArray->size; i++) { builder2 = builder + " "; - grabText = getTextFromAnyVar(from.varData.fastArray->fastVariables[i]); + grabText = varData.fastArray->fastVariables[i].getTextFromAnyVar(); builder.clear(); builder = builder2 + grabText; } @@ -282,11 +273,11 @@ Common::String getTextFromAnyVar(const Variable &from) { Common::String builder2 = ""; Common::String grabText = ""; - VariableStack *stacky = from.varData.theStack->first; + VariableStack *stacky = varData.theStack->first; while (stacky) { builder2 = builder + " "; - grabText = getTextFromAnyVar(stacky->thisVar); + grabText = stacky->thisVar.getTextFromAnyVar(); builder.clear(); builder = builder2 + grabText; stacky = stacky->next; @@ -295,16 +286,16 @@ Common::String getTextFromAnyVar(const Variable &from) { } case SVT_INT: { - Common::String buff = Common::String::format("%i", from.varData.intValue); + Common::String buff = Common::String::format("%i", varData.intValue); return buff; } case SVT_FILE: { - return resourceNameFromNum(from.varData.intValue); + return g_sludge->_resMan->resourceNameFromNum(varData.intValue); } case SVT_OBJTYPE: { - ObjectType *thisType = g_sludge->_objMan->findObjectType(from.varData.intValue); + ObjectType *thisType = g_sludge->_objMan->findObjectType(varData.intValue); if (thisType) return thisType->screenName; break; @@ -314,25 +305,25 @@ Common::String getTextFromAnyVar(const Variable &from) { break; } - return typeName[from.varType]; + return typeName[varType]; } -bool getBoolean(const Variable &from) { - switch (from.varType) { +bool Variable::getBoolean() const { + switch (varType) { case SVT_NULL: return false; case SVT_INT: - return (bool)(from.varData.intValue != 0); + return (bool)(varData.intValue != 0); case SVT_STACK: - return (bool)(from.varData.theStack->first != NULL); + return (bool)(varData.theStack->first != NULL); case SVT_STRING: - return (bool)(from.varData.theString[0] != 0); + return (bool)(varData.theString[0] != 0); case SVT_FASTARRAY: - return (bool)(from.varData.fastArray->size != 0); + return (bool)(varData.fastArray->size != 0); default: break; @@ -340,37 +331,37 @@ bool getBoolean(const Variable &from) { return true; } -bool copyMain(const Variable &from, Variable &to) { - to.varType = from.varType; - switch (to.varType) { +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: - to.varData.intValue = from.varData.intValue; + varData.intValue = from.varData.intValue; return true; case SVT_FASTARRAY: - to.varData.fastArray = from.varData.fastArray; - to.varData.fastArray->timesUsed++; + varData.fastArray = from.varData.fastArray; + varData.fastArray->timesUsed++; return true; case SVT_STRING: - to.varData.theString = createCString(from.varData.theString); - return to.varData.theString ? true : false; + varData.theString = createCString(from.varData.theString); + return varData.theString ? true : false; case SVT_STACK: - to.varData.theStack = from.varData.theStack; - to.varData.theStack->timesUsed++; + varData.theStack = from.varData.theStack; + varData.theStack->timesUsed++; return true; case SVT_COSTUME: - to.varData.costumeHandler = from.varData.costumeHandler; + varData.costumeHandler = from.varData.costumeHandler; return true; case SVT_ANIM: - to.varData.animHandler = copyAnim(from.varData.animHandler); + varData.animHandler = new PersonaAnimation(from.varData.animHandler); return true; case SVT_NULL: @@ -383,39 +374,36 @@ bool copyMain(const Variable &from, Variable &to) { return false; } -bool copyVariable(const Variable &from, Variable &to) { - unlinkVar(to); - return copyMain(from, to); +bool Variable::copyFrom(const Variable &from) { + unlinkVar(); + return copyMain(from); } -Variable *fastArrayGetByIndex(FastArrayHandler *vS, uint theIndex) { - if ((int)theIndex >= vS->size) +Variable *FastArrayHandler::fastArrayGetByIndex(uint theIndex) { + if ((int)theIndex >= size) return NULL; - return &vS->fastVariables[theIndex]; + return &fastVariables[theIndex]; } -bool makeFastArraySize(Variable &to, int size) { +bool Variable::makeFastArraySize(int size) { if (size < 0) return fatal("Can't create a fast array with a negative number of elements!"); - unlinkVar(to); - to.varType = SVT_FASTARRAY; - to.varData.fastArray = new FastArrayHandler; - if (!checkNew(to.varData.fastArray)) + unlinkVar(); + varType = SVT_FASTARRAY; + varData.fastArray = new FastArrayHandler; + if (!checkNew(varData.fastArray)) return false; - to.varData.fastArray->fastVariables = new Variable[size]; - if (!checkNew(to.varData.fastArray->fastVariables)) + varData.fastArray->fastVariables = new Variable[size]; + if (!checkNew(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; + varData.fastArray->size = size; + varData.fastArray->timesUsed = 1; return true; } -bool makeFastArrayFromStack(Variable &to, const StackHandler *stacky) { - int size = stackSize(stacky); - if (!makeFastArraySize(to, size)) +bool Variable::makeFastArrayFromStack(const StackHandler *stacky) { + int size = stacky->getStackSize(); + if (!makeFastArraySize(size)) return false; // Now let's fill up the new array @@ -423,7 +411,7 @@ bool makeFastArrayFromStack(Variable &to, const StackHandler *stacky) { VariableStack *allV = stacky->first; size = 0; while (allV) { - copyMain(allV->thisVar, to.varData.fastArray->fastVariables[size]); + varData.fastArray->fastVariables[size].copyMain(allV->thisVar); size++; allV = allV->next; } @@ -435,7 +423,7 @@ bool addVarToStack(const Variable &va, VariableStack *&thisStack) { if (!checkNew(newStack)) return false; - if (!copyMain(va, newStack->thisVar)) + if (!newStack->thisVar.copyMain(va)) return false; newStack->next = thisStack; thisStack = newStack; @@ -459,16 +447,18 @@ bool addVarToStackQuick(Variable &va, VariableStack *&thisStack) { return true; } -bool stackSetByIndex(VariableStack *vS, uint theIndex, const Variable &va) { +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 copyVariable(va, vS->thisVar); + return vS->thisVar.copyFrom(va); } -Variable *stackGetByIndex(VariableStack *vS, uint theIndex) { +Variable *VariableStack::stackGetByIndex(uint theIndex) { + VariableStack *vS = this; while (theIndex--) { vS = vS->next; if (!vS) { @@ -484,10 +474,10 @@ int deleteVarFromStack(const Variable &va, VariableStack *&thisStack, bool allOf int reply = 0; while (*huntVar) { - if (compareVars((*huntVar)->thisVar, va)) { + if (va.compareVars((*huntVar)->thisVar)) { killMe = *huntVar; *huntVar = killMe->next; - unlinkVar(killMe->thisVar); + killMe->thisVar.unlinkVar(); delete killMe; if (!allOfEm) return 1; @@ -501,28 +491,25 @@ int deleteVarFromStack(const Variable &va, VariableStack *&thisStack, bool allOf } // Would be a LOT better just to keep this up to date in the above function... ah well -VariableStack *stackFindLast(VariableStack *hunt) { - if (hunt == NULL) - return NULL; - +VariableStack *VariableStack::stackFindLast() { + VariableStack *hunt = this; while (hunt->next) hunt = hunt->next; return hunt; } -bool getValueType(int &toHere, VariableType vT, const Variable &v) { - //if (! v) return false; - if (v.varType != vT) { +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[v.varType]; + e2 += typeName[varType]; fatal(e1, e2); return false; } - toHere = v.varData.intValue; + toHere = varData.intValue; return true; } @@ -533,8 +520,212 @@ void trimStack(VariableStack *&stack) { //debugC(2, kSludgeDebugStackMachine, "Variable %s was removed from stack", getTextFromAnyVar(killMe->thisVar)); // When calling this, we've ALWAYS checked that stack != NULL - unlinkVar(killMe->thisVar); + 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) ? 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 |