diff options
author | Colin Snover | 2017-02-08 11:52:36 -0600 |
---|---|---|
committer | Colin Snover | 2017-04-23 13:07:25 -0500 |
commit | 866419fa71d398edcf087e67f7367deeadd04f14 (patch) | |
tree | 9ef58907e16ec7c8474207c208476c2d44b40432 /engines | |
parent | 42406cb11a775b129cfe5a913ee239f129eeae71 (diff) | |
download | scummvm-rg350-866419fa71d398edcf087e67f7367deeadd04f14.tar.gz scummvm-rg350-866419fa71d398edcf087e67f7367deeadd04f14.tar.bz2 scummvm-rg350-866419fa71d398edcf087e67f7367deeadd04f14.zip |
SCI: Implement fallback detection for SCI3
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/detection.cpp | 11 | ||||
-rw-r--r-- | engines/sci/resource.cpp | 64 | ||||
-rw-r--r-- | engines/sci/resource.h | 4 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 2 |
4 files changed, 61 insertions, 20 deletions
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 422bbba310..cc6bb000b6 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -379,6 +379,15 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R return "qfg3"; } + if (sierraId == "l7") + return "lsl7"; + + if (sierraId == "p2") + return "phantasmagoria2"; + + if (sierraId == "lite") + return "lighthouse"; + return sierraId; } @@ -628,7 +637,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, s_fallbackDesc.platform = Common::kPlatformAmiga; // Determine the game id - Common::String sierraGameId = resMan.findSierraGameId(); + Common::String sierraGameId = resMan.findSierraGameId(s_fallbackDesc.platform == Common::kPlatformMacintosh); // If we don't have a game id, the game is not SCI if (sierraGameId.empty()) diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index f6486acff7..c4df47d1b6 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -30,6 +30,7 @@ #include "common/memstream.h" #endif +#include "sci/parser/vocabulary.h" #include "sci/resource.h" #include "sci/resource_intern.h" #include "sci/util.h" @@ -2690,15 +2691,19 @@ static SciSpan<const byte>::const_iterator findSci0ExportsBlock(const SciSpan<co // This code duplicates Script::relocateOffsetSci3, but we can't use // that here since we can't instantiate scripts at this point. -static int relocateOffsetSci3(const SciSpan<const byte> &buf, uint32 offset) { +static int relocateOffsetSci3(const SciSpan<const byte> &buf, uint32 offset, const bool isBE) { int relocStart = buf.getUint32LEAt(8); int relocCount = buf.getUint16LEAt(18); SciSpan<const byte>::const_iterator seeker = buf.cbegin() + relocStart; for (int i = 0; i < relocCount; ++i) { - if (seeker.getUint32SE() == offset) { - // TODO: Find out what UINT16 at (seeker + 8) means - return buf.getUint16SEAt(offset) + (seeker + 4).getUint32SE(); + const uint32 candidateOffset = isBE ? seeker.getUint32BE() : seeker.getUint32LE(); + if (candidateOffset == offset) { + if (isBE) { + return buf.getUint16BEAt(offset) + (seeker + 4).getUint32BE(); + } else { + return buf.getUint16LEAt(offset) + (seeker + 4).getUint32LE(); + } } seeker += 10; } @@ -2706,7 +2711,7 @@ static int relocateOffsetSci3(const SciSpan<const byte> &buf, uint32 offset) { return -1; } -reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) { +reg_t ResourceManager::findGameObject(const bool addSci11ScriptOffset, const bool isBE) { Resource *script = findResource(ResourceId(kResourceTypeScript, 0), false); if (!script) @@ -2746,36 +2751,63 @@ reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) { return make_reg(1, offset); } else { - return make_reg(1, relocateOffsetSci3(*script, 22)); + return make_reg(1, relocateOffsetSci3(*script, 22, isBE)); } } -Common::String ResourceManager::findSierraGameId() { +Common::String ResourceManager::findSierraGameId(const bool isBE) { // In SCI0-SCI1, the heap is embedded in the script. In SCI1.1 - SCI2.1, // it's in a separate heap resource - Resource *heap = 0; - int nameSelector = 3; + Resource *heap = nullptr; + int nameSelector = -1; if (getSciVersion() < SCI_VERSION_1_1) { heap = findResource(ResourceId(kResourceTypeScript, 0), false); + nameSelector = 3; } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) { heap = findResource(ResourceId(kResourceTypeHeap, 0), false); - nameSelector += 5; + nameSelector = 8; } else if (getSciVersion() == SCI_VERSION_3) { - warning("TODO: findSierraGameId(): SCI3 equivalent"); + heap = findResource(ResourceId(kResourceTypeScript, 0), false); + + Resource *vocab = findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS), false); + const uint16 numSelectors = isBE ? vocab->getUint16BEAt(0) : vocab->getUint16LEAt(0); + for (uint16 i = 0; i < numSelectors; ++i) { + uint16 selectorOffset; + uint16 selectorSize; + if (isBE) { + selectorOffset = vocab->getUint16BEAt((i + 1) * sizeof(uint16)); + selectorSize = vocab->getUint16BEAt(selectorOffset); + } else { + selectorOffset = vocab->getUint16LEAt((i + 1) * sizeof(uint16)); + selectorSize = vocab->getUint16LEAt(selectorOffset); + } + + Common::String selectorName = Common::String((const char *)vocab->getUnsafeDataAt(selectorOffset + 2, selectorSize), selectorSize); + if (selectorName == "name") { + nameSelector = i; + break; + } + } } - if (!heap) + if (!heap || nameSelector == -1) return ""; - int16 gameObjectOffset = findGameObject(false).getOffset(); + int16 gameObjectOffset = findGameObject(false, isBE).getOffset(); if (!gameObjectOffset) return ""; - // Seek to the name selector of the first export - SciSpan<const byte>::const_iterator offsetPtr = heap->cbegin() + gameObjectOffset + nameSelector * 2; - uint16 offset = !isSci11Mac() ? offsetPtr.getUint16LE() : offsetPtr.getUint16BE(); + int32 offset; + if (getSciVersion() == SCI_VERSION_3) { + offset = relocateOffsetSci3(*heap, gameObjectOffset + /* base selector offset */ 0x110 + nameSelector * sizeof(uint16), isBE); + } else { + // Seek to the name selector of the first export + SciSpan<const byte>::const_iterator offsetPtr = heap->cbegin() + gameObjectOffset + nameSelector * sizeof(uint16); + offset = !isSci11Mac() ? offsetPtr.getUint16LE() : offsetPtr.getUint16BE(); + } + return heap->getStringAt(offset); } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 6a67bf7414..85bd915e5d 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -436,7 +436,7 @@ public: /** * Finds the internal Sierra ID of the current game from script 0. */ - Common::String findSierraGameId(); + Common::String findSierraGameId(const bool isBE); /** * Finds the location of the game object from script 0. @@ -444,7 +444,7 @@ public: * games. Needs to be false when the heap is accessed directly inside * findSierraGameId(). */ - reg_t findGameObject(bool addSci11ScriptOffset = true); + reg_t findGameObject(const bool addSci11ScriptOffset, const bool isBE); /** * Converts a map resource type to our type diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index ff503293aa..026c423d75 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -242,7 +242,7 @@ Common::Error SciEngine::run() { // Add the after market GM patches for the specified game, if they exist _resMan->addNewGMPatch(_gameId); - _gameObjectAddress = _resMan->findGameObject(); + _gameObjectAddress = _resMan->findGameObject(true, isBE()); _scriptPatcher = new ScriptPatcher(); SegManager *segMan = new SegManager(_resMan, _scriptPatcher); |