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

waltervn at users.sourceforge.net waltervn at users.sourceforge.net
Tue May 12 13:28:15 CEST 2009


Revision: 40478
          http://scummvm.svn.sourceforge.net/scummvm/?rev=40478&view=rev
Author:   waltervn
Date:     2009-05-12 11:28:15 +0000 (Tue, 12 May 2009)

Log Message:
-----------
SCI: Message: Added resource-internal recursion (currently untested).

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-12 10:20:12 UTC (rev 40477)
+++ scummvm/trunk/engines/sci/engine/kstring.cpp	2009-05-12 11:28:15 UTC (rev 40478)
@@ -727,9 +727,6 @@
 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 @@
 	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 @@
 
 	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 @@
 
 			if (buffer)
 				state.getText(buffer);
+
 			// Talker id
 			return make_reg(0, talker);
 		} else {
@@ -783,6 +778,7 @@
 
 			if (buffer)
 				state.getText(buffer);
+
 			// Talker id
 			return make_reg(0, talker);
 		} else {
@@ -796,11 +792,14 @@
 
 			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 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 @@
 	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);
 

Modified: scummvm/trunk/engines/sci/engine/message.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/message.cpp	2009-05-12 10:20:12 UTC (rev 40477)
+++ scummvm/trunk/engines/sci/engine/message.cpp	2009-05-12 11:28:15 UTC (rev 40478)
@@ -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::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;
+}
+
+void MessageState::advanceCursor(bool increaseSeq) {
+	_engineCursor.index_record += ((_version == 2101) ? 4 : 11);
+	_engineCursor.index++;
+
+	if (increaseSeq)
+		_engineCursor.nextSeq++;
+}
+
 int MessageState::getMessage(MessageTuple *t) {
-	MessageTuple looking_at;
+	// Reset the cursor
+	initCursor();
+	_engineCursor.nextSeq = t->seq;
 
-	initIndexRecordCursor();
-	_lastMessage.seq = t->seq - 1;
+	// Do a linear search for the message
+	while (1) {
+		MessageTuple looking_at;
+		parse(&_engineCursor, &looking_at);
 
-	while (_engineCursor.index != _recordCount) {
-		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);
+
+		// Message tuple is not present
+		if (_engineCursor.index == _recordCount)
+			return 0;
 	}
 
-	// FIXME: Recursion not handled yet
-
-	return 0;
+	return getNext();
 }
 
 int MessageState::getNext() {
-	if (_engineCursor.index == _recordCount)
-		return 0;
+	if (_engineCursor.index != _recordCount) {
+		MessageTuple mesg;
+		parse(&_engineCursor, &mesg);
+		MessageTuple ref;
+		parseRef(&_engineCursor, &ref);
 
-	MessageTuple mesg;
-	parse(&_engineCursor, &mesg);
+		if (_engineCursor.nextSeq == mesg.seq) {
+			// We found the right sequence number, check for recursion
 
-	if (_lastMessage.seq == mesg.seq - 1)
-		return 1;
+			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;
+			}
+		}
+	}
+
+	// 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 @@
 
 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();
+	_cursorStack.clear();
+	initCursor();
+
 	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);
-
-	if (tester) {
-		int version = READ_LE_UINT16(tester->data);
-		state->initialize(resmgr);
-		state->setVersion(version);
-	}
-}
-
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/engine/message.h
===================================================================
--- scummvm/trunk/engines/sci/engine/message.h	2009-05-12 10:20:12 UTC (rev 40477)
+++ scummvm/trunk/engines/sci/engine/message.h	2009-05-12 11:28:15 UTC (rev 40478)
@@ -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 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


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