aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorColin Snover2017-02-08 11:52:36 -0600
committerColin Snover2017-04-23 13:07:25 -0500
commit866419fa71d398edcf087e67f7367deeadd04f14 (patch)
tree9ef58907e16ec7c8474207c208476c2d44b40432 /engines
parent42406cb11a775b129cfe5a913ee239f129eeae71 (diff)
downloadscummvm-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.cpp11
-rw-r--r--engines/sci/resource.cpp64
-rw-r--r--engines/sci/resource.h4
-rw-r--r--engines/sci/sci.cpp2
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);