diff options
| -rw-r--r-- | engines/glk/advsys/vm.cpp | 34 | ||||
| -rw-r--r-- | engines/glk/advsys/vm.h | 23 | 
2 files changed, 56 insertions, 1 deletions
| 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<int, 500> {  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 | 
