aboutsummaryrefslogtreecommitdiff
path: root/engines/parallaction
diff options
context:
space:
mode:
authorNicola Mettifogo2007-08-13 23:44:13 +0000
committerNicola Mettifogo2007-08-13 23:44:13 +0000
commit0f489597aa63ebd4460506f7231d7c2bca0c8639 (patch)
tree0c2d721259bd0b05ed82dd8d781bc314fbb11f36 /engines/parallaction
parenta2a450dfaec31651a8c84fc6aeccab2816375d2a (diff)
downloadscummvm-rg350-0f489597aa63ebd4460506f7231d7c2bca0c8639.tar.gz
scummvm-rg350-0f489597aa63ebd4460506f7231d7c2bca0c8639.tar.bz2
scummvm-rg350-0f489597aa63ebd4460506f7231d7c2bca0c8639.zip
Changed instruction parsing to array of function pointers.
svn-id: r28601
Diffstat (limited to 'engines/parallaction')
-rw-r--r--engines/parallaction/animation.cpp285
-rw-r--r--engines/parallaction/parallaction.h25
2 files changed, 185 insertions, 125 deletions
diff --git a/engines/parallaction/animation.cpp b/engines/parallaction/animation.cpp
index c532e43bb7..43d1042f2a 100644
--- a/engines/parallaction/animation.cpp
+++ b/engines/parallaction/animation.cpp
@@ -278,154 +278,189 @@ int16 addLocal(const char *name, LocalVariable *locals, int16 value = 0, int16 m
}
+DECLARE_INSTRUCTION_PARSER(animation) {
+ if (!scumm_stricmp(_tokens[1], _instParseCtxt.a->_label._text)) {
+ _instParseCtxt.inst->_opBase._a = _instParseCtxt.a;
+ } else {
+ _instParseCtxt.inst->_opBase._a = findAnimation(_tokens[1]);
+ }
+}
-void Parallaction::parseScriptLine(Instruction *inst, Animation *a, LocalVariable *locals) {
-// printf("parseScriptLine()\n");
- if (_tokens[0][1] == '.') {
- _tokens[0][1] = '\0';
- a = findAnimation(&_tokens[0][2]);
+DECLARE_INSTRUCTION_PARSER(loop) {
+ _instParseCtxt.inst->_opBase._loopCounter = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(x) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_left;
+ _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(y) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_top;
+ _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(z) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_z;
+ _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(f) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_frame;
+ _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(inc) {
+ if (!scumm_stricmp(_tokens[1], "X")) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_left;
+ } else
+ if (!scumm_stricmp(_tokens[1], "Y")) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_top;
+ } else
+ if (!scumm_stricmp(_tokens[1], "Z")) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_z;
+ } else
+ if (!scumm_stricmp(_tokens[1], "F")) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_frame;
+ } else {
+ _instParseCtxt.inst->_flags |= kInstUsesLocal;
+ _instParseCtxt.inst->_opA = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
}
- if (_tokens[1][1] == '.') {
- _tokens[1][1] = '\0';
- a = findAnimation(&_tokens[1][2]);
+ _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
+
+ if (!scumm_stricmp(_tokens[3], "mod")) {
+ _instParseCtxt.inst->_flags |= kInstMod;
}
+}
- int16 _si = _instructionNames->lookup(_tokens[0]);
- inst->_index = _si;
- switch (inst->_index) {
- case INST_ON: // on
- case INST_OFF: // off
- case INST_START: // start
- if (!scumm_stricmp(_tokens[1], a->_label._text)) {
- inst->_opBase._a = a;
- } else {
- inst->_opBase._a = findAnimation(_tokens[1]);
- }
- break;
-
- case INST_LOOP: // loop
- inst->_opBase._loopCounter = getLValue(inst, _tokens[1], locals, a);
- break;
-
- case INST_X: // x
- inst->_opA._pvalue = &a->_left;
- inst->_opB = getLValue(inst, _tokens[1], locals, a);
- break;
-
- case INST_Y: // y
- inst->_opA._pvalue = &a->_top;
- inst->_opB = getLValue(inst, _tokens[1], locals, a);
- break;
-
- case INST_Z: // z
- inst->_opA._pvalue = &a->_z;
- inst->_opB = getLValue(inst, _tokens[1], locals, a);
- break;
-
- case INST_F: // f
- inst->_opA._pvalue = &a->_frame;
- inst->_opB = getLValue(inst, _tokens[1], locals, a);
- break;
-
- case INST_INC: // inc
- case INST_DEC: // dec
- if (!scumm_stricmp(_tokens[1], "X")) {
- inst->_opA._pvalue = &a->_left;
- } else
- if (!scumm_stricmp(_tokens[1], "Y")) {
- inst->_opA._pvalue = &a->_top;
- } else
- if (!scumm_stricmp(_tokens[1], "Z")) {
- inst->_opA._pvalue = &a->_z;
- } else
- if (!scumm_stricmp(_tokens[1], "F")) {
- inst->_opA._pvalue = &a->_frame;
- } else {
- inst->_flags |= kInstUsesLocal;
- inst->_opA = getLValue(inst, _tokens[1], locals, a);
- }
+DECLARE_INSTRUCTION_PARSER(set) {
+ // WORKAROUND: At least one script (balzo.script) in Amiga versions didn't declare
+ // local variables before using them, thus leading to crashes. The line launching the
+ // script was commented out on Dos version. This workaround enables the engine
+ // to dynamically add a local variable when it is encountered the first time in
+ // the script, so should fix any other occurrence as well.
+ if (findLocal(_tokens[1], _instParseCtxt.locals) == -1) {
+ addLocal(_tokens[1], _instParseCtxt.locals);
+ }
- inst->_opB = getLValue(inst, _tokens[2], locals, a);
+ _instParseCtxt.inst->_opA = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+ _instParseCtxt.inst->_flags |= kInstUsesLocal;
+ _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
+}
- if (!scumm_stricmp(_tokens[3], "mod")) {
- inst->_flags |= kInstMod;
- }
- break;
-
- case INST_SET: // set
- // WORKAROUND: At least one script (balzo.script) in Amiga versions didn't declare
- // local variables before using them, thus leading to crashes. The line launching the
- // script was commented out on Dos version. This workaround enables the engine
- // to dynamically add a local variable when it is encountered the first time in
- // the script, so should fix any other occurrence as well.
- if (findLocal(_tokens[1], locals) == -1) {
- addLocal(_tokens[1], locals);
- }
- inst->_opA = getLValue(inst, _tokens[1], locals, a);
- inst->_flags |= kInstUsesLocal;
- inst->_opB = getLValue(inst, _tokens[2], locals, a);
- break;
-
- case INST_MOVE: // move
- inst->_opA = getLValue(inst, _tokens[1], locals, a);
- inst->_opB = getLValue(inst, _tokens[2], locals, a);
- break;
-
- case INST_PUT: // put
- if (!scumm_stricmp(_tokens[1], a->_label._text)) {
- inst->_opBase._a = a;
- } else {
- inst->_opBase._a = findAnimation(_tokens[1]);
- }
+DECLARE_INSTRUCTION_PARSER(move) {
+ _instParseCtxt.inst->_opA = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+ _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
+}
- inst->_opA = getLValue(inst, _tokens[2], locals, a);
- inst->_opB = getLValue(inst, _tokens[3], locals, a);
- if (!scumm_stricmp(_tokens[4], "masked")) {
- inst->_flags |= kInstMaskedPut;
- }
- break;
- case INST_CALL: { // call
- int index = _callableNames->lookup(_tokens[1]);
- if (index == Table::notFound)
- error("unknown callable '%s'", _tokens[1]);
- inst->_opBase._index = index - 1;
+DECLARE_INSTRUCTION_PARSER(put) {
+ if (!scumm_stricmp(_tokens[1], _instParseCtxt.a->_label._text)) {
+ _instParseCtxt.inst->_opBase._a = _instParseCtxt.a;
+ } else {
+ _instParseCtxt.inst->_opBase._a = findAnimation(_tokens[1]);
+ }
+
+ _instParseCtxt.inst->_opA = getLValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
+ _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[3], _instParseCtxt.locals, _instParseCtxt.a);
+ if (!scumm_stricmp(_tokens[4], "masked")) {
+ _instParseCtxt.inst->_flags |= kInstMaskedPut;
}
- break;
+}
- case INST_SOUND: // sound
- inst->_opBase._z = findZone(_tokens[1]);
- break;
- case INST_ENDLOOP: // endloop
- case INST_SHOW: // show
- case INST_WAIT: // wait
- break;
+DECLARE_INSTRUCTION_PARSER(call) {
+ int index = _callableNames->lookup(_tokens[1]);
+ if (index == Table::notFound)
+ error("unknown callable '%s'", _tokens[1]);
+ _instParseCtxt.inst->_opBase._index = index - 1;
+}
- default: { // local definition
- int16 val = atoi(_tokens[2]);
- int16 index;
- if (_tokens[3][0] != '\0') {
- index = addLocal(_tokens[0], locals, val, atoi(_tokens[3]), atoi(_tokens[4]));
- } else {
- index = addLocal(_tokens[0], locals, val);
- }
+DECLARE_INSTRUCTION_PARSER(sound) {
+ _instParseCtxt.inst->_opBase._z = findZone(_tokens[1]);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(null) {
+
+}
+
+
+DECLARE_INSTRUCTION_PARSER(defLocal) {
+ int16 val = atoi(_tokens[2]);
+ int16 index;
+
+ if (_tokens[3][0] != '\0') {
+ index = addLocal(_tokens[0], _instParseCtxt.locals, val, atoi(_tokens[3]), atoi(_tokens[4]));
+ } else {
+ index = addLocal(_tokens[0], _instParseCtxt.locals, val);
+ }
+
+ _instParseCtxt.inst->_opA._local = &_instParseCtxt.locals[index];
+ _instParseCtxt.inst->_opB._value = _instParseCtxt.locals[index]._value;
- inst->_opA._local = &locals[index];
- inst->_opB._value = locals[index]._value;
+ _instParseCtxt.inst->_flags = kInstUsesLiteral | kInstUsesLocal;
+ _instParseCtxt.inst->_index = INST_SET;
+}
+
+
+
+
+void Parallaction::parseScriptLine(Instruction *inst, Animation *a, LocalVariable *locals) {
+// printf("parseScriptLine()\n");
+
+ static const Opcode opcodes[] = {
+ INSTRUCTION_PARSER(defLocal), // unknown opcode -> local definition
+ INSTRUCTION_PARSER(animation), // on
+ INSTRUCTION_PARSER(animation), // off
+ INSTRUCTION_PARSER(x),
+ INSTRUCTION_PARSER(y),
+ INSTRUCTION_PARSER(z),
+ INSTRUCTION_PARSER(f),
+ INSTRUCTION_PARSER(loop),
+ INSTRUCTION_PARSER(null), // endloop
+ INSTRUCTION_PARSER(null), // show
+ INSTRUCTION_PARSER(inc),
+ INSTRUCTION_PARSER(inc), // dec
+ INSTRUCTION_PARSER(set),
+ INSTRUCTION_PARSER(put),
+ INSTRUCTION_PARSER(call),
+ INSTRUCTION_PARSER(null), // wait
+ INSTRUCTION_PARSER(animation), // start
+ INSTRUCTION_PARSER(sound),
+ INSTRUCTION_PARSER(move)
+ };
+
+ _instructionParsers = opcodes;
- inst->_flags = kInstUsesLiteral | kInstUsesLocal;
- inst->_index = INST_SET;
+ if (_tokens[0][1] == '.') {
+ _tokens[0][1] = '\0';
+ a = findAnimation(&_tokens[0][2]);
}
- break;
+ if (_tokens[1][1] == '.') {
+ _tokens[1][1] = '\0';
+ a = findAnimation(&_tokens[1][2]);
}
+ int16 _si = _instructionNames->lookup(_tokens[0]);
+ inst->_index = _si;
+
+ _instParseCtxt.a = a;
+ _instParseCtxt.inst = inst;
+ _instParseCtxt.locals = locals;
+
+ (this->*_instructionParsers[inst->_index])();
return;
}
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 9907f9a956..d491e1f807 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -302,6 +302,8 @@ struct BackgroundInfo {
#define DECLARE_COMMAND_OPCODE(op) void Parallaction::cmdOp_##op()
#define COMMAND_OPCODE(op) &Parallaction::cmdOp_##op
+#define DECLARE_INSTRUCTION_PARSER(sig) void Parallaction::instParse_##sig()
+#define INSTRUCTION_PARSER(sig) &Parallaction::instParse_##sig
#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction::instOp_##op()
#define INSTRUCTION_OPCODE(op) &Parallaction::instOp_##op
@@ -365,6 +367,29 @@ public:
DECLARE_COMMAND_OPCODE(move);
DECLARE_COMMAND_OPCODE(stop);
+ const Opcode *_instructionParsers;
+
+ struct {
+ Animation *a;
+ Instruction *inst;
+ LocalVariable *locals;
+ } _instParseCtxt;
+
+ DECLARE_INSTRUCTION_PARSER(animation);
+ DECLARE_INSTRUCTION_PARSER(loop);
+ DECLARE_INSTRUCTION_PARSER(x);
+ DECLARE_INSTRUCTION_PARSER(y);
+ DECLARE_INSTRUCTION_PARSER(z);
+ DECLARE_INSTRUCTION_PARSER(f);
+ DECLARE_INSTRUCTION_PARSER(inc);
+ DECLARE_INSTRUCTION_PARSER(set);
+ DECLARE_INSTRUCTION_PARSER(move);
+ DECLARE_INSTRUCTION_PARSER(put);
+ DECLARE_INSTRUCTION_PARSER(call);
+ DECLARE_INSTRUCTION_PARSER(sound);
+ DECLARE_INSTRUCTION_PARSER(null);
+ DECLARE_INSTRUCTION_PARSER(defLocal);
+
const Opcode *_instructionOpcodes;
struct {