[Scummvm-git-logs] scummvm master -> efddaf84ebc138cad41f7f13f3cc6545b8954940
bgK
bastien.bouclet at gmail.com
Fri Aug 11 19:06:25 CEST 2017
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
ee588a8c33 MOHAWK: Riven: Patch an invalid card change when entering Gehn's office
efddaf84eb MOHAWK: Riven: b_Data1.mhk is not required to play the CD version
Commit: ee588a8c33b3f75c9ee64ca28ef5010e292b2458
https://github.com/scummvm/scummvm/commit/ee588a8c33b3f75c9ee64ca28ef5010e292b2458
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2017-08-11T19:05:55+02:00
Commit Message:
MOHAWK: Riven: Patch an invalid card change when entering Gehn's office
Fixes #10118.
Changed paths:
engines/mohawk/riven_card.cpp
engines/mohawk/riven_scripts.cpp
engines/mohawk/riven_scripts.h
diff --git a/engines/mohawk/riven_card.cpp b/engines/mohawk/riven_card.cpp
index 3aab79d..feea22a 100644
--- a/engines/mohawk/riven_card.cpp
+++ b/engines/mohawk/riven_card.cpp
@@ -130,13 +130,7 @@ void RivenCard::applyPatches(uint16 id) {
forwardEnabled.index
};
- // Script data is expected to be in big endian
- for (uint i = 0; i < ARRAYSIZE(patchData); i++) {
- patchData[i] = TO_BE_16(patchData[i]);
- }
-
- Common::MemoryReadStream patchStream((const byte *)(patchData), ARRAYSIZE(patchData) * sizeof(uint16));
- RivenScriptPtr patchScript = _vm->_scriptMan->readScript(&patchStream);
+ RivenScriptPtr patchScript = _vm->_scriptMan->readScriptFromData(patchData, ARRAYSIZE(patchData));
// Append the patch to the existing script
RivenScriptPtr loadScript = getScript(kCardLoadScript);
@@ -145,6 +139,111 @@ void RivenCard::applyPatches(uint16 id) {
debugC(kRivenDebugPatches, "Applied fix always enabled forward hotspot in card %x", globalId);
}
+ // In Gehn's office, after having encountered him once before and coming back
+ // with the trap book, the draw update script of card 1 tries to switch to
+ // card 2 while still loading card 1. Switching cards is not allowed during
+ // draw update scripts, resulting in an use after free crash.
+ //
+ // Here we backport the fix that has been made in the DVD version to the CD version.
+ //
+ // Script before patch:
+ // == Script 1 ==
+ // type: CardUpdate
+ // switch (agehn) {
+ // case 1:
+ // switch (atrapbook) {
+ // case 1:
+ // obutton = 1;
+ // transition(16);
+ // switchCard(2);
+ // break;
+ // }
+ // break;
+ // case 2:
+ // activatePLST(5);
+ // break;
+ // case 3:
+ // activatePLST(5);
+ // break;
+ // }
+ //
+ //
+ // Script after patch:
+ // == Script 1 ==
+ // type: CardUpdate
+ // switch (agehn) {
+ // case 1:
+ // switch (atrapbook) {
+ // case 1:
+ // obutton = 1;
+ // activatePLST(6);
+ // break;
+ // }
+ // break;
+ // case 2:
+ // activatePLST(5);
+ // break;
+ // case 3:
+ // activatePLST(5);
+ // break;
+ // }
+ //
+ // == Script 2 ==
+ // type: CardEnter
+ // switch (agehn) {
+ // case 1:
+ // switch (atrapbook) {
+ // case 1:
+ // transition(16);
+ // switchCard(2);
+ // break;
+ // }
+ // break;
+ // }
+ if (globalId == 0x2E76 && !(_vm->getFeatures() & GF_DVD)) {
+ uint16 aGehnVariable = _vm->getStack()->getIdFromName(kVariableNames, "agehn");
+ uint16 aTrapBookVariable = _vm->getStack()->getIdFromName(kVariableNames, "atrapbook");
+ uint16 patchData[] = {
+ 1, // Command count in script
+ kRivenCommandSwitch,
+ 2, // Unused
+ aGehnVariable,
+ 1, // Branches count
+
+ 1, // agehn == 1 branch
+ 1, // Command count in sub-script
+ kRivenCommandSwitch,
+ 2, // Unused
+ aTrapBookVariable,
+ 1, // Branches count
+
+ 1, // atrapbook == 1 branch
+ 2, // Command count in sub-script
+ kRivenCommandTransition,
+ 1, // Argument count
+ kRivenTransitionBlend,
+ kRivenCommandChangeCard,
+ 1, // Argument count
+ 2 // Card id
+ };
+
+ // Add the new script to the list
+ RivenTypedScript patchScript;
+ patchScript.type = kCardEnterScript;
+ patchScript.script = _vm->_scriptMan->readScriptFromData(patchData, ARRAYSIZE(patchData));
+ _scripts.push_back(patchScript);
+
+ // Add a black picture to the card's list to be able to use it in the second part of the patch
+ Picture blackPicture;
+ blackPicture.index = 6;
+ blackPicture.id = 117;
+ blackPicture.rect = Common::Rect(608, 392);
+ _pictureList.push_back(blackPicture);
+
+ debugC(kRivenDebugPatches, "Applied invalid card change during screen update (1/2) to card %x", globalId);
+ // The second part of this patch is in the script patches
+ }
+
// Apply script patches
for (uint i = 0; i < _scripts.size(); i++) {
_scripts[i].script->applyCardPatches(_vm, globalId, _scripts[i].type, 0xFFFF);
@@ -698,7 +797,7 @@ RivenScriptPtr RivenCard::onKeyAction(RivenKeyAction keyAction) {
static const char *upNames [] = { "up", nullptr };
static const char *downNames [] = { "down", nullptr };
- static const char **hotspotNames;
+ const char **hotspotNames = nullptr;
switch (keyAction) {
case kKeyActionMoveForward:
hotspotNames = forwardNames;
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index 21c18fa..cb040ee 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -179,6 +179,16 @@ RivenScriptPtr RivenScriptManager::createScriptFromData(uint16 commandCount, ...
return readScript(&readStream);
}
+RivenScriptPtr RivenScriptManager::readScriptFromData(uint16 *data, uint16 size) {
+ // Script data is expected to be in big endian
+ for (uint i = 0; i < size; i++) {
+ data[i] = TO_BE_16(data[i]);
+ }
+
+ Common::MemoryReadStream patchStream((const byte *)(data), size * sizeof(uint16));
+ return _vm->_scriptMan->readScript(&patchStream);
+}
+
RivenScriptPtr RivenScriptManager::createScriptWithCommand(RivenCommand *command) {
assert(command);
@@ -312,6 +322,29 @@ void RivenScript::applyCardPatches(MohawkEngine_Riven *vm, uint32 cardGlobalId,
debugC(kRivenDebugPatches, "Applied missing closing sound patch to card %x", cardGlobalId);
}
+ // Second part of the patch to fix the invalid card change when entering Gehn's office
+ // The first part is in the card patches.
+ if (cardGlobalId == 0x2E76 && scriptType == kCardUpdateScript && !(vm->getFeatures() & GF_DVD)) {
+ shouldApplyPatches = true;
+
+ for (uint i = 0; i < _commands.size(); i++) {
+ int transitionIndex = -1;
+ if (_commands[i]->getType() == kRivenCommandTransition) {
+ transitionIndex = i;
+ }
+ if (transitionIndex >= 0) {
+ _commands.remove_at(transitionIndex + 1);
+ _commands.remove_at(transitionIndex);
+
+ RivenSimpleCommand::ArgumentArray arguments;
+ arguments.push_back(6);
+ _commands.push_back(RivenCommandPtr(new RivenSimpleCommand(vm, kRivenCommandActivatePLST, arguments)));
+ }
+ }
+
+ debugC(kRivenDebugPatches, "Applied invalid card change during screen update (2/2) to card %x", cardGlobalId);
+ }
+
if (shouldApplyPatches) {
for (uint i = 0; i < _commands.size(); i++) {
_commands[i]->applyCardPatches(cardGlobalId, scriptType, hotspotId);
diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h
index e77b9ae..25cf363 100644
--- a/engines/mohawk/riven_scripts.h
+++ b/engines/mohawk/riven_scripts.h
@@ -170,6 +170,14 @@ public:
/** Read a single script from a stream */
RivenScriptPtr readScript(Common::ReadStream *stream);
+ /**
+ * Read a script from an array of uint16
+ * @param data Script data array. Will be modified.
+ * @param size Number of uint16 in data
+ * @return
+ */
+ RivenScriptPtr readScriptFromData(uint16 *data, uint16 size);
+
/** Create a script from the caller provided arguments containing raw data */
RivenScriptPtr createScriptFromData(uint16 commandCount, ...);
Commit: efddaf84ebc138cad41f7f13f3cc6545b8954940
https://github.com/scummvm/scummvm/commit/efddaf84ebc138cad41f7f13f3cc6545b8954940
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2017-08-11T19:05:55+02:00
Commit Message:
MOHAWK: Riven: b_Data1.mhk is not required to play the CD version
Changed paths:
engines/mohawk/riven.cpp
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 6c2b1a2..c7f8d1c 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -390,8 +390,9 @@ bool MohawkEngine_Riven::checkDatafiles() {
const char **datafiles = listExpectedDatafiles();
for (int i = 0; datafiles[i] != nullptr; i++) {
if (!SearchMan.hasFile(datafiles[i])) {
- if (strcmp(datafiles[i], "j_Data3.mhk") == 0) {
- // j_Data3.mhk comes from the 1.02 patch. It is not required to play.
+ if (strcmp(datafiles[i], "j_Data3.mhk") == 0
+ || strcmp(datafiles[i], "b_Data1.mhk") == 0) {
+ // j_Data3.mhk and b_Data1.mhk come from the 1.02 patch. They are not required to play.
continue;
}
More information about the Scummvm-git-logs
mailing list