From 9c0771552d97f8e8aec1ba93d7ff689b0e58a64c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 10 Jun 2019 21:06:12 -0700 Subject: GLK: ADVSYS: Remaining opcode implementations --- engines/glk/advsys/vm.cpp | 34 ++++++++++++++++++++++++++++++++++ engines/glk/advsys/vm.h | 23 ++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) (limited to 'engines/glk') diff --git a/engines/glk/advsys/vm.cpp b/engines/glk/advsys/vm.cpp index dbfe0ad3a1..53950fc5a4 100644 --- a/engines/glk/advsys/vm.cpp +++ b/engines/glk/advsys/vm.cpp @@ -84,6 +84,11 @@ OpcodeMethod VM::_METHODS[0x34] = { VM::VM(OSystem *syst, const GlkGameDescription &gameDesc) : GlkInterface(syst, gameDesc), Game(), _fp(_stack), _pc(0), _status(IN_PROGRESS) { + Common::fill(&_nouns[0], &_nouns[20], 0); + Common::fill(&_nounWords[0], &_nounWords[20], -1); + Common::fill(&_adjectives[0], &_adjectives[20], (int *)nullptr); + Common::fill(&_adjectiveWords[0], &_adjectiveWords[100], -1); + Common::fill(&_adjectiveLists[0], &_adjectiveLists[100], -1); } ExecutionResult VM::execute(int offset) { @@ -328,30 +333,58 @@ void VM::opASET() { } void VM::opTMP() { + int val = readCodeByte(); + _stack.top() = _fp[-val - 1]; } void VM::opTSET() { + int val = readCodeByte(); + _fp[-val - 1] = _stack.top(); } void VM::opTSPACE() { + _stack.allocate(readCodeByte()); } void VM::opCLASS() { + _stack.top() = getObjectField(_stack.top(), O_CLASS); } void VM::opMATCH() { + int idx = _stack.pop() - 1; + _stack.top() = match(_stack.top(), _nouns[idx], _adjectives[idx]) ? TRUE : NIL; } void VM::opPNOUN() { + int noun = _stack.top(); + Common::String str; + + // Add the adjectives + bool space = false; + for (int *aPtr = _adjectives[noun - 1]; *aPtr; ++aPtr, space = true) { + if (space) + str += " "; + str += _wordText[_adjectiveWords[aPtr - _adjectiveLists]]; + } + + // Add the noun + if (space) + str += " "; + str += _wordText[_nounWords[noun - 1]]; + + print(str); } void VM::opRESTART() { + restart(); } void VM::opRAND() { + _stack.top() = getRandomNumber(_stack.top()); } void VM::opRNDMIZE() { + // No implementation } void VM::opSEND() { @@ -376,6 +409,7 @@ void VM::opSEND() { } void VM::opVOWEL() { + // No implementation } } // End of namespace AdvSys diff --git a/engines/glk/advsys/vm.h b/engines/glk/advsys/vm.h index e7477b9f1b..b5c5b48463 100644 --- a/engines/glk/advsys/vm.h +++ b/engines/glk/advsys/vm.h @@ -121,10 +121,22 @@ typedef void (VM::*OpcodeMethod)(); */ class FixedStack : public Common::FixedStack { public: + /** + * Resize the stack + */ void resize(size_t newSize) { - assert(newSize <= _size); + assert(newSize <= 500); _size = newSize; } + + /** + * Allocate extra space on the stack + */ + void allocate(size_t amount) { + uint oldSize = _size; + resize(_size + amount); + Common::fill(&_stack[oldSize], &_stack[oldSize + amount], 0); + } }; /** @@ -176,11 +188,20 @@ public: */ class VM : public GlkInterface, public Game { private: + // Execution fields static OpcodeMethod _METHODS[0x34]; int _pc; ExecutionResult _status; FixedStack _stack; FunctionPointer _fp; + + // Parser fields + int *_adjectives[20]; + int _adjectiveLists[100]; + int _adjectiveWords[100]; + int _nouns[20]; + int _nounWords[20]; + Common::String _wordText[100]; private: /** * Execute a single opcode within the script -- cgit v1.2.3