[Scummvm-cvs-logs] SF.net SVN: scummvm:[40529] scummvm/trunk/engines/sci/engine

waltervn at users.sourceforge.net waltervn at users.sourceforge.net
Wed May 13 21:03:12 CEST 2009


Revision: 40529
          http://scummvm.svn.sourceforge.net/scummvm/?rev=40529&view=rev
Author:   waltervn
Date:     2009-05-13 19:03:12 +0000 (Wed, 13 May 2009)

Log Message:
-----------
SCI: Message: Added a few more subfunctions; cleanup.

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/kstring.cpp
    scummvm/trunk/engines/sci/engine/message.cpp
    scummvm/trunk/engines/sci/engine/message.h

Modified: scummvm/trunk/engines/sci/engine/kstring.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kstring.cpp	2009-05-13 18:12:17 UTC (rev 40528)
+++ scummvm/trunk/engines/sci/engine/kstring.cpp	2009-05-13 19:03:12 UTC (rev 40529)
@@ -722,107 +722,143 @@
 	return argv[2];
 }
 
-#define DUMMY_MESSAGE "No MESSAGE support in SCI yet"
+#define DUMMY_MESSAGE "Message not found!"
 
 static MessageState state;
 
+enum kMessageFunc {
+	K_MESSAGE_GET,
+	K_MESSAGE_NEXT,
+	K_MESSAGE_SIZE,
+	K_MESSAGE_REFCOND,
+	K_MESSAGE_REFVERB,
+	K_MESSAGE_REFNOUN,
+	K_MESSAGE_PUSH,
+	K_MESSAGE_POP,
+	K_MESSAGE_LASTMESSAGE
+};
+
 reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
 	MessageTuple tuple;
+	int func;
+	// For earlier version of of this function (GetMessage)
+	bool isGetMessage = argc == 4;
 
-	if (argc == 4) {
-		// Earlier version of of this function (GetMessage)
+	if (isGetMessage) {
+		func = K_MESSAGE_GET;
+
 		tuple.noun = UKPV(0);
-		int module = UKPV(1);
 		tuple.verb = UKPV(2);
 		tuple.cond = 0;
 		tuple.seq = 1;
+	} else {
+		func = UKPV(0);
 
-		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);
-
-			if (buffer) {
-				state.getText(buffer);
-				return argv[3];
-			}
+		if (argc >= 6) {
+			tuple.noun = UKPV(2);
+			tuple.verb = UKPV(3);
+			tuple.cond = UKPV(4);
+			tuple.seq = UKPV(5);
 		}
-
-		return NULL_REG;
 	}
 
-	switch (UKPV(0)) {
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-		tuple.noun = UKPV(2);
-		tuple.verb = UKPV(3);
-		tuple.cond = UKPV(4);
-		tuple.seq = UKPV(5);
-	}
+	switch (func) {
+	case K_MESSAGE_GET:
+	case K_MESSAGE_NEXT: {
+		reg_t bufferReg;
+		char *buffer = NULL;
+		const char *str;
+		reg_t retval;
 
-	switch (UKPV(0)) {
-	case 0 :
-		if (state.loadRes(s->resmgr, UKPV(1), true) && state.getMessage(&tuple)) {
-			char *buffer = NULL;
+		if (func == K_MESSAGE_GET) {
+			state.loadRes(s->resmgr, UKPV(1), true);
+			state.findTuple(tuple);
 
-			if ((argc == 7) && (argv[6] != NULL_REG))
-				buffer = kernel_dereference_char_pointer(s, argv[6], state.getLength() + 1);
+			if (isGetMessage)
+				bufferReg = (argc == 4 ? argv[3] : NULL_REG);
+			else
+				bufferReg = (argc == 7 ? argv[6] : NULL_REG);
+		} else {
+			bufferReg = (argc == 2 ? argv[1] : NULL_REG);
+		}
 
-			int talker = state.getTalker();
+		if (state.getMessage()) {
+			str = state.getText();
+			if (isGetMessage)
+				retval = bufferReg;
+			else
+				retval = make_reg(0, state.getTalker());
+		} else {
+			str = DUMMY_MESSAGE;
+			retval = NULL_REG;
+		}
 
-			if (buffer)
-				state.getText(buffer);
+		if (!bufferReg.isNull()) {
+			int len = strlen(str) + 1;
+			buffer = kernel_dereference_char_pointer(s, bufferReg, len);
 
-			// Talker id
-			return make_reg(0, talker);
-		} else {
-			char *buffer = NULL;
+			if (buffer) {
+				strcpy(buffer, str);
+			} else {
+				warning("Message: buffer "PREG" invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(bufferReg), len, str);
 
-			if ((argc == 7) && (argv[6] != NULL_REG))
-				buffer = kernel_dereference_char_pointer(s, argv[6], strlen(DUMMY_MESSAGE) + 1);
+				// Set buffer to empty string if possible
+				buffer = kernel_dereference_char_pointer(s, bufferReg, 1);
+				if (buffer)
+					*buffer = 0;
+			}
 
-			if (buffer)
-				strcpy(buffer, DUMMY_MESSAGE);
+			state.gotoNext();
+		}
 
+		return retval;
+	}
+	case K_MESSAGE_SIZE: {
+		MessageState tempState;
+
+		if (tempState.loadRes(s->resmgr, UKPV(1), false) && tempState.findTuple(tuple) && tempState.getMessage())
+			return make_reg(0, strlen(tempState.getText()));
+		else
 			return NULL_REG;
+	}
+	case K_MESSAGE_REFCOND:
+	case K_MESSAGE_REFVERB:
+	case K_MESSAGE_REFNOUN: {
+		MessageState tempState;
+
+		if (tempState.loadRes(s->resmgr, UKPV(1), false) && tempState.findTuple(tuple)) {
+			MessageTuple t = tempState.getRefTuple();
+			switch (func) {
+			case K_MESSAGE_REFCOND:
+				return make_reg(0, t.cond);
+			case K_MESSAGE_REFVERB:
+				return make_reg(0, t.verb);
+			case K_MESSAGE_REFNOUN:
+				return make_reg(0, t.noun);
+			}
 		}
-	case 1 :
-		if (state.getNext()) {
-			char *buffer = NULL;
 
-			if ((argc == 2) && (argv[1] != NULL_REG))
-				buffer = kernel_dereference_char_pointer(s, argv[1], state.getLength() + 1);
+		return NULL_REG;
+	}
+	case K_MESSAGE_LASTMESSAGE: {
+		MessageTuple msg = state.getLastTuple();
+		int module = state.getLastModule();
+		byte *buffer = kernel_dereference_bulk_pointer(s, argv[1], 10);
 
-			int talker = state.getTalker();
-
-			if (buffer)
-				state.getText(buffer);
-
-			// Talker id
-			return make_reg(0, talker);
+		if (buffer) {
+			WRITE_LE_UINT16(buffer, module);
+			WRITE_LE_UINT16(buffer + 2, msg.noun);
+			WRITE_LE_UINT16(buffer + 4, msg.verb);
+			WRITE_LE_UINT16(buffer + 6, msg.cond);
+			WRITE_LE_UINT16(buffer + 8, msg.seq);
 		} else {
-			char *buffer = NULL;
-
-			if ((argc == 2) && (argv[1] != NULL_REG))
-				buffer = kernel_dereference_char_pointer(s, argv[1], strlen(DUMMY_MESSAGE) + 1);
-
-			if (buffer)
-				strcpy(buffer, DUMMY_MESSAGE);
-
-			return NULL_REG;
+			warning("Message: buffer "PREG" invalid or too small to hold the tuple", PRINT_REG(argv[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;
+		return NULL_REG;
 	}
 	default:
-		warning("kMessage subfunction %i invoked (not implemented)", UKPV(0));
+		warning("Message: subfunction %i invoked (not implemented)", func);
 	}
 
 	return NULL_REG;

Modified: scummvm/trunk/engines/sci/engine/message.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/message.cpp	2009-05-13 18:12:17 UTC (rev 40528)
+++ scummvm/trunk/engines/sci/engine/message.cpp	2009-05-13 19:03:12 UTC (rev 40529)
@@ -28,29 +28,37 @@
 
 namespace Sci {
 
-void MessageState::parse(IndexRecordCursor *cursor, MessageTuple *t) {
-	t->noun = *(cursor->index_record + 0);
-	t->verb = *(cursor->index_record + 1);
+MessageTuple MessageState::getTuple() {
+	MessageTuple t;
+
+	t.noun = *(_engineCursor.index_record + 0);
+	t.verb = *(_engineCursor.index_record + 1);
 	if (_version == 2101) {
-		t->cond = 0;
-		t->seq = 1;
+		t.cond = 0;
+		t.seq = 1;
 	} else {
-		t->cond = *(cursor->index_record + 2);
-		t->seq = *(cursor->index_record + 3);
+		t.cond = *(_engineCursor.index_record + 2);
+		t.seq = *(_engineCursor.index_record + 3);
 	}
+
+	return t;
 }
 
-void MessageState::parseRef(IndexRecordCursor *cursor, MessageTuple *t) {
+MessageTuple MessageState::getRefTuple() {
+	MessageTuple t;
+
 	if (_version == 2101) {
-		t->noun = 0;
-		t->verb = 0;
-		t->cond = 0;
+		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.noun = *(_engineCursor.index_record + 7);
+		t.verb = *(_engineCursor.index_record + 8);
+		t.cond = *(_engineCursor.index_record + 9);
 	}
-	t->seq = 1;
+	t.seq = 1;
+
+	return t;
 }
 
 void MessageState::initCursor() {
@@ -67,20 +75,22 @@
 		_engineCursor.nextSeq++;
 }
 
-int MessageState::getMessage(MessageTuple *t) {
+int MessageState::findTuple(MessageTuple &t) {
+	if (_module == -1)
+		return 0;
+
 	// Reset the cursor
 	initCursor();
-	_engineCursor.nextSeq = t->seq;
+	_engineCursor.nextSeq = t.seq;
 
 	// Do a linear search for the message
 	while (1) {
-		MessageTuple looking_at;
-		parse(&_engineCursor, &looking_at);
+		MessageTuple looking_at = getTuple();
 
-		if (t->noun == looking_at.noun && 
-			t->verb == looking_at.verb && 
-			t->cond == looking_at.cond && 
-			t->seq == looking_at.seq)
+		if (t.noun == looking_at.noun && 
+			t.verb == looking_at.verb && 
+			t.cond == looking_at.cond && 
+			t.seq == looking_at.seq)
 			break;
 
 		advanceCursor(false);
@@ -90,15 +100,16 @@
 			return 0;
 	}
 
-	return getNext();
+	return 1;
 }
 
-int MessageState::getNext() {
+int MessageState::getMessage() {
+	if (_module == -1)
+		return 0;
+
 	if (_engineCursor.index != _recordCount) {
-		MessageTuple mesg;
-		parse(&_engineCursor, &mesg);
-		MessageTuple ref;
-		parseRef(&_engineCursor, &ref);
+		MessageTuple mesg = getTuple();
+		MessageTuple ref = getRefTuple();
 
 		if (_engineCursor.nextSeq == mesg.seq) {
 			// We found the right sequence number, check for recursion
@@ -107,8 +118,8 @@
 				// Recursion, advance the current cursor and load the reference
 				advanceCursor(true);
 
-				if (getMessage(&ref))
-					return getNext();
+				if (findTuple(ref))
+					return getMessage();
 				else {
 					// Reference not found
 					return 0;
@@ -123,7 +134,7 @@
 	// 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();
+		return getMessage();
 	}
 
 	// Stack is empty, no message available
@@ -134,10 +145,22 @@
 	return (_version == 2101) ? -1 : *(_engineCursor.index_record + 4);
 }
 
-void MessageState::getText(char *buffer) {
+MessageTuple &MessageState::getLastTuple() {
+	return _lastReturned;
+}
+
+int MessageState::getLastModule() {
+	return _lastReturnedModule;
+}
+
+char *MessageState::getText() {
 	int offset = READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5));
-	char *stringptr = (char *)_currentResource->data + offset;
-	strcpy(buffer, stringptr);
+	return (char *)_currentResource->data + offset;
+}
+
+void MessageState::gotoNext() {
+	_lastReturned = getTuple();
+	_lastReturnedModule = _module;
 	advanceCursor(true);
 }
 
@@ -148,24 +171,27 @@
 }
 
 int MessageState::loadRes(ResourceManager *resmgr, int module, bool lock) {
-	if (_module == module)
-		return 1;
+	if (_locked) {
+		// We already have a locked resource
+		if (_module == module) {
+			// If it's the same resource, we are done
+			return 1;
+		}
 
-	// Unlock old resource
-	if (_module != -1) {
+		// Otherwise, free the old resource
 		resmgr->unlockResource(_currentResource, _module, kResourceTypeMessage);
-		_module = -1;
+		_locked = false;
 	}
 
 	_currentResource = resmgr->findResource(kResourceTypeMessage, module, lock);
 
 	if (_currentResource == NULL || _currentResource->data == NULL) {
-		warning("Message subsystem: failed to load %d.msg", module);
+		warning("Message: failed to load %d.msg", module);
 		return 0;
 	}
 
-	if (lock)
-		_module = module;
+	_module = module;
+	_locked = lock;
 
 	_version = READ_LE_UINT16(_currentResource->data);
 

Modified: scummvm/trunk/engines/sci/engine/message.h
===================================================================
--- scummvm/trunk/engines/sci/engine/message.h	2009-05-13 18:12:17 UTC (rev 40528)
+++ scummvm/trunk/engines/sci/engine/message.h	2009-05-13 19:03:12 UTC (rev 40529)
@@ -48,30 +48,32 @@
 
 class MessageState {
 public:
-	MessageState() : _module(-1) { }
-	int getMessage(MessageTuple *t);
-	int getNext();
+	MessageState() : _module(-1), _locked(false) { }
+	int findTuple(MessageTuple &t);
+	MessageTuple getTuple();
+	MessageTuple getRefTuple();
+	int getMessage();
+	void gotoNext();
+	char *getText();
 	int getTalker();
 	int getLength();
-	void getText(char *buffer);
+	MessageTuple &getLastTuple();
+	int getLastModule();
 	int loadRes(ResourceManager *resmgr, int module, bool lock);
-	int isInitialized() { return _initialized; }
-	void initialize(ResourceManager *resmgr);
-	void setVersion(int version) { _version = version; }
 
 private:
-	void parse(IndexRecordCursor *cursor, MessageTuple *t);
-	void parseRef(IndexRecordCursor *cursor, MessageTuple *t);
 	void initCursor();
 	void advanceCursor(bool increaseSeq);
 
-	int _initialized;
 	Resource *_currentResource;
 	int _module;
+	bool _locked;
 	int _recordCount;
 	byte *_indexRecords;
 	CursorStack _cursorStack;
 	IndexRecordCursor _engineCursor;
+	MessageTuple _lastReturned;
+	int _lastReturnedModule;
 	int _version;
 };
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list