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:
parent
3d86ab9942
commit
8e8e3225da
4 changed files with 104 additions and 0 deletions
|
@ -1726,6 +1726,16 @@ void ScummEngine::applyWorkaroundIfNeeded(ResType type, int idx) {
|
||||||
delete[] patchedScript;
|
delete[] patchedScript;
|
||||||
} else
|
} 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
|
// There is a cracked version of Maniac Mansion v2 that attempts to
|
||||||
// remove the security door copy protection. With it, any code is
|
// remove the security door copy protection. With it, any code is
|
||||||
// accepted as long as you get the last digit wrong. Unfortunately,
|
// accepted as long as you get the last digit wrong. Unfortunately,
|
||||||
|
@ -1771,5 +1781,72 @@ bool ScummEngine::verifyMI2MacBootScript(byte *buf, int size) {
|
||||||
return true;
|
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
|
} // End of namespace Scumm
|
||||||
|
|
|
@ -2777,6 +2777,8 @@ void ScummEngine_v5::decodeParseString() {
|
||||||
strcpy(tmpBuf + diff, "5000");
|
strcpy(tmpBuf + diff, "5000");
|
||||||
strcpy(tmpBuf + diff + 4, tmp + sizeof("NCREDIT-NOTE-AMOUNT") - 1);
|
strcpy(tmpBuf + diff + 4, tmp + sizeof("NCREDIT-NOTE-AMOUNT") - 1);
|
||||||
printString(textSlot, (byte *)tmpBuf);
|
printString(textSlot, (byte *)tmpBuf);
|
||||||
|
} if (_game.id == GID_MONKEY && _roomResource == 25 && vm.slot[_currentScript].number == 205) {
|
||||||
|
printPatchedMI1CannibalString(textSlot, _scriptPointer);
|
||||||
} else {
|
} else {
|
||||||
printString(textSlot, _scriptPointer);
|
printString(textSlot, _scriptPointer);
|
||||||
}
|
}
|
||||||
|
@ -2810,4 +2812,26 @@ void ScummEngine_v5::decodeParseString() {
|
||||||
_string[textSlot].saveDefault();
|
_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
|
} // End of namespace Scumm
|
||||||
|
|
|
@ -701,6 +701,8 @@ public:
|
||||||
void applyWorkaroundIfNeeded(ResType type, int idx);
|
void applyWorkaroundIfNeeded(ResType type, int idx);
|
||||||
bool verifyMI2MacBootScript();
|
bool verifyMI2MacBootScript();
|
||||||
bool verifyMI2MacBootScript(byte *buf, int size);
|
bool verifyMI2MacBootScript(byte *buf, int size);
|
||||||
|
bool tryPatchMI1CannibalScript(byte *buf, int size);
|
||||||
|
|
||||||
int getResourceDataSize(const byte *ptr) const;
|
int getResourceDataSize(const byte *ptr) const;
|
||||||
void dumpResource(const char *tag, int index, const byte *ptr, int length = -1);
|
void dumpResource(const char *tag, int index, const byte *ptr, int length = -1);
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ protected:
|
||||||
void setupScummVars() override;
|
void setupScummVars() override;
|
||||||
void resetScummVars() override;
|
void resetScummVars() override;
|
||||||
virtual void decodeParseString();
|
virtual void decodeParseString();
|
||||||
|
void printPatchedMI1CannibalString(int textSlot, const byte *ptr);
|
||||||
|
|
||||||
void saveLoadWithSerializer(Common::Serializer &s) override;
|
void saveLoadWithSerializer(Common::Serializer &s) override;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue