diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/glk/advsys/advsys.h | 7 | ||||
-rw-r--r-- | engines/glk/advsys/definitions.h | 1 | ||||
-rw-r--r-- | engines/glk/advsys/game.h | 9 | ||||
-rw-r--r-- | engines/glk/advsys/glk_interface.cpp | 30 | ||||
-rw-r--r-- | engines/glk/advsys/glk_interface.h | 46 | ||||
-rw-r--r-- | engines/glk/advsys/vm.cpp | 278 | ||||
-rw-r--r-- | engines/glk/advsys/vm.h | 223 | ||||
-rw-r--r-- | engines/glk/module.mk | 2 |
8 files changed, 591 insertions, 5 deletions
diff --git a/engines/glk/advsys/advsys.h b/engines/glk/advsys/advsys.h index ea2558fa58..9aa1305415 100644 --- a/engines/glk/advsys/advsys.h +++ b/engines/glk/advsys/advsys.h @@ -24,8 +24,7 @@ #define GLK_ADVSYS_ADVSYS #include "common/scummsys.h" -#include "glk/glk_api.h" -#include "glk/advsys/game.h" +#include "glk/advsys/vm.h" namespace Glk { namespace AdvSys { @@ -33,7 +32,7 @@ namespace AdvSys { /** * AdvSys game interpreter */ -class AdvSys : public GlkAPI, public Game { +class AdvSys : public VM { private: winid_t _window; private: @@ -55,7 +54,7 @@ public: /** * Constructor */ - AdvSys(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc) {} + AdvSys(OSystem *syst, const GlkGameDescription &gameDesc) : VM(syst, gameDesc) {} /** * Run the game diff --git a/engines/glk/advsys/definitions.h b/engines/glk/advsys/definitions.h index 8c96a9ea0a..39e07ca3aa 100644 --- a/engines/glk/advsys/definitions.h +++ b/engines/glk/advsys/definitions.h @@ -26,7 +26,6 @@ namespace Glk { namespace AdvSys { -#define NIL 0 } // End of namespace AdvSys } // End of namespace Glk diff --git a/engines/glk/advsys/game.h b/engines/glk/advsys/game.h index d74245b67c..40b4fb65ec 100644 --- a/engines/glk/advsys/game.h +++ b/engines/glk/advsys/game.h @@ -29,6 +29,8 @@ namespace Glk { namespace AdvSys { +#define NIL 0 + /** * Actions */ @@ -306,6 +308,13 @@ public: } /** + * Gets a code byte + */ + int getCodeWord(int offset) const { + return READ_LE_UINT16(_codeSpace + offset); + } + + /** * Read a word */ int readWord(int offset) const { diff --git a/engines/glk/advsys/glk_interface.cpp b/engines/glk/advsys/glk_interface.cpp new file mode 100644 index 0000000000..3bc6800d0c --- /dev/null +++ b/engines/glk/advsys/glk_interface.cpp @@ -0,0 +1,30 @@ +/* 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 "glk/advsys/glk_interface.h" + +namespace Glk { +namespace AdvSys { + + +} // End of namespace AdvSys +} // End of namespace Glk diff --git a/engines/glk/advsys/glk_interface.h b/engines/glk/advsys/glk_interface.h new file mode 100644 index 0000000000..58ff831509 --- /dev/null +++ b/engines/glk/advsys/glk_interface.h @@ -0,0 +1,46 @@ +/* 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. + * + */ + +#ifndef GLK_ADVSYS_GLK_INTERFACE +#define GLK_ADVSYS_GLK_INTERFACE + +#include "glk/glk_api.h" + +namespace Glk { +namespace AdvSys { + +/** + * Interface class that sits between AdvSys and the GLK base, providing methods for + * input and output + */ +class GlkInterface : public GlkAPI { +public: + /** + * Constructor + */ + GlkInterface(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc) {} +}; + +} // End of namespace AdvSys +} // End of namespace Glk + +#endif diff --git a/engines/glk/advsys/vm.cpp b/engines/glk/advsys/vm.cpp new file mode 100644 index 0000000000..a467a592d2 --- /dev/null +++ b/engines/glk/advsys/vm.cpp @@ -0,0 +1,278 @@ +/* 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 "glk/advsys/vm.h" + +namespace Glk { +namespace AdvSys { + +OpcodeMethod VM::_METHODS[0x34] = { + &VM::opBRT, + &VM::opBRF, + &VM::opBR, + &VM::opT, + &VM::opNIL, + &VM::opPUSH, + &VM::opNOT, + &VM::opADD, + &VM::opSUB, + &VM::opMUL, + &VM::opDIV, + &VM::opREM, + &VM::opBAND, + &VM::opBOR, + &VM::opBNOT, + &VM::opLT, + &VM::opEQ, + &VM::opGT, + &VM::opLIT, + &VM::opVAR, + &VM::opGETP, + &VM::opSETP, + &VM::opSET, + &VM::opPRINT, + &VM::opTERPRI, + &VM::opPNUMBER, + &VM::opFINISH, + &VM::opCHAIN, + &VM::opABORT, + &VM::opEXIT, + &VM::opRETURN, + &VM::opCALL, + &VM::opSVAR, + &VM::opSSET, + &VM::opSPLIT, + &VM::opSNLIT, + &VM::opYORN, + &VM::opSAVE, + &VM::opRESTORE, + &VM::opARG, + &VM::opASET, + &VM::opTMP, + &VM::opTSET, + &VM::opTSPACE, + &VM::opCLASS, + &VM::opMATCH, + &VM::opPNOUN, + &VM::opRESTART, + &VM::opRAND, + &VM::opRNDMIZE, + &VM::opSEND, + &VM::opVOWEL +}; + +VM::VM(OSystem *syst, const GlkGameDescription &gameDesc) : GlkInterface(syst, gameDesc), Game(), + _pc(0), _status(IN_PROGRESS) { +} + +ExecutionResult VM::execute(int offset) { + // Set the code pointer + _pc = offset; + + // Clear the stack + _stack.clear(); + + // Iterate through the script + for (_status = IN_PROGRESS; !shouldQuit() && _status == IN_PROGRESS; ) + executeOpcode(); + + return _status; +} + +void VM::executeOpcode() { + // Get next opcode + uint opcode = getCodeByte(_pc); + ++_pc; + + if (opcode >= OP_BRT && opcode <= OP_VOWEL) { + (this->*_METHODS[(int)opcode - 1])(); + } else if (opcode >= OP_XVAR && opcode < OP_XSET) { + _stack.back() = getVariable((int)opcode - OP_XVAR); + } else if (opcode >= OP_XSET && opcode < OP_XPLIT) { + setVariable((int)opcode - OP_XSET, _stack.back()); + } else if (opcode >= OP_XPLIT && opcode < OP_XNLIT) { + _stack.back() = (int)opcode - OP_XPLIT; + } else if (opcode >= OP_XNLIT && (int)opcode < 256) { + _stack.back() = OP_XNLIT - opcode; + } else { + error("Unknown opcode %x at offset %d", opcode, _pc); + } +} + +void VM::opBRT() { +} + +void VM::opBRF() { +} + +void VM::opBR() { +} + +void VM::opT() { +} + +void VM::opNIL() { +} + +void VM::opPUSH() { +} + +void VM::opNOT() { +} + +void VM::opADD() { +} + +void VM::opSUB() { +} + +void VM::opMUL() { +} + +void VM::opDIV() { +} + +void VM::opREM() { +} + +void VM::opBAND() { +} + +void VM::opBOR() { +} + +void VM::opBNOT() { +} + +void VM::opLT() { +} + +void VM::opEQ() { +} + +void VM::opGT() { +} + +void VM::opLIT() { +} + +void VM::opVAR() { +} + +void VM::opGETP() { +} + +void VM::opSETP() { +} + +void VM::opSET() { +} + +void VM::opPRINT() { +} + +void VM::opTERPRI() { +} + +void VM::opPNUMBER() { +} + +void VM::opFINISH() { +} + +void VM::opCHAIN() { +} + +void VM::opABORT() { +} + +void VM::opEXIT() { +} + +void VM::opRETURN() { +} + +void VM::opCALL() { +} + +void VM::opSVAR() { +} + +void VM::opSSET() { +} + +void VM::opSPLIT() { +} + +void VM::opSNLIT() { +} + +void VM::opYORN() { +} + +void VM::opSAVE() { +} + +void VM::opRESTORE() { +} + +void VM::opARG() { +} + +void VM::opASET() { +} + +void VM::opTMP() { +} + +void VM::opTSET() { +} + +void VM::opTSPACE() { +} + +void VM::opCLASS() { +} + +void VM::opMATCH() { +} + +void VM::opPNOUN() { +} + +void VM::opRESTART() { +} + +void VM::opRAND() { +} + +void VM::opRNDMIZE() { +} + +void VM::opSEND() { +} + +void VM::opVOWEL() { +} + +} // End of namespace AdvSys +} // End of namespace Glk diff --git a/engines/glk/advsys/vm.h b/engines/glk/advsys/vm.h new file mode 100644 index 0000000000..84cd313961 --- /dev/null +++ b/engines/glk/advsys/vm.h @@ -0,0 +1,223 @@ +/* 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. + * + */ + +#ifndef GLK_ADVSYS_VM +#define GLK_ADVSYS_VM + +#include "glk/advsys/glk_interface.h" +#include "glk/advsys/game.h" +#include "common/array.h" + +namespace Glk { +namespace AdvSys { + +/** + * Execution result states + */ +enum ExecutionResult { + IN_PROGRESS = 0, ///< Default state whilst script is in progress + FINISH = 1, ///< Script was finished + CHAIN = 2, ///< Another script is being chained to + ABORT = 3 ///< Script was aborted +}; + +/** + * Opcode list + */ +enum Opcode { + OP_BRT = 0x01, ///< Branch on true + OP_BRF = 0x02, ///< Branch on false + OP_BR = 0x03, ///< Branch unconditionally + OP_T = 0x04, ///< Load top of stack with t + OP_NIL = 0x05, ///< Load top of stack with nil + OP_PUSH = 0x06, ///< Push nil onto stack + OP_NOT = 0x07, ///< Logical negate top of stack + OP_ADD = 0x08, ///< Add two numeric expressions + OP_SUB = 0x09, ///< Subtract two numeric expressions + OP_MUL = 0x0A, ///< Multiply two numeric expressions + OP_DIV = 0x0B, ///< Divide two numeric expressions + OP_REM = 0x0C, ///< Remainder of two numeric expressions + OP_BAND = 0x0D, ///< Bitwise and of two numeric expressions + OP_BOR = 0x0E, ///< Bitwise or of two numeric expressions + OP_BNOT = 0x0F, ///< Bitwise not + OP_LT = 0x10, ///< Less than + OP_EQ = 0x11, ///< Equal to + OP_GT = 0x12, ///< Greater than + OP_LIT = 0x13, ///< Load literal + OP_VAR = 0x14, ///< Load a variable value + OP_GETP = 0x15, ///< Get the value of an object property + OP_SETP = 0x16, ///< Set the value of an object property + OP_SET = 0x17, ///< Set the value of a variable + OP_PRINT = 0x18, ///< Print messages + OP_TERPRI = 0x19, ///< Terminate the print line + OP_PNUMBER = 0x1A, ///< Print a number + OP_FINISH = 0x1B, ///< Finish handling this command + OP_CHAIN = 0x1C, ///< Chain to the next handler + OP_ABORT = 0x1D, ///< Abort this command + OP_EXIT = 0x1E, ///< Exit the game + OP_RETURN = 0x1F, ///< Return from function + OP_CALL = 0x20, ///< Call subroutine + OP_SVAR = 0x21, ///< Short load a variable + OP_SSET = 0x22, ///< Short set a variable + OP_SPLIT = 0x23, ///< Short load a positive literal + OP_SNLIT = 0x24, ///< Short load a negative literal + OP_YORN = 0x25, ///< Yes or No predicate + OP_SAVE = 0x26, ///< Save data structures + OP_RESTORE = 0x27, ///< Restore data structures + OP_ARG = 0x28, ///< Load an argument value + OP_ASET = 0x29, ///< Set an argument value + OP_TMP = 0x2A, ///< Load a temporary variable value + OP_TSET = 0x2B, ///< Set a temporary variable + OP_TSPACE = 0x2C, ///< Allocate temporary variable space + OP_CLASS = 0x2D, ///< Get the class of an object + OP_MATCH = 0x2E, ///< Match a noun phrase with an object + OP_PNOUN = 0x2F, ///< Print a noun phrase + OP_RESTART = 0x30, ///< Restart the current game + OP_RAND = 0x31, ///< Generate a random number + OP_RNDMIZE = 0x32, ///< Seed the random number generator + OP_SEND = 0x33, ///< Send a message to an object + OP_VOWEL = 0x34, ///< Check for vowel beginning string + + OP_XVAR = 0x40, ///< Extra short load a variable + OP_XSET = 0x60, ///< Extra short set a variable + OP_XPLIT = 0x80, ///< Extra short load a positive literal + OP_XNLIT = 0xC0 ///< Extra short load a negative literal +}; + +class VM; +typedef void (VM::*OpcodeMethod)(); + +/** + * Main VM for AdvSys + */ +class VM : public GlkInterface, public Game { + class ArrayStack : public Common::Array<int> { + public: + /** + * Push a value onto the stack + */ + void push(int v) { push_back(v); } + + /** + * Pop a value from the stack + */ + int pop() { + int v = back(); + pop_back(); + return v; + } + }; +private: + static OpcodeMethod _METHODS[0x34]; + int _pc; + ExecutionResult _status; + ArrayStack _stack; +private: + /** + * Execute a single opcode within the script + */ + void executeOpcode(); + + /** + * Get the next code byte and increments the PC counter + */ + int readCodeByte() { + return getCodeByte(_pc++); + } + + /** + * Gets the next code word and increases the PC counter to after it + */ + int readCodeWord() { + return getCodeWord(_pc += 2); + } +private: + void opBRT(); + void opBRF(); + void opBR(); + void opT(); + void opNIL(); + void opPUSH(); + void opNOT(); + void opADD(); + void opSUB(); + void opMUL(); + void opDIV(); + void opREM(); + void opBAND(); + void opBOR(); + void opBNOT(); + void opLT(); + void opEQ(); + void opGT(); + void opLIT(); + void opVAR(); + void opGETP(); + void opSETP(); + void opSET(); + void opPRINT(); + void opTERPRI(); + void opPNUMBER(); + void opFINISH(); + void opCHAIN(); + void opABORT(); + void opEXIT(); + void opRETURN(); + void opCALL(); + void opSVAR(); + void opSSET(); + void opSPLIT(); + void opSNLIT(); + void opYORN(); + void opSAVE(); + void opRESTORE(); + void opARG(); + void opASET(); + void opTMP(); + void opTSET(); + void opTSPACE(); + void opCLASS(); + void opMATCH(); + void opPNOUN(); + void opRESTART(); + void opRAND(); + void opRNDMIZE(); + void opSEND(); + void opVOWEL(); +public: + /** + * Constructor + */ + VM(OSystem *syst, const GlkGameDescription &gameDesc); + + /** + * Exeecute a script + * @param offset Script offset + * @returns Script result code + */ + ExecutionResult execute(int offset); +}; + +} // End of namespace AdvSys +} // End of namespace Glk + +#endif diff --git a/engines/glk/module.mk b/engines/glk/module.mk index 827b5e4d78..b599f02fb9 100644 --- a/engines/glk/module.mk +++ b/engines/glk/module.mk @@ -28,6 +28,8 @@ MODULE_OBJS := \ advsys/advsys.o \ advsys/detection.o \ advsys/game.o \ + advsys/glk_interface.o \ + advsys/vm.o \ alan2/alan2.o \ alan2/decode.o \ alan2/detection.o \ |