aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/console.cpp
diff options
context:
space:
mode:
authorFilippos Karapetis2010-10-20 17:31:29 +0000
committerFilippos Karapetis2010-10-20 17:31:29 +0000
commit3d85d6804bb13a8cd2822b771aa2e6d4c8276a1d (patch)
tree5cdb3d4a52cd6cc932e13b84e22958d03df48ece /engines/sci/console.cpp
parent64c0d2a1d1f2b2688e86092834f2e559c437cd29 (diff)
downloadscummvm-rg350-3d85d6804bb13a8cd2822b771aa2e6d4c8276a1d.tar.gz
scummvm-rg350-3d85d6804bb13a8cd2822b771aa2e6d4c8276a1d.tar.bz2
scummvm-rg350-3d85d6804bb13a8cd2822b771aa2e6d4c8276a1d.zip
SCI: Added a new debug command, "find_callk"
This command can be used to find the object methods (including their corresponding objects and owner scripts) that call a specific kernel call. This shall aid us track all the spots where a particular kernel function is called from, therefore it'll be a bit easier to find examples where unimplemented kernel functions are called svn-id: r53646
Diffstat (limited to 'engines/sci/console.cpp')
-rw-r--r--engines/sci/console.cpp80
1 files changed, 79 insertions, 1 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 79f63fded4..668b27c870 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -166,6 +166,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
DCmd_Register("snk", WRAP_METHOD(Console, cmdStepCallk)); // alias
DCmd_Register("disasm", WRAP_METHOD(Console, cmdDisassemble));
DCmd_Register("disasm_addr", WRAP_METHOD(Console, cmdDisassembleAddress));
+ DCmd_Register("find_callk", WRAP_METHOD(Console, cmdFindKernelFunctionCall));
DCmd_Register("send", WRAP_METHOD(Console, cmdSend));
DCmd_Register("go", WRAP_METHOD(Console, cmdGo));
DCmd_Register("logkernel", WRAP_METHOD(Console, cmdLogKernel));
@@ -2637,11 +2638,88 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) {
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");
+ return true;
+ }
+
+ 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());
+
+ int scriptSegment;
+ Script *script;
+ SegManager *segMan = _engine->getEngineState()->_segMan;
+
+ while (itr != resources->end()) {
+ // Load script
+ scriptSegment = segMan->instantiateScript(itr->getNumber());
+ script = segMan->getScript(scriptSegment);
+
+ // Iterate through all the script's objects
+ ObjMap::iterator it;
+ const ObjMap::iterator end = script->_objects.end();
+ for (it = script->_objects.begin(); it != end; ++it) {
+ const Object *obj = segMan->getObject(it->_value.getPos());
+ const char *objName = segMan->getObjectName(it->_value.getPos());
+
+ // Now dissassemble each method of the script object
+ for (uint16 i = 0; i < obj->getMethodCount(); i++) {
+ reg_t fptr = obj->getFunction(i);
+ uint16 offset = fptr.offset;
+ int16 opparams[4];
+ byte extOpcode;
+ byte opcode;
+
+ while (true) {
+ offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams);
+ opcode = extOpcode >> 1;
+
+ if (opcode == op_callk) {
+ uint16 kFuncNum = opparams[0];
+ uint16 argc = opparams[1];
+
+ if (kFuncNum == kernelFuncNum) {
+ DebugPrintf("Called from script %d, object %s, method %s(%d) with %d parameters\n",
+ itr->getNumber(), objName,
+ _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), i, argc);
+ }
+ }
+
+ // Check for end of function/script
+ if (opcode == op_ret || offset >= script->getBufSize())
+ break;
+ } // while (true)
+ } // for (uint16 i = 0; i < obj->getMethodCount(); i++)
+ } // for (it = script->_objects.begin(); it != end; ++it)
+
+ segMan->uninstantiateScript(itr->getNumber());
+ ++itr;
+ }
+
+ delete resources;
+
+ return true;
+}
+
bool Console::cmdSend(int argc, const char **argv) {
if (argc < 3) {
DebugPrintf("Sends a message to an object.\n");
DebugPrintf("Usage: %s <object> <selector name> <param1> <param2> ... <paramn>\n", argv[0]);
- DebugPrintf("Example: send ?fooScript cue\n");
+ DebugPrintf("Example: %s ?fooScript cue\n", argv[0]);
return true;
}