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

m_kiewitz at users.sourceforge.net m_kiewitz at users.sourceforge.net
Wed Jul 7 20:35:08 CEST 2010


Revision: 50737
          http://scummvm.svn.sourceforge.net/scummvm/?rev=50737&view=rev
Author:   m_kiewitz
Date:     2010-07-07 18:35:07 +0000 (Wed, 07 Jul 2010)

Log Message:
-----------
SCI: adding support to kernel signatures that invalid references may also get allowed - doing exactly this for kGraph(restoreBox) - fixes castle of dr. brain when quitting the game - maybe a game specific workaround would be better?!?!

Modified Paths:
--------------
    scummvm/trunk/engines/sci/console.cpp
    scummvm/trunk/engines/sci/engine/kernel.cpp
    scummvm/trunk/engines/sci/engine/kernel.h

Modified: scummvm/trunk/engines/sci/console.cpp
===================================================================
--- scummvm/trunk/engines/sci/console.cpp	2010-07-07 16:51:36 UTC (rev 50736)
+++ scummvm/trunk/engines/sci/console.cpp	2010-07-07 18:35:07 UTC (rev 50737)
@@ -3157,10 +3157,11 @@
 }
 
 void Console::printBasicVarInfo(reg_t variable) {
-	int segType = g_sci->getKernel()->findRegType(variable);
+	int regType = g_sci->getKernel()->findRegType(variable);
+	int segType = regType;
 	SegManager *segMan = g_sci->getEngineState()->_segMan;
 
-	segType &= SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_NODE | SIG_TYPE_LIST | SIG_TYPE_UNINITIALIZED | SIG_TYPE_INVALID;
+	segType &= SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_NODE | SIG_TYPE_LIST | SIG_TYPE_UNINITIALIZED | SIG_TYPE_ERROR;
 
 	switch (segType) {
 	case SIG_TYPE_INTEGER: {
@@ -3184,12 +3185,15 @@
 	case SIG_TYPE_UNINITIALIZED:
 		DebugPrintf(" (uninitialized)");
 		break;
-	case SIG_TYPE_INVALID:
-		DebugPrintf(" (invalid)");
+	case SIG_TYPE_ERROR:
+		DebugPrintf(" (error)");
 		break;
 	default:
 		DebugPrintf(" (??\?)");
 	}
+
+	if (regType & SIG_IS_INVALID)
+		DebugPrintf(" IS INVALID!");
 }
 
 void Console::printList(List *list) {

Modified: scummvm/trunk/engines/sci/engine/kernel.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kernel.cpp	2010-07-07 16:51:36 UTC (rev 50736)
+++ scummvm/trunk/engines/sci/engine/kernel.cpp	2010-07-07 18:35:07 UTC (rev 50737)
@@ -364,7 +364,9 @@
     { MAP_CALL(FlushResources),    SIG_EVERYWHERE,           "i",                    NULL,            NULL },
     { MAP_CALL(TimesSin),          SIG_EVERYWHERE,           "ii",                   NULL,            NULL },
     { MAP_CALL(TimesCos),          SIG_EVERYWHERE,           "ii",                   NULL,            NULL },
-    { MAP_CALL(Graph),             SIG_EVERYWHERE,           "i(.*)",                NULL,            NULL }, // subop
+    { MAP_CALL(Graph),             SIG_EVERYWHERE,           "i([!.]*)",             NULL,            NULL }, // subop
+	// ^^ we allow invalid references here, because kGraph(restoreBox) gets called with old non-existant handles often
+	//    this should get limited to this call only as soon as subop signatures are available
     { MAP_CALL(Joystick),          SIG_EVERYWHERE,           "i(.*)",                NULL,            NULL }, // subop
     { MAP_CALL(FileIO),            SIG_EVERYWHERE,           "i(.*)",                NULL,            NULL }, // subop
     { MAP_CALL(Memory),            SIG_EVERYWHERE,           "i(.*)",                NULL,            NULL }, // subop
@@ -543,7 +545,8 @@
 	//  we also check, if the written signature makes any sense
 	curPos = writtenSig;
 	while (*curPos) {
-		switch (*curPos) {
+		curChar = *curPos;
+		switch (curChar) {
 		case '[': // either or
 			if (eitherOr)
 				error("signature for k%s: '[' used within '[]'", kernelName);
@@ -584,6 +587,7 @@
 		case 'l':
 		case 'n':
 		case '.':
+		case '!':
 			if ((hadOptional) & (!optional))
 				error("signature for k%s: non-optional type may not follow optional type", kernelName);
 			validType = true;
@@ -634,8 +638,13 @@
 			case 'l':
 			case 'n':
 			case '.':
+			case '!':
 				// and we also got some signature pending?
 				if (signature) {
+					if (!(signature & SIG_MAYBE_ANY))
+						error("signature for k%s: invalid ('!') may only get used in combination with a real type", kernelName);
+					if ((signature & SIG_IS_INVALID) && ((signature & SIG_MAYBE_ANY) == (SIG_TYPE_NULL | SIG_TYPE_INTEGER)))
+						error("signature for k%s: invalid ('!') should not be used on exclusive null/integer type", kernelName);
 					if (optional) {
 						signature |= SIG_IS_OPTIONAL;
 						if (curChar != ')')
@@ -662,37 +671,44 @@
 			break;
 		case '0':
 			if (signature & SIG_TYPE_NULL)
-				error("signature for k%s: NULL specified more than once", kernelName);
+				error("signature for k%s: NULL ('0') specified more than once", kernelName);
 			signature |= SIG_TYPE_NULL;
 			break;
 		case 'i':
 			if (signature & SIG_TYPE_INTEGER)
-				error("signature for k%s: integer specified more than once", kernelName);
+				error("signature for k%s: integer ('i') specified more than once", kernelName);
 			signature |= SIG_TYPE_INTEGER | SIG_TYPE_NULL;
 			break;
 		case 'o':
 			if (signature & SIG_TYPE_OBJECT)
-				error("signature for k%s: object specified more than once", kernelName);
+				error("signature for k%s: object ('o') specified more than once", kernelName);
 			signature |= SIG_TYPE_OBJECT;
 			break;
 		case 'r':
 			if (signature & SIG_TYPE_REFERENCE)
-				error("signature for k%s: reference specified more than once", kernelName);
+				error("signature for k%s: reference ('r') specified more than once", kernelName);
 			signature |= SIG_TYPE_REFERENCE;
 			break;
 		case 'l':
 			if (signature & SIG_TYPE_LIST)
-				error("signature for k%s: list specified more than once", kernelName);
+				error("signature for k%s: list ('l') specified more than once", kernelName);
 			signature |= SIG_TYPE_LIST;
 			break;
 		case 'n':
 			if (signature & SIG_TYPE_NODE)
-				error("signature for k%s: node specified more than once", kernelName);
+				error("signature for k%s: node ('n') specified more than once", kernelName);
 			signature |= SIG_TYPE_NODE;
 			break;
 		case '.':
+			if (signature & SIG_MAYBE_ANY)
+				error("signature for k%s: maybe-any ('.') shouldn't get specified with other types in front of it", kernelName);
 			signature |= SIG_MAYBE_ANY;
 			break;
+		case '!':
+			if (signature & SIG_IS_INVALID)
+				error("signature for k%s: invalid ('!') specified more than once", kernelName);
+			signature |= SIG_IS_INVALID;
+			break;
 		case '*': // accepts more of the same parameter
 			signature |= SIG_MORE_MAY_FOLLOW;
 			break;
@@ -708,7 +724,7 @@
 	return result;
 }
 
-int Kernel::findRegType(reg_t reg) {
+uint16 Kernel::findRegType(reg_t reg) {
 	// No segment? Must be integer
 	if (!reg.segment)
 		return SIG_TYPE_INTEGER | (reg.offset ? 0 : SIG_TYPE_NULL);
@@ -719,21 +735,24 @@
 	// Otherwise it's an object
 	SegmentObj *mobj = _segMan->getSegmentObj(reg.segment);
 	if (!mobj)
-		return SIG_TYPE_INVALID;
+		return SIG_TYPE_ERROR;
 
+	uint16 result = 0;
 	if (!mobj->isValidOffset(reg.offset))
-		return SIG_TYPE_INVALID;
+		result |= SIG_IS_INVALID;
 
 	switch (mobj->getType()) {
 	case SEG_TYPE_SCRIPT:
 		if (reg.offset <= (*(Script *)mobj).getBufSize() &&
 			reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET &&
 		    RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) {
-			return ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE;
+			result |= ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE;
 		} else
-			return SIG_TYPE_REFERENCE;
+			result |= SIG_TYPE_REFERENCE;
+		break;
 	case SEG_TYPE_CLONES:
-		return SIG_TYPE_OBJECT;
+		result |= SIG_TYPE_OBJECT;
+		break;
 	case SEG_TYPE_LOCALS:
 	case SEG_TYPE_STACK:
 	case SEG_TYPE_SYS_STRINGS:
@@ -743,14 +762,18 @@
 	case SEG_TYPE_ARRAY:
 	case SEG_TYPE_STRING:
 #endif
-		return SIG_TYPE_REFERENCE;
+		result |= SIG_TYPE_REFERENCE;
+		break;
 	case SEG_TYPE_LISTS:
-		return SIG_TYPE_LIST;
+		result |= SIG_TYPE_LIST;
+		break;
 	case SEG_TYPE_NODES:
-		return SIG_TYPE_NODE;
+		result |= SIG_TYPE_NODE;
+		break;
 	default:
-		return 0;
+		return SIG_TYPE_ERROR;
 	}
+	return result;
 }
 
 struct SignatureDebugType {
@@ -762,11 +785,12 @@
 	{ SIG_TYPE_NULL,          "null" },
 	{ SIG_TYPE_INTEGER,       "integer" },
 	{ SIG_TYPE_UNINITIALIZED, "uninitialized" },
-	{ SIG_TYPE_INVALID,       "invalid" },
 	{ SIG_TYPE_OBJECT,        "object" },
 	{ SIG_TYPE_REFERENCE,     "reference" },
 	{ SIG_TYPE_LIST,          "list" },
 	{ SIG_TYPE_NODE,          "node" },
+	{ SIG_TYPE_ERROR,         "error" },
+	{ SIG_IS_INVALID,         "invalid" },
 	{ 0,                      NULL }
 };
 
@@ -830,10 +854,11 @@
 	while (nextSig && argc) {
 		curSig = nextSig;
 		int type = findRegType(*argv);
-		if (!type)
-			return false; // couldn't determine type
 
-		if (!(type & curSig))
+		if ((type & SIG_IS_INVALID) && (!(curSig & SIG_IS_INVALID)))
+			return false; // pointer is invalid and signature doesn't allow that?
+
+		if (!((type & ~SIG_IS_INVALID) & curSig))
 			return false; // type mismatch
 
 		if (!(curSig & SIG_MORE_MAY_FOLLOW)) {

Modified: scummvm/trunk/engines/sci/engine/kernel.h
===================================================================
--- scummvm/trunk/engines/sci/engine/kernel.h	2010-07-07 16:51:36 UTC (rev 50736)
+++ scummvm/trunk/engines/sci/engine/kernel.h	2010-07-07 18:35:07 UTC (rev 50737)
@@ -101,14 +101,15 @@
 	SIG_TYPE_NULL          =  0x01, // may be 0:0       [0]
 	SIG_TYPE_INTEGER       =  0x02, // may be 0:*       [i], automatically also allows null
 	SIG_TYPE_UNINITIALIZED =  0x04, // may be FFFF:*    -> not allowable, only used for comparsion
-	SIG_TYPE_INVALID       =  0x08, // invalid segment or offset -> not allowable, only used for comparsion
-	SIG_TYPE_OBJECT        =  0x10, // may be object    [o]
-	SIG_TYPE_REFERENCE     =  0x20, // may be reference [r]
-	SIG_TYPE_LIST          =  0x40, // may be list      [l]
-	SIG_TYPE_NODE          =  0x80, // may be node      [n]
-	SIG_IS_OPTIONAL        = 0x100, // is optional
-	SIG_NEEDS_MORE         = 0x200, // needs at least one additional parameter following
-	SIG_MORE_MAY_FOLLOW    = 0x400  // may have more parameters of the same type following
+	SIG_TYPE_OBJECT        =  0x08, // may be object    [o]
+	SIG_TYPE_REFERENCE     =  0x10, // may be reference [r]
+	SIG_TYPE_LIST          =  0x20, // may be list      [l]
+	SIG_TYPE_NODE          =  0x40, // may be node      [n]
+	SIG_TYPE_ERROR         =  0x80, // happens, when there is a identification error - only used for comparsion
+	SIG_IS_INVALID         = 0x100, // ptr is invalid   [!] -> invalid offset
+	SIG_IS_OPTIONAL        = 0x200, // is optional
+	SIG_NEEDS_MORE         = 0x400, // needs at least one additional parameter following
+	SIG_MORE_MAY_FOLLOW    = 0x800  // may have more parameters of the same type following
 };
 
 // this does not include SIG_TYPE_UNINITIALIZED, because we can not allow uninitialized values anywhere
@@ -196,7 +197,7 @@
 	 *	       KSIG_INVALID set if the type of reg can be determined, but is invalid.
 	 *	       0 on error.
 	 */
-	int findRegType(reg_t reg);
+	uint16 findRegType(reg_t reg);
 
 	/******************** Text functionality ********************/
 	/**


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