aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippos Karapetis2019-06-08 13:57:00 +0300
committerFilippos Karapetis2019-06-08 13:57:34 +0300
commitd2f5023ee9ec5534a9f7a4754c4f1e805c0fb605 (patch)
tree11bfdde4332ab07727c9fba812ff13fe4b21858d
parent3915be8ff1cbb0a5aa9a63cb443829578d97e745 (diff)
downloadscummvm-rg350-d2f5023ee9ec5534a9f7a4754c4f1e805c0fb605.tar.gz
scummvm-rg350-d2f5023ee9ec5534a9f7a4754c4f1e805c0fb605.tar.bz2
scummvm-rg350-d2f5023ee9ec5534a9f7a4754c4f1e805c0fb605.zip
SCI: Do not apply script patches when checking for static selectors
Fixes bug #10969
-rw-r--r--engines/sci/engine/kernel.cpp5
-rw-r--r--engines/sci/engine/kernel.h2
-rw-r--r--engines/sci/engine/script.cpp19
-rw-r--r--engines/sci/engine/script.h18
-rw-r--r--engines/sci/engine/script_patches.cpp4
-rw-r--r--engines/sci/engine/seg_manager.cpp14
-rw-r--r--engines/sci/engine/seg_manager.h16
-rw-r--r--engines/sci/engine/static_selectors.cpp11
8 files changed, 43 insertions, 46 deletions
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 17f799a77f..d75c910d30 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -112,11 +112,6 @@ int Kernel::findSelector(const char *selectorName) const {
return -1;
}
-// used by Script patcher to figure out, if it's okay to initialize signature/patch-table
-bool Kernel::selectorNamesAvailable() {
- return !_selectorNames.empty();
-}
-
void Kernel::loadSelectorNames() {
Resource *r = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS), 0);
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 558224fdec..a27df1ad08 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -168,8 +168,6 @@ public:
*/
int findSelector(const char *selectorName) const;
- bool selectorNamesAvailable();
-
// Script dissection/dumping functions
void dissectScript(int scriptNumber, Vocabulary *vocab);
void dumpScriptObject(const SciSpan<const byte> &script, SciSpan<const byte> object);
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 0dea69214a..25d12833c3 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -80,7 +80,7 @@ enum {
kSci11ExportTableOffset = 8
};
-void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptPatcher) {
+void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptPatcher, bool applyScriptPatches) {
freeScript();
Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), false);
@@ -147,7 +147,8 @@ void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptP
}
// Check scripts (+ possibly SCI 1.1 heap) for matching signatures and patch those, if found
- scriptPatcher->processScript(_nr, outBuffer);
+ if (applyScriptPatches)
+ scriptPatcher->processScript(_nr, outBuffer);
if (getSciVersion() <= SCI_VERSION_1_LATE) {
// Some buggy game scripts contain two export tables (e.g. script 912
@@ -1119,7 +1120,7 @@ void Script::initializeObjectsSci0(SegManager *segMan, SegmentId segmentId) {
relocateSci0Sci21(segmentId);
}
-void Script::initializeObjectsSci11(SegManager *segMan, SegmentId segmentId) {
+void Script::initializeObjectsSci11(SegManager *segMan, SegmentId segmentId, bool applyScriptPatches) {
SciSpan<const byte> seeker = _heap.subspan(4 + _heap.getUint16SEAt(2) * 2);
Common::Array<reg_t> mismatchedVarCountObjects;
@@ -1129,7 +1130,7 @@ void Script::initializeObjectsSci11(SegManager *segMan, SegmentId segmentId) {
// Copy base from species class, as we need its selector IDs
obj->setSuperClassSelector(
- segMan->getClassAddress(obj->getSuperClassSelector().getOffset(), SCRIPT_GET_LOCK, 0));
+ segMan->getClassAddress(obj->getSuperClassSelector().getOffset(), SCRIPT_GET_LOCK, 0, applyScriptPatches));
// -propDict- is used by Obj::isMemberOf to determine if an object
// is an instance of a class. For classes, we therefore relocate
@@ -1187,12 +1188,12 @@ void Script::initializeObjectsSci11(SegManager *segMan, SegmentId segmentId) {
}
#ifdef ENABLE_SCI32
-void Script::initializeObjectsSci3(SegManager *segMan, SegmentId segmentId) {
+void Script::initializeObjectsSci3(SegManager *segMan, SegmentId segmentId, bool applyScriptPatches) {
SciSpan<const byte> seeker = getSci3ObjectsPointer();
while (seeker.getUint16SEAt(0) == SCRIPT_OBJECT_MAGIC_NUMBER) {
Object *obj = scriptObjInit(make_reg32(segmentId, seeker - *_buf));
- obj->setSuperClassSelector(segMan->getClassAddress(obj->getSuperClassSelector().getOffset(), SCRIPT_GET_LOCK, 0));
+ obj->setSuperClassSelector(segMan->getClassAddress(obj->getSuperClassSelector().getOffset(), SCRIPT_GET_LOCK, 0, applyScriptPatches));
seeker += seeker.getUint16SEAt(2);
}
@@ -1200,14 +1201,14 @@ void Script::initializeObjectsSci3(SegManager *segMan, SegmentId segmentId) {
}
#endif
-void Script::initializeObjects(SegManager *segMan, SegmentId segmentId) {
+void Script::initializeObjects(SegManager *segMan, SegmentId segmentId, bool applyScriptPatches) {
if (getSciVersion() <= SCI_VERSION_1_LATE)
initializeObjectsSci0(segMan, segmentId);
else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE)
- initializeObjectsSci11(segMan, segmentId);
+ initializeObjectsSci11(segMan, segmentId, applyScriptPatches);
#ifdef ENABLE_SCI32
else if (getSciVersion() == SCI_VERSION_3)
- initializeObjectsSci3(segMan, segmentId);
+ initializeObjectsSci3(segMan, segmentId, applyScriptPatches);
#endif
}
diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h
index f4afca7681..e1a4b9613b 100644
--- a/engines/sci/engine/script.h
+++ b/engines/sci/engine/script.h
@@ -133,7 +133,7 @@ public:
~Script();
void freeScript(const bool keepLocalsSegment = false);
- void load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptPatcher);
+ void load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptPatcher, bool applyScriptPatches = true);
virtual bool isValidOffset(uint32 offset) const;
virtual SegmentRef dereference(reg_t pointer);
@@ -180,10 +180,11 @@ public:
/**
* Initializes the script's objects (SCI0)
- * @param segMan A reference to the segment manager
- * @param segmentId The script's segment id
+ * @param segMan A reference to the segment manager
+ * @param segmentId The script's segment id
+ * @param applyScriptPatches Apply patches for the script, if available
*/
- void initializeObjects(SegManager *segMan, SegmentId segmentId);
+ void initializeObjects(SegManager *segMan, SegmentId segmentId, bool applyScriptPatches);
// script lock operations
@@ -336,10 +337,11 @@ private:
/**
* Initializes the script's objects (SCI1.1 - SCI2.1)
- * @param segMan A reference to the segment manager
- * @param segmentId The script's segment id
+ * @param segMan A reference to the segment manager
+ * @param segmentId The script's segment id
+ * @applyScriptPatches Apply patches for the script, if available
*/
- void initializeObjectsSci11(SegManager *segMan, SegmentId segmentId);
+ void initializeObjectsSci11(SegManager *segMan, SegmentId segmentId, bool applyScriptPatches);
#ifdef ENABLE_SCI32
/**
@@ -347,7 +349,7 @@ private:
* @param segMan A reference to the segment manager
* @param segmentId The script's segment id
*/
- void initializeObjectsSci3(SegManager *segMan, SegmentId segmentId);
+ void initializeObjectsSci3(SegManager *segMan, SegmentId segmentId, bool applyScriptPatches);
#endif
LocalVariables *allocLocalsSegment(SegManager *segMan);
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 806fb36913..4412ffb533 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -14067,10 +14067,6 @@ void ScriptPatcher::processScript(uint16 scriptNr, SciSpan<byte> scriptData) {
_isMacSci11 = (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1);
if (!_runtimeTable) {
- // Abort, in case selectors are not yet initialized (happens for games w/o selector-dictionary)
- if (!g_sci->getKernel()->selectorNamesAvailable())
- return;
-
// signature table needs to get initialized (Magic DWORD set, selector table set)
initSignature(signatureTable);
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 45666336e9..fd6b86e405 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -347,11 +347,11 @@ SegmentId SegManager::getScriptSegment(int script_id) const {
return _scriptSegMap.getVal(script_id, 0);
}
-SegmentId SegManager::getScriptSegment(int script_nr, ScriptLoadType load) {
+SegmentId SegManager::getScriptSegment(int script_nr, ScriptLoadType load, bool applyScriptPatches) {
SegmentId segment;
if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD)
- instantiateScript(script_nr);
+ instantiateScript(script_nr, applyScriptPatches);
segment = getScriptSegment(script_nr);
@@ -1003,7 +1003,7 @@ void SegManager::createClassTable() {
}
}
-reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, uint16 callerSegment) {
+reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, uint16 callerSegment, bool applyScriptPatches) {
if (classnr == 0xffff)
return NULL_REG;
@@ -1012,7 +1012,7 @@ reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, uint16 calle
} else {
Class *the_class = &_classTable[classnr];
if (!the_class->reg.getSegment()) {
- getScriptSegment(the_class->script, lock);
+ getScriptSegment(the_class->script, lock, applyScriptPatches);
if (!the_class->reg.getSegment()) {
if (lock == SCRIPT_GET_DONT_LOAD)
@@ -1028,7 +1028,7 @@ reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, uint16 calle
}
}
-int SegManager::instantiateScript(int scriptNum) {
+int SegManager::instantiateScript(int scriptNum, bool applyScriptPatches) {
SegmentId segmentId = getScriptSegment(scriptNum);
Script *scr = getScriptIfLoaded(segmentId);
if (scr) {
@@ -1042,10 +1042,10 @@ int SegManager::instantiateScript(int scriptNum) {
scr = allocateScript(scriptNum, &segmentId);
}
- scr->load(scriptNum, _resMan, _scriptPatcher);
+ scr->load(scriptNum, _resMan, _scriptPatcher, applyScriptPatches);
scr->initializeLocals(this);
scr->initializeClasses(this);
- scr->initializeObjects(this, segmentId);
+ scr->initializeObjects(this, segmentId, applyScriptPatches);
#ifdef ENABLE_SCI32
g_sci->_guestAdditions->instantiateScriptHook(*scr);
#endif
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index d13edf0ef2..fdef0b6463 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -98,10 +98,11 @@ public:
* Determines the segment occupied by a certain script. Optionally
* load it, or load & lock it.
* @param[in] script_nr Number of the script to look up
- * @param[in] load flag determining whether to load/lock the script
- * @return The script's segment ID, or 0 on failure
+ * @param[in] load Flag determining whether to load/lock the script
+ * @param[in] applyScriptPatches Apply patches for the script, if available
+ * @return The script's segment ID, or 0 on failure
*/
- SegmentId getScriptSegment(int script_nr, ScriptLoadType load);
+ SegmentId getScriptSegment(int script_nr, ScriptLoadType load, bool applyScriptPatches = true);
/**
* Makes sure that a script and its superclasses get loaded to the heap.
@@ -109,10 +110,11 @@ public:
* increased. All scripts containing superclasses of this script are loaded
* recursively as well, unless 'recursive' is set to zero. The
* complementary function is "uninstantiateScript()" below.
- * @param[in] script_nr The script number to load
- * @return The script's segment ID or 0 if out of heap
+ * @param[in] script_nr The script number to load
+ * @param[in] applyScriptPatches Apply patches for the script, if available
+ * @return The script's segment ID or 0 if out of heap
*/
- int instantiateScript(int script_nr);
+ int instantiateScript(int script_nr, bool applyScriptPatches = true);
/**
* Decreases the numer of lockers of a script and unloads it if that number
@@ -128,7 +130,7 @@ private:
public:
// TODO: document this
- reg_t getClassAddress(int classnr, ScriptLoadType lock, uint16 callerSegment);
+ reg_t getClassAddress(int classnr, ScriptLoadType lock, uint16 callerSegment, bool applyScriptPatches = true);
/**
* Return a pointer to the specified script.
diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp
index 08c6f5d75a..ae6c7afc84 100644
--- a/engines/sci/engine/static_selectors.cpp
+++ b/engines/sci/engine/static_selectors.cpp
@@ -224,11 +224,14 @@ Common::StringArray Kernel::checkStaticSelectorNames() {
void Kernel::findSpecificSelectors(Common::StringArray &selectorNames) {
// Now, we need to find out selectors which keep changing place...
// We do that by dissecting game objects, and looking for selectors at
- // specified locations.
+ // specified locations. We need to load some game scripts here to
+ // find these selectors, but all of the loaded scripts will be
+ // purged at the end of this function, as the segment manager will be
+ // reset.
// We need to initialize script 0 here, to make sure that it's always
// located at segment 1.
- _segMan->instantiateScript(0);
+ _segMan->instantiateScript(0, false);
// The Actor class contains the init, xLast and yLast selectors, which
// we reference directly. It's always in script 998, so we need to
@@ -242,7 +245,7 @@ void Kernel::findSpecificSelectors(Common::StringArray &selectorNames) {
#endif
if (_resMan->testResource(ResourceId(kResourceTypeScript, actorScript))) {
- _segMan->instantiateScript(actorScript);
+ _segMan->instantiateScript(actorScript, false);
const Object *actorClass = _segMan->getObject(_segMan->findObjectByName("Actor"));
@@ -284,7 +287,7 @@ void Kernel::findSpecificSelectors(Common::StringArray &selectorNames) {
if (!_resMan->testResource(ResourceId(kResourceTypeScript, classReferences[i].script)))
continue;
- _segMan->instantiateScript(classReferences[i].script);
+ _segMan->instantiateScript(classReferences[i].script, false);
const Object *targetClass = _segMan->getObject(_segMan->findObjectByName(classReferences[i].className));
int targetSelectorPos = 0;