aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWillem Jan Palenstijn2011-03-14 20:10:17 +0100
committerWillem Jan Palenstijn2011-03-14 20:34:16 +0100
commitc1cdc49ac57880c069607600b53d1ee958b723a2 (patch)
tree351f4748d40e7f53f5c3dd229ccf60f2f2bc063f
parent4c5950dff2314aa50cf240543024dab7a13242a6 (diff)
downloadscummvm-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.cpp65
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;
}