From 2c62e5f99c3bf24630eb37d6ddd34eac330b3d91 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sun, 18 Dec 2016 17:26:57 +0100 Subject: ADL: Add workarounds for hires5 --- engines/adl/adl.cpp | 28 ++++++++++++++++++++++++++-- engines/adl/adl.h | 4 ++++ engines/adl/adl_v2.cpp | 2 ++ engines/adl/adl_v4.cpp | 1 + engines/adl/hires5.cpp | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp index 834b53a53c..bc5bc74f3a 100644 --- a/engines/adl/adl.cpp +++ b/engines/adl/adl.cpp @@ -300,6 +300,30 @@ void AdlEngine::readCommands(Common::ReadStream &stream, Commands &commands) { } } +void AdlEngine::removeCommand(Commands &commands, uint idx) { + Commands::iterator cmds; + uint i = 0; + for (cmds = commands.begin(); cmds != commands.end(); ++cmds) { + if (i++ == idx) { + commands.erase(cmds); + return; + } + } + + error("Command %d not found", idx); +} + +Command &AdlEngine::getCommand(Commands &commands, uint idx) { + Commands::iterator cmds; + uint i = 0; + for (cmds = commands.begin(); cmds != commands.end(); ++cmds) { + if (i++ == idx) + return *cmds; + } + + error("Command %d not found", idx); +} + void AdlEngine::checkInput(byte verb, byte noun) { // Try room-local command list first if (doOneCommand(_roomData.commands, verb, noun)) @@ -1343,14 +1367,14 @@ Common::String AdlEngine::verbStr(uint i) const { if (i == IDI_ANY) return "*"; else - return Common::String::format("%d/%s", i, _priVerbs[i - 1].c_str()); + return Common::String::format("%d/%s", i, (i - 1 < _priVerbs.size() ? _priVerbs[i - 1].c_str() : "")); } Common::String AdlEngine::nounStr(uint i) const { if (i == IDI_ANY) return "*"; else - return Common::String::format("%d/%s", i, _priNouns[i - 1].c_str()); + return Common::String::format("%d/%s", i, (i - 1 < _priNouns.size() ? _priNouns[i - 1].c_str() : "")); } Common::String AdlEngine::msgStr(uint i) const { diff --git a/engines/adl/adl.h b/engines/adl/adl.h index a825200587..87e99a5537 100644 --- a/engines/adl/adl.h +++ b/engines/adl/adl.h @@ -252,9 +252,13 @@ protected: virtual Common::String formatNounError(const Common::String &verb, const Common::String &noun) const; void loadWords(Common::ReadStream &stream, WordMap &map, Common::StringArray &pri) const; void readCommands(Common::ReadStream &stream, Commands &commands); + void removeCommand(Commands &commands, uint idx); + Command &getCommand(Commands &commands, uint idx); void checkInput(byte verb, byte noun); virtual bool isInputValid(byte verb, byte noun, bool &is_any); virtual bool isInputValid(const Commands &commands, byte verb, byte noun, bool &is_any); + virtual void applyRoomWorkarounds(byte roomNr) { } + virtual void applyRegionWorkarounds() { } virtual void setupOpcodeTables(); virtual void initState(); diff --git a/engines/adl/adl_v2.cpp b/engines/adl/adl_v2.cpp index 46bd6aa4d3..8670bd08df 100644 --- a/engines/adl/adl_v2.cpp +++ b/engines/adl/adl_v2.cpp @@ -245,6 +245,8 @@ void AdlEngine_v2::loadRoom(byte roomNr) { stream->seek(commandOffset); readCommands(*stream, _roomData.commands); } + + applyRoomWorkarounds(roomNr); } void AdlEngine_v2::showRoom() { diff --git a/engines/adl/adl_v4.cpp b/engines/adl/adl_v4.cpp index 267399fb61..456ee10dca 100644 --- a/engines/adl/adl_v4.cpp +++ b/engines/adl/adl_v4.cpp @@ -219,6 +219,7 @@ void AdlEngine_v4::loadRegion(byte region) { } } + applyRegionWorkarounds(); restoreVars(); } diff --git a/engines/adl/hires5.cpp b/engines/adl/hires5.cpp index f298cecf55..a3ed6d890e 100644 --- a/engines/adl/hires5.cpp +++ b/engines/adl/hires5.cpp @@ -45,6 +45,8 @@ private: void runIntro(); void init(); void initGameState(); + void applyRegionWorkarounds(); + void applyRoomWorkarounds(byte roomNr); // AdlEngine_v4 bool isInventoryFull(); @@ -297,6 +299,36 @@ void HiRes5Engine::initGameState() { _state.room = 5; } +void HiRes5Engine::applyRegionWorkarounds() { + // WORKAROUND: Remove/fix buggy commands + switch (_state.region) { + case 3: + // "USE PIN" references a missing message, but cannot + // be triggered due to shadowing of the "USE" verb. + // We remove it anyway to allow script dumping to proceed. + // TODO: Investigate if we should fix this command instead + // of removing it. + removeCommand(_roomCommands, 12); + break; + case 14: + // "WITH SHOVEL" references a missing message. This bug + // is game-breaking in the original, but unlikely to occur + // in practice due to the "DIG" command not asking for what + // to dig with. Probably a remnant of an earlier version + // of the script. + removeCommand(_roomCommands, 0); + } +} + +void HiRes5Engine::applyRoomWorkarounds(byte roomNr) { + // WORKAROUND: Remove/fix buggy commands + if (_state.region == 17 && roomNr == 49) { + // "GET WATER" references a missing message when you already + // have water. This message should be 117 instead of 17. + getCommand(_roomData.commands, 8).script[4] = 117; + } +} + Engine *HiRes5Engine_create(OSystem *syst, const AdlGameDescription *gd) { return new HiRes5Engine(syst, gd); } -- cgit v1.2.3