aboutsummaryrefslogtreecommitdiff
path: root/sword2/interpreter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sword2/interpreter.cpp')
-rw-r--r--sword2/interpreter.cpp753
1 files changed, 0 insertions, 753 deletions
diff --git a/sword2/interpreter.cpp b/sword2/interpreter.cpp
deleted file mode 100644
index 1a6e7080b8..0000000000
--- a/sword2/interpreter.cpp
+++ /dev/null
@@ -1,753 +0,0 @@
-/* Copyright (C) 1994-1998 Revolution Software Ltd.
- * Copyright (C) 2003-2006 The ScummVM project
- *
- * 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.
- *
- * $URL$
- * $Id$
- */
-
-#include "common/stdafx.h"
-#include "common/util.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/interpreter.h"
-#include "sword2/logic.h"
-#include "sword2/memory.h"
-#include "sword2/resman.h"
-
-namespace Sword2 {
-
-#define STACK_SIZE 10
-
-// The machine code table
-
-#ifndef REDUCE_MEMORY_USAGE
-# define OPCODE(x) { &Logic::x, #x }
-#else
-# define OPCODE(x) { &Logic::x, "" }
-#endif
-
-typedef int32 (Logic::*OpcodeProc)(int32 *);
-struct OpcodeEntry {
- OpcodeProc proc;
- const char *desc;
-};
-
-static const OpcodeEntry opcodes[] = {
- /* 00 */
- OPCODE(fnTestFunction),
- OPCODE(fnTestFlags),
- OPCODE(fnRegisterStartPoint),
- OPCODE(fnInitBackground),
- /* 04 */
- OPCODE(fnSetSession),
- OPCODE(fnBackSprite),
- OPCODE(fnSortSprite),
- OPCODE(fnForeSprite),
- /* 08 */
- OPCODE(fnRegisterMouse),
- OPCODE(fnAnim),
- OPCODE(fnRandom),
- OPCODE(fnPreLoad),
- /* 0C */
- OPCODE(fnAddSubject),
- OPCODE(fnInteract),
- OPCODE(fnChoose),
- OPCODE(fnWalk),
- /* 10 */
- OPCODE(fnWalkToAnim),
- OPCODE(fnTurn),
- OPCODE(fnStandAt),
- OPCODE(fnStand),
- /* 14 */
- OPCODE(fnStandAfterAnim),
- OPCODE(fnPause),
- OPCODE(fnMegaTableAnim),
- OPCODE(fnAddMenuObject),
- /* 18 */
- OPCODE(fnStartConversation),
- OPCODE(fnEndConversation),
- OPCODE(fnSetFrame),
- OPCODE(fnRandomPause),
- /* 1C */
- OPCODE(fnRegisterFrame),
- OPCODE(fnNoSprite),
- OPCODE(fnSendSync),
- OPCODE(fnUpdatePlayerStats),
- /* 20 */
- OPCODE(fnPassGraph),
- OPCODE(fnInitFloorMouse),
- OPCODE(fnPassMega),
- OPCODE(fnFaceXY),
- /* 24 */
- OPCODE(fnEndSession),
- OPCODE(fnNoHuman),
- OPCODE(fnAddHuman),
- OPCODE(fnWeWait),
- /* 28 */
- OPCODE(fnTheyDoWeWait),
- OPCODE(fnTheyDo),
- OPCODE(fnWalkToTalkToMega),
- OPCODE(fnFadeDown),
- /* 2C */
- OPCODE(fnISpeak),
- OPCODE(fnTotalRestart),
- OPCODE(fnSetWalkGrid),
- OPCODE(fnSpeechProcess),
- /* 30 */
- OPCODE(fnSetScaling),
- OPCODE(fnStartEvent),
- OPCODE(fnCheckEventWaiting),
- OPCODE(fnRequestSpeech),
- /* 34 */
- OPCODE(fnGosub),
- OPCODE(fnTimedWait),
- OPCODE(fnPlayFx),
- OPCODE(fnStopFx),
- /* 38 */
- OPCODE(fnPlayMusic),
- OPCODE(fnStopMusic),
- OPCODE(fnSetValue),
- OPCODE(fnNewScript),
- /* 3C */
- OPCODE(fnGetSync),
- OPCODE(fnWaitSync),
- OPCODE(fnRegisterWalkGrid),
- OPCODE(fnReverseMegaTableAnim),
- /* 40 */
- OPCODE(fnReverseAnim),
- OPCODE(fnAddToKillList),
- OPCODE(fnSetStandbyCoords),
- OPCODE(fnBackPar0Sprite),
- /* 44 */
- OPCODE(fnBackPar1Sprite),
- OPCODE(fnForePar0Sprite),
- OPCODE(fnForePar1Sprite),
- OPCODE(fnSetPlayerActionEvent),
- /* 48 */
- OPCODE(fnSetScrollCoordinate),
- OPCODE(fnStandAtAnim),
- OPCODE(fnSetScrollLeftMouse),
- OPCODE(fnSetScrollRightMouse),
- /* 4C */
- OPCODE(fnColour),
- OPCODE(fnFlash),
- OPCODE(fnPreFetch),
- OPCODE(fnGetPlayerSaveData),
- /* 50 */
- OPCODE(fnPassPlayerSaveData),
- OPCODE(fnSendEvent),
- OPCODE(fnAddWalkGrid),
- OPCODE(fnRemoveWalkGrid),
- /* 54 */
- OPCODE(fnCheckForEvent),
- OPCODE(fnPauseForEvent),
- OPCODE(fnClearEvent),
- OPCODE(fnFaceMega),
- /* 58 */
- OPCODE(fnPlaySequence),
- OPCODE(fnShadedSprite),
- OPCODE(fnUnshadedSprite),
- OPCODE(fnFadeUp),
- /* 5C */
- OPCODE(fnDisplayMsg),
- OPCODE(fnSetObjectHeld),
- OPCODE(fnAddSequenceText),
- OPCODE(fnResetGlobals),
- /* 60 */
- OPCODE(fnSetPalette),
- OPCODE(fnRegisterPointerText),
- OPCODE(fnFetchWait),
- OPCODE(fnRelease),
- /* 64 */
- OPCODE(fnPrepareMusic),
- OPCODE(fnSoundFetch),
- OPCODE(fnPrepareMusic), // Again, apparently
- OPCODE(fnSmackerLeadIn),
- /* 68 */
- OPCODE(fnSmackerLeadOut),
- OPCODE(fnStopAllFx),
- OPCODE(fnCheckPlayerActivity),
- OPCODE(fnResetPlayerActivityDelay),
- /* 6C */
- OPCODE(fnCheckMusicPlaying),
- OPCODE(fnPlayCredits),
- OPCODE(fnSetScrollSpeedNormal),
- OPCODE(fnSetScrollSpeedSlow),
- /* 70 */
- OPCODE(fnRemoveChooser),
- OPCODE(fnSetFxVolAndPan),
- OPCODE(fnSetFxVol),
- OPCODE(fnRestoreGame),
- /* 74 */
- OPCODE(fnRefreshInventory),
- OPCODE(fnChangeShadows)
-};
-
-#define push(value) \
-do { \
- assert(stackPtr < ARRAYSIZE(stack)); \
- stack[stackPtr++] = (value); \
-} while (false)
-
-#define push_ptr(ptr) push(_vm->_memory->encodePtr(ptr))
-
-#define pop() (assert(stackPtr < ARRAYSIZE(stack)), stack[--stackPtr])
-
-int Logic::runResScript(uint32 scriptRes, uint32 offset) {
- byte *scriptAddr;
- int result;
-
- scriptAddr = _vm->_resman->openResource(scriptRes);
- result = runScript(scriptAddr, scriptAddr, offset);
- _vm->_resman->closeResource(scriptRes);
-
- return result;
-}
-
-int Logic::runResObjScript(uint32 scriptRes, uint32 objRes, uint32 offset) {
- byte *scriptAddr, *objAddr;
- int result;
-
- scriptAddr = _vm->_resman->openResource(scriptRes);
- objAddr = _vm->_resman->openResource(objRes);
- result = runScript(scriptAddr, objAddr, offset);
- _vm->_resman->closeResource(objRes);
- _vm->_resman->closeResource(scriptRes);
-
- return result;
-}
-
-int Logic::runScript(byte *scriptData, byte *objectData, uint32 offset) {
- byte pc[4];
-
- WRITE_LE_UINT32(pc, offset);
- return runScript2(scriptData, objectData, pc);
-}
-
-// This form of the runScript function is only called directly from
-// the processSession() function, which uses it to update the script PC in the
-// current object hub. For reasons which I do not understand, I couldn't get it
-// to work if I called the function first with a dummy offset variable, and
-// and then updated the object hub myself.
-
-int Logic::runScript2(byte *scriptData, byte *objectData, byte *offsetPtr) {
- // Interestingly, unlike our BASS engine the stack is a local variable.
- // I don't know whether or not this is relevant to the working of the
- // BS2 engine.
-
- int32 stack[STACK_SIZE];
- int32 stackPtr = 0;
-
- uint32 offset = READ_LE_UINT32(offsetPtr);
-
- ResHeader header;
-
- header.read(scriptData);
-
- scriptData += ResHeader::size() + ObjectHub::size();
-
- // The script data format:
- // int32_TYPE 1 Size of variable space in bytes
- // ... The variable space
- // int32_TYPE 1 numberOfScripts
- // int32_TYPE numberOfScripts The offsets for each script
-
- // Initialise some stuff
-
- uint32 ip = 0; // Code pointer
- int scriptNumber;
-
- // Get the start of variables and start of code
-
- byte *localVars = scriptData + 4;
- byte *code = scriptData + READ_LE_UINT32(scriptData) + 4;
- uint32 noScripts = READ_LE_UINT32(code);
-
- code += 4;
-
- byte *offsetTable = code;
-
- if (offset < noScripts) {
- ip = READ_LE_UINT32(offsetTable + offset * 4);
- scriptNumber = offset;
- debug(8, "Starting script %d from %d", scriptNumber, ip);
- } else {
- uint i;
-
- ip = offset;
-
- for (i = 1; i < noScripts; i++) {
- if (READ_LE_UINT32(offsetTable + 4 * i) >= ip)
- break;
- }
-
- scriptNumber = i - 1;
- debug(8, "Resuming script %d from %d", scriptNumber, ip);
- }
-
- // There are a couple of known script bugs related to interacting with
- // certain objects. We try to work around a few of them.
-
- bool checkMopBug = false;
- bool checkPyramidBug = false;
- bool checkElevatorBug = false;
-
- if (scriptNumber == 2) {
- if (strcmp((char *)header.name, "mop_73") == 0)
- checkMopBug = true;
- else if (strcmp((char *)header.name, "titipoco_81") == 0)
- checkPyramidBug = true;
- else if (strcmp((char *)header.name, "lift_82") == 0)
- checkElevatorBug = true;
- }
-
- code += noScripts * 4;
-
- // Code should now be pointing at an identifier and a checksum
- byte *checksumBlock = code;
-
- code += 4 * 3;
-
- if (READ_LE_UINT32(checksumBlock) != 12345678) {
- error("Invalid script in object %s", header.name);
- return 0;
- }
-
- int32 codeLen = READ_LE_UINT32(checksumBlock + 4);
- int32 checksum = 0;
-
- for (int i = 0; i < codeLen; i++)
- checksum += (unsigned char) code[i];
-
- if (checksum != (int32)READ_LE_UINT32(checksumBlock + 8)) {
- debug(1, "Checksum error in object %s", header.name);
- // This could be bad, but there has been a report about someone
- // who had problems running the German version because of
- // checksum errors. Could there be a version where checksums
- // weren't properly calculated?
- }
-
- bool runningScript = true;
-
- int parameterReturnedFromMcodeFunction = 0; // Allow scripts to return things
- int savedStartOfMcode = 0; // For saving start of mcode commands
-
- while (runningScript) {
- int i;
- int32 a, b;
- int curCommand, parameter, value; // Command and parameter variables
- int retVal;
- int caseCount;
- bool foundCase;
- byte *ptr;
-
- curCommand = code[ip++];
-
- switch (curCommand) {
-
- // Script-related opcodes
-
- case CP_END_SCRIPT:
- // End the script
- runningScript = false;
-
- // WORKAROUND: The dreaded pyramid bug makes the torch
- // untakeable when you speak to Titipoco. This is
- // because one of the conditions for the torch to be
- // takeable is that Titipoco isn't doing anything out
- // of the ordinary. Global variable 913 has to be 0 to
- // signify that he is in his "idle" state.
- //
- // Unfortunately, simply the act of speaking to him
- // sets variable 913 to 1 (probably to stop him from
- // turning around every now and then). The script may
- // then go on to set the variable to different values
- // to trigger various behaviours in him, but if you
- // have run out of these cases the script won't ever
- // set it back to 0 again.
- //
- // So if his click hander finishes, and variable 913 is
- // 1, we set it back to 0 manually.
-
- if (checkPyramidBug && readVar(913) == 1) {
- warning("Working around pyramid bug: Resetting Titipoco's state");
- writeVar(913, 0);
- }
-
- // WORKAROUND: The not-so-known-but-should-be-dreaded
- // elevator bug.
- //
- // The click handler for the top of the elevator only
- // handles using the elevator, not examining it. When
- // examining it, the mouse cursor is removed but never
- // restored.
-
- if (checkElevatorBug && readVar(RIGHT_BUTTON)) {
- warning("Working around elevator bug: Restoring mouse pointer");
- fnAddHuman(NULL);
- }
-
- debug(9, "CP_END_SCRIPT");
- break;
- case CP_QUIT:
- // Quit out for a cycle
- WRITE_LE_UINT32(offsetPtr, ip);
- debug(9, "CP_QUIT");
- return 0;
- case CP_TERMINATE:
- // Quit out immediately without affecting the offset
- // pointer
- debug(9, "CP_TERMINATE");
- return 3;
- case CP_RESTART_SCRIPT:
- // Start the script again
- ip = FROM_LE_32(offsetTable[scriptNumber]);
- debug(9, "CP_RESTART_SCRIPT");
- break;
-
- // Stack-related opcodes
-
- case CP_PUSH_INT32:
- // Push a long word value on to the stack
- Read32ip(parameter);
- push(parameter);
- debug(9, "CP_PUSH_INT32: %d", parameter);
- break;
- case CP_PUSH_LOCAL_VAR32:
- // Push the contents of a local variable
- Read16ip(parameter);
- push(READ_LE_UINT32(localVars + parameter));
- debug(9, "CP_PUSH_LOCAL_VAR32: localVars[%d] => %d", parameter / 4, READ_LE_UINT32(localVars + parameter));
- break;
- case CP_PUSH_GLOBAL_VAR32:
- // Push a global variable
- Read16ip(parameter);
- push(readVar(parameter));
- debug(9, "CP_PUSH_GLOBAL_VAR32: scriptVars[%d] => %d", parameter, readVar(parameter));
- break;
- case CP_PUSH_LOCAL_ADDR:
- // Push the address of a local variable
-
- // From what I understand, some scripts store data
- // (e.g. mouse pointers) in their local variable space
- // from the very beginning, and use this mechanism to
- // pass that data to the opcode function. I don't yet
- // know the conceptual difference between this and the
- // CP_PUSH_DEREFERENCED_STRUCTURE opcode.
-
- Read16ip(parameter);
- push_ptr(localVars + parameter);
- debug(9, "CP_PUSH_LOCAL_ADDR: &localVars[%d] => %p", parameter / 4, localVars + parameter);
- break;
- case CP_PUSH_STRING:
- // Push the address of a string on to the stack
- // Get the string size
- Read8ip(parameter);
-
- // ip now points to the string
- ptr = code + ip;
- push_ptr(ptr);
- debug(9, "CP_PUSH_STRING: \"%s\"", ptr);
- ip += (parameter + 1);
- break;
- case CP_PUSH_DEREFERENCED_STRUCTURE:
- // Push the address of a dereferenced structure
- Read32ip(parameter);
- ptr = objectData + 4 + ResHeader::size() + ObjectHub::size() + parameter;
- push_ptr(ptr);
- debug(9, "CP_PUSH_DEREFERENCED_STRUCTURE: %d => %p", parameter, ptr);
- break;
- case CP_POP_LOCAL_VAR32:
- // Pop a value into a local word variable
- Read16ip(parameter);
- value = pop();
- WRITE_LE_UINT32(localVars + parameter, value);
- debug(9, "CP_POP_LOCAL_VAR32: localVars[%d] = %d", parameter / 4, value);
- break;
- case CP_POP_GLOBAL_VAR32:
- // Pop a global variable
- Read16ip(parameter);
- value = pop();
-
- // WORKAROUND for bug #1214168: The not-at-all dreaded
- // mop bug.
- //
- // At the London Docks, global variable 1003 keeps
- // track of Nico:
- //
- // 0: Hiding behind the first crate.
- // 1: Hiding behind the second crate.
- // 2: Standing in plain view on the deck.
- // 3: Hiding on the roof.
- //
- // The bug happens when trying to pick up the mop while
- // hiding on the roof. Nico climbs down, the mop is
- // picked up, but the variable remains set to 3.
- // Visually, everything looks ok. But as far as the
- // scripts are concerned, she's still hiding up on the
- // roof. This is not fatal, but leads to a number of
- // glitches until the state is corrected. E.g. trying
- // to climb back up the ladder will cause Nico to climb
- // down again.
- //
- // Global variable 1017 keeps track of the mop. Setting
- // it to 2 means that the mop has been picked up. We
- // use that as the signal that Nico's state needs to be
- // updated as well.
-
- if (checkMopBug && parameter == 1017 && readVar(1003) != 2) {
- warning("Working around mop bug: Setting Nico's state");
- writeVar(1003, 2);
- }
-
- writeVar(parameter, value);
- debug(9, "CP_POP_GLOBAL_VAR32: scriptsVars[%d] = %d", parameter, value);
- break;
- case CP_ADDNPOP_LOCAL_VAR32:
- Read16ip(parameter);
- value = READ_LE_UINT32(localVars + parameter) + pop();
- WRITE_LE_UINT32(localVars + parameter, value);
- debug(9, "CP_ADDNPOP_LOCAL_VAR32: localVars[%d] => %d", parameter / 4, value);
- break;
- case CP_SUBNPOP_LOCAL_VAR32:
- Read16ip(parameter);
- value = READ_LE_UINT32(localVars + parameter) - pop();
- WRITE_LE_UINT32(localVars + parameter, value);
- debug(9, "CP_SUBNPOP_LOCAL_VAR32: localVars[%d] => %d", parameter / 4, value);
- break;
- case CP_ADDNPOP_GLOBAL_VAR32:
- // Add and pop a global variable
- Read16ip(parameter);
- value = readVar(parameter) + pop();
- writeVar(parameter, value);
- debug(9, "CP_ADDNPOP_GLOBAL_VAR32: scriptVars[%d] => %d", parameter, value);
- break;
- case CP_SUBNPOP_GLOBAL_VAR32:
- // Sub and pop a global variable
- Read16ip(parameter);
- value = readVar(parameter) - pop();
- writeVar(parameter, value);
- debug(9, "CP_SUBNPOP_GLOBAL_VAR32: scriptVars[%d] => %d", parameter, value);
- break;
-
- // Jump opcodes
-
- case CP_SKIPONTRUE:
- // Skip if the value on the stack is true
- Read32ipLeaveip(parameter);
- value = pop();
- if (!value) {
- ip += 4;
- debug(9, "CP_SKIPONTRUE: %d (IS FALSE (NOT SKIPPED))", parameter);
- } else {
- ip += parameter;
- debug(9, "CP_SKIPONTRUE: %d (IS TRUE (SKIPPED))", parameter);
- }
- break;
- case CP_SKIPONFALSE:
- // Skip if the value on the stack is false
- Read32ipLeaveip(parameter);
- value = pop();
- if (value) {
- ip += 4;
- debug(9, "CP_SKIPONFALSE: %d (IS TRUE (NOT SKIPPED))", parameter);
- } else {
- ip += parameter;
- debug(9, "CP_SKIPONFALSE: %d (IS FALSE (SKIPPED))", parameter);
- }
- break;
- case CP_SKIPALWAYS:
- // skip a block
- Read32ipLeaveip(parameter);
- ip += parameter;
- debug(9, "CP_SKIPALWAYS: %d", parameter);
- break;
- case CP_SWITCH:
- // switch
- value = pop();
- Read32ip(caseCount);
-
- // Search the cases
- foundCase = false;
- for (i = 0; i < caseCount && !foundCase; i++) {
- if (value == (int32)READ_LE_UINT32(code + ip)) {
- // We have found the case, so lets
- // jump to it
- foundCase = true;
- ip += READ_LE_UINT32(code + ip + 4);
- } else
- ip += 4 * 2;
- }
-
- // If we found no matching case then use the default
-
- if (!foundCase)
- ip += READ_LE_UINT32(code + ip);
-
- debug(9, "CP_SWITCH: [SORRY, NO DEBUG INFO]");
- break;
- case CP_SAVE_MCODE_START:
- // Save the start position on an mcode instruction in
- // case we need to restart it again
- savedStartOfMcode = ip - 1;
- debug(9, "CP_SAVE_MCODE_START");
- break;
- case CP_CALL_MCODE:
- // Call an mcode routine
- Read16ip(parameter);
- assert(parameter < ARRAYSIZE(opcodes));
- // amount to adjust stack by (no of parameters)
- Read8ip(value);
- debug(9, "CP_CALL_MCODE: '%s', %d", opcodes[parameter].desc, value);
- stackPtr -= value;
- assert(stackPtr >= 0);
- retVal = (this->*opcodes[parameter].proc)(&stack[stackPtr]);
-
- switch (retVal & 7) {
- case IR_STOP:
- // Quit out for a cycle
- WRITE_LE_UINT32(offsetPtr, ip);
- return 0;
- case IR_CONT:
- // Continue as normal
- break;
- case IR_TERMINATE:
- // Return without updating the offset
- return 2;
- case IR_REPEAT:
- // Return setting offset to start of this
- // function call
- WRITE_LE_UINT32(offsetPtr, savedStartOfMcode);
- return 0;
- case IR_GOSUB:
- // that's really neat
- WRITE_LE_UINT32(offsetPtr, ip);
- return 2;
- default:
- error("Bad return code (%d) from '%s'", retVal & 7, opcodes[parameter].desc);
- }
- parameterReturnedFromMcodeFunction = retVal >> 3;
- break;
- case CP_JUMP_ON_RETURNED:
- // Jump to a part of the script depending on
- // the return value from an mcode routine
-
- // Get the maximum value
- Read8ip(parameter);
- debug(9, "CP_JUMP_ON_RETURNED: %d => %d",
- parameterReturnedFromMcodeFunction,
- READ_LE_UINT32(code + ip + parameterReturnedFromMcodeFunction * 4));
- ip += READ_LE_UINT32(code + ip + parameterReturnedFromMcodeFunction * 4);
- break;
-
- // Operators
-
- case OP_ISEQUAL:
- b = pop();
- a = pop();
- push(a == b);
- debug(9, "OP_ISEQUAL: RESULT = %d", a == b);
- break;
- case OP_NOTEQUAL:
- b = pop();
- a = pop();
- push(a != b);
- debug(9, "OP_NOTEQUAL: RESULT = %d", a != b);
- break;
- case OP_GTTHAN:
- b = pop();
- a = pop();
- push(a > b);
- debug(9, "OP_GTTHAN: RESULT = %d", a > b);
- break;
- case OP_LSTHAN:
- b = pop();
- a = pop();
- push(a < b);
- debug(9, "OP_LSTHAN: RESULT = %d", a < b);
- break;
- case OP_GTTHANE:
- b = pop();
- a = pop();
- push(a >= b);
- debug(9, "OP_GTTHANE: RESULT = %d", a >= b);
- break;
- case OP_LSTHANE:
- b = pop();
- a = pop();
- push(a <= b);
- debug(9, "OP_LSTHANE: RESULT = %d", a <= b);
- break;
- case OP_PLUS:
- b = pop();
- a = pop();
- push(a + b);
- debug(9, "OP_PLUS: RESULT = %d", a + b);
- break;
- case OP_MINUS:
- b = pop();
- a = pop();
- push(a - b);
- debug(9, "OP_MINUS: RESULT = %d", a - b);
- break;
- case OP_TIMES:
- b = pop();
- a = pop();
- push(a * b);
- debug(9, "OP_TIMES: RESULT = %d", a * b);
- break;
- case OP_DIVIDE:
- b = pop();
- a = pop();
- push(a / b);
- debug(9, "OP_DIVIDE: RESULT = %d", a / b);
- break;
- case OP_ANDAND:
- b = pop();
- a = pop();
- push(a && b);
- debug(9, "OP_ANDAND: RESULT = %d", a && b);
- break;
- case OP_OROR:
- b = pop();
- a = pop();
- push(a || b);
- debug(9, "OP_OROR: RESULT = %d", a || b);
- break;
-
- // Debugging opcodes, I think
-
- case CP_DEBUGON:
- debug(9, "CP_DEBUGON");
- break;
- case CP_DEBUGOFF:
- debug(9, "CP_DEBUGOFF");
- break;
- case CP_TEMP_TEXT_PROCESS:
- Read32ip(parameter);
- debug(9, "CP_TEMP_TEXT_PROCESS: %d", parameter);
- break;
- default:
- error("Invalid script command %d", curCommand);
- return 3;
- }
- }
-
- return 1;
-}
-
-} // End of namespace Sword2