SCUMM: Add missing Lemonhead lines in English CD Monkey Island 1

Apparently these were lost when the game was converted from floppy to CD
version. Not just in the English version, but that's all I have. We
should come up with a way to make it easy to add other languages,
though.
This commit is contained in:
Torbjörn Andersson 2021-08-03 17:57:51 +02:00 committed by Filippos Karapetis
parent 3d86ab9942
commit 8e8e3225da
4 changed files with 104 additions and 0 deletions

View File

@ -1726,6 +1726,16 @@ void ScummEngine::applyWorkaroundIfNeeded(ResType type, int idx) {
delete[] patchedScript;
} else
// For some reason, the CD version of Monkey Island 1 removes some of
// the text when giving the wimpy idol to the cannibals. It looks like
// a mistake, because one of the text that is printed is immediately
// overwritten. This probably affects all CD versions, so we just have
// to add further patches as they are reported.
if (_game.id == GID_MONKEY && type == rtRoom && idx == 25) {
tryPatchMI1CannibalScript(getResourceAddress(type, idx), size);
} else
// There is a cracked version of Maniac Mansion v2 that attempts to
// remove the security door copy protection. With it, any code is
// accepted as long as you get the last digit wrong. Unfortunately,
@ -1771,5 +1781,72 @@ bool ScummEngine::verifyMI2MacBootScript(byte *buf, int size) {
return true;
}
bool ScummEngine::tryPatchMI1CannibalScript(byte *buf, int size) {
assert(_game.id == GID_MONKEY);
int expectedSize = -1;
int scriptOffset = -1;
int scriptLength = -1;
Common::String expectedMd5;
int patchOffset = -1;
int patchLength = -1;
switch (_language) {
case Common::EN_ANY:
expectedSize = 82906;
scriptOffset = 73883;
scriptLength = 607;
expectedMd5 = "98b1126a836ef5bfefff10b605b20555";
patchOffset = 167;
patchLength = 126;
break;
default:
return false;
}
if (size == expectedSize) {
// There isn't enough space in the script for the revised
// texts, so these abbreviations will be expanded in
// decodeParseString().
const byte patchData[] = {
0x14, 0x03, 0x0F, // print(3,[Text("/LMH.001/");
0x2F, 0x4C, 0x4D, 0x48,
0x2E, 0x30, 0x30, 0x31,
0x2F, 0x00,
0xAE, 0x02, // WaitForMessage();
0x14, 0x03, 0x0F, // print(3,[Text("/LMH.001/");
0x2F, 0x4C, 0x4D, 0x48,
0x2E, 0x30, 0x30, 0x32,
0x2F, // No terminating 0x00!
};
byte *scriptPtr = buf + scriptOffset;
// Check that the data is a local script.
if (READ_BE_UINT32(scriptPtr) != MKTAG('L','S','C','R'))
return false;
// Check that the first instruction to be patched is o5_print
if (scriptPtr[patchOffset] != 0x14)
return false;
// Check that the MD5 sum matches a known patchable script.
Common::MemoryReadStream stream(buf + scriptOffset, scriptLength);
Common::String md5 = Common::computeStreamMD5AsString(stream);
if (md5 != expectedMd5)
return false;
// Pad the rest of the replaced script part with spaces before
// terminating the string.
memcpy(scriptPtr + patchOffset, patchData, sizeof(patchData));
memset(scriptPtr + patchOffset + sizeof(patchData), 32, patchLength - sizeof(patchData) - 1);
scriptPtr[patchOffset + patchLength - 1] = 0;
}
return true;
}
} // End of namespace Scumm

View File

@ -2777,6 +2777,8 @@ void ScummEngine_v5::decodeParseString() {
strcpy(tmpBuf + diff, "5000");
strcpy(tmpBuf + diff + 4, tmp + sizeof("NCREDIT-NOTE-AMOUNT") - 1);
printString(textSlot, (byte *)tmpBuf);
} if (_game.id == GID_MONKEY && _roomResource == 25 && vm.slot[_currentScript].number == 205) {
printPatchedMI1CannibalString(textSlot, _scriptPointer);
} else {
printString(textSlot, _scriptPointer);
}
@ -2810,4 +2812,26 @@ void ScummEngine_v5::decodeParseString() {
_string[textSlot].saveDefault();
}
void ScummEngine_v5::printPatchedMI1CannibalString(int textSlot, const byte *ptr) {
const char *msg = (const char *)ptr;
#define MSG_WAIT "\xFF\x03"
if (strncmp((const char *)ptr, "/LMH.001/", 9) == 0) {
msg =
"Oooh, that's nice." MSG_WAIT
"Simple. Just like one of mine." MSG_WAIT
"And little. Like mine.";
} else if (strncmp((const char *)ptr, "/LMH.002/", 9) == 0) {
msg =
"And it says, `Made by Lemonhead`^" MSG_WAIT
"^just like one of mine!" MSG_WAIT
"We should take this to the Great Monkey.";
}
#undef MSG_WAIT
printString(textSlot, (const byte *)msg);
}
} // End of namespace Scumm

View File

@ -701,6 +701,8 @@ public:
void applyWorkaroundIfNeeded(ResType type, int idx);
bool verifyMI2MacBootScript();
bool verifyMI2MacBootScript(byte *buf, int size);
bool tryPatchMI1CannibalScript(byte *buf, int size);
int getResourceDataSize(const byte *ptr) const;
void dumpResource(const char *tag, int index, const byte *ptr, int length = -1);

View File

@ -65,6 +65,7 @@ protected:
void setupScummVars() override;
void resetScummVars() override;
virtual void decodeParseString();
void printPatchedMI1CannibalString(int textSlot, const byte *ptr);
void saveLoadWithSerializer(Common::Serializer &s) override;