mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-14 13:58:01 +00:00
2550 lines
63 KiB
C++
2550 lines
63 KiB
C++
/* 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.
|
|
*
|
|
*/
|
|
|
|
#if 0
|
|
#include <SDL/SDL.h>
|
|
#endif
|
|
|
|
#include "debug.h"
|
|
#include "allfiles.h"
|
|
#include "sludger.h"
|
|
#include "builtin.h"
|
|
#include "stringy.h"
|
|
#include "newfatal.h"
|
|
#include "cursors.h"
|
|
#include "statusba.h"
|
|
#include "loadsave.h"
|
|
#include "backdrop.h"
|
|
#include "bg_effects.h"
|
|
#include "sprites.h"
|
|
#include "fonttext.h"
|
|
#include "sprbanks.h"
|
|
#include "people.h"
|
|
#include "sound.h"
|
|
#include "objtypes.h"
|
|
#include "floor.h"
|
|
#include "zbuffer.h"
|
|
#include "talk.h"
|
|
#include "region.h"
|
|
#include "language.h"
|
|
#include "moreio.h"
|
|
#include "movie.h"
|
|
#include "savedata.h"
|
|
#include "freeze.h"
|
|
#include "colours.h"
|
|
#include "language.h"
|
|
#include "thumbnail.h"
|
|
#include "graphics.h"
|
|
#include "CommonCode/utf8.h"
|
|
|
|
namespace Sludge {
|
|
|
|
extern char *gamePath;
|
|
|
|
int speechMode = 0;
|
|
int cameraX, cameraY;
|
|
float cameraZoom = 1.0;
|
|
spritePalette pastePalette;
|
|
|
|
char *launchMe = NULL;
|
|
variable *launchResult = NULL;
|
|
|
|
extern int lastFramesPerSecond, thumbWidth, thumbHeight;
|
|
extern bool allowAnyFilename;
|
|
extern bool captureAllKeys;
|
|
extern short fontSpace;
|
|
extern eventHandlers *currentEvents;
|
|
extern variableStack *noStack;
|
|
extern statusStuff *nowStatus;
|
|
extern screenRegion *overRegion;
|
|
extern HWND hMainWindow;
|
|
extern unsigned int sceneWidth, sceneHeight;
|
|
extern int numBIFNames, numUserFunc;
|
|
extern char builtInFunctionNames[][25];
|
|
|
|
extern char * *allUserFunc;
|
|
extern char * *allBIFNames;
|
|
extern inputType input;
|
|
extern char *loadNow;
|
|
|
|
#if 0
|
|
extern GLuint backdropTextureName;
|
|
#endif
|
|
|
|
extern float speechSpeed;
|
|
extern unsigned char brightnessLevel;
|
|
extern unsigned char fadeMode;
|
|
extern unsigned short saveEncoding;
|
|
extern frozenStuffStruct *frozenStuff;
|
|
extern unsigned int currentBlankColour;
|
|
extern unsigned int languageID;
|
|
extern unsigned char currentBurnR, currentBurnG, currentBurnB;
|
|
|
|
int paramNum[] = { -1, 0, 1, 1, -1, -1, 1, 3, 4, 1, 0, 0, 8, -1, // SAY->MOVEMOUSE
|
|
-1, 0, 0, -1, -1, 1, 1, 1, 1, 4, 1, 1, 2, 1,// FOCUS->REMOVEREGION
|
|
2, 2, 0, 0, 2, // ANIMATE->SETSCALE
|
|
-1, 2, 1, 0, 0, 0, 1, 0, 3, // new/push/pop stack, status stuff
|
|
2, 0, 0, 3, 1, 0, 2, // delFromStack->completeTimers
|
|
-1, -1, -1, 2, 2, 0, 3, 1, // anim, costume, pO, setC, wait, sS, substring, stringLength
|
|
0, 1, 1, 0, 2, // dark, save, load, quit, rename
|
|
1, 3, 3, 1, 2, 1, 1, 3, 1, 0, 0, 2, 1, // stackSize, pasteString, startMusic, defvol, vol, stopmus, stopsound, setfont, alignStatus, show x 2, pos'Status, setFloor
|
|
-1, -1, 1, 1, 2, 1, 1, 1, -1, -1, -1, 1, 1, // force, jump, peekstart, peekend, enqueue, getSavedGames, inFont, loopSound, removeChar, stopCharacter
|
|
1, 0, 3, 3, 1, 2, 1, 2, 2, // launch, howFrozen, pastecol, litcol, checksaved, float, cancelfunc, walkspeed, delAll
|
|
2, 3, 1, 2, 2, 0, 0, 1, 2, 3, 1, -1, // extras, mixoverlay, pastebloke, getMScreenX/Y, setSound(Default/-)Volume, looppoints, speechMode, setLightMap
|
|
-1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, // think, getCharacterDirection, is(char/region/moving), deleteGame, renameGame, hardScroll, stringWidth, speechSpeed, normalCharacter
|
|
2, 1, 2, 1, 3, 1, 1, 2, 1, // fetchEvent, setBrightness, spin, fontSpace, burnString, captureAll, cacheSound, setSpinSpeed, transitionMode
|
|
1, 0, 0, 1, 0, 2, 1, 1, 1, // movie(Start/Abort/Playing), updateDisplay, getSoundCache, savedata, loaddata, savemode, freeSound
|
|
3, 0, 3, 3, 2, 1, 1, // setParallax, clearParallax, setBlankColour, setBurnColour, getPixelColour, makeFastArray, getCharacterScale
|
|
0, 2, 0, // getLanguage, launchWith, getFramesPerSecond
|
|
3, 2, 2, 0, 0, 1, // readThumbnail, setThumbnailSize, hasFlag, snapshot, clearSnapshot, anyFilename
|
|
2, 1, // regGet, fatal
|
|
4, 3, -1, 0, // chr AA, max AA, setBackgroundEffect, doBackgroundEffect
|
|
2, // setCharacterAngleOffset
|
|
2, 5, // setCharacterTransparency, setCharacterColourise
|
|
1, // zoomCamera
|
|
1, 0, 0 // playMovie, stopMovie, pauseMovie
|
|
};
|
|
|
|
bool failSecurityCheck(char *fn) {
|
|
if (fn == NULL) return true;
|
|
|
|
int a = 0;
|
|
|
|
while (fn[a]) {
|
|
switch (fn[a]) {
|
|
case ':':
|
|
case '\\':
|
|
case '/':
|
|
case '*':
|
|
case '?':
|
|
case '"':
|
|
case '<':
|
|
case '>':
|
|
case '|':
|
|
fatal("Filenames may not contain the following characters: \n\n\\ / : \" < > | ? *\n\nConsequently, the following filename is not allowed:", fn);
|
|
return true;
|
|
}
|
|
a ++;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
loadedFunction *saverFunc;
|
|
|
|
typedef builtReturn(* builtInSludgeFunc)(int numParams, loadedFunction *fun);
|
|
struct builtInFunctionData {
|
|
builtInSludgeFunc func;
|
|
};
|
|
|
|
#define builtIn(a) static builtReturn builtIn_ ## a (int numParams, loadedFunction * fun)
|
|
#define UNUSEDALL (void) (0 && sizeof(numParams) && sizeof (fun));
|
|
|
|
static builtReturn sayCore(int numParams, loadedFunction *fun, bool sayIt) {
|
|
int fileNum = -1;
|
|
char *newText;
|
|
int objT, p;
|
|
killSpeechTimers();
|
|
|
|
switch (numParams) {
|
|
case 3:
|
|
if (!getValueType(fileNum, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
// No break; here
|
|
|
|
case 2:
|
|
newText = getTextFromAnyVar(fun->stack->thisVar);
|
|
if (!newText) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(objT, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
p = wrapSpeech(newText, objT, fileNum, sayIt);
|
|
fun->timeLeft = p;
|
|
//debugOut ("BUILTIN: sayCore: %s (%i)\n", newText, p);
|
|
fun->isSpeech = true;
|
|
delete newText;
|
|
newText = NULL;
|
|
return BR_KEEP_AND_PAUSE;
|
|
}
|
|
|
|
fatal("Function should have either 2 or 3 parameters");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark Built in functions
|
|
|
|
builtIn(say) {
|
|
UNUSEDALL
|
|
return sayCore(numParams, fun, true);
|
|
}
|
|
|
|
builtIn(think) {
|
|
UNUSEDALL
|
|
return sayCore(numParams, fun, false);
|
|
}
|
|
|
|
builtIn(freeze) {
|
|
UNUSEDALL
|
|
freeze();
|
|
freezeSubs();
|
|
fun->freezerLevel = 0;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(unfreeze) {
|
|
UNUSEDALL
|
|
unfreeze();
|
|
unfreezeSubs();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(howFrozen) {
|
|
UNUSEDALL
|
|
setVariable(fun->reg, SVT_INT, howFrozen());
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setCursor) {
|
|
UNUSEDALL
|
|
personaAnimation *aa = getAnimationFromVar(fun->stack->thisVar);
|
|
pickAnimCursor(aa);
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getMouseX) {
|
|
UNUSEDALL
|
|
setVariable(fun->reg, SVT_INT, input.mouseX + cameraX);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getMouseY) {
|
|
UNUSEDALL
|
|
setVariable(fun->reg, SVT_INT, input.mouseY + cameraY);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getMouseScreenX) {
|
|
UNUSEDALL
|
|
setVariable(fun->reg, SVT_INT, input.mouseX * cameraZoom);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getMouseScreenY) {
|
|
UNUSEDALL
|
|
setVariable(fun->reg, SVT_INT, input.mouseY * cameraZoom);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getStatusText) {
|
|
UNUSEDALL
|
|
makeTextVar(fun->reg, statusBarText());
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getMatchingFiles) {
|
|
UNUSEDALL
|
|
char *newText = getTextFromAnyVar(fun->stack->thisVar);
|
|
if (!newText) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
unlinkVar(fun->reg);
|
|
|
|
// Return value
|
|
fun->reg.varType = SVT_STACK;
|
|
fun->reg.varData.theStack = new stackHandler;
|
|
if (!checkNew(fun->reg.varData.theStack)) return BR_ERROR;
|
|
fun->reg.varData.theStack->first = NULL;
|
|
fun->reg.varData.theStack->last = NULL;
|
|
fun->reg.varData.theStack->timesUsed = 1;
|
|
if (!getSavedGamesStack(fun->reg.varData.theStack, newText)) return BR_ERROR;
|
|
delete newText;
|
|
newText = NULL;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(saveGame) {
|
|
UNUSEDALL
|
|
|
|
if (frozenStuff) {
|
|
fatal("Can't save game state while the engine is frozen");
|
|
}
|
|
|
|
loadNow = getTextFromAnyVar(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
|
|
char *aaaaa = encodeFilename(loadNow);
|
|
delete[] loadNow;
|
|
if (failSecurityCheck(aaaaa)) return BR_ERROR; // Won't fail if encoded, how cool is that? OK, not very.
|
|
|
|
loadNow = joinStrings(":", aaaaa);
|
|
delete[] aaaaa;
|
|
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
saverFunc = fun;
|
|
return BR_KEEP_AND_PAUSE;
|
|
}
|
|
|
|
builtIn(fileExists) {
|
|
UNUSEDALL
|
|
loadNow = getTextFromAnyVar(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
char *aaaaa = encodeFilename(loadNow);
|
|
delete loadNow;
|
|
if (failSecurityCheck(aaaaa)) return BR_ERROR;
|
|
#if 0
|
|
FILE *fp = fopen(aaaaa, "rb");
|
|
if (!fp) {
|
|
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);
|
|
}
|
|
fp = fopen(aaaaa, "rb");
|
|
if (chdir(currentDir)) {
|
|
debugOut("Error: Failed changing to directory %s\n", currentDir);
|
|
}
|
|
}
|
|
#endif
|
|
// Return value
|
|
setVariable(fun->reg, SVT_INT, 0/*(fp != NULL)*/);//TODO:false value
|
|
#if 0
|
|
if (fp) fclose(fp);
|
|
delete[] aaaaa;
|
|
loadNow = NULL;
|
|
#endif
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(loadGame) {
|
|
UNUSEDALL
|
|
char *aaaaa = getTextFromAnyVar(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
loadNow = encodeFilename(aaaaa);
|
|
delete aaaaa;
|
|
|
|
if (frozenStuff) {
|
|
fatal("Can't load a saved game while the engine is frozen");
|
|
}
|
|
if (failSecurityCheck(loadNow)) return BR_ERROR;
|
|
Common::File fd;
|
|
if (fd.open(loadNow)) {
|
|
fd.close();
|
|
return BR_KEEP_AND_PAUSE;
|
|
}
|
|
delete loadNow;
|
|
loadNow = NULL;
|
|
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
//--------------------------------------
|
|
#pragma mark -
|
|
#pragma mark Background image - Painting
|
|
|
|
builtIn(blankScreen) {
|
|
UNUSEDALL
|
|
blankScreen(0, 0, sceneWidth, sceneHeight);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(blankArea) {
|
|
UNUSEDALL
|
|
int x1, y1, x2, y2;
|
|
if (!getValueType(y2, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x2, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(y1, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x1, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
blankScreen(x1, y1, x2, y2);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(darkBackground) {
|
|
UNUSEDALL
|
|
darkScreen();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(addOverlay) {
|
|
UNUSEDALL
|
|
int fileNumber, xPos, yPos;
|
|
if (!getValueType(yPos, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(xPos, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
loadBackDrop(fileNumber, xPos, yPos);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(mixOverlay) {
|
|
UNUSEDALL
|
|
int fileNumber, xPos, yPos;
|
|
if (!getValueType(yPos, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(xPos, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
mixBackDrop(fileNumber, xPos, yPos);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(pasteImage) {
|
|
UNUSEDALL
|
|
int x, y;
|
|
if (!getValueType(y, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
personaAnimation *pp = getAnimationFromVar(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
if (pp == NULL) return BR_CONTINUE;
|
|
|
|
pasteCursor(x, y, pp);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark Background Image - Scrolling
|
|
|
|
builtIn(setSceneDimensions) {
|
|
UNUSEDALL
|
|
int x, y;
|
|
if (!getValueType(y, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (killResizeBackdrop(x, y)) {
|
|
blankScreen(0, 0, x, y);
|
|
return BR_CONTINUE;
|
|
}
|
|
fatal("Out of memory creating new backdrop.");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(aimCamera) {
|
|
UNUSEDALL
|
|
if (!getValueType(cameraY, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(cameraX, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
cameraX -= (float)(winWidth >> 1) / cameraZoom;
|
|
cameraY -= (float)(winHeight >> 1) / cameraZoom;
|
|
|
|
if (cameraX < 0) cameraX = 0;
|
|
else if (cameraX > sceneWidth - (float)winWidth / cameraZoom) cameraX = sceneWidth - (float)winWidth / cameraZoom;
|
|
if (cameraY < 0) cameraY = 0;
|
|
else if (cameraY > sceneHeight - (float)winHeight / cameraZoom) cameraY = sceneHeight - (float)winHeight / cameraZoom;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
|
|
builtIn(zoomCamera) {
|
|
UNUSEDALL
|
|
int z;
|
|
if (!getValueType(z, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
input.mouseX = input.mouseX * cameraZoom;
|
|
input.mouseY = input.mouseY * cameraZoom;
|
|
|
|
|
|
cameraZoom = (float) z * 0.01;
|
|
if ((float) winWidth / cameraZoom > sceneWidth) cameraZoom = (float)winWidth / sceneWidth;
|
|
if ((float) winHeight / cameraZoom > sceneHeight) cameraZoom = (float)winHeight / sceneHeight;
|
|
setPixelCoords(false);
|
|
|
|
input.mouseX = input.mouseX / cameraZoom;
|
|
input.mouseY = input.mouseY / cameraZoom;
|
|
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark Variables
|
|
|
|
|
|
builtIn(pickOne) {
|
|
UNUSEDALL
|
|
if (!numParams) {
|
|
fatal("Built-in function should have at least 1 parameter");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
int i;
|
|
#if 0
|
|
i = rand() % numParams;
|
|
#endif
|
|
|
|
// Return value
|
|
while (numParams --) {
|
|
if (i == numParams) copyVariable(fun->stack->thisVar, fun->reg);
|
|
trimStack(fun->stack);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(substring) {
|
|
UNUSEDALL
|
|
char *wholeString;
|
|
char *newString;
|
|
int start, length;
|
|
|
|
//debugOut ("BUILTIN: substring\n");
|
|
|
|
if (!getValueType(length, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(start, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
wholeString = getTextFromAnyVar(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
|
|
if (u8_strlen(wholeString) < start + length) {
|
|
length = u8_strlen(wholeString) - start;
|
|
if (u8_strlen(wholeString) < start) {
|
|
start = 0;
|
|
}
|
|
}
|
|
if (length < 0) {
|
|
length = 0;
|
|
}
|
|
|
|
int startoffset = u8_offset(wholeString, start);
|
|
int endoffset = u8_offset(wholeString, start + length);
|
|
|
|
newString = new char[endoffset - startoffset + 1];
|
|
if (!checkNew(newString)) {
|
|
return BR_ERROR;
|
|
}
|
|
|
|
memcpy(newString, wholeString + startoffset, endoffset - startoffset);
|
|
newString[endoffset - startoffset] = 0;
|
|
|
|
makeTextVar(fun->reg, newString);
|
|
delete newString;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(stringLength) {
|
|
UNUSEDALL
|
|
char *newText = getTextFromAnyVar(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, stringLength(newText));
|
|
delete[] newText;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(newStack) {
|
|
UNUSEDALL
|
|
unlinkVar(fun->reg);
|
|
|
|
// Return value
|
|
fun->reg.varType = SVT_STACK;
|
|
fun->reg.varData.theStack = new stackHandler;
|
|
if (!checkNew(fun->reg.varData.theStack)) return BR_ERROR;
|
|
fun->reg.varData.theStack->first = NULL;
|
|
fun->reg.varData.theStack->last = NULL;
|
|
fun->reg.varData.theStack->timesUsed = 1;
|
|
while (numParams --) {
|
|
if (!addVarToStack(fun->stack->thisVar, fun->reg.varData.theStack->first)) return BR_ERROR;
|
|
if (fun->reg.varData.theStack->last == NULL) {
|
|
fun->reg.varData.theStack->last = fun->reg.varData.theStack->first;
|
|
}
|
|
trimStack(fun->stack);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
// wait is exactly the same function, but limited to 2 parameters
|
|
#define builtIn_wait builtIn_newStack
|
|
|
|
builtIn(stackSize) {
|
|
UNUSEDALL
|
|
switch (fun->stack->thisVar.varType) {
|
|
case SVT_STACK:
|
|
// Return value
|
|
setVariable(fun->reg, SVT_INT, stackSize(fun->stack->thisVar.varData.theStack));
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
|
|
case SVT_FASTARRAY:
|
|
// Return value
|
|
setVariable(fun->reg, SVT_INT, fun->stack->thisVar.varData.fastArray->size);
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
fatal("Parameter isn't a stack or a fast array.");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(copyStack) {
|
|
UNUSEDALL
|
|
if (fun->stack->thisVar.varType != SVT_STACK) {
|
|
fatal("Parameter isn't a stack.");
|
|
return BR_ERROR;
|
|
}
|
|
// Return value
|
|
if (!copyStack(fun->stack->thisVar, fun->reg)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(pushToStack) {
|
|
UNUSEDALL
|
|
if (fun->stack->next->thisVar.varType != SVT_STACK) {
|
|
fatal("Parameter isn't a stack");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
if (!addVarToStack(fun->stack->thisVar, fun->stack->next->thisVar.varData.theStack->first))
|
|
return BR_ERROR;
|
|
|
|
if (fun->stack->next->thisVar.varData.theStack->first->next == NULL)
|
|
fun->stack->next->thisVar.varData.theStack->last = fun->stack->next->thisVar.varData.theStack->first;
|
|
|
|
trimStack(fun->stack);
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(enqueue) {
|
|
UNUSEDALL
|
|
if (fun->stack->next->thisVar.varType != SVT_STACK) {
|
|
fatal("Parameter isn't a stack");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
if (fun->stack->next->thisVar.varData.theStack->first == NULL) {
|
|
if (!addVarToStack(fun->stack->thisVar, fun->stack->next->thisVar.varData.theStack->first))
|
|
return BR_ERROR;
|
|
|
|
fun->stack->next->thisVar.varData.theStack->last = fun->stack->next->thisVar.varData.theStack->first;
|
|
} else {
|
|
if (!addVarToStack(fun->stack->thisVar,
|
|
fun->stack->next->thisVar.varData.theStack->last->next))
|
|
return BR_ERROR;
|
|
fun->stack->next->thisVar.varData.theStack->last = fun->stack->next->thisVar.varData.theStack->last->next;
|
|
}
|
|
|
|
trimStack(fun->stack);
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(deleteFromStack) {
|
|
UNUSEDALL
|
|
if (fun->stack->next->thisVar.varType != SVT_STACK) {
|
|
fatal("Parameter isn't a stack.");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
// Return value
|
|
setVariable(fun->reg, SVT_INT,
|
|
deleteVarFromStack(fun->stack->thisVar,
|
|
fun->stack->next->thisVar.varData.theStack->first, false));
|
|
|
|
// Horrible hacking because 'last' value might now be wrong!
|
|
fun->stack->next->thisVar.varData.theStack->last = stackFindLast(fun->stack->next->thisVar.varData.theStack->first);
|
|
|
|
trimStack(fun->stack);
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(deleteAllFromStack) {
|
|
UNUSEDALL
|
|
if (fun->stack->next->thisVar.varType != SVT_STACK) {
|
|
fatal("Parameter isn't a stack.");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
// Return value
|
|
setVariable(fun->reg, SVT_INT,
|
|
deleteVarFromStack(fun->stack->thisVar,
|
|
fun->stack->next->thisVar.varData.theStack->first, true));
|
|
|
|
// Horrible hacking because 'last' value might now be wrong!
|
|
fun->stack->next->thisVar.varData.theStack->last = stackFindLast(fun->stack->next->thisVar.varData.theStack->first);
|
|
|
|
trimStack(fun->stack);
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(popFromStack) {
|
|
UNUSEDALL
|
|
if (fun->stack->thisVar.varType != SVT_STACK) {
|
|
fatal("Parameter isn't a stack.");
|
|
return BR_ERROR;
|
|
}
|
|
if (fun->stack->thisVar.varData.theStack->first == NULL) {
|
|
fatal("The stack's empty.");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
// Return value
|
|
copyVariable(fun->stack->thisVar.varData.theStack->first->thisVar, fun->reg);
|
|
trimStack(fun->stack->thisVar.varData.theStack->first);
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(peekStart) {
|
|
UNUSEDALL
|
|
if (fun->stack->thisVar.varType != SVT_STACK) {
|
|
fatal("Parameter isn't a stack.");
|
|
return BR_ERROR;
|
|
}
|
|
if (fun->stack->thisVar.varData.theStack->first == NULL) {
|
|
fatal("The stack's empty.");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
// Return value
|
|
copyVariable(fun->stack->thisVar.varData.theStack->first->thisVar, fun->reg);
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(peekEnd) {
|
|
UNUSEDALL
|
|
if (fun->stack->thisVar.varType != SVT_STACK) {
|
|
fatal("Parameter isn't a stack.");
|
|
return BR_ERROR;
|
|
}
|
|
if (fun->stack->thisVar.varData.theStack->first == NULL) {
|
|
fatal("The stack's empty.");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
// Return value
|
|
copyVariable(fun->stack->thisVar.varData.theStack->last->thisVar, fun->reg);
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(random) {
|
|
UNUSEDALL
|
|
int num;
|
|
|
|
if (!getValueType(num, SVT_INT, fun->stack->thisVar))
|
|
return BR_ERROR;
|
|
|
|
trimStack(fun->stack);
|
|
if (num <= 0) num = 1;
|
|
setVariable(fun->reg, SVT_INT, 0 /*rand() % num*/); //TODO:false value
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
static bool getRGBParams(int &red, int &green, int &blue, loadedFunction *fun) {
|
|
if (!getValueType(blue, SVT_INT, fun->stack->thisVar)) return false;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(green, SVT_INT, fun->stack->thisVar)) return false;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(red, SVT_INT, fun->stack->thisVar)) return false;
|
|
trimStack(fun->stack);
|
|
return true;
|
|
}
|
|
|
|
builtIn(setStatusColour) {
|
|
UNUSEDALL
|
|
int red, green, blue;
|
|
|
|
if (!getRGBParams(red, green, blue, fun))
|
|
return BR_ERROR;
|
|
|
|
statusBarColour((byte) red, (byte) green, (byte) blue);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setLitStatusColour) {
|
|
UNUSEDALL
|
|
int red, green, blue;
|
|
|
|
if (!getRGBParams(red, green, blue, fun))
|
|
return BR_ERROR;
|
|
|
|
statusBarLitColour((byte) red, (byte) green, (byte) blue);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setPasteColour) {
|
|
UNUSEDALL
|
|
int red, green, blue;
|
|
|
|
if (!getRGBParams(red, green, blue, fun))
|
|
return BR_ERROR;
|
|
|
|
setFontColour(pastePalette, (byte) red, (byte) green, (byte) blue);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setBlankColour) {
|
|
UNUSEDALL
|
|
int red, green, blue;
|
|
|
|
if (!getRGBParams(red, green, blue, fun))
|
|
return BR_ERROR;
|
|
|
|
currentBlankColour = makeColour(red & 255, green & 255, blue & 255);
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setBurnColour) {
|
|
UNUSEDALL
|
|
int red, green, blue;
|
|
|
|
if (!getRGBParams(red, green, blue, fun))
|
|
return BR_ERROR;
|
|
|
|
currentBurnR = red;
|
|
currentBurnG = green;
|
|
currentBurnB = blue;
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
|
|
builtIn(setFont) {
|
|
UNUSEDALL
|
|
int fileNumber, newHeight;
|
|
if (!getValueType(newHeight, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
// newDebug (" Height:", newHeight);
|
|
trimStack(fun->stack);
|
|
char *newText = getTextFromAnyVar(fun->stack->thisVar);
|
|
if (!newText) return BR_ERROR;
|
|
// newDebug (" Character supported:", newText);
|
|
trimStack(fun->stack);
|
|
if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
// newDebug (" File:", fileNumber);
|
|
trimStack(fun->stack);
|
|
if (!loadFont(fileNumber, newText, newHeight)) return BR_ERROR;
|
|
// newDebug (" Done!");
|
|
delete newText;
|
|
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(inFont) {
|
|
UNUSEDALL
|
|
char *newText = getTextFromAnyVar(fun->stack->thisVar);
|
|
if (!newText) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
// Return value
|
|
|
|
setVariable(fun->reg, SVT_INT, isInFont(newText));
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(pasteString) {
|
|
UNUSEDALL
|
|
char *newText = getTextFromAnyVar(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
int y, x;
|
|
if (!getValueType(y, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (x == IN_THE_CENTRE) x = (winWidth - stringWidth(newText)) >> 1;
|
|
fixFont(pastePalette);
|
|
pasteStringToBackdrop(newText, x, y, pastePalette);
|
|
delete[] newText;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(anim) {
|
|
UNUSEDALL
|
|
if (numParams < 2) {
|
|
fatal("Built-in function anim() must have at least 2 parameters.");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
// First store the frame numbers and take 'em off the stack
|
|
personaAnimation *ba = createPersonaAnim(numParams - 1, fun->stack);
|
|
|
|
// Only remaining paramter is the file number
|
|
int fileNumber;
|
|
if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
// Load the required sprite bank
|
|
loadedSpriteBank *sprBanky = loadBankForAnim(fileNumber);
|
|
if (!sprBanky) return BR_ERROR; // File not found, fatal done already
|
|
setBankFile(ba, sprBanky);
|
|
|
|
// Return value
|
|
newAnimationVariable(fun->reg, ba);
|
|
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(costume) {
|
|
UNUSEDALL
|
|
persona *newPersona = new persona;
|
|
if (!checkNew(newPersona)) return BR_ERROR;
|
|
newPersona->numDirections = numParams / 3;
|
|
if (numParams == 0 || newPersona->numDirections * 3 != numParams) {
|
|
fatal("Illegal number of parameters (should be greater than 0 and divisible by 3)");
|
|
return BR_ERROR;
|
|
}
|
|
int iii;
|
|
newPersona->animation = new personaAnimation * [numParams];
|
|
if (!checkNew(newPersona->animation)) return BR_ERROR;
|
|
for (iii = numParams - 1; iii >= 0; iii --) {
|
|
newPersona->animation[iii] = getAnimationFromVar(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
}
|
|
|
|
// Return value
|
|
newCostumeVariable(fun->reg, newPersona);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(launch) {
|
|
UNUSEDALL
|
|
char *newTextA = getTextFromAnyVar(fun->stack->thisVar);
|
|
if (!newTextA) return BR_ERROR;
|
|
|
|
char *newText = encodeFilename(newTextA);
|
|
|
|
trimStack(fun->stack);
|
|
if (newTextA[0] == 'h' &&
|
|
newTextA[1] == 't' &&
|
|
newTextA[2] == 't' &&
|
|
newTextA[3] == 'p' &&
|
|
(newTextA[4] == ':' || (newTextA[4] == 's' && newTextA[5] == ':'))) {
|
|
|
|
// IT'S A WEBSITE!
|
|
launchMe = copyString(newTextA);
|
|
} else {
|
|
char *gameDir;
|
|
#ifdef _WIN32
|
|
gameDir = joinStrings(gamePath, "\\");
|
|
#else
|
|
gameDir = joinStrings(gamePath, "/");
|
|
#endif
|
|
launchMe = joinStrings(gameDir, newText);
|
|
delete newText;
|
|
if (!launchMe) return BR_ERROR;
|
|
}
|
|
delete newTextA;
|
|
setGraphicsWindow(false);
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
launchResult = &fun->reg;
|
|
|
|
return BR_KEEP_AND_PAUSE;
|
|
}
|
|
|
|
builtIn(pause) {
|
|
UNUSEDALL
|
|
int theTime;
|
|
if (!getValueType(theTime, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (theTime > 0) {
|
|
fun->timeLeft = theTime - 1;
|
|
fun->isSpeech = false;
|
|
return BR_KEEP_AND_PAUSE;
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(completeTimers) {
|
|
UNUSEDALL
|
|
completeTimers();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(callEvent) {
|
|
UNUSEDALL
|
|
int obj1, obj2;
|
|
if (!getValueType(obj2, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(obj1, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
int fNum = getCombinationFunction(obj1, obj2);
|
|
|
|
// Return value
|
|
if (fNum) {
|
|
setVariable(fun->reg, SVT_FUNC, fNum);
|
|
return BR_CALLAFUNC;
|
|
}
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
#if 0
|
|
SDL_Event quit_event;
|
|
#endif
|
|
|
|
bool reallyWantToQuit = false;
|
|
|
|
builtIn(quitGame) {
|
|
UNUSEDALL
|
|
reallyWantToQuit = true;
|
|
#if 0
|
|
quit_event.type = SDL_QUIT;
|
|
SDL_PushEvent(&quit_event);
|
|
#endif
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Movie functions
|
|
|
|
// The old movie functions are deprecated and does nothing.
|
|
builtIn(_rem_movieStart) {
|
|
UNUSEDALL
|
|
trimStack(fun->stack);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(_rem_movieAbort) {
|
|
UNUSEDALL
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(_rem_moviePlaying) {
|
|
UNUSEDALL
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(playMovie) {
|
|
UNUSEDALL
|
|
int fileNumber, r;
|
|
|
|
if (movieIsPlaying) return BR_PAUSE;
|
|
|
|
if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
r = playMovie(fileNumber);
|
|
|
|
setVariable(fun->reg, SVT_INT, r);
|
|
|
|
if (r && (!fun->next)) {
|
|
restartFunction(fun);
|
|
return BR_ALREADY_GONE;
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(stopMovie) {
|
|
UNUSEDALL
|
|
int r;
|
|
|
|
r = stopMovie();
|
|
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(pauseMovie) {
|
|
UNUSEDALL
|
|
int r;
|
|
|
|
r = pauseMovie();
|
|
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Audio functions
|
|
|
|
builtIn(startMusic) {
|
|
UNUSEDALL
|
|
int fromTrack, musChan, fileNumber;
|
|
if (!getValueType(fromTrack, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(musChan, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!playMOD(fileNumber, musChan, fromTrack)) return BR_CONTINUE; //BR_ERROR;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(stopMusic) {
|
|
UNUSEDALL
|
|
int v;
|
|
if (!getValueType(v, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
stopMOD(v);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setMusicVolume) {
|
|
UNUSEDALL
|
|
int musChan, v;
|
|
if (!getValueType(v, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(musChan, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setMusicVolume(musChan, v);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setDefaultMusicVolume) {
|
|
UNUSEDALL
|
|
int v;
|
|
if (!getValueType(v, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setDefaultMusicVolume(v);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(playSound) {
|
|
UNUSEDALL
|
|
int fileNumber;
|
|
if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!startSound(fileNumber, false)) return BR_CONTINUE; // Was BR_ERROR
|
|
return BR_CONTINUE;
|
|
}
|
|
builtIn(loopSound) {
|
|
UNUSEDALL
|
|
int fileNumber;
|
|
|
|
if (numParams < 1) {
|
|
fatal("Built-in function loopSound() must have at least 1 parameter.");
|
|
return BR_ERROR;
|
|
} else if (numParams < 2) {
|
|
|
|
if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!startSound(fileNumber, true)) return BR_CONTINUE; // Was BR_ERROR
|
|
return BR_CONTINUE;
|
|
} else {
|
|
// We have more than one sound to play!
|
|
|
|
int doLoop = 2;
|
|
soundList *s = NULL;
|
|
soundList *old = NULL;
|
|
|
|
// Should we loop?
|
|
if (fun->stack->thisVar.varType != SVT_FILE) {
|
|
getValueType(doLoop, SVT_INT, fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
numParams--;
|
|
}
|
|
while (numParams) {
|
|
if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar)) {
|
|
fatal("Illegal parameter given built-in function loopSound().");
|
|
return BR_ERROR;
|
|
}
|
|
s = new soundList;
|
|
if (!checkNew(s)) return BR_ERROR;
|
|
|
|
s-> next = old;
|
|
s-> prev = NULL;
|
|
s-> sound = fileNumber;
|
|
old = s;
|
|
|
|
trimStack(fun->stack);
|
|
numParams--;
|
|
}
|
|
while (s->next) s = s-> next;
|
|
if (doLoop > 1) {
|
|
s->next = old;
|
|
old->prev = s;
|
|
} else if (doLoop) {
|
|
s->next = s;
|
|
}
|
|
old->vol = -1;
|
|
playSoundList(old);
|
|
return BR_CONTINUE;
|
|
}
|
|
}
|
|
|
|
builtIn(stopSound) {
|
|
UNUSEDALL
|
|
int v;
|
|
if (!getValueType(v, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
huntKillSound(v);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setDefaultSoundVolume) {
|
|
UNUSEDALL
|
|
int v;
|
|
if (!getValueType(v, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setDefaultSoundVolume(v);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setSoundVolume) {
|
|
UNUSEDALL
|
|
int musChan, v;
|
|
if (!getValueType(v, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(musChan, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setSoundVolume(musChan, v);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
|
|
builtIn(setSoundLoopPoints) {
|
|
UNUSEDALL
|
|
int musChan, theEnd, theStart;
|
|
if (!getValueType(theEnd, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(theStart, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(musChan, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setSoundLoop(musChan, theStart, theEnd);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark Extra room bits
|
|
|
|
builtIn(setFloor) {
|
|
UNUSEDALL
|
|
if (fun->stack->thisVar.varType == SVT_FILE) {
|
|
int v;
|
|
getValueType(v, SVT_FILE, fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
if (!setFloor(v)) return BR_ERROR;
|
|
} else {
|
|
trimStack(fun->stack);
|
|
setFloorNull();
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(showFloor) {
|
|
UNUSEDALL
|
|
drawFloor();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setZBuffer) {
|
|
UNUSEDALL
|
|
if (fun->stack->thisVar.varType == SVT_FILE) {
|
|
int v;
|
|
getValueType(v, SVT_FILE, fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
if (!setZBuffer(v)) return BR_ERROR;
|
|
} else {
|
|
trimStack(fun->stack);
|
|
killZBuffer();
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setLightMap) {
|
|
UNUSEDALL
|
|
switch (numParams) {
|
|
case 2:
|
|
if (!getValueType(lightMapMode, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
lightMapMode %= LIGHTMAPMODE_NUM;
|
|
// No break;
|
|
|
|
case 1:
|
|
if (fun->stack->thisVar.varType == SVT_FILE) {
|
|
int v;
|
|
getValueType(v, SVT_FILE, fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
if (!loadLightMap(v)) return BR_ERROR;
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
} else {
|
|
trimStack(fun->stack);
|
|
killLightMap();
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fatal("Function should have either 2 or 3 parameters");
|
|
return BR_ERROR;
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Objects
|
|
|
|
builtIn(setSpeechMode) {
|
|
UNUSEDALL
|
|
if (!getValueType(speechMode, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (speechMode < 0 || speechMode > 2) {
|
|
fatal("Valid parameters are be SPEECHANDTEXT, SPEECHONLY or TEXTONLY");
|
|
return BR_ERROR;
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(somethingSpeaking) {
|
|
UNUSEDALL
|
|
int i = isThereAnySpeechGoingOn();
|
|
if (i == -1) {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
} else {
|
|
setVariable(fun->reg, SVT_OBJTYPE, i);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(skipSpeech) {
|
|
UNUSEDALL
|
|
killSpeechTimers();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getOverObject) {
|
|
UNUSEDALL
|
|
if (overRegion)
|
|
// Return value
|
|
setVariable(fun->reg, SVT_OBJTYPE, overRegion->thisType->objectNum);
|
|
else
|
|
// Return value
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(rename) {
|
|
UNUSEDALL
|
|
char *newText = getTextFromAnyVar(fun->stack->thisVar);
|
|
int objT;
|
|
if (!newText) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(objT, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
objectType *o = findObjectType(objT);
|
|
delete o->screenName;
|
|
o->screenName = newText;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getObjectX) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
onScreenPerson *pers = findPerson(objectNumber);
|
|
if (pers) {
|
|
setVariable(fun->reg, SVT_INT, pers->x);
|
|
} else {
|
|
screenRegion *la = getRegionForObject(objectNumber);
|
|
if (la) {
|
|
setVariable(fun->reg, SVT_INT, la->sX);
|
|
} else {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
}
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getObjectY) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
onScreenPerson *pers = findPerson(objectNumber);
|
|
if (pers) {
|
|
setVariable(fun->reg, SVT_INT, pers->y);
|
|
} else {
|
|
screenRegion *la = getRegionForObject(objectNumber);
|
|
if (la) {
|
|
setVariable(fun->reg, SVT_INT, la->sY);
|
|
} else {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
}
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
|
|
builtIn(addScreenRegion) {
|
|
UNUSEDALL
|
|
int sX, sY, x1, y1, x2, y2, di, objectNumber;
|
|
if (!getValueType(di, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(sY, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(sX, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(y2, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x2, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(y1, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x1, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (addScreenRegion(x1, y1, x2, y2, sX, sY, di, objectNumber)) return BR_CONTINUE;
|
|
return BR_ERROR;
|
|
|
|
}
|
|
|
|
builtIn(removeScreenRegion) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
removeScreenRegion(objectNumber);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(showBoxes) {
|
|
UNUSEDALL
|
|
showBoxes();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(removeAllScreenRegions) {
|
|
UNUSEDALL
|
|
killAllRegions();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(addCharacter) {
|
|
UNUSEDALL
|
|
persona *p;
|
|
int x, y, objectNumber;
|
|
|
|
p = getCostumeFromVar(fun->stack->thisVar);
|
|
if (p == NULL) return BR_ERROR;
|
|
|
|
trimStack(fun->stack);
|
|
if (!getValueType(y, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (addPerson(x, y, objectNumber, p)) return BR_CONTINUE;
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(hideCharacter) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setShown(false, objectNumber);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(showCharacter) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setShown(true, objectNumber);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(removeAllCharacters) {
|
|
UNUSEDALL
|
|
killSpeechTimers();
|
|
killMostPeople();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setCharacterDrawMode) {
|
|
UNUSEDALL
|
|
int obj, di;
|
|
if (!getValueType(di, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setDrawMode(di, obj);
|
|
return BR_CONTINUE;
|
|
}
|
|
builtIn(setCharacterTransparency) {
|
|
UNUSEDALL
|
|
int obj, x;
|
|
if (!getValueType(x, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setPersonTransparency(obj, x);
|
|
return BR_CONTINUE;
|
|
}
|
|
builtIn(setCharacterColourise) {
|
|
UNUSEDALL
|
|
int obj, r, g, b, mix;
|
|
if (!getValueType(mix, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(b, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(g, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(r, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setPersonColourise(obj, r, g, b, mix);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setScale) {
|
|
UNUSEDALL
|
|
int val1, val2;
|
|
if (!getValueType(val2, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(val1, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setScale((short int) val1, (short int) val2);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(stopCharacter) {
|
|
UNUSEDALL
|
|
int obj;
|
|
if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
// Return value
|
|
setVariable(fun->reg, SVT_INT, stopPerson(obj));
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(pasteCharacter) {
|
|
UNUSEDALL
|
|
int obj;
|
|
if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
onScreenPerson *thisPerson = findPerson(obj);
|
|
if (thisPerson) {
|
|
personaAnimation *myAnim;
|
|
myAnim = thisPerson->myAnim;
|
|
if (myAnim != thisPerson->lastUsedAnim) {
|
|
thisPerson->lastUsedAnim = myAnim;
|
|
thisPerson->frameNum = 0;
|
|
thisPerson->frameTick = myAnim->frames[0].howMany;
|
|
}
|
|
|
|
int fNum = myAnim->frames[thisPerson->frameNum].frameNum;
|
|
fixScaleSprite(thisPerson->x, thisPerson->y, myAnim->theSprites->bank.sprites[abs(fNum)], myAnim->theSprites->bank.myPalette, thisPerson, 0, 0, fNum < 0);
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
} else {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(animate) {
|
|
UNUSEDALL
|
|
int obj;
|
|
personaAnimation *pp = getAnimationFromVar(fun->stack->thisVar);
|
|
if (pp == NULL) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
animatePerson(obj, pp);
|
|
setVariable(fun->reg, SVT_INT, timeForAnim(pp));
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setCostume) {
|
|
UNUSEDALL
|
|
int obj;
|
|
persona *pp = getCostumeFromVar(fun->stack->thisVar);
|
|
if (pp == NULL) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
animatePerson(obj, pp);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(floatCharacter) {
|
|
UNUSEDALL
|
|
int obj, di;
|
|
if (!getValueType(di, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, floatCharacter(di, obj));
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setCharacterWalkSpeed) {
|
|
UNUSEDALL
|
|
int obj, di;
|
|
if (!getValueType(di, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, setCharacterWalkSpeed(di, obj));
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(turnCharacter) {
|
|
UNUSEDALL
|
|
int obj, di;
|
|
if (!getValueType(di, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, turnPersonToFace(obj, di));
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setCharacterExtra) {
|
|
UNUSEDALL
|
|
int obj, di;
|
|
if (!getValueType(di, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, setPersonExtra(obj, di));
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(removeCharacter) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
removeOneCharacter(objectNumber);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
static builtReturn moveChr(int numParams, loadedFunction *fun, bool force, bool immediate) {
|
|
switch (numParams) {
|
|
case 3: {
|
|
int x, y, objectNumber;
|
|
|
|
if (!getValueType(y, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
if (force) {
|
|
if (forceWalkingPerson(x, y, objectNumber, fun, -1)) return BR_PAUSE;
|
|
} else if (immediate) {
|
|
jumpPerson(x, y, objectNumber);
|
|
} else {
|
|
if (makeWalkingPerson(x, y, objectNumber, fun, -1)) return BR_PAUSE;
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
case 2: {
|
|
int toObj, objectNumber;
|
|
screenRegion *reggie;
|
|
|
|
if (!getValueType(toObj, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
reggie = getRegionForObject(toObj);
|
|
if (reggie == NULL) return BR_CONTINUE;
|
|
|
|
if (force) {
|
|
if (forceWalkingPerson(reggie->sX, reggie->sY, objectNumber, fun, reggie->di)) return BR_PAUSE;
|
|
} else if (immediate) {
|
|
jumpPerson(reggie->sX, reggie->sY, objectNumber);
|
|
} else {
|
|
if (makeWalkingPerson(reggie->sX, reggie->sY, objectNumber, fun, reggie->di)) return BR_PAUSE;
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
default:
|
|
fatal("Built-in function must have either 2 or 3 parameters.");
|
|
return BR_ERROR;
|
|
}
|
|
}
|
|
|
|
builtIn(moveCharacter) {
|
|
UNUSEDALL
|
|
return moveChr(numParams, fun, false, false);
|
|
}
|
|
|
|
builtIn(forceCharacter) {
|
|
UNUSEDALL
|
|
return moveChr(numParams, fun, true, false);
|
|
}
|
|
|
|
builtIn(jumpCharacter) {
|
|
UNUSEDALL
|
|
return moveChr(numParams, fun, false, true);
|
|
}
|
|
|
|
builtIn(clearStatus) {
|
|
UNUSEDALL
|
|
clearStatusBar();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(removeLastStatus) {
|
|
UNUSEDALL
|
|
killLastStatus();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(addStatus) {
|
|
UNUSEDALL
|
|
addStatusBar();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(statusText) {
|
|
UNUSEDALL
|
|
char *newText = getTextFromAnyVar(fun->stack->thisVar);
|
|
if (!newText) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setStatusBar(newText);
|
|
delete newText;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(lightStatus) {
|
|
UNUSEDALL
|
|
int val;
|
|
if (!getValueType(val, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setLitStatus(val);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(positionStatus) {
|
|
UNUSEDALL
|
|
int x, y;
|
|
if (!getValueType(y, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
positionStatus(x, y);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(alignStatus) {
|
|
UNUSEDALL
|
|
int val;
|
|
if (!getValueType(val, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
nowStatus->alignStatus = (short) val;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
static bool getFuncNumForCallback(int numParams, loadedFunction *fun, int &functionNum) {
|
|
switch (numParams) {
|
|
case 0:
|
|
functionNum = 0;
|
|
break;
|
|
|
|
case 1:
|
|
if (!getValueType(functionNum, SVT_FUNC, fun->stack->thisVar)) return false;
|
|
trimStack(fun->stack);
|
|
break;
|
|
|
|
default:
|
|
fatal("Too many parameters.");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
builtIn(onLeftMouse) {
|
|
UNUSEDALL
|
|
int functionNum;
|
|
if (getFuncNumForCallback(numParams, fun, functionNum)) {
|
|
currentEvents->leftMouseFunction = functionNum;
|
|
return BR_CONTINUE;
|
|
}
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(onLeftMouseUp) {
|
|
UNUSEDALL
|
|
int functionNum;
|
|
if (getFuncNumForCallback(numParams, fun, functionNum)) {
|
|
currentEvents->leftMouseUpFunction = functionNum;
|
|
return BR_CONTINUE;
|
|
}
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(onRightMouse) {
|
|
UNUSEDALL
|
|
int functionNum;
|
|
if (getFuncNumForCallback(numParams, fun, functionNum)) {
|
|
currentEvents->rightMouseFunction = functionNum;
|
|
return BR_CONTINUE;
|
|
}
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(onRightMouseUp) {
|
|
UNUSEDALL
|
|
int functionNum;
|
|
if (getFuncNumForCallback(numParams, fun, functionNum)) {
|
|
currentEvents->rightMouseUpFunction = functionNum;
|
|
return BR_CONTINUE;
|
|
}
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(onFocusChange) {
|
|
UNUSEDALL
|
|
int functionNum;
|
|
if (getFuncNumForCallback(numParams, fun, functionNum)) {
|
|
currentEvents->focusFunction = functionNum;
|
|
return BR_CONTINUE;
|
|
}
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(onMoveMouse) {
|
|
UNUSEDALL
|
|
int functionNum;
|
|
if (getFuncNumForCallback(numParams, fun, functionNum)) {
|
|
currentEvents->moveMouseFunction = functionNum;
|
|
return BR_CONTINUE;
|
|
}
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(onKeyboard) {
|
|
UNUSEDALL
|
|
int functionNum;
|
|
if (getFuncNumForCallback(numParams, fun, functionNum)) {
|
|
currentEvents->spaceFunction = functionNum;
|
|
return BR_CONTINUE;
|
|
}
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(spawnSub) {
|
|
UNUSEDALL
|
|
int functionNum;
|
|
if (getFuncNumForCallback(numParams, fun, functionNum)) {
|
|
if (!startNewFunctionNum(functionNum, 0, NULL, noStack)) return BR_ERROR;
|
|
return BR_CONTINUE;
|
|
}
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(cancelSub) {
|
|
UNUSEDALL
|
|
int functionNum;
|
|
if (getFuncNumForCallback(numParams, fun, functionNum)) {
|
|
bool killedMyself;
|
|
cancelAFunction(functionNum, fun, killedMyself);
|
|
if (killedMyself) {
|
|
abortFunction(fun);
|
|
return BR_ALREADY_GONE;
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(stringWidth) {
|
|
UNUSEDALL
|
|
char *theText = getTextFromAnyVar(fun->stack->thisVar);
|
|
if (!theText) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
// Return value
|
|
setVariable(fun->reg, SVT_INT, stringWidth(theText));
|
|
delete theText;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(hardScroll) {
|
|
UNUSEDALL
|
|
int v;
|
|
if (!getValueType(v, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
hardScroll(v);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
|
|
builtIn(isScreenRegion) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, getRegionForObject(objectNumber) != NULL);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setSpeechSpeed) {
|
|
UNUSEDALL
|
|
int number;
|
|
if (!getValueType(number, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
speechSpeed = number * 0.01;
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setFontSpacing) {
|
|
UNUSEDALL
|
|
int fontSpaceI;
|
|
if (!getValueType(fontSpaceI, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
fontSpace = fontSpaceI;
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(transitionLevel) {
|
|
UNUSEDALL
|
|
int number;
|
|
if (!getValueType(number, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
if (number < 0)
|
|
brightnessLevel = 0;
|
|
else if (number > 255)
|
|
brightnessLevel = 255;
|
|
else
|
|
brightnessLevel = number;
|
|
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(captureAllKeys) {
|
|
UNUSEDALL
|
|
captureAllKeys = getBoolean(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, captureAllKeys);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
|
|
builtIn(spinCharacter) {
|
|
UNUSEDALL
|
|
int number, objectNumber;
|
|
if (!getValueType(number, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
onScreenPerson *thisPerson = findPerson(objectNumber);
|
|
if (thisPerson) {
|
|
thisPerson->wantAngle = number;
|
|
thisPerson->spinning = true;
|
|
thisPerson->continueAfterWalking = fun;
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
return BR_PAUSE;
|
|
} else {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
return BR_CONTINUE;
|
|
}
|
|
}
|
|
|
|
builtIn(getCharacterDirection) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
onScreenPerson *thisPerson = findPerson(objectNumber);
|
|
if (thisPerson) {
|
|
setVariable(fun->reg, SVT_INT, thisPerson->direction);
|
|
} else {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(isCharacter) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
onScreenPerson *thisPerson = findPerson(objectNumber);
|
|
setVariable(fun->reg, SVT_INT, thisPerson != NULL);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(normalCharacter) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
onScreenPerson *thisPerson = findPerson(objectNumber);
|
|
if (thisPerson) {
|
|
thisPerson->myAnim = thisPerson->myPersona->animation[thisPerson->direction];
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
} else {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(isMoving) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
onScreenPerson *thisPerson = findPerson(objectNumber);
|
|
if (thisPerson) {
|
|
setVariable(fun->reg, SVT_INT, thisPerson->walking);
|
|
} else {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(fetchEvent) {
|
|
UNUSEDALL
|
|
int obj1, obj2;
|
|
if (!getValueType(obj2, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(obj1, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
int fNum = getCombinationFunction(obj1, obj2);
|
|
|
|
// Return value
|
|
if (fNum) {
|
|
setVariable(fun->reg, SVT_FUNC, fNum);
|
|
} else {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(deleteFile) {
|
|
UNUSEDALL
|
|
|
|
char *namNormal = getTextFromAnyVar(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
char *nam = encodeFilename(namNormal);
|
|
delete namNormal;
|
|
if (failSecurityCheck(nam)) return BR_ERROR;
|
|
setVariable(fun->reg, SVT_INT, remove(nam));
|
|
delete nam;
|
|
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(renameFile) {
|
|
UNUSEDALL
|
|
char *temp;
|
|
|
|
temp = getTextFromAnyVar(fun->stack->thisVar);
|
|
char *newnam = encodeFilename(temp);
|
|
trimStack(fun->stack);
|
|
if (failSecurityCheck(newnam)) return BR_ERROR;
|
|
delete temp;
|
|
|
|
temp = getTextFromAnyVar(fun->stack->thisVar);
|
|
char *nam = encodeFilename(temp);
|
|
trimStack(fun->stack);
|
|
if (failSecurityCheck(nam)) return BR_ERROR;
|
|
delete temp;
|
|
|
|
setVariable(fun->reg, SVT_INT, rename(nam, newnam));
|
|
delete nam;
|
|
delete newnam;
|
|
|
|
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(cacheSound) {
|
|
UNUSEDALL
|
|
int fileNumber;
|
|
if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (cacheSound(fileNumber) == -1) return BR_ERROR;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(burnString) {
|
|
UNUSEDALL
|
|
char *newText = getTextFromAnyVar(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
int y, x;
|
|
if (!getValueType(y, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (x == IN_THE_CENTRE) x = (winWidth - stringWidth(newText)) >> 1;
|
|
fixFont(pastePalette);
|
|
burnStringToBackdrop(newText, x, y, pastePalette);
|
|
delete[] newText;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setCharacterSpinSpeed) {
|
|
UNUSEDALL
|
|
int speed, who;
|
|
if (!getValueType(speed, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(who, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
onScreenPerson *thisPerson = findPerson(who);
|
|
|
|
if (thisPerson) {
|
|
thisPerson->spinSpeed = speed;
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
} else {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setCharacterAngleOffset) {
|
|
UNUSEDALL
|
|
int angle, who;
|
|
if (!getValueType(angle, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(who, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
onScreenPerson *thisPerson = findPerson(who);
|
|
|
|
if (thisPerson) {
|
|
thisPerson->angleOffset = angle;
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
} else {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
|
|
builtIn(transitionMode) {
|
|
UNUSEDALL
|
|
int n;
|
|
if (!getValueType(n, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
fadeMode = n;
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
|
|
// Removed function - does nothing
|
|
builtIn(_rem_updateDisplay) {
|
|
UNUSEDALL
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, true);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getSoundCache) {
|
|
UNUSEDALL
|
|
fun->reg.varType = SVT_STACK;
|
|
fun->reg.varData.theStack = new stackHandler;
|
|
if (!checkNew(fun->reg.varData.theStack)) return BR_ERROR;
|
|
fun->reg.varData.theStack->first = NULL;
|
|
fun->reg.varData.theStack->last = NULL;
|
|
fun->reg.varData.theStack->timesUsed = 1;
|
|
if (!getSoundCacheStack(fun->reg.varData.theStack)) return BR_ERROR;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(saveCustomData) {
|
|
UNUSEDALL
|
|
// saveCustomData (thisStack, fileName);
|
|
char *fileNameB = getTextFromAnyVar(fun->stack->thisVar);
|
|
if (!checkNew(fileNameB)) return BR_ERROR;
|
|
|
|
char *fileName = encodeFilename(fileNameB);
|
|
delete fileNameB;
|
|
|
|
if (failSecurityCheck(fileName)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
if (fun->stack->thisVar.varType != SVT_STACK) {
|
|
fatal("First parameter isn't a stack");
|
|
return BR_ERROR;
|
|
}
|
|
if (!stackToFile(fileName, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
delete fileName;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(loadCustomData) {
|
|
UNUSEDALL
|
|
|
|
char *newTextA = getTextFromAnyVar(fun->stack->thisVar);
|
|
if (!checkNew(newTextA)) return BR_ERROR;
|
|
|
|
char *newText = encodeFilename(newTextA);
|
|
delete newTextA;
|
|
|
|
if (failSecurityCheck(newText)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
unlinkVar(fun->reg);
|
|
fun->reg.varType = SVT_STACK;
|
|
fun->reg.varData.theStack = new stackHandler;
|
|
if (!checkNew(fun->reg.varData.theStack)) return BR_ERROR;
|
|
fun->reg.varData.theStack->first = NULL;
|
|
fun->reg.varData.theStack->last = NULL;
|
|
fun->reg.varData.theStack->timesUsed = 1;
|
|
if (!fileToStack(newText, fun->reg.varData.theStack)) return BR_ERROR;
|
|
delete newText;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setCustomEncoding) {
|
|
UNUSEDALL
|
|
int n;
|
|
if (!getValueType(n, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
saveEncoding = n;
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(freeSound) {
|
|
UNUSEDALL
|
|
int v;
|
|
if (!getValueType(v, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
huntKillFreeSound(v);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(parallaxAdd) {
|
|
UNUSEDALL
|
|
if (frozenStuff) {
|
|
fatal("Can't set background parallax image while frozen");
|
|
return BR_ERROR;
|
|
} else {
|
|
int wrapX, wrapY, v;
|
|
if (!getValueType(wrapY, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(wrapX, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(v, SVT_FILE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
if (!loadParallax(v, wrapX, wrapY)) return BR_ERROR;
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(parallaxClear) {
|
|
UNUSEDALL
|
|
killParallax();
|
|
setVariable(fun->reg, SVT_INT, 1);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getPixelColour) {
|
|
UNUSEDALL
|
|
int x, y;
|
|
if (!getValueType(y, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
unlinkVar(fun->reg);
|
|
fun->reg.varType = SVT_STACK;
|
|
fun->reg.varData.theStack = new stackHandler;
|
|
if (!checkNew(fun->reg.varData.theStack)) return BR_ERROR;
|
|
fun->reg.varData.theStack->first = NULL;
|
|
fun->reg.varData.theStack->last = NULL;
|
|
fun->reg.varData.theStack->timesUsed = 1;
|
|
if (!getRGBIntoStack(x, y, fun->reg.varData.theStack)) return BR_ERROR;
|
|
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(makeFastArray) {
|
|
UNUSEDALL
|
|
switch (fun->stack->thisVar.varType) {
|
|
case SVT_STACK: {
|
|
bool success = makeFastArrayFromStack(fun->reg, fun->stack->thisVar.varData.theStack);
|
|
trimStack(fun->stack);
|
|
return success ? BR_CONTINUE : BR_ERROR;
|
|
}
|
|
break;
|
|
|
|
case SVT_INT: {
|
|
int i = fun->stack->thisVar.varData.intValue;
|
|
trimStack(fun->stack);
|
|
return makeFastArraySize(fun->reg, i) ? BR_CONTINUE : BR_ERROR;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
fatal("Parameter must be a number or a stack.");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(getCharacterScale) {
|
|
UNUSEDALL
|
|
int objectNumber;
|
|
if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
onScreenPerson *pers = findPerson(objectNumber);
|
|
if (pers) {
|
|
setVariable(fun->reg, SVT_INT, pers->scale * 100);
|
|
} else {
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(getLanguageID) {
|
|
UNUSEDALL
|
|
setVariable(fun->reg, SVT_INT, gameSettings.languageID);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
// Removed function
|
|
builtIn(_rem_launchWith) {
|
|
UNUSEDALL
|
|
|
|
trimStack(fun->stack);
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, false);
|
|
|
|
return BR_CONTINUE;
|
|
|
|
}
|
|
|
|
builtIn(getFramesPerSecond) {
|
|
UNUSEDALL
|
|
setVariable(fun->reg, SVT_INT, lastFramesPerSecond);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(showThumbnail) {
|
|
UNUSEDALL
|
|
int x, y;
|
|
if (!getValueType(y, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(x, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
|
|
// Encode the name!Encode the name!
|
|
char *aaaaa = getTextFromAnyVar(fun->stack->thisVar);
|
|
// deb ("Got name:", aaaaa;)
|
|
trimStack(fun->stack);
|
|
// deb ("About to encode", aaaaa);
|
|
char *file = encodeFilename(aaaaa);
|
|
// deb ("Made new name", file);
|
|
// deb ("aaaaa is still ", aaaaa);
|
|
delete[] aaaaa;
|
|
// deb ("Deleted", "aaaaa");
|
|
showThumbnail(file, x, y);
|
|
delete[] file;
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(setThumbnailSize) {
|
|
UNUSEDALL
|
|
if (!getValueType(thumbHeight, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(thumbWidth, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (thumbWidth < 0 || thumbHeight < 0 || thumbWidth > winWidth || thumbHeight > winHeight) {
|
|
char buff[50];
|
|
sprintf(buff, "%d x %d", thumbWidth, thumbHeight);
|
|
fatal("Invalid thumbnail size", buff);
|
|
return BR_ERROR;
|
|
}
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(hasFlag) {
|
|
UNUSEDALL
|
|
int objNum, flagIndex;
|
|
if (!getValueType(flagIndex, SVT_INT, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
if (!getValueType(objNum, SVT_OBJTYPE, fun->stack->thisVar)) return BR_ERROR;
|
|
trimStack(fun->stack);
|
|
objectType *objT = findObjectType(objNum);
|
|
if (!objT) return BR_ERROR;
|
|
setVariable(fun->reg, SVT_INT, objT->flags & (1 << flagIndex));
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(snapshotGrab) {
|
|
UNUSEDALL
|
|
return snapshot() ? BR_CONTINUE : BR_ERROR;
|
|
}
|
|
|
|
builtIn(snapshotClear) {
|
|
UNUSEDALL
|
|
nosnapshot();
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(bodgeFilenames) {
|
|
UNUSEDALL
|
|
bool lastValue = allowAnyFilename;
|
|
allowAnyFilename = getBoolean(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, lastValue);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
// Deprecated - does nothing.
|
|
builtIn(_rem_registryGetString) {
|
|
UNUSEDALL
|
|
trimStack(fun->stack);
|
|
trimStack(fun->stack);
|
|
setVariable(fun->reg, SVT_INT, 0);
|
|
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(quitWithFatalError) {
|
|
UNUSEDALL
|
|
char *mess = getTextFromAnyVar(fun->stack->thisVar);
|
|
trimStack(fun->stack);
|
|
fatal(mess);
|
|
return BR_ERROR;
|
|
}
|
|
|
|
builtIn(_rem_setCharacterAA) {
|
|
UNUSEDALL
|
|
|
|
trimStack(fun->stack);
|
|
trimStack(fun->stack);
|
|
trimStack(fun->stack);
|
|
trimStack(fun->stack);
|
|
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(_rem_setMaximumAA) {
|
|
UNUSEDALL
|
|
|
|
trimStack(fun->stack);
|
|
trimStack(fun->stack);
|
|
trimStack(fun->stack);
|
|
|
|
return BR_CONTINUE;
|
|
|
|
}
|
|
|
|
builtIn(setBackgroundEffect) {
|
|
UNUSEDALL
|
|
bool done = blur_createSettings(numParams, fun->stack);
|
|
setVariable(fun->reg, SVT_INT, done ? 1 : 0);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
builtIn(doBackgroundEffect) {
|
|
UNUSEDALL
|
|
bool done = blurScreen();
|
|
setVariable(fun->reg, SVT_INT, done ? 1 : 0);
|
|
return BR_CONTINUE;
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark Other functions
|
|
|
|
//-------------------------------------
|
|
|
|
#define FUNC(special,name) {builtIn_ ## name},
|
|
static builtInFunctionData builtInFunctionArray[] = {
|
|
#include "CommonCode/functionlist.h"
|
|
};
|
|
#undef FUNC
|
|
|
|
#define FUNC(special,name) {#name},
|
|
char builtInFunctionNames[][25] = {
|
|
#include "CommonCode/functionlist.h"
|
|
};
|
|
#undef FUNC
|
|
|
|
#define NUM_FUNCS (sizeof (builtInFunctionArray) / sizeof (builtInFunctionArray[0]))
|
|
|
|
|
|
|
|
builtReturn callBuiltIn(int whichFunc, int numParams, loadedFunction *fun) {
|
|
// fprintf (stderr, "Calling function %d: %s\n", whichFunc, builtInFunctionNames[whichFunc]); fflush (stderr);
|
|
if (numBIFNames) {
|
|
|
|
// deb ("IN:", (fun->originalNumber < numUserFunc) ? allUserFunc[fun->originalNumber] : "Unknown user function");
|
|
// deb ("GO:", (whichFunc < numBIFNames) ? allBIFNames[whichFunc] : "Unknown built-in function");
|
|
|
|
setFatalInfo(
|
|
(fun->originalNumber < numUserFunc) ? allUserFunc[fun->originalNumber] : "Unknown user function",
|
|
(whichFunc < numBIFNames) ? allBIFNames[whichFunc] : "Unknown built-in function");
|
|
}
|
|
|
|
if (whichFunc < NUM_FUNCS) {
|
|
if (paramNum[whichFunc] != -1) {
|
|
if (paramNum[whichFunc] != numParams) {
|
|
char buff[100];
|
|
sprintf(buff, "Built in function must have %i parameter%s",
|
|
paramNum[whichFunc],
|
|
(paramNum[whichFunc] == 1) ? "" : "s");
|
|
|
|
fatal(copyString(buff));
|
|
return BR_ERROR;
|
|
}
|
|
}
|
|
|
|
if (builtInFunctionArray[whichFunc].func) {
|
|
//fprintf (stderr, "Calling %i: %s\n", whichFunc, builtInFunctionNames[whichFunc]);
|
|
return builtInFunctionArray[whichFunc].func(numParams, fun);
|
|
}
|
|
}
|
|
|
|
fatal("Unknown / unimplemented built-in function.");
|
|
return BR_ERROR;
|
|
}
|
|
|
|
} // End of namespace Sludge
|