aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/advsys
diff options
context:
space:
mode:
authorPaul Gilbert2019-06-10 19:04:35 -0700
committerPaul Gilbert2019-06-10 19:08:58 -0700
commitebdc4ec3faf509625ac94948cbbb0996d440c37e (patch)
tree7464384bcc5f2cd8199c81d5ab2da0905d212bb4 /engines/glk/advsys
parent1de8c3d7308512b4eae556511a468d9b59d26f90 (diff)
downloadscummvm-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/advsys')
-rw-r--r--engines/glk/advsys/vm.cpp34
-rw-r--r--engines/glk/advsys/vm.h74
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