aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorDenis Kasak2009-06-10 02:59:53 +0000
committerDenis Kasak2009-06-10 02:59:53 +0000
commit10b8d82baa0137348473a846b85a20715808215f (patch)
tree3153964f047542f8a3c8ee8766b594a4639fc756 /engines
parentba49e539d16cc2e48db70434ade95b9da96d0219 (diff)
downloadscummvm-rg350-10b8d82baa0137348473a846b85a20715808215f.tar.gz
scummvm-rg350-10b8d82baa0137348473a846b85a20715808215f.tar.bz2
scummvm-rg350-10b8d82baa0137348473a846b85a20715808215f.zip
Made handleMathExpression() properly handle mathematical expressions inside GPL bytecode (instead of just searching for the ending byte). The actual callbacks still need to be implemented.
svn-id: r41415
Diffstat (limited to 'engines')
-rw-r--r--engines/draci/gpldisasm.cpp125
1 files changed, 107 insertions, 18 deletions
diff --git a/engines/draci/gpldisasm.cpp b/engines/draci/gpldisasm.cpp
index ec27bbf0cc..d91952b481 100644
--- a/engines/draci/gpldisasm.cpp
+++ b/engines/draci/gpldisasm.cpp
@@ -56,6 +56,7 @@
#include "common/debug.h"
#include "common/stream.h"
+#include "common/stack.h"
#include "draci/gpldisasm.h"
#include "draci/draci.h"
@@ -64,8 +65,8 @@ namespace Draci {
// FIXME: Change parameter types to names once I figure out what they are exactly
GPL2Command gplCommands[] = {
- { 0, 0, "gplend", 0, { 0 } },
- { 0, 1, "exit", 0, { 0 } },
+ { 0, 0, "gplend", 0, { 0 } },
+ { 0, 1, "exit", 0, { 0 } },
{ 1, 1, "goto", 1, { 3 } },
{ 2, 1, "Let", 2, { 3, 4 } },
{ 3, 1, "if", 2, { 4, 3 } },
@@ -121,38 +122,126 @@ GPL2Command gplCommands[] = {
{ 27, 1, "FeedPassword", 3, { 1, 1, 1 } }
};
+Common::String operators[] = {
+ "oper_and",
+ "oper_or",
+ "oper_xor",
+ "oper_equals",
+ "oper_not_equal",
+ "oper_less_than",
+ "oper_greater_than",
+ "oper_less_or_equal",
+ "oper_greater_or_equal",
+ "oper_multiply",
+ "oper_divide",
+ "oper_remainder",
+ "oper_plus",
+ "oper_minus"
+};
+
+Common::String functions[] = {
+ "F_Not",
+ "F_Random",
+ "F_IsIcoOn",
+ "F_IsIcoAct",
+ "F_IcoStat",
+ "F_ActIco",
+ "F_IsObjOn",
+ "F_IsObjOff",
+ "F_IsObjAway",
+ "F_ObjStat",
+ "F_LastBlock",
+ "F_AtBegin",
+ "F_BlockVar",
+ "F_HasBeen",
+ "F_MaxLine",
+ "F_ActPhase",
+ "F_Cheat"
+};
+
const unsigned int kNumCommands = sizeof gplCommands / sizeof gplCommands[0];
-// FIXME: Handle math expressions properly instead of just skipping them
+enum mathExpressionObject {
+ kMathEnd,
+ kMathNumber,
+ kMathOperator,
+ kMathFunctionCall,
+ kMathVariable
+};
+
+// FIXME: The evaluator is now complete but I still need to implement callbacks
void handleMathExpression(Common::MemoryReadStream &reader) {
- uint16 temp;
+ Common::Stack<uint16> stk;
+ mathExpressionObject obj;
+
+ // Read in initial math object
+ obj = (mathExpressionObject) reader.readUint16LE();
+
+ uint16 value;
while (1) {
- temp = reader.readUint16LE();
- if (temp == 0) {
+ if (obj == kMathEnd) {
+ break;
+ }
+
+ switch (obj) {
+
+ // If the object type is not known, assume that it's a number
+ default:
+ case kMathNumber:
+ value = reader.readUint16LE();
+ stk.push(value);
+ debugC(3, kDraciBytecodeDebugLevel, "\t\t-number %hu", value);
+ break;
+
+ case kMathOperator:
+ value = reader.readUint16LE();
+ stk.pop();
+ stk.pop();
+ debugC(3, kDraciBytecodeDebugLevel, "\t\t-operator %s",
+ operators[value-1].c_str());
+ break;
+
+ case kMathVariable:
+ value = reader.readUint16LE();
+ stk.push(value);
+ debugC(3, kDraciBytecodeDebugLevel, "\t\t-variable %hu", value);
+ break;
+
+ case kMathFunctionCall:
+ value = reader.readUint16LE();
+
+ // FIXME: Pushing dummy value for now, but should push return value
+ stk.push(0);
+
+ debugC(3, kDraciBytecodeDebugLevel, "\t\t-functioncall %s",
+ functions[value-1].c_str());
break;
}
- temp = reader.readUint16LE();
+
+ obj = (mathExpressionObject) reader.readUint16LE();
}
+
return;
}
GPL2Command *findCommand(byte num, byte subnum) {
unsigned int i = 0;
while (1) {
-
+
// Command not found
if (i >= kNumCommands) {
break;
}
// Return found command
- if (gplCommands[i]._number == num && gplCommands[i]._subNumber == subnum) {
+ if (gplCommands[i]._number == num &&
+ gplCommands[i]._subNumber == subnum) {
return &gplCommands[i];
}
-
- ++i;
+
+ ++i;
}
-
+
return NULL;
}
@@ -162,24 +251,24 @@ int gpldisasm(byte *gplcode, uint16 len) {
while (!reader.eos()) {
// read in command pair
uint16 cmdpair = reader.readUint16BE();
-
+
// extract high byte, i.e. the command number
byte num = (cmdpair >> 8) & 0xFF;
-
+
// extract low byte, i.e. the command subnumber
byte subnum = cmdpair & 0xFF;
GPL2Command *cmd;
if ((cmd = findCommand(num, subnum))) {
-
- // Print command name
+
+ // Print command name
debugC(2, kDraciBytecodeDebugLevel, "%s", cmd->_name.c_str());
for (uint16 i = 0; i < cmd->_numParams; ++i) {
if (cmd->_paramTypes[i] == 4) {
debugC(3, kDraciBytecodeDebugLevel, "\t<MATHEXPR>");
handleMathExpression(reader);
- }
+ }
else {
debugC(3, kDraciBytecodeDebugLevel, "\t%hu", reader.readUint16LE());
}
@@ -190,7 +279,7 @@ int gpldisasm(byte *gplcode, uint16 len) {
num, subnum);
}
-
+
}
return 0;