[Scummvm-cvs-logs] SF.net SVN: scummvm:[41773] scummvm/trunk/engines/gob
drmccoy at users.sourceforge.net
drmccoy at users.sourceforge.net
Mon Jun 22 18:30:35 CEST 2009
Revision: 41773
http://scummvm.svn.sourceforge.net/scummvm/?rev=41773&view=rev
Author: drmccoy
Date: 2009-06-22 16:30:35 +0000 (Mon, 22 Jun 2009)
Log Message:
-----------
Renaming parse.h and parse.cpp to expression.h and expression.cpp
Modified Paths:
--------------
scummvm/trunk/engines/gob/gob.cpp
scummvm/trunk/engines/gob/inter.cpp
scummvm/trunk/engines/gob/inter_v1.cpp
scummvm/trunk/engines/gob/inter_v2.cpp
scummvm/trunk/engines/gob/inter_v6.cpp
scummvm/trunk/engines/gob/module.mk
scummvm/trunk/engines/gob/script.cpp
Added Paths:
-----------
scummvm/trunk/engines/gob/expression.cpp
scummvm/trunk/engines/gob/expression.h
Removed Paths:
-------------
scummvm/trunk/engines/gob/parse.cpp
scummvm/trunk/engines/gob/parse.h
Copied: scummvm/trunk/engines/gob/expression.cpp (from rev 41772, scummvm/trunk/engines/gob/parse.cpp)
===================================================================
--- scummvm/trunk/engines/gob/expression.cpp (rev 0)
+++ scummvm/trunk/engines/gob/expression.cpp 2009-06-22 16:30:35 UTC (rev 41773)
@@ -0,0 +1,1145 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+
+#include "gob/gob.h"
+#include "gob/expression.h"
+#include "gob/global.h"
+#include "gob/game.h"
+#include "gob/script.h"
+#include "gob/inter.h"
+
+namespace Gob {
+
+Expression::Stack::Stack(size_t size) {
+ opers = new byte[size];
+ values = new int32[size];
+ memset(opers , 0, size * sizeof(byte ));
+ memset(values, 0, size * sizeof(int32));
+}
+
+Expression::Stack::~Stack() {
+ delete[] opers;
+ delete[] values;
+}
+
+Expression::StackFrame::StackFrame(const Stack &stack) {
+ opers = stack.opers - 1;
+ values = stack.values - 1;
+ pos = -1;
+}
+
+void Expression::StackFrame::push(int count) {
+ opers += count;
+ values += count;
+ pos += count;
+}
+
+void Expression::StackFrame::pop(int count) {
+ opers -= count;
+ values -= count;
+ pos -= count;
+}
+
+Expression::Expression(GobEngine *vm) : _vm(vm) {
+ _resultStr[0] = 0;
+ _resultInt = 0;
+}
+
+int32 Expression::encodePtr(byte *ptr, int type) {
+ int32 offset = 0;
+
+ switch (type) {
+ case kExecPtr:
+ offset = _vm->_game->_script->getOffset(ptr);
+ break;
+ case kInterVar:
+ offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0));
+ break;
+ case kResStr:
+ offset = ptr - ((byte *) _resultStr);
+ break;
+ default:
+ error("Expression::encodePtr(): Unknown pointer type");
+ }
+ assert((offset & 0xF0000000) == 0);
+ return (type << 28) | offset;
+}
+
+byte *Expression::decodePtr(int32 n) {
+ byte *ptr;
+
+ switch (n >> 28) {
+ case kExecPtr:
+ ptr = _vm->_game->_script->getData();
+ break;
+ case kInterVar:
+ ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0);
+ break;
+ case kResStr:
+ ptr = (byte *) _resultStr;
+ break;
+ default:
+ error("Expression::decodePtr(): Unknown pointer type");
+ }
+ return ptr + (n & 0x0FFFFFFF);
+}
+
+void Expression::skipExpr(char stopToken) {
+ int16 dimCount;
+ byte operation;
+ int16 num;
+ int16 dim;
+
+ num = 0;
+ while (true) {
+ operation = _vm->_game->_script->readByte();
+
+ if ((operation >= 14) && (operation <= OP_FUNC)) {
+ switch (operation) {
+ case 14:
+ _vm->_game->_script->skip(4);
+ if (_vm->_game->_script->peekByte() == 97)
+ _vm->_game->_script->skip(1);
+ break;
+
+ case OP_LOAD_VAR_INT16:
+ case OP_LOAD_VAR_INT8:
+ case OP_LOAD_IMM_INT16:
+ case OP_LOAD_VAR_INT32:
+ case OP_LOAD_VAR_INT32_AS_INT16:
+ _vm->_game->_script->skip(2);
+ break;
+
+ case OP_LOAD_IMM_INT32:
+ _vm->_game->_script->skip(4);
+ break;
+
+ case OP_LOAD_IMM_INT8:
+ _vm->_game->_script->skip(1);
+ break;
+
+ case OP_LOAD_IMM_STR:
+ _vm->_game->_script->skip(strlen(_vm->_game->_script->peekString()) + 1);
+ break;
+
+ case OP_LOAD_VAR_STR:
+ _vm->_game->_script->skip(2);
+ if (_vm->_game->_script->peekByte() == 13) {
+ _vm->_game->_script->skip(1);
+ skipExpr(OP_END_MARKER);
+ }
+ break;
+
+ case 15:
+ _vm->_game->_script->skip(2);
+
+ case OP_ARRAY_INT8:
+ case OP_ARRAY_INT32:
+ case OP_ARRAY_INT16:
+ case OP_ARRAY_STR:
+ dimCount = _vm->_game->_script->peekByte(2);
+ // skip header and dimensions
+ _vm->_game->_script->skip(3 + dimCount);
+ // skip indices
+ for (dim = 0; dim < dimCount; dim++)
+ skipExpr(OP_END_MARKER);
+
+ if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) {
+ _vm->_game->_script->skip(1);
+ skipExpr(OP_END_MARKER);
+ }
+ break;
+
+ case OP_FUNC:
+ _vm->_game->_script->skip(1);
+ skipExpr(OP_END_EXPR);
+ }
+ continue;
+ } // if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC))
+
+ if (operation == OP_BEGIN_EXPR) {
+ num++;
+ continue;
+ }
+
+ if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8)))
+ continue;
+
+ if ((operation >= OP_OR) && (operation <= OP_NEQ))
+ continue;
+
+ if (operation == OP_END_EXPR)
+ num--;
+
+ if (operation != stopToken)
+ continue;
+
+ if ((stopToken != OP_END_EXPR) || (num < 0))
+ return;
+ }
+}
+
+void Expression::printExpr(char stopToken) {
+ // Expression printing disabled by default
+ return;
+
+ int32 savedPos = _vm->_game->_script->pos();
+ printExpr_internal(stopToken);
+
+ // restore IP to start of expression
+ _vm->_game->_script->seek(savedPos);
+}
+
+void Expression::printExpr_internal(char stopToken) {
+ int16 dimCount;
+ byte operation;
+ int16 num;
+ int16 dim;
+ byte *arrDesc;
+ byte func;
+
+ num = 0;
+ while (true) {
+ operation = _vm->_game->_script->readByte();
+
+ if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) {
+ // operands
+
+ switch (operation) {
+ case OP_LOAD_VAR_INT16: // int16 variable load
+ debugN(5, "var16_%d", _vm->_game->_script->readUint16());
+ break;
+
+ case OP_LOAD_VAR_INT8: // int8 variable load:
+ debugN(5, "var8_%d", _vm->_game->_script->readUint16());
+ break;
+
+ case OP_LOAD_IMM_INT32: // int32/uint32 immediate
+ debugN(5, "%d", _vm->_game->_script->readInt32());
+ break;
+
+ case OP_LOAD_IMM_INT16: // int16 immediate
+ debugN(5, "%d", _vm->_game->_script->readInt16());
+ break;
+
+ case OP_LOAD_IMM_INT8: // int8 immediate
+ debugN(5, "%d", _vm->_game->_script->readInt8());
+ break;
+
+ case OP_LOAD_IMM_STR: // string immediate
+ debugN(5, "\42%s\42", _vm->_game->_script->readString());
+ break;
+
+ case OP_LOAD_VAR_INT32:
+ case OP_LOAD_VAR_INT32_AS_INT16:
+ debugN(5, "var_%d", _vm->_game->_script->readUint16());
+ break;
+
+ case OP_LOAD_VAR_STR: // string variable load
+ debugN(5, "(&var_%d)", _vm->_game->_script->readUint16());
+ if (_vm->_game->_script->peekByte() == 13) {
+ _vm->_game->_script->skip(1);
+ debugN(5, "{");
+ printExpr_internal(OP_END_MARKER); // this also prints the closing }
+ }
+ break;
+
+ case OP_ARRAY_INT8: // int8 array access
+ case OP_ARRAY_INT32: // int32 array access
+ case OP_ARRAY_INT16: // int16 array access
+ case OP_ARRAY_STR: // string array access
+ debugN(5, "\n");
+ if (operation == OP_ARRAY_STR)
+ debugN(5, "(&");
+
+ debugN(5, "var_%d[", _vm->_game->_script->readInt16());
+ dimCount = _vm->_game->_script->readByte();
+ arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos();
+ _vm->_game->_script->skip(dimCount);
+ for (dim = 0; dim < dimCount; dim++) {
+ printExpr_internal(OP_END_MARKER);
+ debugN(5, " of %d", (int16) arrDesc[dim]);
+ if (dim != dimCount - 1)
+ debugN(5, ",");
+ }
+ debugN(5, "]");
+ if (operation == OP_ARRAY_STR)
+ debugN(5, ")");
+
+ if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) {
+ _vm->_game->_script->skip(1);
+ debugN(5, "{");
+ printExpr_internal(OP_END_MARKER); // this also prints the closing }
+ }
+ break;
+
+ case OP_FUNC: // function
+ func = _vm->_game->_script->readByte();
+ if (func == FUNC_SQR)
+ debugN(5, "sqr(");
+ else if (func == FUNC_RAND)
+ debugN(5, "rand(");
+ else if (func == FUNC_ABS)
+ debugN(5, "abs(");
+ else if ((func == FUNC_SQRT1) || (func == FUNC_SQRT2) || (func == FUNC_SQRT3))
+ debugN(5, "sqrt(");
+ else
+ debugN(5, "id(");
+ printExpr_internal(OP_END_EXPR);
+ break;
+ }
+ continue;
+ } // if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC))
+
+ // operators
+ switch (operation) {
+ case OP_BEGIN_EXPR:
+ debugN(5, "(");
+ break;
+
+ case OP_NOT:
+ debugN(5, "!");
+ break;
+
+ case OP_END_EXPR:
+ debugN(5, ")");
+ break;
+
+ case OP_NEG:
+ debugN(5, "-");
+ break;
+
+ case OP_ADD:
+ debugN(5, "+");
+ break;
+
+ case OP_SUB:
+ debugN(5, "-");
+ break;
+
+ case OP_BITOR:
+ debugN(5, "|");
+ break;
+
+ case OP_MUL:
+ debugN(5, "*");
+ break;
+
+ case OP_DIV:
+ debugN(5, "/");
+ break;
+
+ case OP_MOD:
+ debugN(5, "%%");
+ break;
+
+ case OP_BITAND:
+ debugN(5, "&");
+ break;
+
+ case OP_OR:
+ debugN(5, "||");
+ break;
+
+ case 31:
+ debugN(5, "&&");
+ break;
+
+ case OP_LESS:
+ debugN(5, "<");
+ break;
+
+ case OP_LEQ:
+ debugN(5, "<=");
+ break;
+
+ case OP_GREATER:
+ debugN(5, ">");
+ break;
+
+ case OP_GEQ:
+ debugN(5, ">=");
+ break;
+
+ case OP_EQ:
+ debugN(5, "==");
+ break;
+
+ case OP_NEQ:
+ debugN(5, "!=");
+ break;
+
+ case 99:
+ debugN(5, "\n");
+ break;
+
+ case OP_END_MARKER:
+ debugN(5, "}");
+ if (stopToken != OP_END_MARKER) {
+ debugN(5, "Closing paren without opening?");
+ }
+ break;
+
+ default:
+ debugN(5, "<%d>", (int16) operation);
+ error("Expression::printExpr(): invalid operator in expression");
+ break;
+ }
+
+ if (operation == OP_BEGIN_EXPR) {
+ num++;
+ continue;
+ }
+
+ if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8)))
+ continue;
+
+ if ((operation >= OP_OR) && (operation <= OP_NEQ))
+ continue;
+
+ if (operation == OP_END_EXPR)
+ num--;
+
+ if (operation == stopToken) {
+ if ((stopToken != OP_END_EXPR) || (num < 0)) {
+ return;
+ }
+ }
+ }
+}
+
+
+void Expression::printVarIndex() {
+ byte *arrDesc;
+ int16 dim;
+ int16 dimCount;
+ int16 operation;
+ int16 temp;
+
+ int32 pos = _vm->_game->_script->pos();
+
+ operation = _vm->_game->_script->readByte();
+ switch (operation) {
+ case OP_LOAD_VAR_INT32:
+ case OP_LOAD_VAR_STR:
+ temp = _vm->_game->_script->readUint16() * 4;
+ debugN(5, "&var_%d", temp);
+ if ((operation == OP_LOAD_VAR_STR) && (_vm->_game->_script->peekByte() == 13)) {
+ _vm->_game->_script->skip(1);
+ debugN(5, "+");
+ printExpr(OP_END_MARKER);
+ }
+ break;
+
+ case OP_ARRAY_INT32:
+ case OP_ARRAY_STR:
+ debugN(5, "&var_%d[", _vm->_game->_script->readUint16());
+ dimCount = _vm->_game->_script->readByte();
+ arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos();
+ _vm->_game->_script->skip(dimCount);
+ for (dim = 0; dim < dimCount; dim++) {
+ printExpr(OP_END_MARKER);
+ debugN(5, " of %d", (int16) arrDesc[dim]);
+ if (dim != dimCount - 1)
+ debugN(5, ",");
+ }
+ debugN(5, "]");
+
+ if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) {
+ _vm->_game->_script->skip(1);
+ debugN(5, "+");
+ printExpr(OP_END_MARKER);
+ }
+ break;
+
+ default:
+ debugN(5, "var_0");
+ break;
+ }
+ debugN(5, "\n");
+
+ _vm->_game->_script->seek(pos);
+ return;
+}
+
+int Expression::cmpHelper(const StackFrame &stackFrame) {
+ byte type = stackFrame.opers[-3];
+ int cmpTemp = 0;
+
+ if (type == OP_LOAD_IMM_INT16) {
+ cmpTemp = (int)stackFrame.values[-3] - (int)stackFrame.values[-1];
+ } else if (type == OP_LOAD_IMM_STR) {
+ if ((char *)decodePtr(stackFrame.values[-3]) != _resultStr) {
+ strcpy(_resultStr, (char *)decodePtr(stackFrame.values[-3]));
+ stackFrame.values[-3] = encodePtr((byte *) _resultStr, kResStr);
+ }
+ cmpTemp = strcmp(_resultStr, (char *)decodePtr(stackFrame.values[-1]));
+ }
+
+ return cmpTemp;
+}
+
+bool Expression::getVarBase(uint32 &varBase, bool mindStop,
+ uint16 *size, uint16 *type) {
+
+ varBase = 0;
+
+ byte operation = _vm->_game->_script->peekByte();
+ while ((operation == 14) || (operation == 15)) {
+ _vm->_game->_script->skip(1);
+
+ if (operation == 14) {
+ // Add a direct offset
+
+ varBase += _vm->_game->_script->readInt16() * 4;
+
+ if (size)
+ *size = _vm->_game->_script->peekUint16();
+ if (type)
+ *type = 14;
+
+ _vm->_game->_script->skip(2);
+
+ debugC(2, kDebugParser, "varBase: %d, by %d", varBase, operation);
+
+ if (_vm->_game->_script->peekByte() != 97) {
+ if (mindStop)
+ return true;
+ } else
+ _vm->_game->_script->skip(1);
+
+ } else if (operation == 15) {
+ // Add an offset from an array
+
+ varBase += _vm->_game->_script->readInt16() * 4;
+
+ uint16 offset1 = _vm->_game->_script->readUint16();
+
+ if (size)
+ *size = offset1;
+ if (type)
+ *type = 15;
+
+ uint8 dimCount = _vm->_game->_script->readByte();
+ byte *dimArray = _vm->_game->_script->getData() + _vm->_game->_script->pos();
+
+ _vm->_game->_script->skip(dimCount);
+
+ uint16 offset2 = 0;
+ for (int i = 0; i < dimCount; i++) {
+ int16 dim = CLIP<int>(parseValExpr(OP_END_MARKER), 0, dimArray[i] - 1);
+
+ offset2 = offset2 * dimArray[i] + dim;
+ }
+
+ varBase += offset2 * offset1 * 4;
+
+ debugC(2, kDebugParser, "varBase: %d, by %d", varBase, operation);
+
+ if (_vm->_game->_script->peekByte() != 97) {
+ if (mindStop)
+ return true;
+ } else
+ _vm->_game->_script->skip(1);
+ }
+
+ operation = _vm->_game->_script->peekByte();
+ }
+
+ return false;
+}
+
+int16 Expression::parseVarIndex(uint16 *size, uint16 *type) {
+ int16 temp2;
+ byte *arrDesc;
+ int16 dim;
+ int16 dimCount;
+ int16 operation;
+ int16 temp;
+ int16 offset;
+ int16 val;
+ uint32 varBase;
+
+ if (getVarBase(varBase, true, size, type))
+ return varBase;
+
+ operation = _vm->_game->_script->readByte();
+
+ if (size)
+ *size = 0;
+ if (type)
+ *type = operation;
+
+ debugC(5, kDebugParser, "var parse = %d", operation);
+ switch (operation) {
+ case OP_ARRAY_INT8:
+ case OP_ARRAY_INT32:
+ case OP_ARRAY_INT16:
+ case OP_ARRAY_STR:
+ temp = _vm->_game->_script->readInt16();
+ dimCount = _vm->_game->_script->readByte();
+ arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos();
+ _vm->_game->_script->skip(dimCount);
+ offset = 0;
+ for (dim = 0; dim < dimCount; dim++) {
+ temp2 = parseValExpr(OP_END_MARKER);
+ offset = arrDesc[dim] * offset + temp2;
+ }
+ if (operation == OP_ARRAY_INT8)
+ return varBase + temp + offset;
+ if (operation == OP_ARRAY_INT32)
+ return varBase + (temp + offset) * 4;
+ if (operation == OP_ARRAY_INT16)
+ return varBase + (temp + offset) * 2;
+ temp *= 4;
+ offset *= 4;
+ if (_vm->_game->_script->peekByte() == 13) {
+ _vm->_game->_script->skip(1);
+ temp += parseValExpr(OP_END_MARKER);
+ }
+ return varBase + offset * _vm->_global->_inter_animDataSize + temp;
+
+ case OP_LOAD_VAR_INT16:
+ return varBase + _vm->_game->_script->readInt16() * 2;
+
+ case OP_LOAD_VAR_INT8:
+ return varBase + _vm->_game->_script->readInt16();
+
+ case OP_LOAD_VAR_INT32:
+ case OP_LOAD_VAR_INT32_AS_INT16:
+ case OP_LOAD_VAR_STR:
+ temp = _vm->_game->_script->readInt16() * 4;
+ debugC(5, kDebugParser, "oper = %d", _vm->_game->_script->peekInt16());
+ if ((operation == OP_LOAD_VAR_STR) && (_vm->_game->_script->peekByte() == 13)) {
+ _vm->_game->_script->skip(1);
+ val = parseValExpr(OP_END_MARKER);
+ temp += val;
+ debugC(5, kDebugParser, "parse subscript = %d", val);
+ }
+ return varBase + temp;
+
+ default:
+ return 0;
+ }
+}
+
+int16 Expression::parseValExpr(byte stopToken) {
+ parseExpr(stopToken, 0);
+
+ return _resultInt;
+}
+
+// Load a value according to the operation
+void Expression::loadValue(byte operation, uint32 varBase, const StackFrame &stackFrame) {
+ int16 dimCount;
+ int16 temp;
+ int16 temp2;
+ int16 offset;
+ int16 dim;
+ byte *arrDescPtr;
+ int32 prevPrevVal;
+ int32 prevVal;
+ int32 curVal;
+
+ switch (operation) {
+ case OP_ARRAY_INT8:
+ case OP_ARRAY_INT32:
+ case OP_ARRAY_INT16:
+ case OP_ARRAY_STR:
+ *stackFrame.opers = (operation == OP_ARRAY_STR) ? OP_LOAD_IMM_STR : OP_LOAD_IMM_INT16;
+ temp = _vm->_game->_script->readInt16();
+ dimCount = _vm->_game->_script->readByte();
+ arrDescPtr = _vm->_game->_script->getData() + _vm->_game->_script->pos();
+ _vm->_game->_script->skip(dimCount);
+ offset = 0;
+ for (dim = 0; dim < dimCount; dim++) {
+ temp2 = parseValExpr(OP_END_MARKER);
+ offset = offset * arrDescPtr[dim] + temp2;
+ }
+ if (operation == OP_ARRAY_INT8)
+ *stackFrame.values = (int8) READ_VARO_UINT8(varBase + temp + offset);
+ else if (operation == OP_ARRAY_INT32)
+ *stackFrame.values = READ_VARO_UINT32(varBase + temp * 4 + offset * 4);
+ else if (operation == OP_ARRAY_INT16)
+ *stackFrame.values = (int16) READ_VARO_UINT16(varBase + temp * 2 + offset * 2);
+ else if (operation == OP_ARRAY_STR) {
+ *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8(
+ varBase + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4),
+ kInterVar);
+ if (_vm->_game->_script->peekByte() == 13) {
+ _vm->_game->_script->skip(1);
+ temp2 = parseValExpr(OP_END_MARKER);
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = READ_VARO_UINT8(varBase + temp * 4 +
+ offset * 4 * _vm->_global->_inter_animDataSize + temp2);
+ }
+ }
+ break;
+
+ case OP_LOAD_VAR_INT16:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readInt16() * 2);
+ break;
+
+ case OP_LOAD_VAR_INT8:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = (int8) READ_VARO_UINT8(varBase + _vm->_game->_script->readInt16());
+ break;
+
+ case OP_LOAD_IMM_INT32:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = _vm->_game->_script->readInt32();
+ break;
+
+ case OP_LOAD_IMM_INT16:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = _vm->_game->_script->readInt16();
+ break;
+
+ case OP_LOAD_IMM_INT8:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = _vm->_game->_script->readInt8();
+ break;
+
+ case OP_LOAD_IMM_STR:
+ *stackFrame.opers = OP_LOAD_IMM_STR;
+ *stackFrame.values = encodePtr((byte *) _vm->_game->_script->readString(), kExecPtr);
+ break;
+
+ case OP_LOAD_VAR_INT32:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = READ_VARO_UINT32(varBase + _vm->_game->_script->readInt16() * 4);
+ break;
+
+ case OP_LOAD_VAR_INT32_AS_INT16:
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readInt16() * 4);
+ break;
+
+ case OP_LOAD_VAR_STR:
+ *stackFrame.opers = OP_LOAD_IMM_STR;
+ temp = _vm->_game->_script->readInt16() * 4;
+ *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8(varBase + temp), kInterVar);
+ if (_vm->_game->_script->peekByte() == 13) {
+ _vm->_game->_script->skip(1);
+ temp += parseValExpr(OP_END_MARKER);
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = READ_VARO_UINT8(varBase + temp);
+ }
+ break;
+
+ case OP_FUNC:
+ operation = _vm->_game->_script->readByte();
+ parseExpr(OP_END_EXPR, 0);
+
+ switch (operation) {
+ case FUNC_SQRT1:
+ case FUNC_SQRT2:
+ case FUNC_SQRT3:
+ curVal = 1;
+ prevVal = 1;
+
+ do {
+ prevPrevVal = prevVal;
+ prevVal = curVal;
+ curVal = (curVal + _resultInt / curVal) / 2;
+ } while ((curVal != prevVal) && (curVal != prevPrevVal));
+ _resultInt = curVal;
+ break;
+
+ case FUNC_SQR:
+ _resultInt =
+ _resultInt * _resultInt;
+ break;
+
+ case FUNC_ABS:
+ if (_resultInt < 0)
+ _resultInt = -_resultInt;
+ break;
+
+ case FUNC_RAND:
+ _resultInt =
+ _vm->_util->getRandom(_resultInt);
+ break;
+ }
+
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ *stackFrame.values = _resultInt;
+ break;
+ }
+}
+
+void Expression::simpleArithmetic1(StackFrame &stackFrame) {
+ switch (stackFrame.opers[-1]) {
+ case OP_ADD:
+ if (stackFrame.opers[-2] == OP_LOAD_IMM_STR) {
+ if ((char *) decodePtr(stackFrame.values[-2]) != _resultStr) {
+ strcpy(_resultStr, (char *) decodePtr(stackFrame.values[-2]));
+ stackFrame.values[-2] = encodePtr((byte *) _resultStr, kResStr);
+ }
+ strcat(_resultStr, (char *) decodePtr(stackFrame.values[0]));
+ stackFrame.pop(2);
+ }
+ break;
+
+ case OP_MUL:
+ stackFrame.values[-2] *= stackFrame.values[0];
+ stackFrame.pop(2);
+ break;
+
+ case OP_DIV:
+ stackFrame.values[-2] /= stackFrame.values[0];
+ stackFrame.pop(2);
+ break;
+
+ case OP_MOD:
+ stackFrame.values[-2] %= stackFrame.values[0];
+ stackFrame.pop(2);
+ break;
+
+ case OP_BITAND:
+ stackFrame.values[-2] &= stackFrame.values[0];
+ stackFrame.pop(2);
+ break;
+ }
+}
+
+void Expression::simpleArithmetic2(StackFrame &stackFrame) {
+ if (stackFrame.pos > 1) {
+ if (stackFrame.opers[-2] == OP_NEG) {
+ stackFrame.opers[-2] = OP_LOAD_IMM_INT16;
+ stackFrame.values[-2] = -stackFrame.values[-1];
+ stackFrame.pop();
+ } else if (stackFrame.opers[-2] == OP_NOT) {
+ stackFrame.opers[-2] = (stackFrame.opers[-1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop();
+ }
+ }
+
+ if (stackFrame.pos > 2) {
+ switch (stackFrame.opers[-2]) {
+ case OP_MUL:
+ stackFrame.values[-3] *= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_DIV:
+ stackFrame.values[-3] /= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_MOD:
+ stackFrame.values[-3] %= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_BITAND:
+ stackFrame.values[-3] &= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+ }
+ }
+
+}
+
+// Complex arithmetics with brackets
+bool Expression::complexArithmetic(Stack &stack, StackFrame &stackFrame, int16 brackStart) {
+ switch (stackFrame.opers[-2]) {
+ case OP_ADD:
+ if (stack.opers[brackStart] == OP_LOAD_IMM_INT16) {
+ stack.values[brackStart] += stackFrame.values[-1];
+ } else if (stack.opers[brackStart] == OP_LOAD_IMM_STR) {
+ if ((char *) decodePtr(stack.values[brackStart]) != _resultStr) {
+ strcpy(_resultStr, (char *) decodePtr(stack.values[brackStart]));
+ stack.values[brackStart] =
+ encodePtr((byte *) _resultStr, kResStr);
+ }
+ strcat(_resultStr, (char *) decodePtr(stackFrame.values[-1]));
+ }
+ stackFrame.pop(2);
+ break;
+
+ case OP_SUB:
+ stack.values[brackStart] -= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_BITOR:
+ stack.values[brackStart] |= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_MUL:
+ stackFrame.values[-3] *= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_DIV:
+ stackFrame.values[-3] /= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_MOD:
+ stackFrame.values[-3] %= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_BITAND:
+ stackFrame.values[-3] &= stackFrame.values[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_OR:
+ // (x OR false) == x
+ // (x OR true) == true
+ if (stackFrame.opers[-3] == GOB_FALSE)
+ stackFrame.opers[-3] = stackFrame.opers[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_AND:
+ // (x AND false) == false
+ // (x AND true) == x
+ if (stackFrame.opers[-3] == GOB_TRUE)
+ stackFrame.opers[-3] = stackFrame.opers[-1];
+ stackFrame.pop(2);
+ break;
+
+ case OP_LESS:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) < 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ case OP_LEQ:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) <= 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ case OP_GREATER:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) > 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ case OP_GEQ:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) >= 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ case OP_EQ:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) == 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ case OP_NEQ:
+ stackFrame.opers[-3] = (cmpHelper(stackFrame) != 0) ? GOB_TRUE : GOB_FALSE;
+ stackFrame.pop(2);
+ break;
+
+ default:
+ return true;
+ }
+
+ return false;
+}
+
+// Assign the result to the appropriate _result variable
+void Expression::getResult(byte operation, int32 value, byte *type) {
+ if (type != 0)
+ *type = operation;
+
+ switch (operation) {
+ case OP_NOT:
+ if (type != 0)
+ *type ^= 1;
+ break;
+
+ case OP_LOAD_IMM_INT16:
+ _resultInt = value;
+ break;
+
+ case OP_LOAD_IMM_STR:
+ if ((char *) decodePtr(value) != _resultStr)
+ strcpy(_resultStr, (char *) decodePtr(value));
+ break;
+
+ case OP_LOAD_VAR_INT32:
+ case OP_LOAD_VAR_INT32_AS_INT16:
+ break;
+
+ default:
+ _resultInt = 0;
+ if (type != 0)
+ *type = OP_LOAD_IMM_INT16;
+ break;
+ }
+}
+
+int16 Expression::parseExpr(byte stopToken, byte *type) {
+ Stack stack;
+ StackFrame stackFrame(stack);
+ byte operation;
+ bool escape;
+ int16 brackStart;
+ uint32 varBase;
+
+ while (true) {
+ getVarBase(varBase);
+
+ stackFrame.push();
+
+ operation = _vm->_game->_script->readByte();
+ if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) {
+
+ loadValue(operation, varBase, stackFrame);
+
+ if ((stackFrame.pos > 0) && ((stackFrame.opers[-1] == OP_NEG) || (stackFrame.opers[-1] == OP_NOT))) {
+ stackFrame.pop();
+
+ if (*stackFrame.opers == OP_NEG) {
+ *stackFrame.opers = OP_LOAD_IMM_INT16;
+ stackFrame.values[0] = -stackFrame.values[1];
+ } else
+ *stackFrame.opers = (stackFrame.opers[1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE;
+ }
+
+ if (stackFrame.pos <= 0)
+ continue;
+
+ simpleArithmetic1(stackFrame);
+
+ continue;
+ } // (op >= OP_ARRAY_INT8) && (op <= OP_FUNC)
+
+ if ((operation == stopToken) || (operation == OP_OR) ||
+ (operation == OP_AND) || (operation == OP_END_EXPR)) {
+ while (stackFrame.pos >= 2) {
+ escape = false;
+ if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) &&
+ ((operation == OP_END_EXPR) || (operation == stopToken))) {
+ stackFrame.opers[-2] = stackFrame.opers[-1];
+ if ((stackFrame.opers[-2] == OP_LOAD_IMM_INT16) || (stackFrame.opers[-2] == OP_LOAD_IMM_STR))
+ stackFrame.values[-2] = stackFrame.values[-1];
+
+ stackFrame.pop();
+
+ simpleArithmetic2(stackFrame);
+
+ if (operation != stopToken)
+ break;
+ } // if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) && ...)
+
+ for (brackStart = (stackFrame.pos - 2); (brackStart > 0) &&
+ (stack.opers[brackStart] < OP_OR) && (stack.opers[brackStart] != OP_BEGIN_EXPR);
+ brackStart--)
+ ;
+
+ if ((stack.opers[brackStart] >= OP_OR) || (stack.opers[brackStart] == OP_BEGIN_EXPR))
+ brackStart++;
+
+ if (complexArithmetic(stack, stackFrame, brackStart))
+ break;
+
+ } // while (stackFrame.pos >= 2)
+
+ if ((operation == OP_OR) || (operation == OP_AND)) {
+ if (stackFrame.opers[-1] == OP_LOAD_IMM_INT16) {
+ if (stackFrame.values[-1] != 0)
+ stackFrame.opers[-1] = GOB_TRUE;
+ else
+ stackFrame.opers[-1] = GOB_FALSE;
+ }
+
+ if (((operation == OP_OR) && (stackFrame.opers[-1] == GOB_TRUE)) ||
+ ((operation == OP_AND) && (stackFrame.opers[-1] == GOB_FALSE))) {
+ if ((stackFrame.pos > 1) && (stackFrame.opers[-2] == OP_BEGIN_EXPR)) {
+ skipExpr(OP_END_EXPR);
+ stackFrame.opers[-2] = stackFrame.opers[-1];
+ stackFrame.pop(2);
+ } else {
+ skipExpr(stopToken);
+ }
+ operation = _vm->_game->_script->peekByte(-1);
+ if ((stackFrame.pos > 0) && (stackFrame.opers[-1] == OP_NOT)) {
+ if (stackFrame.opers[0] == GOB_FALSE)
+ stackFrame.opers[-1] = GOB_TRUE;
+ else
+ stackFrame.opers[-1] = GOB_FALSE;
+
+ stackFrame.pop();
+ }
+ } else
+ stackFrame.opers[0] = operation;
+ } else
+ stackFrame.pop();
+
+ if (operation != stopToken)
+ continue;
+
+ getResult(stack.opers[0], stack.values[0], type);
+
+ return 0;
+ } // (operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR)
+
+ if ((operation < OP_NEG) || (operation > OP_NOT)) {
+ if ((operation < OP_LESS) || (operation > OP_NEQ))
+ continue;
+
+ if (stackFrame.pos > 2) {
+ if (stackFrame.opers[-2] == OP_ADD) {
+ if (stackFrame.opers[-3] == OP_LOAD_IMM_INT16) {
+ stackFrame.values[-3] += stackFrame.values[-1];
+ } else if (stackFrame.opers[-3] == OP_LOAD_IMM_STR) {
+ if ((char *) decodePtr(stackFrame.values[-3]) != _resultStr) {
+ strcpy(_resultStr, (char *) decodePtr(stackFrame.values[-3]));
+ stackFrame.values[-3] = encodePtr((byte *) _resultStr, kResStr);
+ }
+ strcat(_resultStr, (char *) decodePtr(stackFrame.values[-1]));
+ }
+ stackFrame.pop(2);
+
+ } else if (stackFrame.opers[-2] == OP_SUB) {
+ stackFrame.values[-3] -= stackFrame.values[-1];
+ stackFrame.pop(2);
+ } else if (stackFrame.opers[-2] == OP_BITOR) {
+ stackFrame.values[-3] |= stackFrame.values[-1];
+ stackFrame.pop(2);
+ }
+ }
+ }
+ *stackFrame.opers = operation;
+ }
+}
+
+int32 Expression::getResultInt() {
+ return _resultInt;
+}
+
+char *Expression::getResultStr() {
+ return _resultStr;
+}
+
+} // End of namespace Gob
Property changes on: scummvm/trunk/engines/gob/expression.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Copied: scummvm/trunk/engines/gob/expression.h (from rev 41772, scummvm/trunk/engines/gob/parse.h)
===================================================================
--- scummvm/trunk/engines/gob/expression.h (rev 0)
+++ scummvm/trunk/engines/gob/expression.h 2009-06-22 16:30:35 UTC (rev 41773)
@@ -0,0 +1,178 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_EXPRESSION_H
+#define GOB_EXPRESSION_H
+
+#include "common/scummsys.h"
+
+namespace Gob {
+
+class GobEngine;
+
+enum {
+ OP_NEG = 1,
+ OP_ADD = 2,
+ OP_SUB = 3,
+ OP_BITOR = 4,
+ OP_MUL = 5,
+ OP_DIV = 6,
+ OP_MOD = 7,
+ OP_BITAND = 8,
+ OP_BEGIN_EXPR = 9,
+ OP_END_EXPR = 10,
+ OP_NOT = 11,
+
+ OP_END_MARKER = 12, // Marks end of an array or string
+
+
+ OP_ARRAY_INT8 = 16,
+ OP_LOAD_VAR_INT16 = 17,
+ OP_LOAD_VAR_INT8 = 18,
+ OP_LOAD_IMM_INT32 = 19,
+ OP_LOAD_IMM_INT16 = 20,
+ OP_LOAD_IMM_INT8 = 21,
+ OP_LOAD_IMM_STR = 22,
+ OP_LOAD_VAR_INT32 = 23,
+ OP_LOAD_VAR_INT32_AS_INT16 = 24,
+ OP_LOAD_VAR_STR = 25,
+ OP_ARRAY_INT32 = 26,
+ OP_ARRAY_INT16 = 27,
+ OP_ARRAY_STR = 28,
+
+ OP_FUNC = 29,
+
+ OP_OR = 30, // Logical OR
+ OP_AND = 31, // Logical AND
+ OP_LESS = 32,
+ OP_LEQ = 33,
+ OP_GREATER = 34,
+ OP_GEQ = 35,
+ OP_EQ = 36,
+ OP_NEQ = 37
+};
+
+enum {
+ FUNC_SQRT1 = 0,
+ FUNC_SQRT2 = 1,
+ FUNC_SQRT3 = 6,
+
+ FUNC_SQR = 5,
+ FUNC_ABS = 7,
+ FUNC_RAND = 10
+};
+
+enum {
+ TYPE_IMM_INT8 = OP_LOAD_IMM_INT8, // 21
+ TYPE_IMM_INT32 = OP_LOAD_IMM_INT32, // 19
+ TYPE_IMM_INT16 = OP_LOAD_IMM_INT16, // 20
+ TYPE_IMM_STR = OP_LOAD_IMM_STR, // 22
+ TYPE_VAR_INT8 = OP_LOAD_VAR_INT8, // 18
+ TYPE_VAR_INT16 = OP_LOAD_VAR_INT16, // 17
+ TYPE_VAR_INT32 = OP_LOAD_VAR_INT32, // 23
+ TYPE_VAR_STR = OP_LOAD_VAR_STR, // 25
+ TYPE_ARRAY_INT8 = OP_ARRAY_INT8, // 16
+ TYPE_ARRAY_INT16 = OP_ARRAY_INT16, // 27
+ TYPE_ARRAY_INT32 = OP_ARRAY_INT32, // 26
+ TYPE_ARRAY_STR = OP_ARRAY_STR, // 28
+ TYPE_VAR_INT32_AS_INT16 = OP_LOAD_VAR_INT32_AS_INT16 // 24
+};
+
+enum {
+ // FIXME: The following two 'truth values' are stored inside the list
+ // of "operators". So they somehow coincide with OP_LOAD_VAR_INT32
+ // and OP_LOAD_VAR_INT32_AS_INT16. I haven't yet quite understood
+ // how, resp. what that means. You have been warned.
+ GOB_TRUE = 24,
+ GOB_FALSE = 23
+};
+
+class Expression {
+public:
+ Expression(GobEngine *vm);
+ virtual ~Expression() {}
+
+ void skipExpr(char stopToken);
+ void printExpr(char stopToken);
+ void printVarIndex(void);
+
+ int16 parseVarIndex(uint16 *size = 0, uint16 *type = 0);
+ int16 parseValExpr(byte stopToken = 99);
+ int16 parseExpr(byte stopToken, byte *type);
+
+ int32 getResultInt();
+ char *getResultStr();
+
+private:
+ class Stack {
+ public:
+ byte *opers;
+ int32 *values;
+
+ Stack(size_t size = 20);
+ ~Stack();
+ };
+ class StackFrame {
+ public:
+ byte *opers;
+ int32 *values;
+ int16 pos;
+
+ StackFrame(const Stack &stack);
+
+ void push(int count = 1);
+ void pop(int count = 1);
+ };
+
+ enum PointerType {
+ kExecPtr = 0,
+ kInterVar = 1,
+ kResStr = 2
+ };
+
+ GobEngine *_vm;
+
+ int32 _resultInt;
+ char _resultStr[200];
+
+ int32 encodePtr(byte *ptr, int type);
+ byte *decodePtr(int32 n);
+
+ void printExpr_internal(char stopToken);
+
+ bool getVarBase(uint32 &varBase, bool mindStop = false,
+ uint16 *size = 0, uint16 *type = 0);
+ int cmpHelper(const StackFrame &stackFrame);
+ void loadValue(byte operation, uint32 varBase, const StackFrame &stackFrame);
+
+ void simpleArithmetic1(StackFrame &stackFrame);
+ void simpleArithmetic2(StackFrame &stackFrame);
+ bool complexArithmetic(Stack &stack, StackFrame &stackFrame, int16 brackStart);
+ void getResult(byte operation, int32 value, byte *type);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_EXPRESSION_H
Property changes on: scummvm/trunk/engines/gob/expression.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Modified: scummvm/trunk/engines/gob/gob.cpp
===================================================================
--- scummvm/trunk/engines/gob/gob.cpp 2009-06-22 16:30:06 UTC (rev 41772)
+++ scummvm/trunk/engines/gob/gob.cpp 2009-06-22 16:30:35 UTC (rev 41773)
@@ -47,7 +47,6 @@
#include "gob/map.h"
#include "gob/mult.h"
#include "gob/palanim.h"
-#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/videoplayer.h"
#include "gob/save/saveload.h"
Modified: scummvm/trunk/engines/gob/inter.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter.cpp 2009-06-22 16:30:06 UTC (rev 41772)
+++ scummvm/trunk/engines/gob/inter.cpp 2009-06-22 16:30:35 UTC (rev 41773)
@@ -33,10 +33,10 @@
#include "gob/util.h"
#include "gob/draw.h"
#include "gob/game.h"
+#include "gob/expression.h"
#include "gob/script.h"
#include "gob/scenery.h"
#include "gob/sound/sound.h"
-#include "gob/parse.h"
namespace Gob {
Modified: scummvm/trunk/engines/gob/inter_v1.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v1.cpp 2009-06-22 16:30:06 UTC (rev 41772)
+++ scummvm/trunk/engines/gob/inter_v1.cpp 2009-06-22 16:30:35 UTC (rev 41773)
@@ -34,8 +34,8 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
+#include "gob/expression.h"
#include "gob/script.h"
-#include "gob/parse.h"
#include "gob/goblin.h"
#include "gob/inter.h"
#include "gob/map.h"
Modified: scummvm/trunk/engines/gob/inter_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v2.cpp 2009-06-22 16:30:06 UTC (rev 41772)
+++ scummvm/trunk/engines/gob/inter_v2.cpp 2009-06-22 16:30:35 UTC (rev 41773)
@@ -36,8 +36,8 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
+#include "gob/expression.h"
#include "gob/script.h"
-#include "gob/parse.h"
#include "gob/goblin.h"
#include "gob/map.h"
#include "gob/mult.h"
Modified: scummvm/trunk/engines/gob/inter_v6.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v6.cpp 2009-06-22 16:30:06 UTC (rev 41772)
+++ scummvm/trunk/engines/gob/inter_v6.cpp 2009-06-22 16:30:35 UTC (rev 41773)
@@ -32,8 +32,8 @@
#include "gob/helper.h"
#include "gob/global.h"
#include "gob/game.h"
+#include "gob/expression.h"
#include "gob/script.h"
-#include "gob/parse.h"
#include "gob/draw.h"
#include "gob/sound/sound.h"
#include "gob/videoplayer.h"
Modified: scummvm/trunk/engines/gob/module.mk
===================================================================
--- scummvm/trunk/engines/gob/module.mk 2009-06-22 16:30:06 UTC (rev 41772)
+++ scummvm/trunk/engines/gob/module.mk 2009-06-22 16:30:35 UTC (rev 41773)
@@ -9,6 +9,7 @@
draw_bargon.o \
draw_fascin.o \
driver_vga.o \
+ expression.o \
game.o \
game_v1.o \
game_v2.o \
@@ -43,7 +44,6 @@
mult_v1.o \
mult_v2.o \
palanim.o \
- parse.o \
scenery.o \
scenery_v1.o \
scenery_v2.o \
Deleted: scummvm/trunk/engines/gob/parse.cpp
===================================================================
--- scummvm/trunk/engines/gob/parse.cpp 2009-06-22 16:30:06 UTC (rev 41772)
+++ scummvm/trunk/engines/gob/parse.cpp 2009-06-22 16:30:35 UTC (rev 41773)
@@ -1,1145 +0,0 @@
-/* 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.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/endian.h"
-
-#include "gob/gob.h"
-#include "gob/parse.h"
-#include "gob/global.h"
-#include "gob/game.h"
-#include "gob/script.h"
-#include "gob/inter.h"
-
-namespace Gob {
-
-Expression::Stack::Stack(size_t size) {
- opers = new byte[size];
- values = new int32[size];
- memset(opers , 0, size * sizeof(byte ));
- memset(values, 0, size * sizeof(int32));
-}
-
-Expression::Stack::~Stack() {
- delete[] opers;
- delete[] values;
-}
-
-Expression::StackFrame::StackFrame(const Stack &stack) {
- opers = stack.opers - 1;
- values = stack.values - 1;
- pos = -1;
-}
-
-void Expression::StackFrame::push(int count) {
- opers += count;
- values += count;
- pos += count;
-}
-
-void Expression::StackFrame::pop(int count) {
- opers -= count;
- values -= count;
- pos -= count;
-}
-
-Expression::Expression(GobEngine *vm) : _vm(vm) {
- _resultStr[0] = 0;
- _resultInt = 0;
-}
-
-int32 Expression::encodePtr(byte *ptr, int type) {
- int32 offset = 0;
-
- switch (type) {
- case kExecPtr:
- offset = _vm->_game->_script->getOffset(ptr);
- break;
- case kInterVar:
- offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0));
- break;
- case kResStr:
- offset = ptr - ((byte *) _resultStr);
- break;
- default:
- error("Expression::encodePtr(): Unknown pointer type");
- }
- assert((offset & 0xF0000000) == 0);
- return (type << 28) | offset;
-}
-
-byte *Expression::decodePtr(int32 n) {
- byte *ptr;
-
- switch (n >> 28) {
- case kExecPtr:
- ptr = _vm->_game->_script->getData();
- break;
- case kInterVar:
- ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0);
- break;
- case kResStr:
- ptr = (byte *) _resultStr;
- break;
- default:
- error("Expression::decodePtr(): Unknown pointer type");
- }
- return ptr + (n & 0x0FFFFFFF);
-}
-
-void Expression::skipExpr(char stopToken) {
- int16 dimCount;
- byte operation;
- int16 num;
- int16 dim;
-
- num = 0;
- while (true) {
- operation = _vm->_game->_script->readByte();
-
- if ((operation >= 14) && (operation <= OP_FUNC)) {
- switch (operation) {
- case 14:
- _vm->_game->_script->skip(4);
- if (_vm->_game->_script->peekByte() == 97)
- _vm->_game->_script->skip(1);
- break;
-
- case OP_LOAD_VAR_INT16:
- case OP_LOAD_VAR_INT8:
- case OP_LOAD_IMM_INT16:
- case OP_LOAD_VAR_INT32:
- case OP_LOAD_VAR_INT32_AS_INT16:
- _vm->_game->_script->skip(2);
- break;
-
- case OP_LOAD_IMM_INT32:
- _vm->_game->_script->skip(4);
- break;
-
- case OP_LOAD_IMM_INT8:
- _vm->_game->_script->skip(1);
- break;
-
- case OP_LOAD_IMM_STR:
- _vm->_game->_script->skip(strlen(_vm->_game->_script->peekString()) + 1);
- break;
-
- case OP_LOAD_VAR_STR:
- _vm->_game->_script->skip(2);
- if (_vm->_game->_script->peekByte() == 13) {
- _vm->_game->_script->skip(1);
- skipExpr(OP_END_MARKER);
- }
- break;
-
- case 15:
- _vm->_game->_script->skip(2);
-
- case OP_ARRAY_INT8:
- case OP_ARRAY_INT32:
- case OP_ARRAY_INT16:
- case OP_ARRAY_STR:
- dimCount = _vm->_game->_script->peekByte(2);
- // skip header and dimensions
- _vm->_game->_script->skip(3 + dimCount);
- // skip indices
- for (dim = 0; dim < dimCount; dim++)
- skipExpr(OP_END_MARKER);
-
- if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) {
- _vm->_game->_script->skip(1);
- skipExpr(OP_END_MARKER);
- }
- break;
-
- case OP_FUNC:
- _vm->_game->_script->skip(1);
- skipExpr(OP_END_EXPR);
- }
- continue;
- } // if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC))
-
- if (operation == OP_BEGIN_EXPR) {
- num++;
- continue;
- }
-
- if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8)))
- continue;
-
- if ((operation >= OP_OR) && (operation <= OP_NEQ))
- continue;
-
- if (operation == OP_END_EXPR)
- num--;
-
- if (operation != stopToken)
- continue;
-
- if ((stopToken != OP_END_EXPR) || (num < 0))
- return;
- }
-}
-
-void Expression::printExpr(char stopToken) {
- // Expression printing disabled by default
- return;
-
- int32 savedPos = _vm->_game->_script->pos();
- printExpr_internal(stopToken);
-
- // restore IP to start of expression
- _vm->_game->_script->seek(savedPos);
-}
-
-void Expression::printExpr_internal(char stopToken) {
- int16 dimCount;
- byte operation;
- int16 num;
- int16 dim;
- byte *arrDesc;
- byte func;
-
- num = 0;
- while (true) {
- operation = _vm->_game->_script->readByte();
-
- if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) {
- // operands
-
- switch (operation) {
- case OP_LOAD_VAR_INT16: // int16 variable load
- debugN(5, "var16_%d", _vm->_game->_script->readUint16());
- break;
-
- case OP_LOAD_VAR_INT8: // int8 variable load:
- debugN(5, "var8_%d", _vm->_game->_script->readUint16());
- break;
-
- case OP_LOAD_IMM_INT32: // int32/uint32 immediate
- debugN(5, "%d", _vm->_game->_script->readInt32());
- break;
-
- case OP_LOAD_IMM_INT16: // int16 immediate
- debugN(5, "%d", _vm->_game->_script->readInt16());
- break;
-
- case OP_LOAD_IMM_INT8: // int8 immediate
- debugN(5, "%d", _vm->_game->_script->readInt8());
- break;
-
- case OP_LOAD_IMM_STR: // string immediate
- debugN(5, "\42%s\42", _vm->_game->_script->readString());
- break;
-
- case OP_LOAD_VAR_INT32:
- case OP_LOAD_VAR_INT32_AS_INT16:
- debugN(5, "var_%d", _vm->_game->_script->readUint16());
- break;
-
- case OP_LOAD_VAR_STR: // string variable load
- debugN(5, "(&var_%d)", _vm->_game->_script->readUint16());
- if (_vm->_game->_script->peekByte() == 13) {
- _vm->_game->_script->skip(1);
- debugN(5, "{");
- printExpr_internal(OP_END_MARKER); // this also prints the closing }
- }
- break;
-
- case OP_ARRAY_INT8: // int8 array access
- case OP_ARRAY_INT32: // int32 array access
- case OP_ARRAY_INT16: // int16 array access
- case OP_ARRAY_STR: // string array access
- debugN(5, "\n");
- if (operation == OP_ARRAY_STR)
- debugN(5, "(&");
-
- debugN(5, "var_%d[", _vm->_game->_script->readInt16());
- dimCount = _vm->_game->_script->readByte();
- arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos();
- _vm->_game->_script->skip(dimCount);
- for (dim = 0; dim < dimCount; dim++) {
- printExpr_internal(OP_END_MARKER);
- debugN(5, " of %d", (int16) arrDesc[dim]);
- if (dim != dimCount - 1)
- debugN(5, ",");
- }
- debugN(5, "]");
- if (operation == OP_ARRAY_STR)
- debugN(5, ")");
-
- if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) {
- _vm->_game->_script->skip(1);
- debugN(5, "{");
- printExpr_internal(OP_END_MARKER); // this also prints the closing }
- }
- break;
-
- case OP_FUNC: // function
- func = _vm->_game->_script->readByte();
- if (func == FUNC_SQR)
- debugN(5, "sqr(");
- else if (func == FUNC_RAND)
- debugN(5, "rand(");
- else if (func == FUNC_ABS)
- debugN(5, "abs(");
- else if ((func == FUNC_SQRT1) || (func == FUNC_SQRT2) || (func == FUNC_SQRT3))
- debugN(5, "sqrt(");
- else
- debugN(5, "id(");
- printExpr_internal(OP_END_EXPR);
- break;
- }
- continue;
- } // if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC))
-
- // operators
- switch (operation) {
- case OP_BEGIN_EXPR:
- debugN(5, "(");
- break;
-
- case OP_NOT:
- debugN(5, "!");
- break;
-
- case OP_END_EXPR:
- debugN(5, ")");
- break;
-
- case OP_NEG:
- debugN(5, "-");
- break;
-
- case OP_ADD:
- debugN(5, "+");
- break;
-
- case OP_SUB:
- debugN(5, "-");
- break;
-
- case OP_BITOR:
- debugN(5, "|");
- break;
-
- case OP_MUL:
- debugN(5, "*");
- break;
-
- case OP_DIV:
- debugN(5, "/");
- break;
-
- case OP_MOD:
- debugN(5, "%%");
- break;
-
- case OP_BITAND:
- debugN(5, "&");
- break;
-
- case OP_OR:
- debugN(5, "||");
- break;
-
- case 31:
- debugN(5, "&&");
- break;
-
- case OP_LESS:
- debugN(5, "<");
- break;
-
- case OP_LEQ:
- debugN(5, "<=");
- break;
-
- case OP_GREATER:
- debugN(5, ">");
- break;
-
- case OP_GEQ:
- debugN(5, ">=");
- break;
-
- case OP_EQ:
- debugN(5, "==");
- break;
-
- case OP_NEQ:
- debugN(5, "!=");
- break;
-
- case 99:
- debugN(5, "\n");
- break;
-
- case OP_END_MARKER:
- debugN(5, "}");
- if (stopToken != OP_END_MARKER) {
- debugN(5, "Closing paren without opening?");
- }
- break;
-
- default:
- debugN(5, "<%d>", (int16) operation);
- error("Expression::printExpr(): invalid operator in expression");
- break;
- }
-
- if (operation == OP_BEGIN_EXPR) {
- num++;
- continue;
- }
-
- if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8)))
- continue;
-
- if ((operation >= OP_OR) && (operation <= OP_NEQ))
- continue;
-
- if (operation == OP_END_EXPR)
- num--;
-
- if (operation == stopToken) {
- if ((stopToken != OP_END_EXPR) || (num < 0)) {
- return;
- }
- }
- }
-}
-
-
-void Expression::printVarIndex() {
- byte *arrDesc;
- int16 dim;
- int16 dimCount;
- int16 operation;
- int16 temp;
-
- int32 pos = _vm->_game->_script->pos();
-
- operation = _vm->_game->_script->readByte();
- switch (operation) {
- case OP_LOAD_VAR_INT32:
- case OP_LOAD_VAR_STR:
- temp = _vm->_game->_script->readUint16() * 4;
- debugN(5, "&var_%d", temp);
- if ((operation == OP_LOAD_VAR_STR) && (_vm->_game->_script->peekByte() == 13)) {
- _vm->_game->_script->skip(1);
- debugN(5, "+");
- printExpr(OP_END_MARKER);
- }
- break;
-
- case OP_ARRAY_INT32:
- case OP_ARRAY_STR:
- debugN(5, "&var_%d[", _vm->_game->_script->readUint16());
- dimCount = _vm->_game->_script->readByte();
- arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos();
- _vm->_game->_script->skip(dimCount);
- for (dim = 0; dim < dimCount; dim++) {
- printExpr(OP_END_MARKER);
- debugN(5, " of %d", (int16) arrDesc[dim]);
- if (dim != dimCount - 1)
- debugN(5, ",");
- }
- debugN(5, "]");
-
- if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) {
- _vm->_game->_script->skip(1);
- debugN(5, "+");
- printExpr(OP_END_MARKER);
- }
- break;
-
- default:
- debugN(5, "var_0");
- break;
- }
- debugN(5, "\n");
-
- _vm->_game->_script->seek(pos);
- return;
-}
-
-int Expression::cmpHelper(const StackFrame &stackFrame) {
- byte type = stackFrame.opers[-3];
- int cmpTemp = 0;
-
- if (type == OP_LOAD_IMM_INT16) {
- cmpTemp = (int)stackFrame.values[-3] - (int)stackFrame.values[-1];
- } else if (type == OP_LOAD_IMM_STR) {
- if ((char *)decodePtr(stackFrame.values[-3]) != _resultStr) {
- strcpy(_resultStr, (char *)decodePtr(stackFrame.values[-3]));
- stackFrame.values[-3] = encodePtr((byte *) _resultStr, kResStr);
- }
- cmpTemp = strcmp(_resultStr, (char *)decodePtr(stackFrame.values[-1]));
- }
-
- return cmpTemp;
-}
-
-bool Expression::getVarBase(uint32 &varBase, bool mindStop,
- uint16 *size, uint16 *type) {
-
- varBase = 0;
-
- byte operation = _vm->_game->_script->peekByte();
- while ((operation == 14) || (operation == 15)) {
- _vm->_game->_script->skip(1);
-
- if (operation == 14) {
- // Add a direct offset
-
- varBase += _vm->_game->_script->readInt16() * 4;
-
- if (size)
- *size = _vm->_game->_script->peekUint16();
- if (type)
- *type = 14;
-
- _vm->_game->_script->skip(2);
-
- debugC(2, kDebugParser, "varBase: %d, by %d", varBase, operation);
-
- if (_vm->_game->_script->peekByte() != 97) {
- if (mindStop)
- return true;
- } else
- _vm->_game->_script->skip(1);
-
- } else if (operation == 15) {
- // Add an offset from an array
-
- varBase += _vm->_game->_script->readInt16() * 4;
-
- uint16 offset1 = _vm->_game->_script->readUint16();
-
- if (size)
- *size = offset1;
- if (type)
- *type = 15;
-
- uint8 dimCount = _vm->_game->_script->readByte();
- byte *dimArray = _vm->_game->_script->getData() + _vm->_game->_script->pos();
-
- _vm->_game->_script->skip(dimCount);
-
- uint16 offset2 = 0;
- for (int i = 0; i < dimCount; i++) {
- int16 dim = CLIP<int>(parseValExpr(OP_END_MARKER), 0, dimArray[i] - 1);
-
- offset2 = offset2 * dimArray[i] + dim;
- }
-
- varBase += offset2 * offset1 * 4;
-
- debugC(2, kDebugParser, "varBase: %d, by %d", varBase, operation);
-
- if (_vm->_game->_script->peekByte() != 97) {
- if (mindStop)
- return true;
- } else
- _vm->_game->_script->skip(1);
- }
-
- operation = _vm->_game->_script->peekByte();
- }
-
- return false;
-}
-
-int16 Expression::parseVarIndex(uint16 *size, uint16 *type) {
- int16 temp2;
- byte *arrDesc;
- int16 dim;
- int16 dimCount;
- int16 operation;
- int16 temp;
- int16 offset;
- int16 val;
- uint32 varBase;
-
- if (getVarBase(varBase, true, size, type))
- return varBase;
-
- operation = _vm->_game->_script->readByte();
-
- if (size)
- *size = 0;
- if (type)
- *type = operation;
-
- debugC(5, kDebugParser, "var parse = %d", operation);
- switch (operation) {
- case OP_ARRAY_INT8:
- case OP_ARRAY_INT32:
- case OP_ARRAY_INT16:
- case OP_ARRAY_STR:
- temp = _vm->_game->_script->readInt16();
- dimCount = _vm->_game->_script->readByte();
- arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos();
- _vm->_game->_script->skip(dimCount);
- offset = 0;
- for (dim = 0; dim < dimCount; dim++) {
- temp2 = parseValExpr(OP_END_MARKER);
- offset = arrDesc[dim] * offset + temp2;
- }
- if (operation == OP_ARRAY_INT8)
- return varBase + temp + offset;
- if (operation == OP_ARRAY_INT32)
- return varBase + (temp + offset) * 4;
- if (operation == OP_ARRAY_INT16)
- return varBase + (temp + offset) * 2;
- temp *= 4;
- offset *= 4;
- if (_vm->_game->_script->peekByte() == 13) {
- _vm->_game->_script->skip(1);
- temp += parseValExpr(OP_END_MARKER);
- }
- return varBase + offset * _vm->_global->_inter_animDataSize + temp;
-
- case OP_LOAD_VAR_INT16:
- return varBase + _vm->_game->_script->readInt16() * 2;
-
- case OP_LOAD_VAR_INT8:
- return varBase + _vm->_game->_script->readInt16();
-
- case OP_LOAD_VAR_INT32:
- case OP_LOAD_VAR_INT32_AS_INT16:
- case OP_LOAD_VAR_STR:
- temp = _vm->_game->_script->readInt16() * 4;
- debugC(5, kDebugParser, "oper = %d", _vm->_game->_script->peekInt16());
- if ((operation == OP_LOAD_VAR_STR) && (_vm->_game->_script->peekByte() == 13)) {
- _vm->_game->_script->skip(1);
- val = parseValExpr(OP_END_MARKER);
- temp += val;
- debugC(5, kDebugParser, "parse subscript = %d", val);
- }
- return varBase + temp;
-
- default:
- return 0;
- }
-}
-
-int16 Expression::parseValExpr(byte stopToken) {
- parseExpr(stopToken, 0);
-
- return _resultInt;
-}
-
-// Load a value according to the operation
-void Expression::loadValue(byte operation, uint32 varBase, const StackFrame &stackFrame) {
- int16 dimCount;
- int16 temp;
- int16 temp2;
- int16 offset;
- int16 dim;
- byte *arrDescPtr;
- int32 prevPrevVal;
- int32 prevVal;
- int32 curVal;
-
- switch (operation) {
- case OP_ARRAY_INT8:
- case OP_ARRAY_INT32:
- case OP_ARRAY_INT16:
- case OP_ARRAY_STR:
- *stackFrame.opers = (operation == OP_ARRAY_STR) ? OP_LOAD_IMM_STR : OP_LOAD_IMM_INT16;
- temp = _vm->_game->_script->readInt16();
- dimCount = _vm->_game->_script->readByte();
- arrDescPtr = _vm->_game->_script->getData() + _vm->_game->_script->pos();
- _vm->_game->_script->skip(dimCount);
- offset = 0;
- for (dim = 0; dim < dimCount; dim++) {
- temp2 = parseValExpr(OP_END_MARKER);
- offset = offset * arrDescPtr[dim] + temp2;
- }
- if (operation == OP_ARRAY_INT8)
- *stackFrame.values = (int8) READ_VARO_UINT8(varBase + temp + offset);
- else if (operation == OP_ARRAY_INT32)
- *stackFrame.values = READ_VARO_UINT32(varBase + temp * 4 + offset * 4);
- else if (operation == OP_ARRAY_INT16)
- *stackFrame.values = (int16) READ_VARO_UINT16(varBase + temp * 2 + offset * 2);
- else if (operation == OP_ARRAY_STR) {
- *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8(
- varBase + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4),
- kInterVar);
- if (_vm->_game->_script->peekByte() == 13) {
- _vm->_game->_script->skip(1);
- temp2 = parseValExpr(OP_END_MARKER);
- *stackFrame.opers = OP_LOAD_IMM_INT16;
- *stackFrame.values = READ_VARO_UINT8(varBase + temp * 4 +
- offset * 4 * _vm->_global->_inter_animDataSize + temp2);
- }
- }
- break;
-
- case OP_LOAD_VAR_INT16:
- *stackFrame.opers = OP_LOAD_IMM_INT16;
- *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readInt16() * 2);
- break;
-
- case OP_LOAD_VAR_INT8:
- *stackFrame.opers = OP_LOAD_IMM_INT16;
- *stackFrame.values = (int8) READ_VARO_UINT8(varBase + _vm->_game->_script->readInt16());
- break;
-
- case OP_LOAD_IMM_INT32:
- *stackFrame.opers = OP_LOAD_IMM_INT16;
- *stackFrame.values = _vm->_game->_script->readInt32();
- break;
-
- case OP_LOAD_IMM_INT16:
- *stackFrame.opers = OP_LOAD_IMM_INT16;
- *stackFrame.values = _vm->_game->_script->readInt16();
- break;
-
- case OP_LOAD_IMM_INT8:
- *stackFrame.opers = OP_LOAD_IMM_INT16;
- *stackFrame.values = _vm->_game->_script->readInt8();
- break;
-
- case OP_LOAD_IMM_STR:
- *stackFrame.opers = OP_LOAD_IMM_STR;
- *stackFrame.values = encodePtr((byte *) _vm->_game->_script->readString(), kExecPtr);
- break;
-
- case OP_LOAD_VAR_INT32:
- *stackFrame.opers = OP_LOAD_IMM_INT16;
- *stackFrame.values = READ_VARO_UINT32(varBase + _vm->_game->_script->readInt16() * 4);
- break;
-
- case OP_LOAD_VAR_INT32_AS_INT16:
- *stackFrame.opers = OP_LOAD_IMM_INT16;
- *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readInt16() * 4);
- break;
-
- case OP_LOAD_VAR_STR:
- *stackFrame.opers = OP_LOAD_IMM_STR;
- temp = _vm->_game->_script->readInt16() * 4;
- *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8(varBase + temp), kInterVar);
- if (_vm->_game->_script->peekByte() == 13) {
- _vm->_game->_script->skip(1);
- temp += parseValExpr(OP_END_MARKER);
- *stackFrame.opers = OP_LOAD_IMM_INT16;
- *stackFrame.values = READ_VARO_UINT8(varBase + temp);
- }
- break;
-
- case OP_FUNC:
- operation = _vm->_game->_script->readByte();
- parseExpr(OP_END_EXPR, 0);
-
- switch (operation) {
- case FUNC_SQRT1:
- case FUNC_SQRT2:
- case FUNC_SQRT3:
- curVal = 1;
- prevVal = 1;
-
- do {
- prevPrevVal = prevVal;
- prevVal = curVal;
- curVal = (curVal + _resultInt / curVal) / 2;
- } while ((curVal != prevVal) && (curVal != prevPrevVal));
- _resultInt = curVal;
- break;
-
- case FUNC_SQR:
- _resultInt =
- _resultInt * _resultInt;
- break;
-
- case FUNC_ABS:
- if (_resultInt < 0)
- _resultInt = -_resultInt;
- break;
-
- case FUNC_RAND:
- _resultInt =
- _vm->_util->getRandom(_resultInt);
- break;
- }
-
- *stackFrame.opers = OP_LOAD_IMM_INT16;
- *stackFrame.values = _resultInt;
- break;
- }
-}
-
-void Expression::simpleArithmetic1(StackFrame &stackFrame) {
- switch (stackFrame.opers[-1]) {
- case OP_ADD:
- if (stackFrame.opers[-2] == OP_LOAD_IMM_STR) {
- if ((char *) decodePtr(stackFrame.values[-2]) != _resultStr) {
- strcpy(_resultStr, (char *) decodePtr(stackFrame.values[-2]));
- stackFrame.values[-2] = encodePtr((byte *) _resultStr, kResStr);
- }
- strcat(_resultStr, (char *) decodePtr(stackFrame.values[0]));
- stackFrame.pop(2);
- }
- break;
-
- case OP_MUL:
- stackFrame.values[-2] *= stackFrame.values[0];
- stackFrame.pop(2);
- break;
-
- case OP_DIV:
- stackFrame.values[-2] /= stackFrame.values[0];
- stackFrame.pop(2);
- break;
-
- case OP_MOD:
- stackFrame.values[-2] %= stackFrame.values[0];
- stackFrame.pop(2);
- break;
-
- case OP_BITAND:
- stackFrame.values[-2] &= stackFrame.values[0];
- stackFrame.pop(2);
- break;
- }
-}
-
-void Expression::simpleArithmetic2(StackFrame &stackFrame) {
- if (stackFrame.pos > 1) {
- if (stackFrame.opers[-2] == OP_NEG) {
- stackFrame.opers[-2] = OP_LOAD_IMM_INT16;
- stackFrame.values[-2] = -stackFrame.values[-1];
- stackFrame.pop();
- } else if (stackFrame.opers[-2] == OP_NOT) {
- stackFrame.opers[-2] = (stackFrame.opers[-1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE;
- stackFrame.pop();
- }
- }
-
- if (stackFrame.pos > 2) {
- switch (stackFrame.opers[-2]) {
- case OP_MUL:
- stackFrame.values[-3] *= stackFrame.values[-1];
- stackFrame.pop(2);
- break;
-
- case OP_DIV:
- stackFrame.values[-3] /= stackFrame.values[-1];
- stackFrame.pop(2);
- break;
-
- case OP_MOD:
- stackFrame.values[-3] %= stackFrame.values[-1];
- stackFrame.pop(2);
- break;
-
- case OP_BITAND:
- stackFrame.values[-3] &= stackFrame.values[-1];
- stackFrame.pop(2);
- break;
- }
- }
-
-}
-
-// Complex arithmetics with brackets
-bool Expression::complexArithmetic(Stack &stack, StackFrame &stackFrame, int16 brackStart) {
- switch (stackFrame.opers[-2]) {
- case OP_ADD:
- if (stack.opers[brackStart] == OP_LOAD_IMM_INT16) {
- stack.values[brackStart] += stackFrame.values[-1];
- } else if (stack.opers[brackStart] == OP_LOAD_IMM_STR) {
- if ((char *) decodePtr(stack.values[brackStart]) != _resultStr) {
- strcpy(_resultStr, (char *) decodePtr(stack.values[brackStart]));
- stack.values[brackStart] =
- encodePtr((byte *) _resultStr, kResStr);
- }
- strcat(_resultStr, (char *) decodePtr(stackFrame.values[-1]));
- }
- stackFrame.pop(2);
- break;
-
- case OP_SUB:
- stack.values[brackStart] -= stackFrame.values[-1];
- stackFrame.pop(2);
- break;
-
- case OP_BITOR:
- stack.values[brackStart] |= stackFrame.values[-1];
- stackFrame.pop(2);
- break;
-
- case OP_MUL:
- stackFrame.values[-3] *= stackFrame.values[-1];
- stackFrame.pop(2);
- break;
-
- case OP_DIV:
- stackFrame.values[-3] /= stackFrame.values[-1];
- stackFrame.pop(2);
- break;
-
- case OP_MOD:
- stackFrame.values[-3] %= stackFrame.values[-1];
- stackFrame.pop(2);
- break;
-
- case OP_BITAND:
- stackFrame.values[-3] &= stackFrame.values[-1];
- stackFrame.pop(2);
- break;
-
- case OP_OR:
- // (x OR false) == x
- // (x OR true) == true
- if (stackFrame.opers[-3] == GOB_FALSE)
- stackFrame.opers[-3] = stackFrame.opers[-1];
- stackFrame.pop(2);
- break;
-
- case OP_AND:
- // (x AND false) == false
- // (x AND true) == x
- if (stackFrame.opers[-3] == GOB_TRUE)
- stackFrame.opers[-3] = stackFrame.opers[-1];
- stackFrame.pop(2);
- break;
-
- case OP_LESS:
- stackFrame.opers[-3] = (cmpHelper(stackFrame) < 0) ? GOB_TRUE : GOB_FALSE;
- stackFrame.pop(2);
- break;
-
- case OP_LEQ:
- stackFrame.opers[-3] = (cmpHelper(stackFrame) <= 0) ? GOB_TRUE : GOB_FALSE;
- stackFrame.pop(2);
- break;
-
- case OP_GREATER:
- stackFrame.opers[-3] = (cmpHelper(stackFrame) > 0) ? GOB_TRUE : GOB_FALSE;
- stackFrame.pop(2);
- break;
-
- case OP_GEQ:
- stackFrame.opers[-3] = (cmpHelper(stackFrame) >= 0) ? GOB_TRUE : GOB_FALSE;
- stackFrame.pop(2);
- break;
-
- case OP_EQ:
- stackFrame.opers[-3] = (cmpHelper(stackFrame) == 0) ? GOB_TRUE : GOB_FALSE;
- stackFrame.pop(2);
- break;
-
- case OP_NEQ:
- stackFrame.opers[-3] = (cmpHelper(stackFrame) != 0) ? GOB_TRUE : GOB_FALSE;
- stackFrame.pop(2);
- break;
-
- default:
- return true;
- }
-
- return false;
-}
-
-// Assign the result to the appropriate _result variable
-void Expression::getResult(byte operation, int32 value, byte *type) {
- if (type != 0)
- *type = operation;
-
- switch (operation) {
- case OP_NOT:
- if (type != 0)
- *type ^= 1;
- break;
-
- case OP_LOAD_IMM_INT16:
- _resultInt = value;
- break;
-
- case OP_LOAD_IMM_STR:
- if ((char *) decodePtr(value) != _resultStr)
- strcpy(_resultStr, (char *) decodePtr(value));
- break;
-
- case OP_LOAD_VAR_INT32:
- case OP_LOAD_VAR_INT32_AS_INT16:
- break;
-
- default:
- _resultInt = 0;
- if (type != 0)
- *type = OP_LOAD_IMM_INT16;
- break;
- }
-}
-
-int16 Expression::parseExpr(byte stopToken, byte *type) {
- Stack stack;
- StackFrame stackFrame(stack);
- byte operation;
- bool escape;
- int16 brackStart;
- uint32 varBase;
-
- while (true) {
- getVarBase(varBase);
-
- stackFrame.push();
-
- operation = _vm->_game->_script->readByte();
- if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) {
-
- loadValue(operation, varBase, stackFrame);
-
- if ((stackFrame.pos > 0) && ((stackFrame.opers[-1] == OP_NEG) || (stackFrame.opers[-1] == OP_NOT))) {
- stackFrame.pop();
-
- if (*stackFrame.opers == OP_NEG) {
- *stackFrame.opers = OP_LOAD_IMM_INT16;
- stackFrame.values[0] = -stackFrame.values[1];
- } else
- *stackFrame.opers = (stackFrame.opers[1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE;
- }
-
- if (stackFrame.pos <= 0)
- continue;
-
- simpleArithmetic1(stackFrame);
-
- continue;
- } // (op >= OP_ARRAY_INT8) && (op <= OP_FUNC)
-
- if ((operation == stopToken) || (operation == OP_OR) ||
- (operation == OP_AND) || (operation == OP_END_EXPR)) {
- while (stackFrame.pos >= 2) {
- escape = false;
- if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) &&
- ((operation == OP_END_EXPR) || (operation == stopToken))) {
- stackFrame.opers[-2] = stackFrame.opers[-1];
- if ((stackFrame.opers[-2] == OP_LOAD_IMM_INT16) || (stackFrame.opers[-2] == OP_LOAD_IMM_STR))
- stackFrame.values[-2] = stackFrame.values[-1];
-
- stackFrame.pop();
-
- simpleArithmetic2(stackFrame);
-
- if (operation != stopToken)
- break;
- } // if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) && ...)
-
- for (brackStart = (stackFrame.pos - 2); (brackStart > 0) &&
- (stack.opers[brackStart] < OP_OR) && (stack.opers[brackStart] != OP_BEGIN_EXPR);
- brackStart--)
- ;
-
- if ((stack.opers[brackStart] >= OP_OR) || (stack.opers[brackStart] == OP_BEGIN_EXPR))
- brackStart++;
-
- if (complexArithmetic(stack, stackFrame, brackStart))
- break;
-
- } // while (stackFrame.pos >= 2)
-
- if ((operation == OP_OR) || (operation == OP_AND)) {
- if (stackFrame.opers[-1] == OP_LOAD_IMM_INT16) {
- if (stackFrame.values[-1] != 0)
- stackFrame.opers[-1] = GOB_TRUE;
- else
- stackFrame.opers[-1] = GOB_FALSE;
- }
-
- if (((operation == OP_OR) && (stackFrame.opers[-1] == GOB_TRUE)) ||
- ((operation == OP_AND) && (stackFrame.opers[-1] == GOB_FALSE))) {
- if ((stackFrame.pos > 1) && (stackFrame.opers[-2] == OP_BEGIN_EXPR)) {
- skipExpr(OP_END_EXPR);
- stackFrame.opers[-2] = stackFrame.opers[-1];
- stackFrame.pop(2);
- } else {
- skipExpr(stopToken);
- }
- operation = _vm->_game->_script->peekByte(-1);
- if ((stackFrame.pos > 0) && (stackFrame.opers[-1] == OP_NOT)) {
- if (stackFrame.opers[0] == GOB_FALSE)
- stackFrame.opers[-1] = GOB_TRUE;
- else
- stackFrame.opers[-1] = GOB_FALSE;
-
- stackFrame.pop();
- }
- } else
- stackFrame.opers[0] = operation;
- } else
- stackFrame.pop();
-
- if (operation != stopToken)
- continue;
-
- getResult(stack.opers[0], stack.values[0], type);
-
- return 0;
- } // (operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR)
-
- if ((operation < OP_NEG) || (operation > OP_NOT)) {
- if ((operation < OP_LESS) || (operation > OP_NEQ))
- continue;
-
- if (stackFrame.pos > 2) {
- if (stackFrame.opers[-2] == OP_ADD) {
- if (stackFrame.opers[-3] == OP_LOAD_IMM_INT16) {
- stackFrame.values[-3] += stackFrame.values[-1];
- } else if (stackFrame.opers[-3] == OP_LOAD_IMM_STR) {
- if ((char *) decodePtr(stackFrame.values[-3]) != _resultStr) {
- strcpy(_resultStr, (char *) decodePtr(stackFrame.values[-3]));
- stackFrame.values[-3] = encodePtr((byte *) _resultStr, kResStr);
- }
- strcat(_resultStr, (char *) decodePtr(stackFrame.values[-1]));
- }
- stackFrame.pop(2);
-
- } else if (stackFrame.opers[-2] == OP_SUB) {
- stackFrame.values[-3] -= stackFrame.values[-1];
- stackFrame.pop(2);
- } else if (stackFrame.opers[-2] == OP_BITOR) {
- stackFrame.values[-3] |= stackFrame.values[-1];
- stackFrame.pop(2);
- }
- }
- }
- *stackFrame.opers = operation;
- }
-}
-
-int32 Expression::getResultInt() {
- return _resultInt;
-}
-
-char *Expression::getResultStr() {
- return _resultStr;
-}
-
-} // End of namespace Gob
Deleted: scummvm/trunk/engines/gob/parse.h
===================================================================
--- scummvm/trunk/engines/gob/parse.h 2009-06-22 16:30:06 UTC (rev 41772)
+++ scummvm/trunk/engines/gob/parse.h 2009-06-22 16:30:35 UTC (rev 41773)
@@ -1,178 +0,0 @@
-/* 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.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef GOB_EXPRESSION_H
-#define GOB_EXPRESSION_H
-
-#include "common/scummsys.h"
-
-namespace Gob {
-
-class GobEngine;
-
-enum {
- OP_NEG = 1,
- OP_ADD = 2,
- OP_SUB = 3,
- OP_BITOR = 4,
- OP_MUL = 5,
- OP_DIV = 6,
- OP_MOD = 7,
- OP_BITAND = 8,
- OP_BEGIN_EXPR = 9,
- OP_END_EXPR = 10,
- OP_NOT = 11,
-
- OP_END_MARKER = 12, // Marks end of an array or string
-
-
- OP_ARRAY_INT8 = 16,
- OP_LOAD_VAR_INT16 = 17,
- OP_LOAD_VAR_INT8 = 18,
- OP_LOAD_IMM_INT32 = 19,
- OP_LOAD_IMM_INT16 = 20,
- OP_LOAD_IMM_INT8 = 21,
- OP_LOAD_IMM_STR = 22,
- OP_LOAD_VAR_INT32 = 23,
- OP_LOAD_VAR_INT32_AS_INT16 = 24,
- OP_LOAD_VAR_STR = 25,
- OP_ARRAY_INT32 = 26,
- OP_ARRAY_INT16 = 27,
- OP_ARRAY_STR = 28,
-
- OP_FUNC = 29,
-
- OP_OR = 30, // Logical OR
- OP_AND = 31, // Logical AND
- OP_LESS = 32,
- OP_LEQ = 33,
- OP_GREATER = 34,
- OP_GEQ = 35,
- OP_EQ = 36,
- OP_NEQ = 37
-};
-
-enum {
- FUNC_SQRT1 = 0,
- FUNC_SQRT2 = 1,
- FUNC_SQRT3 = 6,
-
- FUNC_SQR = 5,
- FUNC_ABS = 7,
- FUNC_RAND = 10
-};
-
-enum {
- TYPE_IMM_INT8 = OP_LOAD_IMM_INT8, // 21
- TYPE_IMM_INT32 = OP_LOAD_IMM_INT32, // 19
- TYPE_IMM_INT16 = OP_LOAD_IMM_INT16, // 20
- TYPE_IMM_STR = OP_LOAD_IMM_STR, // 22
- TYPE_VAR_INT8 = OP_LOAD_VAR_INT8, // 18
- TYPE_VAR_INT16 = OP_LOAD_VAR_INT16, // 17
- TYPE_VAR_INT32 = OP_LOAD_VAR_INT32, // 23
- TYPE_VAR_STR = OP_LOAD_VAR_STR, // 25
- TYPE_ARRAY_INT8 = OP_ARRAY_INT8, // 16
- TYPE_ARRAY_INT16 = OP_ARRAY_INT16, // 27
- TYPE_ARRAY_INT32 = OP_ARRAY_INT32, // 26
- TYPE_ARRAY_STR = OP_ARRAY_STR, // 28
- TYPE_VAR_INT32_AS_INT16 = OP_LOAD_VAR_INT32_AS_INT16 // 24
-};
-
-enum {
- // FIXME: The following two 'truth values' are stored inside the list
- // of "operators". So they somehow coincide with OP_LOAD_VAR_INT32
- // and OP_LOAD_VAR_INT32_AS_INT16. I haven't yet quite understood
- // how, resp. what that means. You have been warned.
- GOB_TRUE = 24,
- GOB_FALSE = 23
-};
-
-class Expression {
-public:
- Expression(GobEngine *vm);
- virtual ~Expression() {}
-
- void skipExpr(char stopToken);
- void printExpr(char stopToken);
- void printVarIndex(void);
-
- int16 parseVarIndex(uint16 *size = 0, uint16 *type = 0);
- int16 parseValExpr(byte stopToken = 99);
- int16 parseExpr(byte stopToken, byte *type);
-
- int32 getResultInt();
- char *getResultStr();
-
-private:
- class Stack {
- public:
- byte *opers;
- int32 *values;
-
- Stack(size_t size = 20);
- ~Stack();
- };
- class StackFrame {
- public:
- byte *opers;
- int32 *values;
- int16 pos;
-
- StackFrame(const Stack &stack);
-
- void push(int count = 1);
- void pop(int count = 1);
- };
-
- enum PointerType {
- kExecPtr = 0,
- kInterVar = 1,
- kResStr = 2
- };
-
- GobEngine *_vm;
-
- int32 _resultInt;
- char _resultStr[200];
-
- int32 encodePtr(byte *ptr, int type);
- byte *decodePtr(int32 n);
-
- void printExpr_internal(char stopToken);
-
- bool getVarBase(uint32 &varBase, bool mindStop = false,
- uint16 *size = 0, uint16 *type = 0);
- int cmpHelper(const StackFrame &stackFrame);
- void loadValue(byte operation, uint32 varBase, const StackFrame &stackFrame);
-
- void simpleArithmetic1(StackFrame &stackFrame);
- void simpleArithmetic2(StackFrame &stackFrame);
- bool complexArithmetic(Stack &stack, StackFrame &stackFrame, int16 brackStart);
- void getResult(byte operation, int32 value, byte *type);
-};
-
-} // End of namespace Gob
-
-#endif // GOB_EXPRESSION_H
Modified: scummvm/trunk/engines/gob/script.cpp
===================================================================
--- scummvm/trunk/engines/gob/script.cpp 2009-06-22 16:30:06 UTC (rev 41772)
+++ scummvm/trunk/engines/gob/script.cpp 2009-06-22 16:30:35 UTC (rev 41773)
@@ -29,7 +29,7 @@
#include "gob/gob.h"
#include "gob/script.h"
#include "gob/dataio.h"
-#include "gob/parse.h"
+#include "gob/expression.h"
#include "gob/videoplayer.h"
namespace Gob {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list