diff options
author | Paul Gilbert | 2019-06-10 19:04:35 -0700 |
---|---|---|
committer | Paul Gilbert | 2019-06-10 19:08:58 -0700 |
commit | ebdc4ec3faf509625ac94948cbbb0996d440c37e (patch) | |
tree | 7464384bcc5f2cd8199c81d5ab2da0905d212bb4 /engines/glk | |
parent | 1de8c3d7308512b4eae556511a468d9b59d26f90 (diff) | |
download | scummvm-rg350-ebdc4ec3faf509625ac94948cbbb0996d440c37e.tar.gz scummvm-rg350-ebdc4ec3faf509625ac94948cbbb0996d440c37e.tar.bz2 scummvm-rg350-ebdc4ec3faf509625ac94948cbbb0996d440c37e.zip |
GLK: ADVSYS: Created dedicated function pointer class, cleanup method opcodes
Diffstat (limited to 'engines/glk')
-rw-r--r-- | engines/glk/advsys/vm.cpp | 34 | ||||
-rw-r--r-- | engines/glk/advsys/vm.h | 74 |
2 files changed, 81 insertions, 27 deletions
diff --git a/engines/glk/advsys/vm.cpp b/engines/glk/advsys/vm.cpp index a06cd28512..dbfe0ad3a1 100644 --- a/engines/glk/advsys/vm.cpp +++ b/engines/glk/advsys/vm.cpp @@ -83,7 +83,7 @@ OpcodeMethod VM::_METHODS[0x34] = { }; VM::VM(OSystem *syst, const GlkGameDescription &gameDesc) : GlkInterface(syst, gameDesc), Game(), - _pc(0), _fp(-1), _status(IN_PROGRESS) { + _fp(_stack), _pc(0), _status(IN_PROGRESS) { } ExecutionResult VM::execute(int offset) { @@ -263,21 +263,21 @@ void VM::opRETURN() { _fp = _stack.pop(); _pc = _stack.pop(); - int varsSize = _stack.pop(); - _stack.resize(_stack.size() - varsSize); + int argsSize = _stack.pop(); + _stack.resize(_stack.size() - argsSize); _stack.top() = val; } } void VM::opCALL() { - int varSize = readCodeByte(); - int topIndex = _stack.size() - 1; + int argsSize = readCodeByte(); - _stack.push(varSize); + _stack.push(argsSize); _stack.push(_pc); _stack.push(_fp); - _fp = _stack.size(); - _pc = getActionField(_stack[topIndex - varSize], A_CODE); + + _fp.set(); + _pc = getActionField(_fp[_fp[FP_ARGS_SIZE] + FP_ARGS], A_CODE); } void VM::opSVAR() { @@ -285,7 +285,7 @@ void VM::opSVAR() { } void VM::opSSET() { - setVariable(getCodeByte(), _stack.top()); + setVariable(readCodeByte(), _stack.top()); } void VM::opSPLIT() { @@ -328,8 +328,6 @@ void VM::opASET() { } void VM::opTMP() { - int val = readCodeByte(); - } void VM::opTSET() { @@ -357,21 +355,19 @@ void VM::opRNDMIZE() { } void VM::opSEND() { - int varSize = readCodeByte(); - int topIndex = _stack.size() - 1; - - _stack.push(varSize); + int argsSize = readCodeByte(); + _stack.push(argsSize); _stack.push(_pc); _stack.push(_fp); - _fp = _stack.size(); + _fp.set(); - int val = _stack[topIndex - varSize]; + int val = _fp[_fp[FP_ARGS_SIZE] + FP_ARGS]; if (val) val = getObjectField(val, O_CLASS); else - val = _stack[topIndex - varSize + 1]; + val = _fp[_fp[FP_ARGS_SIZE] + FP_ARGS]; - if (val && (val = getObjectProperty(val, _stack[topIndex - varSize + 2])) != 0) { + if (val && (val = getObjectProperty(val, _fp[_fp[FP_ARGS_SIZE] + 1])) != 0) { _pc = getActionField(val, A_CODE); } else { // Return NIL if there's no action for the given message diff --git a/engines/glk/advsys/vm.h b/engines/glk/advsys/vm.h index e5432d3f0a..e7477b9f1b 100644 --- a/engines/glk/advsys/vm.h +++ b/engines/glk/advsys/vm.h @@ -103,26 +103,84 @@ enum Opcode { OP_XNLIT = 0xC0 ///< Extra short load a negative literal }; +/** + * Indexes useable in function pointer array offsets + */ +enum FPOffset { + FP_FP = 0, + FP_PC = 1, + FP_ARGS_SIZE = 2, + FP_ARGS = 3 +}; + class VM; typedef void (VM::*OpcodeMethod)(); /** + * Fixed stack + */ +class FixedStack : public Common::FixedStack<int, 500> { +public: + void resize(size_t newSize) { + assert(newSize <= _size); + _size = newSize; + } +}; + +/** + * Implements a function pointer reference into the stack. It also allows + * positive array indexing to reference the following: + * 0 = Previous function pointer + * 1 = Return PC + * 2 = Size of argument block + * 3+ = Any function call arguments + */ +class FunctionPointer { +private: + FixedStack &_stack; + int _index; +public: + /** + * Constructor + */ + FunctionPointer(FixedStack &s) : _stack(s), _index(-1) {} + + /** + * Array indexing + */ + int &operator[](int idx) { return _stack[_index - idx - 1]; } + + /** + * Sets the index in the stack of the function pointer + */ + FunctionPointer &operator=(int index) { + _index = index; + return *this; + } + + /** + * Returns the index in the stack of the function pointer + */ + operator int() const { return _index; } + + /** + * Sets the function pointer to the top of the stack + */ + void set() { + _index = _stack.size(); + } +}; + +/** * Main VM for AdvSys */ class VM : public GlkInterface, public Game { - class FixedStack : public Common::FixedStack<int, 500> { - public: - void resize(size_t newSize) { - assert(newSize <= _size); - _size = newSize; - } - }; private: static OpcodeMethod _METHODS[0x34]; int _pc; ExecutionResult _status; FixedStack _stack; - int _fp; + FunctionPointer _fp; private: /** * Execute a single opcode within the script |