diff options
| -rw-r--r-- | engines/sci/engine/kstring.cpp | 24 | ||||
| -rw-r--r-- | engines/sci/engine/message.cpp | 146 | ||||
| -rw-r--r-- | engines/sci/engine/message.h | 17 | 
3 files changed, 110 insertions, 77 deletions
| diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 0de81724b4..21ca298d18 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -727,9 +727,6 @@ reg_t kGetFarText(EngineState *s, int funct_nr, int argc, reg_t *argv) {  static MessageState state;  reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { -	if (!state.isInitialized()) -		message_state_initialize(s->resmgr, &state); -  	MessageTuple tuple;  	switch (UKPV(0)) { @@ -738,9 +735,6 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {  	case 3:  	case 4:  	case 5: -		if (!state.loadRes(UKPV(1))) -			return NULL_REG; -  		tuple.noun = UKPV(2);  		tuple.verb = UKPV(3);  		tuple.cond = UKPV(4); @@ -749,7 +743,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {  	switch (UKPV(0)) {  	case 0 : -		if (state.getMessage(&tuple)) { +		if (state.loadRes(s->resmgr, UKPV(1), true) && state.getMessage(&tuple)) {  			char *buffer = NULL;  			if ((argc == 7) && (argv[6] != NULL_REG)) @@ -759,6 +753,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {  			if (buffer)  				state.getText(buffer); +  			// Talker id  			return make_reg(0, talker);  		} else { @@ -783,6 +778,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {  			if (buffer)  				state.getText(buffer); +  			// Talker id  			return make_reg(0, talker);  		} else { @@ -796,11 +792,14 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {  			return NULL_REG;  		} -	case 2: -		if (state.getMessage(&tuple)) -			return make_reg(0, state.getLength() + 1); +	case 2: { +		MessageState tempState; + +		if (tempState.loadRes(s->resmgr, UKPV(1), false) && tempState.getMessage(&tuple)) +			return make_reg(0, tempState.getLength() + 1);  		else  			return NULL_REG; +	}  	default:  		warning("kMessage subfunction %i invoked (not implemented)", UKPV(0));  	} @@ -809,9 +808,6 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {  }  reg_t kGetMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { -	if (!state.isInitialized()) -		message_state_initialize(s->resmgr, &state); -  	MessageTuple tuple;  	tuple.noun = UKPV(0);  	int module = UKPV(1); @@ -819,7 +815,7 @@ reg_t kGetMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {  	tuple.cond = 0;  	tuple.seq = 0; -	if (state.loadRes(module) && state.getMessage(&tuple)) { +	if (state.loadRes(s->resmgr, module, true) && state.getMessage(&tuple)) {  		int len = state.getLength();  		char *buffer = kernel_dereference_char_pointer(s, argv[3], len + 1); diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index e838c05506..3e06ee419a 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -28,13 +28,6 @@  namespace Sci { -void MessageState::initIndexRecordCursor() { -	_engineCursor.resource_beginning = _currentResource->data; -	_engineCursor.index_record = _indexRecords; -	_engineCursor.index = 0; -	_lastMessage.seq = 0; -} -  void MessageState::parse(IndexRecordCursor *cursor, MessageTuple *t) {  	t->noun = *(cursor->index_record + 0);  	t->verb = *(cursor->index_record + 1); @@ -47,39 +40,93 @@ void MessageState::parse(IndexRecordCursor *cursor, MessageTuple *t) {  	}  } -int MessageState::getMessage(MessageTuple *t) { -	MessageTuple looking_at; +void MessageState::parseRef(IndexRecordCursor *cursor, MessageTuple *t) { +	if (_version == 2101) { +		t->noun = 0; +		t->verb = 0; +		t->cond = 0; +	} else { +		t->noun = *(cursor->index_record + 7); +		t->verb = *(cursor->index_record + 8); +		t->cond = *(cursor->index_record + 9); +	} +	t->seq = 1; +} + +void MessageState::initCursor() { +	_engineCursor.index_record = _indexRecords; +	_engineCursor.index = 0; +	_engineCursor.nextSeq = 0; +} -	initIndexRecordCursor(); -	_lastMessage.seq = t->seq - 1; +void MessageState::advanceCursor(bool increaseSeq) { +	_engineCursor.index_record += ((_version == 2101) ? 4 : 11); +	_engineCursor.index++; -	while (_engineCursor.index != _recordCount) { +	if (increaseSeq) +		_engineCursor.nextSeq++; +} + +int MessageState::getMessage(MessageTuple *t) { +	// Reset the cursor +	initCursor(); +	_engineCursor.nextSeq = t->seq; + +	// Do a linear search for the message +	while (1) { +		MessageTuple looking_at;  		parse(&_engineCursor, &looking_at); +  		if (t->noun == looking_at.noun &&   			t->verb == looking_at.verb &&   			t->cond == looking_at.cond &&   			t->seq == looking_at.seq) -			return 1; +			break; -		_engineCursor.index_record += ((_version == 2101) ? 4 : 11); -		_engineCursor.index++; -	} +		advanceCursor(false); -	// FIXME: Recursion not handled yet +		// Message tuple is not present +		if (_engineCursor.index == _recordCount) +			return 0; +	} -	return 0; +	return getNext();  }  int MessageState::getNext() { -	if (_engineCursor.index == _recordCount) -		return 0; - -	MessageTuple mesg; -	parse(&_engineCursor, &mesg); +	if (_engineCursor.index != _recordCount) { +		MessageTuple mesg; +		parse(&_engineCursor, &mesg); +		MessageTuple ref; +		parseRef(&_engineCursor, &ref); + +		if (_engineCursor.nextSeq == mesg.seq) { +			// We found the right sequence number, check for recursion + +			if (ref.noun != 0) { +				// Recursion, advance the current cursor and load the reference +				advanceCursor(true); + +				if (getMessage(&ref)) +					return getNext(); +				else { +					// Reference not found +					return 0; +				} +			} else { +				// No recursion, we are done +				return 1; +			} +		} +	} -	if (_lastMessage.seq == mesg.seq - 1) -		return 1; +	// We either ran out of records, or found an incorrect sequence number. Go to previous stack frame. +	if (!_cursorStack.empty()) { +		_engineCursor = _cursorStack.pop(); +		return getNext(); +	} +	// Stack is empty, no message available  	return 0;  } @@ -89,60 +136,47 @@ int MessageState::getTalker() {  void MessageState::getText(char *buffer) {  	int offset = READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5)); -	char *stringptr = (char *)_engineCursor.resource_beginning + offset; -	parse(&_engineCursor, &_lastMessage); +	char *stringptr = (char *)_currentResource->data + offset;  	strcpy(buffer, stringptr); -	_engineCursor.index_record += ((_version == 2101) ? 4 : 11); -	_engineCursor.index++; +	advanceCursor(true);  }  int MessageState::getLength() {  	int offset = READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5)); -	char *stringptr = (char *)_engineCursor.resource_beginning + offset; +	char *stringptr = (char *)_currentResource->data + offset;  	return strlen(stringptr);  } -int MessageState::loadRes(int module) { +int MessageState::loadRes(ResourceManager *resmgr, int module, bool lock) {  	if (_module == module)  		return 1;  	// Unlock old resource -	if (_module != -1) -		_resmgr->unlockResource(_currentResource, _module, kResourceTypeMessage); +	if (_module != -1) { +		resmgr->unlockResource(_currentResource, _module, kResourceTypeMessage); +		_module = -1; +	} -	_module = module; -	_currentResource = _resmgr->findResource(kResourceTypeMessage, module, 1); +	_currentResource = resmgr->findResource(kResourceTypeMessage, module, lock);  	if (_currentResource == NULL || _currentResource->data == NULL) { -		sciprintf("Message subsystem: Failed to load %d.MSG\n", module); -		_module = -1; +		warning("Message subsystem: failed to load %d.msg", module);  		return 0;  	} +	if (lock) +		_module = module; + +	_version = READ_LE_UINT16(_currentResource->data); +  	int offs = (_version == 2101) ? 0 : 4;  	_recordCount = READ_LE_UINT16(_currentResource->data + 4 + offs);  	_indexRecords = _currentResource->data + 6 + offs; -	initIndexRecordCursor(); -	return 1; -} - -void MessageState::initialize(ResourceManager *resmgr) { -	_module = -1; -	_resmgr = resmgr; -	_currentResource = NULL; -	_recordCount = 0; -	_initialized = 1; -} - -void message_state_initialize(ResourceManager *resmgr, MessageState *state) { -	Resource *tester = resmgr->findResource(kResourceTypeMessage, 0, 0); +	_cursorStack.clear(); +	initCursor(); -	if (tester) { -		int version = READ_LE_UINT16(tester->data); -		state->initialize(resmgr); -		state->setVersion(version); -	} +	return 1;  }  } // End of namespace Sci diff --git a/engines/sci/engine/message.h b/engines/sci/engine/message.h index 5a8924f4b5..e8f0662440 100644 --- a/engines/sci/engine/message.h +++ b/engines/sci/engine/message.h @@ -27,6 +27,7 @@  #define SCI_ENGINE_MESSAGE_H  #include "sci/scicore/resource.h" +#include "common/stack.h"  namespace Sci { @@ -40,38 +41,40 @@ struct MessageTuple {  struct IndexRecordCursor {  	byte *index_record;  	int index; -	byte *resource_beginning; +	int nextSeq;  }; +typedef Common::Stack<IndexRecordCursor> CursorStack; +  class MessageState {  public: +	MessageState() : _module(-1) { }  	int getMessage(MessageTuple *t);  	int getNext();  	int getTalker();  	int getLength();  	void getText(char *buffer); -	int loadRes(int module); +	int loadRes(ResourceManager *resmgr, int module, bool lock);  	int isInitialized() { return _initialized; }  	void initialize(ResourceManager *resmgr);  	void setVersion(int version) { _version = version; }  private: -	void initIndexRecordCursor();  	void parse(IndexRecordCursor *cursor, MessageTuple *t); +	void parseRef(IndexRecordCursor *cursor, MessageTuple *t); +	void initCursor(); +	void advanceCursor(bool increaseSeq);  	int _initialized; -	ResourceManager *_resmgr;  	Resource *_currentResource;  	int _module;  	int _recordCount;  	byte *_indexRecords; +	CursorStack _cursorStack;  	IndexRecordCursor _engineCursor; -	MessageTuple _lastMessage;  	int _version;  }; -void message_state_initialize(ResourceManager *resmgr, MessageState *state); -  } // End of namespace Sci  #endif // SCI_ENGINE_MESSAGE_H | 
