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

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Fri Jan 7 19:25:38 CET 2011


Revision: 55151
          http://scummvm.svn.sourceforge.net/scummvm/?rev=55151&view=rev
Author:   thebluegr
Date:     2011-01-07 18:25:38 +0000 (Fri, 07 Jan 2011)

Log Message:
-----------
SCI2/2.1: Improvements to the find_callk debug function, and some kernel function updates

- Improved the find_callk function to properly find the end of script objects, by
monitoring jump calls
- Added three extra special calls to find_callk: find kernel function calls to dummy,
unused and unmapped kernel functions
- Updated several kernel function calls because of the above functionality
- The above functionality has also uncovered a VM bug in some SCI2/2.1 opcode - added 
a FIXME for it

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

Modified: scummvm/trunk/engines/sci/console.cpp
===================================================================
--- scummvm/trunk/engines/sci/console.cpp	2011-01-07 17:44:20 UTC (rev 55150)
+++ scummvm/trunk/engines/sci/console.cpp	2011-01-07 18:25:38 UTC (rev 55151)
@@ -2710,27 +2710,13 @@
 	return true;
 }
 
-bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) {
-	if (argc < 2) {
-		DebugPrintf("Finds the scripts and methods that call a specific kernel function.\n");
-		DebugPrintf("Usage: %s <kernel function>\n", argv[0]);
-		DebugPrintf("Example: %s Display\n", argv[0]);
-		return true;
-	}
-
-	// Find the number of the kernel function call
-	int kernelFuncNum = _engine->getKernel()->findKernelFuncPos(argv[1]);
-
-	if (kernelFuncNum < 0) {
-		DebugPrintf("Invalid kernel function requested\n");
-		return true;
-	}
-
+void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
 	Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeScript);
 	Common::sort(resources->begin(), resources->end());
 	Common::List<ResourceId>::iterator itr = resources->begin();
 
-	DebugPrintf("%d scripts found, dissassembling...\n", resources->size());
+	if (showFoundScripts)
+		DebugPrintf("%d scripts found, dissassembling...\n", resources->size());
 
 	int scriptSegment;
 	Script *script;
@@ -2762,6 +2748,7 @@
 				int16 opparams[4];
 				byte extOpcode;
 				byte opcode;
+				uint16 maxJmpOffset = 0;
 
 				while (true) {
 					offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams);
@@ -2778,9 +2765,29 @@
 						}
 					}
 
+					// Monitor all jump opcodes (bt, bnt and jmp), so that if
+					// there is a jump after a ret, we don't stop processing
+					if (opcode == op_bt || opcode == op_bnt || opcode == op_jmp) {
+						uint16 curJmpOffset = offset + (uint16)opparams[0];
+						if (curJmpOffset > maxJmpOffset)
+							maxJmpOffset = curJmpOffset;
+						// FIXME: There seems to be a bug in the way we handle the SCI2 debug opcode
+						// (i.e. 0x7e/0x3f), which is probably why the bugs below occur
+						if (maxJmpOffset >= script->getBufSize()) {
+							warning("Called from script %d, object %s, method %s(%d) with %d parameters", 
+								itr->getNumber(), objName, 
+								_engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), i, 0);
+							warning("Script %d has a jump to an invalid offset (%d, script size is %d) - adjusting", 
+									script->getScriptNumber(), maxJmpOffset, script->getBufSize());
+							maxJmpOffset = script->getBufSize() - 1;
+						}
+					}
+
 					// Check for end of function/script
-					if (opcode == op_ret || offset >= script->getBufSize())
+					if (offset >= script->getBufSize())
 						break;
+					if (opcode == op_ret)// && offset >= maxJmpOffset)
+						break;
 				}	// while (true)
 			}	// for (uint16 i = 0; i < obj->getMethodCount(); i++)
 		}	// for (it = script->_objects.begin(); it != end; ++it)
@@ -2790,7 +2797,70 @@
 	}
 
 	delete resources;
+}
 
+bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) {
+	if (argc < 2) {
+		DebugPrintf("Finds the scripts and methods that call a specific kernel function.\n");
+		DebugPrintf("Usage: %s <kernel function>\n", argv[0]);
+		DebugPrintf("Example: %s Display\n", argv[0]);
+		DebugPrintf("Special usage:\n");
+		DebugPrintf("%s Dummy - find all calls to actual dummy functions "
+					"(mapped to kDummy, and dummy in the kernel table). "
+					"There shouldn't be calls to these (apart from a known "
+					"one in Shivers)\n", argv[0]);
+		DebugPrintf("%s Unused - find all calls to unused functions (mapped to "
+					"kDummy - i.e. mapped in SSCI but dummy in ScummVM, thus "
+					"they'll error out when called). Only debug scripts should "
+					"be calling these\n", argv[0]);
+		DebugPrintf("%s Unmapped - find all calls to currently unmapped or "
+					"unimplemented functions (mapped to kStub/kStubNull)\n", argv[0]);
+		return true;
+	}
+
+	Kernel *kernel = _engine->getKernel();
+	Common::String funcName(argv[1]);
+
+	if (funcName != "Dummy" && funcName != "Unused" && funcName != "Unmapped") {
+		// Find the number of the kernel function call
+		int kernelFuncNum = kernel->findKernelFuncPos(argv[1]);
+
+		if (kernelFuncNum < 0) {
+			DebugPrintf("Invalid kernel function requested\n");
+			return true;
+		}
+
+		printKernelCallsFound(kernelFuncNum, true);
+	} else if (funcName == "Dummy") {
+		// Find all actual dummy kernel functions (mapped to kDummy, and dummy
+		// in the kernel table)
+		for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) {
+			if (kernel->_kernelFuncs[i].function == &kDummy && kernel->getKernelName(i) == "Dummy") {
+				DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str());
+				printKernelCallsFound(i, false);
+			}
+		}
+	} else if (funcName == "Unused") {
+		// Find all actual dummy kernel functions (mapped to kDummy - i.e.
+		// mapped in SSCI but dummy in ScummVM, thus they'll error out when
+		// called)
+		for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) {
+			if (kernel->_kernelFuncs[i].function == &kDummy && kernel->getKernelName(i) != "Dummy") {
+				DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str());
+				printKernelCallsFound(i, false);
+			}
+		}
+	} else if (funcName == "Unmapped") {
+		// Find all unmapped kernel functions (mapped to kStub/kStubNull)
+		for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) {
+			if (kernel->_kernelFuncs[i].function == &kStub ||
+				kernel->_kernelFuncs[i].function == &kStubNull) {
+				DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str());
+				printKernelCallsFound(i, false);
+			}
+		}
+	}
+
 	return true;
 }
 

Modified: scummvm/trunk/engines/sci/console.h
===================================================================
--- scummvm/trunk/engines/sci/console.h	2011-01-07 17:44:20 UTC (rev 55150)
+++ scummvm/trunk/engines/sci/console.h	2011-01-07 18:25:38 UTC (rev 55151)
@@ -165,6 +165,13 @@
 	void hexDumpReg(const reg_t *data, int len, int regsPerLine = 4, int startOffset = 0, bool isArray = false);
 
 private:
+	/**
+	 * Prints all the scripts calling the specified kernel function.
+	 * NOTE: The results produced by this aren't 100% correct, as it
+	 * does not dissect script exports
+	 */
+	void printKernelCallsFound(int kernelFuncNum, bool showFoundScripts);
+
 	SciEngine *_engine;
 	DebugState &_debugState;
 	bool _mouseVisible;

Modified: scummvm/trunk/engines/sci/engine/kernel_tables.h
===================================================================
--- scummvm/trunk/engines/sci/engine/kernel_tables.h	2011-01-07 17:44:20 UTC (rev 55150)
+++ scummvm/trunk/engines/sci/engine/kernel_tables.h	2011-01-07 18:25:38 UTC (rev 55151)
@@ -462,6 +462,7 @@
 	{ MAP_DUMMY(Profiler),        SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(ShiftScreen),     SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(ListOps),         SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
+	// Used by the sysLogger class (e.g. script 952 in GK1CD), a class used to report bugs by Sierra's testers
 	{ MAP_DUMMY(ATan),            SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(Record),          SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(PlayBack),        SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
@@ -503,6 +504,8 @@
 	// VibrateMouse - used in QFG4 floppy
 	// PalCycle
 	// ObjectIntersect - used in QFG4 floppy
+	// MakeSaveCatName - used in the Save/Load dialog of GK1CD (SRDialog, script 64990)
+	// MakeSaveFileName - used in the Save/Load dialog of GK1CD (SRDialog, script 64990)
 
 	// SCI2 empty functions
 
@@ -524,8 +527,6 @@
 	{ MAP_DUMMY(ShowStylePercent), SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(InvertRect),       SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(InputText),        SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
-	{ MAP_DUMMY(MakeSaveCatName),  SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
-	{ MAP_DUMMY(MakeSaveFileName), SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(TextWidth),        SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(PointSize),        SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 
@@ -564,7 +565,6 @@
 	{ MAP_DUMMY(CelRect),           SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(BaseLineSpan),      SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(CelLink),           SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
-	{ MAP_DUMMY(UpdateLine),        SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(AddPolygon),        SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(DeletePolygon),     SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(UpdatePolygon),     SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
@@ -573,7 +573,6 @@
 	{ MAP_DUMMY(Priority),          SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(WinDLL),            SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(DeletePic),         SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
-	{ MAP_DUMMY(GetSierraProfileInt),    SIG_EVERYWHERE,      "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(GetSierraProfileString), SIG_EVERYWHERE,      "(.*)",                  NULL,            NULL },
 
 	// SCI2.1 unmapped functions - TODO!
@@ -585,11 +584,13 @@
 	// ScrollWindow - used by Phantasmagoria 1 and SQ6
 	// AddLine - used by Torin's Passage to highlight the chapter buttons
 	// DeleteLine - used by Torin's Passage to delete the highlight from the chapter buttons
+	// UpdateLine = used by LSL6
 	// GetConfig - used by Phantasmagoria 1
 	// SetPalStyleRange
 	// NewRoom
 	// MorphOn - used by SQ6
 	// SetHotRectangles - used by Phantasmagoria 1
+	// GetSierraProfileInt - used by Phantasmagoria 1
 #endif
 
 	{ NULL, NULL,                  SIG_EVERYWHERE,           NULL,                    NULL,            NULL }
@@ -1040,7 +1041,7 @@
 	/*0x7e*/ "Table",
 	/*0x7f*/ "WinHelp",		// Windows only
 	/*0x80*/ "Dummy",
-	/*0x81*/ "Dummy",
+	/*0x81*/ "Dummy",		// called when changing rooms in most SCI2.1 games (e.g. KQ7, GK2, MUMG deluxe, Phant1)
 	/*0x82*/ "Dummy",
 	/*0x83*/ "PrintDebug",	// debug function, used by Shivers 2 (demo and full)
 	/*0x84*/ "Dummy",


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