aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/alan2/inter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/alan2/inter.cpp')
-rw-r--r--engines/glk/alan2/inter.cpp893
1 files changed, 893 insertions, 0 deletions
diff --git a/engines/glk/alan2/inter.cpp b/engines/glk/alan2/inter.cpp
new file mode 100644
index 0000000000..02b4f4819f
--- /dev/null
+++ b/engines/glk/alan2/inter.cpp
@@ -0,0 +1,893 @@
+/* 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.
+ *
+ */
+
+#include <string>
+#include "glk/alan2/types.h"
+#include "glk/alan2/main.h"
+#include "glk/alan2/parse.h"
+#include "glk/alan2/exe.h"
+#include "glk/alan2/stack.h"
+#include "glk/alan2/sysdep.h"
+
+#include "glk/alan2/inter.h"
+
+#ifdef GLK
+#include "glk/alan2/glkio.h"
+#endif
+
+namespace Glk {
+namespace Alan2 {
+
+/* PRIVATE DATA */
+
+static int pc;
+
+
+#ifdef _PROTOTYPES_
+static void if_(
+ Aword v
+)
+#else
+static void if_(v)
+ Aword v;
+#endif
+{
+ int lev = 1;
+ Aword i;
+
+ if (!v) {
+ /* Skip to next ELSE or ENDIF on same level */
+ while (TRUE) {
+ i = memory[pc++];
+ if (I_CLASS(i) == (Aword)C_STMOP)
+ switch (I_OP(i)) {
+ case I_ELSE:
+ if (lev == 1) return;
+ break;
+ case I_IF:
+ lev++;
+ break;
+ case I_ENDIF:
+ lev--;
+ if (lev == 0) return;
+ break;
+ }
+ }
+ }
+}
+
+
+#ifdef _PROTOTYPES_
+static void else_(void)
+#else
+static void else_()
+#endif
+{
+ int lev = 1;
+ Aword i;
+
+ while (TRUE) {
+ /* Skip to ENDIF on the same level */
+ i = memory[pc++];
+ if (I_CLASS(i) == (Aword)C_STMOP)
+ switch (I_OP(i)) {
+ case I_ENDIF:
+ lev--;
+ if (lev == 0) return;
+ break;
+ case I_IF:
+ lev++;
+ break;
+ }
+ }
+}
+
+
+#ifdef _PROTOTYPES_
+static void depstart(void)
+#else
+static void depstart(void)
+#endif
+{
+ /* A DEPSTART was executed so skip across the redundant DEPCASE to
+ start at the first expression */
+ pc++;
+}
+
+
+#ifdef _PROTOTYPES_
+static void swap(void)
+#else
+static void swap()
+#endif
+{
+ Aptr v1 = pop();
+ Aptr v2 = pop();
+
+ push(v1);
+ push(v2);
+}
+
+
+
+#ifdef _PROTOTYPES_
+static void depexec(
+ Aword v
+)
+#else
+static void depexec(v)
+ Aword v;
+#endif
+{
+ int lev = 1;
+ Aword i;
+
+ if (!v)
+ /* The expression was not true, skip to next CASE on the same
+ level which could be a DEPCASE or DEPELSE */
+ while (TRUE) {
+ i = memory[pc++];
+ if (I_CLASS(i) == (Aword)C_STMOP)
+ switch (I_OP(i)) {
+ case I_DEPSTART:
+ lev++;
+ break;
+ case I_DEPEND:
+ if (lev == 1) return;
+ lev--;
+ break;
+ case I_DEPCASE:
+ case I_DEPELSE:
+ if (lev == 1) return;
+ break;
+ }
+ }
+}
+
+
+#ifdef _PROTOTYPES_
+static void depcase(void)
+#else
+static void depcase()
+#endif
+{
+ int lev = 1;
+ Aword i;
+
+ /* Skip to end of DEPENDING block (next DEPEND on same level) because
+ we have just executed a DEPCASE/DEPELSE statement as a result of a DEPCASE
+ catching */
+
+ while (TRUE) {
+ i = memory[pc++];
+ if (I_CLASS(i) == (Aword)C_STMOP)
+ switch (I_OP(i)) {
+ case I_DEPSTART:
+ lev++;
+ break;
+ case I_DEPEND:
+ lev--;
+ if (lev == 0) return;
+ break;
+ }
+ }
+}
+
+
+#ifdef _PROTOTYPES_
+void interpret(Aaddr adr)
+#else
+void interpret(adr)
+ Aaddr adr;
+#endif
+{
+ Aaddr oldpc;
+ Aword i;
+
+ if (stpflg) printf("\n++++++++++++++++++++++++++++++++++++++++++++++++++");
+
+ oldpc = pc;
+ pc = adr;
+ while(TRUE) {
+ if (stpflg) printf("\n%4x: ", pc);
+ if (pc > memTop)
+ syserr("Interpreting outside program.");
+
+ i = memory[pc++];
+
+ switch (I_CLASS(i)) {
+ case C_CONST:
+ if (stpflg) printf("PUSH \t%5ld", I_OP(i));
+ push(I_OP(i));
+ break;
+ case C_CURVAR:
+ switch (I_OP(i)) {
+ case V_PARAM:
+ if (stpflg) printf("PARAM \t%5ld\t\t(%ld)", top(), params[top()-1].code);
+ push(params[pop()-1].code);
+ break;
+ case V_CURLOC:
+ if (stpflg) printf("CURLOC \t\t\t(%d)", cur.loc);
+ push(cur.loc);
+ break;
+ case V_CURACT:
+ if (stpflg) printf("CURACT \t\t\t(%d)", cur.act);
+ push(cur.act);
+ break;
+ case V_CURVRB:
+ if (stpflg) printf("CURVRB \t\t\t(%d)", cur.vrb);
+ push(cur.vrb);
+ break;
+ case V_SCORE:
+ if (stpflg) printf("CURSCORE \t\t\t(%d)", cur.score);
+ push(cur.score);
+ break;
+ default:
+ syserr("Unknown CURVAR instruction.");
+ break;
+ }
+ break;
+
+ case C_STMOP:
+ switch (I_OP(i)) {
+ case I_PRINT: {
+ Aptr fpos, len;
+ fpos = pop();
+ len = pop();
+ if (stpflg) {
+ printf("PRINT \t%5ld, %5ld\t\"", fpos, len);
+ col = 34; /* To format it better! */
+ }
+ print((char *)fpos, len);
+ if (stpflg)
+ printf("\"");
+ break;
+ }
+ case I_SYSTEM: {
+ Aptr fpos, len;
+ fpos = pop();
+ len = pop();
+ if (stpflg) {
+ printf("SYSTEM \t%5ld, %5ld\t\"", fpos, len);
+ col = 34; /* To format it better! */
+ }
+ sys(fpos, len);
+ break;
+ }
+ case I_GETSTR: {
+ Aptr fpos, len;
+ fpos = pop();
+ len = pop();
+ if (stpflg)
+ printf("GETSTR\t%5ld, %5ld", fpos, len);
+ getstr(fpos, len);
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_QUIT: {
+ if (stpflg)
+ printf("QUIT");
+ quit();
+ break;
+ }
+ case I_LOOK: {
+ if (stpflg)
+ printf("LOOK");
+ look();
+ break;
+ }
+ case I_SAVE: {
+ if (stpflg)
+ printf("SAVE");
+ save();
+ break;
+ }
+ case I_RESTORE: {
+ if (stpflg)
+ printf("RESTORE");
+ restore();
+ break;
+ }
+ case I_RESTART: {
+ if (stpflg)
+ printf("RESTART");
+ restart();
+ break;
+ }
+ case I_LIST: {
+ Aptr cnt;
+ cnt = pop();
+ if (stpflg)
+ printf("LIST \t%5ld", cnt);
+ list(cnt);
+ break;
+ }
+ case I_EMPTY: {
+ Aptr cnt, whr;
+ cnt = pop();
+ whr = pop();
+ if (stpflg)
+ printf("EMPTY \t%5ld, %5ld", cnt, whr);
+ empty(cnt, whr);
+ break;
+ }
+ case I_SCORE: {
+ Aptr sc;
+ sc = pop();
+ if (stpflg)
+ printf("SCORE \t%5ld\t\t(%ld)", sc, scores[sc-1]);
+ score(sc);
+ break;
+ }
+ case I_VISITS: {
+ Aptr v;
+ v = pop();
+ if (stpflg)
+ printf("VISITS \t%5ld", v);
+ visits(v);
+ break;
+ }
+ case I_SCHEDULE: {
+ Aptr evt, whr, aft;
+ evt = pop();
+ whr = pop();
+ aft = pop();
+ if (stpflg)
+ printf("SCHEDULE \t%5ld, %5ld, %5ld", evt, whr, aft);
+ schedule(evt, whr, aft);
+ break;
+ }
+ case I_CANCEL: {
+ Aptr evt;
+ evt = pop();
+ if (stpflg)
+ printf("CANCEL \t%5ld", evt);
+ cancl(evt);
+ break;
+ }
+ case I_MAKE: {
+ Aptr id, atr, val;
+ id = pop();
+ atr = pop();
+ val = pop();
+ if (stpflg) {
+ printf("MAKE \t%5ld, %5ld, ", id, atr);
+ if (val) printf("TRUE"); else printf("FALSE");
+ }
+ make(id, atr, val);
+ break;
+ }
+ case I_SET: {
+ Aptr id, atr, val;
+ id = pop();
+ atr = pop();
+ val = pop();
+ if (stpflg) {
+ printf("SET \t%5ld, %5ld, %5ld", id, atr, val);
+ }
+ set(id, atr, val);
+ break;
+ }
+ case I_STRSET: {
+ Aptr id, atr, str;
+ id = pop();
+ atr = pop();
+ str = pop();
+ if (stpflg) {
+ printf("STRSET\t%5ld, %5ld, %5ld", id, atr, str);
+ }
+ setstr(id, atr, str);
+ break;
+ }
+ case I_INCR: {
+ Aptr id, atr, step;
+ id = pop();
+ atr = pop();
+ step = pop();
+ if (stpflg) {
+ printf("INCR\t%5ld, %5ld, %5ld", id, atr, step);
+ }
+ incr(id, atr, step);
+ break;
+ }
+ case I_DECR: {
+ Aptr id, atr, step;
+ id = pop();
+ atr = pop();
+ step = pop();
+ if (stpflg) {
+ printf("DECR\t%5ld, %5ld, %5ld", id, atr, step);
+ }
+ decr(id, atr, step);
+ break;
+ }
+ case I_ATTRIBUTE: {
+ Aptr id, atr;
+ id = pop();
+ atr = pop();
+ if (stpflg)
+ printf("ATTRIBUTE %5ld, %5ld", id, atr);
+ push(attribute(id, atr));
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_STRATTR: {
+ Aptr id, atr;
+ id = pop();
+ atr = pop();
+ if (stpflg)
+ printf("STRATTR \t%5ld, %5ld", id, atr);
+ push(strattr(id, atr));
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_LOCATE: {
+ Aptr id, whr;
+ id = pop();
+ whr = pop();
+ if (stpflg)
+ printf("LOCATE \t%5ld, %5ld", id, whr);
+ locate(id, whr);
+ break;
+ }
+ case I_WHERE: {
+ Aptr id;
+ id = pop();
+ if (stpflg)
+ printf("WHERE \t%5ld", id);
+ push(where(id));
+ if (stpflg)
+ printf("\t\t(%ld)", top());
+ break;
+ }
+ case I_HERE: {
+ Aptr id;
+ id = pop();
+ if (stpflg)
+ printf("HERE \t%5ld", id);
+ push(isHere(id));
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_NEAR: {
+ Aptr id;
+ id = pop();
+ if (stpflg)
+ printf("NEAR \t%5ld", id);
+ push(isNear(id));
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_USE: {
+ Aptr act, scr;
+ act = pop();
+ scr = pop();
+ if (stpflg)
+ printf("USE \t%5ld, %5ld", act, scr);
+ use(act, scr);
+ break;
+ }
+ case I_IN: {
+ Aptr obj, cnt;
+ obj = pop();
+ cnt = pop();
+ if (stpflg)
+ printf("IN \t%5ld, %5ld ", obj, cnt);
+ push(in(obj, cnt));
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_DESCRIBE: {
+ Aptr id;
+ id = pop();
+ if (stpflg) {
+ printf("DESCRIBE \t%5ld\t", id);
+ col = 34; /* To format it better! */
+ }
+ describe(id);
+ break;
+ }
+ case I_SAY: {
+ Aptr id;
+ id = pop();
+ if (stpflg)
+ printf("SAY \t%5ld\t\t\"", id);
+ say(id);
+ if (stpflg)
+ printf("\"");
+ break;
+ }
+ case I_SAYINT: {
+ Aptr val;
+ val = pop();
+ if (stpflg)
+ printf("SAYINT\t%5ld\t\t\"", val);
+ sayint(val);
+ if (stpflg)
+ printf("\"");
+ break;
+ }
+ case I_SAYSTR: {
+ Aptr adr;
+ adr = pop();
+ if (stpflg)
+ printf("SAYSTR\t%5ld\t\t\"", adr);
+ saystr((char *)adr);
+ if (stpflg)
+ printf("\"");
+ break;
+ }
+ case I_IF: {
+ Aptr v;
+ v = pop();
+ if (stpflg) {
+ printf("IF \t");
+ if (v) printf(" TRUE"); else printf("FALSE");
+ }
+ if_(v);
+ break;
+ }
+ case I_ELSE: {
+ if (stpflg)
+ printf("ELSE");
+ else_();
+ break;
+ }
+ case I_ENDIF: {
+ if (stpflg)
+ printf("ENDIF");
+ break;
+ }
+ case I_AND: {
+ Aptr lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg) {
+ printf("AND \t");
+ if (lh) printf("TRUE, "); else printf("FALSE, ");
+ if (rh) printf("TRUE"); else printf("FALSE");
+ }
+ push(lh && rh);
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_OR: {
+ Aptr lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg) {
+ printf("OR \t");
+ if (lh) printf("TRUE, "); else printf("FALSE, ");
+ if (rh) printf("TRUE"); else printf("FALSE");
+ }
+ push(lh || rh);
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_NE: {
+ Aptr lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("NE \t%5ld, %5ld", lh, rh);
+ push(lh != rh);
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_EQ: {
+ Aptr lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("EQ \t%5ld, %5ld", lh, rh);
+ push(lh == rh);
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_STREQ: {
+ Aptr lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("STREQ \t%5ld, %5ld", lh, rh);
+ push(streq((char *)lh, (char *)rh));
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_STREXACT: {
+ Aptr lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("STREXACT \t%5ld, %5ld", lh, rh);
+ push(strcmp((char *)lh, (char *)rh) == 0);
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ free((void *)lh);
+ free((void *)rh);
+ break;
+ }
+ case I_LE: {
+ Aint lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("LE \t%5ld, %5ld", lh, rh);
+ push(lh <= rh);
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_GE: {
+ Aint lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("GE \t%5ld, %5ld", lh, rh);
+ push(lh >= rh);
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_LT: {
+ Aint lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("LT \t%5ld, %5ld", lh, rh);
+ push((signed int)lh < (signed int)rh);
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_GT: {
+ Aint lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("GT \t%5ld, %5ld", lh, rh);
+ push(lh > rh);
+ if (stpflg)
+ if (top()) printf("\t(TRUE)"); else printf("\t(FALSE)");
+ break;
+ }
+ case I_PLUS: {
+ Aint lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("PLUS \t%5ld, %5ld", lh, rh);
+ push(lh + rh);
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_MINUS: {
+ Aint lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("MINUS \t%5ld, %5ld", lh, rh);
+ push(lh - rh);
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_MULT: {
+ Aint lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("MULT \t%5ld, %5ld", lh, rh);
+ push(lh * rh);
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_DIV: {
+ Aint lh, rh;
+ if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
+ swap();
+ rh = pop();
+ lh = pop();
+ if (stpflg)
+ printf("DIV \t%5ld, %5ld", lh, rh);
+ push(lh / rh);
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_NOT: {
+ Aptr val;
+ val = pop();
+ if (stpflg) {
+ printf("NOT \t");
+ if (val) printf("TRUE"); else printf("FALSE");
+ }
+ push(!val);
+ if (stpflg)
+ if (top()) printf("\t\t(TRUE)"); else printf("\t\t(FALSE)");
+ break;
+ }
+ case I_MAX: {
+ Aptr atr, whr;
+ atr = pop();
+ whr = pop();
+ if (stpflg)
+ printf("MAX \t%5ld, %5ld", atr, whr);
+ push(agrmax(atr, whr));
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_SUM: {
+ Aptr atr, whr;
+ atr = pop();
+ whr = pop();
+ if (stpflg)
+ printf("SUM \t%5ld, %5ld", atr, whr);
+ push(agrsum(atr, whr));
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_COUNT: {
+ Aptr whr;
+ whr = pop();
+ if (stpflg)
+ printf("COUNT \t%5ld", whr);
+ push(agrcount(whr));
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_RND: {
+ Aptr from, to;
+ from = pop();
+ to = pop();
+ if (stpflg)
+ printf("RANDOM \t%5ld, %5ld", from, to);
+ push(rnd(from, to));
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_BTW: {
+ Aint low, high, val;
+ high = pop();
+ low = pop();
+ val = pop();
+ if (stpflg)
+ printf("BETWEEN \t%5ld, %5ld, %5ld", val, low, high);
+ push(btw(val, low, high));
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+ case I_CONTAINS: {
+ Aptr string, substring;
+ substring = pop();
+ string = pop();
+ if (stpflg)
+ printf("CONTAINS \t%5ld, %5ld", string, substring);
+ push(contains(string, substring));
+ if (stpflg)
+ printf("\t(%ld)", top());
+ break;
+ }
+
+ case I_DEPSTART:
+ if (stpflg)
+ printf("DEPSTART");
+ depstart();
+ break;
+
+ case I_DEPCASE:
+ if (stpflg)
+ printf("DEPCASE");
+ depcase();
+ break;
+
+ case I_DEPEXEC: {
+ Aptr v;
+ v = pop();
+ if (stpflg) {
+ printf("DEPEXEC \t");
+ if (v) printf(" TRUE"); else printf("FALSE");
+ }
+ depexec(v);
+ break;
+ }
+
+ case I_DEPELSE:
+ if (stpflg)
+ printf("DEPELSE");
+ depcase();
+ break;
+
+ case I_DEPEND:
+ if (stpflg)
+ printf("DEPEND");
+ break;
+
+ case I_RETURN:
+ if (stpflg)
+ printf("RETURN\n--------------------------------------------------\n");
+ pc = oldpc;
+ return;
+
+ default:
+ syserr("Unknown STMOP instruction.");
+ break;
+ }
+ if (fail) {
+ pc = oldpc;
+ return;
+ }
+ break;
+
+ default:
+ syserr("Unknown instruction class.");
+ break;
+ }
+ }
+}
+
+} // End of namespace Alan2
+} // End of namespace Glk