diff options
author | Willem Jan Palenstijn | 2011-03-14 20:10:17 +0100 |
---|---|---|
committer | Willem Jan Palenstijn | 2011-03-14 20:34:16 +0100 |
commit | c1cdc49ac57880c069607600b53d1ee958b723a2 (patch) | |
tree | 351f4748d40e7f53f5c3dd229ccf60f2f2bc063f | |
parent | 4c5950dff2314aa50cf240543024dab7a13242a6 (diff) | |
download | scummvm-rg350-c1cdc49ac57880c069607600b53d1ee958b723a2.tar.gz scummvm-rg350-c1cdc49ac57880c069607600b53d1ee958b723a2.tar.bz2 scummvm-rg350-c1cdc49ac57880c069607600b53d1ee958b723a2.zip |
SCI: Add code to enumerate shadowed selectors
If an object defines more variables than its base class, some method
selectors may be hidden. This code tries to enumerate the affected
selectors. It may be useful for mass-scanning objects using
'find_callk Dummy'.
It's disabled by default currently since it does things to partially
uninitialized objects that I can't guarantee are 100% safe at this
point.
-rw-r--r-- | engines/sci/engine/object.cpp | 65 |
1 files changed, 58 insertions, 7 deletions
diff --git a/engines/sci/engine/object.cpp b/engines/sci/engine/object.cpp index a4e5d47660..0b2abf1c9b 100644 --- a/engines/sci/engine/object.cpp +++ b/engines/sci/engine/object.cpp @@ -172,8 +172,16 @@ bool Object::initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClas const Object *baseObj = segMan->getObject(getSpeciesSelector()); if (baseObj) { - if (_variables.size() != baseObj->getVarCount()) { - warning("Object %04x:%04x varnum doesn't match baseObj's: obj %d, base %d ", PRINT_REG(_pos), _variables.size(), baseObj->getVarCount()); + uint originalVarCount = _variables.size(); + + if (_variables.size() != baseObj->getVarCount()) + _variables.resize(baseObj->getVarCount()); + // Copy base from species class, as we need its selector IDs + _baseObj = baseObj->_baseObj; + if (doInitSuperClass) + initSuperClass(segMan, addr); + + if (_variables.size() != originalVarCount) { // These objects are probably broken. // An example is 'witchCage' in script 200 in KQ5 (#3034714), // but also 'girl' in script 216 and 'door' in script 22. @@ -182,12 +190,55 @@ bool Object::initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClas // The effect is that a number of its method selectors may be // treated as variable selectors, causing unpredictable effects. + int objScript = segMan->getScript(_pos.segment)->getScriptNumber(); + + // We have to do a little bit of work to get the name of the object + // before any relocations are done. + reg_t nameReg = getNameSelector(); + const char *name; + if (nameReg.isNull()) { + name = "<no name>"; + } else { + nameReg.segment = _pos.segment; + name = segMan->derefString(nameReg); + if (!name) + name = "<invalid name>"; + } + + warning("Object %04x:%04x (name %s, script %d) varnum doesn't " + "match baseObj's: obj %d, base %d ", PRINT_REG(_pos), + name, objScript, originalVarCount, baseObj->getVarCount()); + +#if 0 + // We enumerate the methods selectors which could be hidden here + if (getSciVersion() <= SCI_VERSION_2_1) { + const SegmentRef objRef = segMan->dereference(baseObj->_pos); + assert(objRef.isRaw); + uint segBound = objRef.maxSize/2 - baseObj->getVarCount(); + const byte* buf = (const byte *)baseObj->_baseVars; + if (!buf) { + // While loading this may happen due to objects being loaded + // out of order, and we can't proceed then, unfortunately. + segBound = 0; + } + for (uint i = baseObj->getVarCount(); + i < originalVarCount && i < segBound; ++i) { + uint16 slc = READ_SCI11ENDIAN_UINT16(buf + 2*i); + // Skip any numbers which happen to be varselectors too + bool found = false; + for (uint j = 0; j < baseObj->getVarCount() && !found; ++j) + found = READ_SCI11ENDIAN_UINT16(buf + 2*j) == slc; + if (found) continue; + // Skip any selectors which aren't method selectors, + // so couldn't be mistaken for varselectors + if (lookupSelector(segMan, _pos, slc, 0, 0) != kSelectorMethod) continue; + warning(" Possibly affected selector: %02x (%s)", slc, + g_sci->getKernel()->getSelectorName(slc).c_str()); + } + } +#endif } - _variables.resize(baseObj->getVarCount()); - // Copy base from species class, as we need its selector IDs - _baseObj = baseObj->_baseObj; - if (doInitSuperClass) - initSuperClass(segMan, addr); + return true; } |