bool getRGBIntoStack (unsigned int x, unsigned int y, stackHandler * sH) { if (x >= sceneWidth || y >= sceneHeight) { return fatal ("Co-ordinates are outside current scene!"); } variable newValue; newValue.varType = SVT_NULL; saveTexture (backdropTextureName, backdropTexture); GLubyte * target; if (! NPOT_textures) { target = backdropTexture + 4*getNextPOT(sceneWidth)*y + x*4; } else { target = backdropTexture + 4*sceneWidth*y + x*4; } setVariable (newValue, SVT_INT, target[2]); if (! addVarToStackQuick (newValue, sH -> first)) return false; sH -> last = sH -> first; setVariable (newValue, SVT_INT, target[1]); if (! addVarToStackQuick (newValue, sH -> first)) return false; setVariable (newValue, SVT_INT, target[0]); if (! addVarToStackQuick (newValue, sH -> first)) return false; return true; }
bool getSoundCacheStack (stackHandler * sH) { variable newFileHandle; newFileHandle.varType = SVT_NULL; for (int a = 0; a < MAX_SAMPLES; a ++) { if (soundCache[a].fileLoaded != -1) { setVariable (newFileHandle, SVT_FILE, soundCache[a].fileLoaded); if (! addVarToStackQuick (newFileHandle, sH -> first)) return false; if (sH -> last == NULL) sH -> last = sH -> first; } } return true; }
bool fileToStack(const Common::String &filename, StackHandler *sH) { Variable stringVar; stringVar.varType = SVT_NULL; Common::String checker = saveEncoding ? "[Custom data (encoded)]\r\n" : "[Custom data (ASCII)]\n"; Common::File fd; if (!fd.open(filename)) { #if 0 char currentDir[1000]; if (!getcwd(currentDir, 998)) { debugOut("Can't get current directory.\n"); } if (chdir(gamePath)) { debugOut("Error: Failed changing to directory %s\n", gamePath); } if (chdir(currentDir)) { debugOut("Error: Failed changing to directory %s\n", currentDir); } if (!fd.open(filename)) { return fatal("No such file", filename); } #endif return fatal("No such file", filename); //TODO: false value } encode1 = (byte)saveEncoding & 255; encode2 = (byte)(saveEncoding >> 8); for (uint i = 0; i < checker.size(); ++i) { if (fd.readByte() != checker[i]) { fd.close(); return fatal(LOAD_ERROR "This isn't a SLUDGE custom data file:", filename); } } if (saveEncoding) { checker = readStringEncoded(&fd); if (checker == UTF8_CHECKER) { fd.close(); return fatal( LOAD_ERROR "The current file encoding setting does not match the encoding setting used when this file was created:", filename); } } for (;;) { if (saveEncoding) { char i = fd.readByte() ^ encode1; if (fd.eos()) break; switch (i) { case 0: { Common::String g = readStringEncoded(&fd); makeTextVar(stringVar, g); } break; case 1: setVariable(stringVar, SVT_INT, fd.readUint32LE()); break; case 2: setVariable(stringVar, SVT_INT, fd.readByte()); break; default: fatal(LOAD_ERROR "Corrupt custom data file:", filename); fd.close(); return false; } } else { char *line = readTextPlain(&fd); if (!line) break; makeTextVar(stringVar, line); } if (sH->first == NULL) { // Adds to the TOP of the array... oops! if (!addVarToStackQuick(stringVar, sH->first)) return false; sH->last = sH->first; } else { // Adds to the END of the array... much better if (!addVarToStackQuick(stringVar, sH->last->next)) return false; sH->last = sH->last->next; } } fd.close(); return true; }
bool continueFunction (loadedFunction * fun) { bool keepLooping = true; bool advanceNow; unsigned int param; sludgeCommand com; if (fun -> cancelMe) { abortFunction (fun); return true; } // if (numBIFNames) newDebug ("*** Function:", allUserFunc[fun -> originalNumber]); //debugOut ("SLUDGER: continueFunction\n"); while (keepLooping) { advanceNow = true; param = fun -> compiledLines[fun -> runThisLine].param; com = fun -> compiledLines[fun -> runThisLine].theCommand; // fprintf (stderr, "com: %d param: %d (%s)\n", com, param, // (com < numSludgeCommands) ? sludgeText[com] : ERROR_UNKNOWN_MCODE); fflush(stderr); if (numBIFNames) { setFatalInfo ( (fun -> originalNumber < numUserFunc) ? allUserFunc[fun -> originalNumber] : "Unknown user function", (com < numSludgeCommands) ? sludgeText[com] : ERROR_UNKNOWN_MCODE); // newDebug ( // (com < numSludgeCommands) ? sludgeText[com] : "Unknown SLUDGE machine code", // param); } //debugOut ("SLUDGER: continueFunction - in da loop: %s\n", sludgeText[com]); 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: { 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); // No break! 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: if (dialogValue != 1) fatal (ERROR_HACKER); 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 ii; switch (com) { case SLU_INCREMENT_INDEX: if (! getValueType (ii, SVT_INT, * grab)) return false; setVariable (fun -> reg, SVT_INT, ii); grab -> varData.intValue = ii + 1; break; case SLU_DECREMENT_INDEX: if (! getValueType (ii, SVT_INT, * grab)) return false; setVariable (fun -> reg, SVT_INT, ii); grab -> varData.intValue = ii - 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; }