mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-27 05:32:45 +00:00
GLK: ADVSYS: Subroutine call & return opcodes
This commit is contained in:
parent
8bb7c893f1
commit
75da8ddd06
@ -83,7 +83,7 @@ OpcodeMethod VM::_METHODS[0x34] = {
|
||||
};
|
||||
|
||||
VM::VM(OSystem *syst, const GlkGameDescription &gameDesc) : GlkInterface(syst, gameDesc), Game(),
|
||||
_pc(0), _status(IN_PROGRESS) {
|
||||
_pc(0), _fp(-1), _status(IN_PROGRESS) {
|
||||
}
|
||||
|
||||
ExecutionResult VM::execute(int offset) {
|
||||
@ -238,21 +238,46 @@ void VM::opPNUMBER() {
|
||||
}
|
||||
|
||||
void VM::opFINISH() {
|
||||
_status = FINISH;
|
||||
}
|
||||
|
||||
void VM::opCHAIN() {
|
||||
_status = CHAIN;
|
||||
}
|
||||
|
||||
void VM::opABORT() {
|
||||
_status = ABORT;
|
||||
}
|
||||
|
||||
void VM::opEXIT() {
|
||||
quitGame();
|
||||
_status = ABORT;
|
||||
}
|
||||
|
||||
void VM::opRETURN() {
|
||||
if (_stack.empty()) {
|
||||
_status = CHAIN;
|
||||
} else {
|
||||
int val = _stack.top();
|
||||
_stack.resize(_fp);
|
||||
_fp = _stack.pop();
|
||||
_pc = _stack.pop();
|
||||
|
||||
int varsSize = _stack.pop();
|
||||
_stack.resize(_stack.size() - varsSize);
|
||||
_stack.top() = val;
|
||||
}
|
||||
}
|
||||
|
||||
void VM::opCALL() {
|
||||
int varSize = readCodeByte();
|
||||
int topIndex = _stack.size() - 1;
|
||||
|
||||
_stack.push(varSize);
|
||||
_stack.push(_pc);
|
||||
_stack.push(_fp);
|
||||
_fp = _stack.size();
|
||||
_pc = getActionField(_stack[topIndex - varSize], A_CODE);
|
||||
}
|
||||
|
||||
void VM::opSVAR() {
|
||||
@ -311,6 +336,26 @@ void VM::opRNDMIZE() {
|
||||
}
|
||||
|
||||
void VM::opSEND() {
|
||||
int varSize = readCodeByte();
|
||||
int topIndex = _stack.size() - 1;
|
||||
|
||||
_stack.push(varSize);
|
||||
_stack.push(_pc);
|
||||
_stack.push(_fp);
|
||||
_fp = _stack.size();
|
||||
|
||||
int val = _stack[topIndex - varSize];
|
||||
if (val)
|
||||
val = getObjectField(val, O_CLASS);
|
||||
else
|
||||
val = _stack[topIndex - varSize + 1];
|
||||
|
||||
if (val && (val = getObjectProperty(val, _stack[topIndex - varSize + 2])) != 0) {
|
||||
_pc = getActionField(val, A_CODE);
|
||||
} else {
|
||||
// Return NIL if there's no action for the given message
|
||||
opRETURN();
|
||||
}
|
||||
}
|
||||
|
||||
void VM::opVOWEL() {
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
#include "glk/advsys/glk_interface.h"
|
||||
#include "glk/advsys/game.h"
|
||||
#include "common/array.h"
|
||||
#include "common/stack.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace AdvSys {
|
||||
@ -110,34 +110,19 @@ typedef void (VM::*OpcodeMethod)();
|
||||
* Main VM for AdvSys
|
||||
*/
|
||||
class VM : public GlkInterface, public Game {
|
||||
class ArrayStack : public Common::Array<int> {
|
||||
class FixedStack : public Common::FixedStack<int, 500> {
|
||||
public:
|
||||
/**
|
||||
* Push a value onto the stack
|
||||
*/
|
||||
void push(int v) {
|
||||
push_back(v);
|
||||
void resize(size_t newSize) {
|
||||
assert(newSize <= _size);
|
||||
_size = newSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop a value from the stack
|
||||
*/
|
||||
int pop() {
|
||||
int v = back();
|
||||
pop_back();
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top of the stack (the most recently added value
|
||||
*/
|
||||
int &top() { return back(); }
|
||||
};
|
||||
private:
|
||||
static OpcodeMethod _METHODS[0x34];
|
||||
int _pc;
|
||||
ExecutionResult _status;
|
||||
ArrayStack _stack;
|
||||
FixedStack _stack;
|
||||
int _fp;
|
||||
private:
|
||||
/**
|
||||
* Execute a single opcode within the script
|
||||
|
Loading…
x
Reference in New Issue
Block a user