diff options
author | Filippos Karapetis | 2010-10-20 17:31:29 +0000 |
---|---|---|
committer | Filippos Karapetis | 2010-10-20 17:31:29 +0000 |
commit | 3d85d6804bb13a8cd2822b771aa2e6d4c8276a1d (patch) | |
tree | 5cdb3d4a52cd6cc932e13b84e22958d03df48ece /engines | |
parent | 64c0d2a1d1f2b2688e86092834f2e559c437cd29 (diff) | |
download | scummvm-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')
-rw-r--r-- | engines/sci/console.cpp | 80 | ||||
-rw-r--r-- | engines/sci/console.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/kernel.cpp | 8 | ||||
-rw-r--r-- | engines/sci/engine/kernel.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/segment.h | 2 |
5 files changed, 90 insertions, 2 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; } diff --git a/engines/sci/console.h b/engines/sci/console.h index 8bc2da439c..6dd2cf6b36 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -128,6 +128,7 @@ private: bool cmdStepCallk(int argc, const char **argv); bool cmdDisassemble(int argc, const char **argv); bool cmdDisassembleAddress(int argc, const char **argv); + bool cmdFindKernelFunctionCall(int argc, const char **argv); bool cmdSend(int argc, const char **argv); bool cmdGo(int argc, const char **argv); bool cmdLogKernel(int argc, const char **argv); diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index ff327a0049..b1ee6abaff 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -88,6 +88,14 @@ const Common::String &Kernel::getKernelName(uint number) const { return _kernelNames[number]; } +int Kernel::findKernelFuncPos(Common::String kernelFuncName) { + for (uint32 i = 0; i < _kernelNames.size(); i++) + if (_kernelNames[i] == kernelFuncName) + return i; + + return -1; +} + int Kernel::findSelector(const char *selectorName) const { for (uint pos = 0; pos < _selectorNames.size(); ++pos) { if (_selectorNames[pos] == selectorName) diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index e50c6aaae2..9833f91a5e 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -151,6 +151,7 @@ public: uint getSelectorNamesSize() const; const Common::String &getSelectorName(uint selector); + int findKernelFuncPos(Common::String kernelFuncName); uint getKernelNamesSize() const; const Common::String &getKernelName(uint number) const; diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 6eca708e2e..99a41137e9 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -246,7 +246,7 @@ public: reg_t getInfoSelector() const { return _variables[_offset + 2]; } void setInfoSelector(reg_t value) { _variables[_offset + 2] = value; } - reg_t getNameSelector() const { return _variables[_offset + 3]; } + reg_t getNameSelector() const { return _offset + 3 < (uint16)_variables.size() ? _variables[_offset + 3] : NULL_REG; } void setNameSelector(reg_t value) { _variables[_offset + 3] = value; } reg_t getPropDictSelector() const { return _variables[2]; } |