diff --git a/engines/sci/engine/object.cpp b/engines/sci/engine/object.cpp index a4e5d476601..0b2abf1c9b4 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 = ""; + } else { + nameReg.segment = _pos.segment; + name = segMan->derefString(nameReg); + if (!name) + 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; }