aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/console.cpp6
-rw-r--r--engines/sci/detection_tables.h32
-rw-r--r--engines/sci/engine/features.cpp70
-rw-r--r--engines/sci/engine/features.h15
-rw-r--r--engines/sci/engine/file.cpp2
-rw-r--r--engines/sci/engine/file.h5
-rw-r--r--engines/sci/engine/kernel.cpp13
-rw-r--r--engines/sci/engine/kernel.h27
-rw-r--r--engines/sci/engine/kernel_tables.h111
-rw-r--r--engines/sci/engine/kevent.cpp32
-rw-r--r--engines/sci/engine/kfile.cpp30
-rw-r--r--engines/sci/engine/klists.cpp24
-rw-r--r--engines/sci/engine/kmisc.cpp2
-rw-r--r--engines/sci/engine/kscripts.cpp2
-rw-r--r--engines/sci/engine/ksound.cpp2
-rw-r--r--engines/sci/engine/kstring.cpp341
-rw-r--r--engines/sci/engine/kvideo.cpp2
-rw-r--r--engines/sci/engine/message.cpp2
-rw-r--r--engines/sci/engine/object.cpp8
-rw-r--r--engines/sci/engine/object.h22
-rw-r--r--engines/sci/engine/savegame.cpp2
-rw-r--r--engines/sci/engine/script.cpp18
-rw-r--r--engines/sci/engine/static_selectors.cpp18
-rw-r--r--engines/sci/engine/vm_types.cpp8
-rw-r--r--engines/sci/graphics/compare.cpp4
-rw-r--r--engines/sci/graphics/frameout.cpp6
-rw-r--r--engines/sci/graphics/text16.cpp9
-rw-r--r--engines/sci/graphics/view.cpp2
-rw-r--r--engines/sci/resource.cpp142
-rw-r--r--engines/sci/resource.h2
-rw-r--r--engines/sci/resource_audio.cpp2
-rw-r--r--engines/sci/sci.cpp92
-rw-r--r--engines/sci/sci.h4
-rw-r--r--engines/sci/sound/audio.cpp59
-rw-r--r--engines/sci/sound/drivers/midi.cpp2
-rw-r--r--engines/sci/sound/midiparser_sci.cpp6
-rw-r--r--engines/sci/sound/music.cpp2
-rw-r--r--engines/sci/util.cpp2
38 files changed, 708 insertions, 420 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 1e95393e4d..5cd7b9f7ca 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -483,9 +483,7 @@ bool Console::cmdGetVersion(int argc, const char **argv) {
debugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore");
debugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType()));
#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2)
- debugPrintf("kString type: %s\n", (_engine->_features->detectSci2StringFunctionType() == kSci2StringFunctionOld) ? "SCI2 (old)" : "SCI2.1 (new)");
- if (getSciVersion() == SCI_VERSION_2_1)
+ if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE))
debugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)");
#endif
debugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]);
@@ -1046,7 +1044,7 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) {
if (!script)
debugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber());
- if (getSciVersion() <= SCI_VERSION_2_1) {
+ if (getSciVersion() <= SCI_VERSION_2_1_LATE) {
heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->getNumber()), false);
if (!heap)
debugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->getNumber());
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index f6283bf77b..d37dd18df9 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -1651,7 +1651,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "4948e4e1506f1e1c4e1d47abfa06b7f8", 204385195},
{"resource.map", 0, "40ccafb2195301504eba2e4f4f2c7f3d", 18925},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - English Windows (from the King's Quest Collection)
// Executable scanning reports "2.100.002", VERSION file reports "1.4"
@@ -1659,7 +1659,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "2be9ab94429c721af8e05c507e048a15", 18697},
{"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 203882535},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - English DOS (from FRG)
// SCI interpreter version 2.100.002, VERSION file reports "2.00b"
@@ -1667,7 +1667,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "8676b0fbbd7362989a029fe72fea14c6", 18709},
{"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - English Windows (from FRG)
// SCI interpreter version 2.100.002, VERSION file reports "2.00b"
@@ -1675,7 +1675,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "8676b0fbbd7362989a029fe72fea14c6", 18709},
{"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - German Windows (supplied by markcoolio in bug report #2727402)
// SCI interpreter version 2.100.002
@@ -1683,7 +1683,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "838b9ff132bd6962026fee832e8a7ddb", 18697},
{"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 206626576},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - Spanish DOS (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "2.00"
@@ -1691,7 +1691,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "0b62693cbe87e3aaca3e8655a437f27f", 18709},
{"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Quest 7 - English DOS Non-Interactive Demo
// SCI interpreter version 2.100.002
@@ -1707,7 +1707,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "38e627a37a975aea40cc72b0518b0709", 18412},
{"resource.000", 0, "bad61d50aaa64298fa57a7c6ccd3bccf", 84020382},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// King's Questions mini-game from the King's Quest Collection
// SCI interpreter version 2.000.000
@@ -4110,7 +4110,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "9a3e172cde9963d0a969f26469318cec", 3403},
{"ressci.000", 0, "db3e290481c35c3224e9602e71e4a1f1", 5073868},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage (Multilingual) - English Windows CD
// SCI interpreter version 2.100.002
@@ -4118,7 +4118,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage (Multilingual) - Spanish Windows CD (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "1.0"
@@ -4127,7 +4127,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
// TODO: depend on one of the patches?
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::ES_ESP, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage (Multilingual) - French Windows CD
// SCI interpreter version 2.100.002
@@ -4135,7 +4135,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage - German Windows CD (from m_kiewitz)
// SCI interpreter version 2.100.002
@@ -4144,7 +4144,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "e55c3097329b3c53752301e01c6af2fb", 9787},
{"ressci.000", 0, "118f9bec04bfe17c4f87bbb5ddb43c18", 56127540},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage (Multilingual) - German Windows CD
// SCI interpreter version 2.100.002
@@ -4152,7 +4152,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage (Multilingual) - Italian Windows CD (from glorifindel)
// SCI interpreter version 2.100.002
@@ -4160,7 +4160,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799},
{"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::IT_ITA, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage - French Windows (from LePhilousophe)
// SCI interpreter version 2.100.002
@@ -4168,7 +4168,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "66ed46e3e56f487e688d52f05b33d0ba", 9787},
{"ressci.000", 0, "118f9bec04bfe17c4f87bbb5ddb43c18", 56126981},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Torin's Passage - English Macintosh
{"torin", "", {
@@ -4180,7 +4180,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"Data6", 0, "b639487c83d1dae0e001e700f3631566", 7594881},
{"Data7", 0, "2afd9b5434102b89610916b904c3f73a", 7627374},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#endif // ENABLE_SCI32
// SCI Fanmade Games
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index be062dba64..a993506f7a 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -40,7 +40,6 @@ GameFeatures::GameFeatures(SegManager *segMan, Kernel *kernel) : _segMan(segMan)
_moveCountType = kMoveCountUninitialized;
#ifdef ENABLE_SCI32
_sci21KernelType = SCI_VERSION_NONE;
- _sci2StringFunctionType = kSci2StringFunctionUninitialized;
#endif
_usesCdTrack = Common::File::exists("cdaudio.map");
if (!ConfMan.getBool("use_cdaudio"))
@@ -143,8 +142,8 @@ SciVersion GameFeatures::detectDoSoundType() {
// SCI0LATE. Although the last SCI0EARLY game (lsl2) uses SCI0LATE resources
_doSoundType = g_sci->getResMan()->detectEarlySound() ? SCI_VERSION_0_EARLY : SCI_VERSION_0_LATE;
#ifdef ENABLE_SCI32
- } else if (getSciVersion() >= SCI_VERSION_2_1) {
- _doSoundType = SCI_VERSION_2_1;
+ } else if (getSciVersion() >= SCI_VERSION_2_1_EARLY) {
+ _doSoundType = SCI_VERSION_2_1_EARLY;
#endif
} else if (SELECTOR(nodePtr) == -1) {
// No nodePtr selector, so this game is definitely using newer
@@ -271,7 +270,7 @@ SciVersion GameFeatures::detectLofsType() {
return _lofsType;
}
- if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
+ if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
// SCI1.1 type, i.e. we compensate for the fact that the heap is attached
// to the end of the script
_lofsType = SCI_VERSION_1_1;
@@ -475,7 +474,7 @@ bool GameFeatures::autoDetectSci21KernelType() {
}
warning("autoDetectSci21KernelType(): Sound object not loaded, assuming a SCI2.1 table");
- _sci21KernelType = SCI_VERSION_2_1;
+ _sci21KernelType = SCI_VERSION_2_1_EARLY;
return true;
}
@@ -514,7 +513,7 @@ bool GameFeatures::autoDetectSci21KernelType() {
_sci21KernelType = SCI_VERSION_2;
return true;
} else if (kFuncNum == 0x75) {
- _sci21KernelType = SCI_VERSION_2_1;
+ _sci21KernelType = SCI_VERSION_2_1_EARLY;
return true;
}
}
@@ -532,65 +531,6 @@ SciVersion GameFeatures::detectSci21KernelType() {
}
return _sci21KernelType;
}
-
-Sci2StringFunctionType GameFeatures::detectSci2StringFunctionType() {
- if (_sci2StringFunctionType == kSci2StringFunctionUninitialized) {
- if (getSciVersion() <= SCI_VERSION_1_1) {
- error("detectSci21StringFunctionType() called from SCI1.1 or earlier");
- } else if (getSciVersion() == SCI_VERSION_2) {
- // SCI2 games are always using the old type
- _sci2StringFunctionType = kSci2StringFunctionOld;
- } else if (getSciVersion() == SCI_VERSION_3) {
- // SCI3 games are always using the new type
- _sci2StringFunctionType = kSci2StringFunctionNew;
- } else { // SCI2.1
- if (!autoDetectSci21StringFunctionType())
- _sci2StringFunctionType = kSci2StringFunctionOld;
- else
- _sci2StringFunctionType = kSci2StringFunctionNew;
- }
- }
-
- debugC(1, kDebugLevelVM, "Detected SCI2 kString type: %s", (_sci2StringFunctionType == kSci2StringFunctionOld) ? "old" : "new");
-
- return _sci2StringFunctionType;
-}
-
-bool GameFeatures::autoDetectSci21StringFunctionType() {
- // Look up the script address
- reg_t addr = getDetectionAddr("Str", SELECTOR(size));
-
- if (!addr.getSegment())
- return false;
-
- uint16 offset = addr.getOffset();
- Script *script = _segMan->getScript(addr.getSegment());
-
- while (true) {
- int16 opparams[4];
- byte extOpcode;
- byte opcode;
- offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams);
- opcode = extOpcode >> 1;
-
- // Check for end of script
- if (opcode == op_ret || offset >= script->getBufSize())
- break;
-
- if (opcode == op_callk) {
- uint16 kFuncNum = opparams[0];
-
- // SCI2.1 games which use the new kString functions call kString(8).
- // Earlier ones call the callKernel script function, but not kString
- // directly
- if (_kernel->getKernelName(kFuncNum) == "String")
- return true;
- }
- }
-
- return false; // not found a call to kString
-}
-
#endif
bool GameFeatures::autoDetectMoveCountType() {
diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h
index a4d715fee0..1c410267e6 100644
--- a/engines/sci/engine/features.h
+++ b/engines/sci/engine/features.h
@@ -34,12 +34,6 @@ enum MoveCountType {
kIncrementMoveCount
};
-enum Sci2StringFunctionType {
- kSci2StringFunctionUninitialized,
- kSci2StringFunctionOld,
- kSci2StringFunctionNew
-};
-
class GameFeatures {
public:
GameFeatures(SegManager *segMan, Kernel *kernel);
@@ -82,13 +76,6 @@ public:
* @return Graphics functions type, SCI_VERSION_2 / SCI_VERSION_2_1
*/
SciVersion detectSci21KernelType();
-
- /**
- * Autodetects the string subfunctions used in SCI2 - SCI3
- * @return string subfunctions type, kSci2StringFunctionOld / kSci2StringFunctionNew
- */
- Sci2StringFunctionType detectSci2StringFunctionType();
-
#endif
/**
@@ -132,13 +119,11 @@ private:
bool autoDetectMoveCountType();
#ifdef ENABLE_SCI32
bool autoDetectSci21KernelType();
- bool autoDetectSci21StringFunctionType();
#endif
SciVersion _doSoundType, _setCursorType, _lofsType, _gfxFunctionsType, _messageFunctionType;
#ifdef ENABLE_SCI32
SciVersion _sci21KernelType;
- Sci2StringFunctionType _sci2StringFunctionType;
#endif
MoveCountType _moveCountType;
diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp
index 623caec856..a602cb4503 100644
--- a/engines/sci/engine/file.cpp
+++ b/engines/sci/engine/file.cpp
@@ -129,7 +129,7 @@ reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool u
}
FileHandle *getFileFromHandle(EngineState *s, uint handle) {
- if (handle == 0 || handle == VIRTUALFILE_HANDLE) {
+ if ((handle == 0) || ((handle >= VIRTUALFILE_HANDLE_START) && (handle <= VIRTUALFILE_HANDLE_END))) {
error("Attempt to use invalid file handle (%d)", handle);
return 0;
}
diff --git a/engines/sci/engine/file.h b/engines/sci/engine/file.h
index 052eb735e9..54627d5228 100644
--- a/engines/sci/engine/file.h
+++ b/engines/sci/engine/file.h
@@ -41,8 +41,11 @@ enum {
MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */
};
-#define VIRTUALFILE_HANDLE 200
+#define VIRTUALFILE_HANDLE_START 32000
+#define VIRTUALFILE_HANDLE_SCI32SAVE 32100
#define PHANTASMAGORIA_SAVEGAME_INDEX "phantsg.dir"
+#define VIRTUALFILE_HANDLE_SCIAUDIO 32300
+#define VIRTUALFILE_HANDLE_END 32300
struct SavegameDesc {
int16 id;
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index bfb7bfcd08..3e70eb0788 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -35,6 +35,9 @@ namespace Sci {
Kernel::Kernel(ResourceManager *resMan, SegManager *segMan)
: _resMan(resMan), _segMan(segMan), _invalid("<invalid>") {
+#ifdef ENABLE_SCI32
+ _kernelFunc_StringId = 0;
+#endif
}
Kernel::~Kernel() {
@@ -118,7 +121,7 @@ void Kernel::loadSelectorNames() {
// Starting with KQ7, Mac versions have a BE name table. GK1 Mac and earlier (and all
// other platforms) always use LE.
- bool isBE = (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2_1
+ bool isBE = (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2_1_EARLY
&& g_sci->getGameId() != GID_GK1);
if (!r) { // No such resource?
@@ -603,6 +606,10 @@ void Kernel::mapFunctions() {
}
#ifdef ENABLE_SCI32
+ if (kernelName == "String") {
+ _kernelFunc_StringId = id;
+ }
+
// HACK: Phantasmagoria Mac uses a modified kDoSound (which *nothing*
// else seems to use)!
if (g_sci->getPlatform() == Common::kPlatformMacintosh && g_sci->getGameId() == GID_PHANTASMAGORIA && kernelName == "DoSound") {
@@ -863,7 +870,9 @@ void Kernel::loadKernelNames(GameFeatures *features) {
_kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesSci2);
break;
- case SCI_VERSION_2_1:
+ case SCI_VERSION_2_1_EARLY:
+ case SCI_VERSION_2_1_MIDDLE:
+ case SCI_VERSION_2_1_LATE:
if (features->detectSci21KernelType() == SCI_VERSION_2) {
// Some early SCI2.1 games use a modified SCI2 kernel table instead of
// the SCI2.1 kernel table. We detect which version to use based on
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 57b4d9455b..f62a074ef1 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -173,6 +173,12 @@ public:
typedef Common::Array<KernelFunction> KernelFunctionArray;
KernelFunctionArray _kernelFuncs; /**< Table of kernel functions. */
+#ifdef ENABLE_SCI32
+ // id of kString function, for quick usage in kArray
+ // kArray calls kString in case parameters are strings
+ uint16 _kernelFunc_StringId;
+#endif
+
/**
* Determines whether a list of registers matches a given signature.
* If no signature is given (i.e., if sig is NULL), this is always
@@ -414,6 +420,27 @@ reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv);
reg_t kArray(EngineState *s, int argc, reg_t *argv);
reg_t kListAt(EngineState *s, int argc, reg_t *argv);
reg_t kString(EngineState *s, int argc, reg_t *argv);
+
+reg_t kStringNew(EngineState *s, int argc, reg_t *argv);
+reg_t kStringSize(EngineState *s, int argc, reg_t *argv);
+reg_t kStringAt(EngineState *s, int argc, reg_t *argv);
+reg_t kStringPutAt(EngineState *s, int argc, reg_t *argv);
+reg_t kStringFree(EngineState *s, int argc, reg_t *argv);
+reg_t kStringFill(EngineState *s, int argc, reg_t *argv);
+reg_t kStringCopy(EngineState *s, int argc, reg_t *argv);
+reg_t kStringCompare(EngineState *s, int argc, reg_t *argv);
+reg_t kStringDup(EngineState *s, int argc, reg_t *argv);
+reg_t kStringGetData(EngineState *s, int argc, reg_t *argv);
+reg_t kStringLen(EngineState *s, int argc, reg_t *argv);
+reg_t kStringPrintf(EngineState *s, int argc, reg_t *argv);
+reg_t kStringPrintfBuf(EngineState *s, int argc, reg_t *argv);
+reg_t kStringAtoi(EngineState *s, int argc, reg_t *argv);
+reg_t kStringTrim(EngineState *s, int argc, reg_t *argv);
+reg_t kStringUpper(EngineState *s, int argc, reg_t *argv);
+reg_t kStringLower(EngineState *s, int argc, reg_t *argv);
+reg_t kStringTrn(EngineState *s, int argc, reg_t *argv);
+reg_t kStringTrnExclude(EngineState *s, int argc, reg_t *argv);
+
reg_t kMulDiv(EngineState *s, int argc, reg_t *argv);
reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv);
reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index 2cbd79366d..49dfa17554 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -34,6 +34,15 @@ namespace Sci {
// . -> any type
// i* -> optional multiple integers
// .* -> any parameters afterwards (or none)
+//
+// data types:
+// i - regular integer
+// o - object
+// r - reference
+// n - node
+// 0 - NULL
+// . - any
+// ! - invalid reference/offset
struct SciKernelMapSubEntry {
SciVersion fromVersion;
@@ -56,7 +65,8 @@ struct SciKernelMapSubEntry {
#define SIG_SCI1 SCI_VERSION_1_EGA_ONLY, SCI_VERSION_1_LATE
#define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1
#define SIG_SINCE_SCI11 SCI_VERSION_1_1, SCI_VERSION_NONE
-#define SIG_SCI21 SCI_VERSION_2_1, SCI_VERSION_3
+#define SIG_SINCE_SCI21 SCI_VERSION_2_1_EARLY, SCI_VERSION_3
+#define SIG_UNTIL_SCI21MID SCI_VERSION_2_1_EARLY, SCI_VERSION_2_1_MIDDLE
#define SIG_SCI16 SCI_VERSION_NONE, SCI_VERSION_1_1
#define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE
@@ -65,7 +75,7 @@ struct SciKernelMapSubEntry {
#define SIG_SOUNDSCI0 SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE
#define SIG_SOUNDSCI1EARLY SCI_VERSION_1_EARLY, SCI_VERSION_1_EARLY
#define SIG_SOUNDSCI1LATE SCI_VERSION_1_LATE, SCI_VERSION_1_LATE
-#define SIG_SOUNDSCI21 SCI_VERSION_2_1, SCI_VERSION_3
+#define SIG_SOUNDSCI21 SCI_VERSION_2_1_EARLY, SCI_VERSION_3
#define SIGFOR_ALL 0x3f
#define SIGFOR_DOS 1 << 0
@@ -190,7 +200,7 @@ static const SciKernelMapSubEntry kGraph_subops[] = {
// version, subId, function-mapping, signature, workarounds
static const SciKernelMapSubEntry kPalVary_subops[] = {
- { SIG_SCI21, 0, MAP_CALL(PalVaryInit), "ii(i)(i)(i)", NULL },
+ { SIG_SINCE_SCI21, 0, MAP_CALL(PalVaryInit), "ii(i)(i)(i)", NULL },
{ SIG_SCIALL, 0, MAP_CALL(PalVaryInit), "ii(i)(i)", NULL },
{ SIG_SCIALL, 1, MAP_CALL(PalVaryReverse), "(i)(i)(i)", NULL },
{ SIG_SCIALL, 2, MAP_CALL(PalVaryGetCurrentStep), "", NULL },
@@ -246,6 +256,7 @@ static const SciKernelMapSubEntry kFileIO_subops[] = {
#ifdef ENABLE_SCI32
+// version, subId, function-mapping, signature, workarounds
static const SciKernelMapSubEntry kSave_subops[] = {
{ SIG_SCI32, 0, MAP_CALL(SaveGame), "[r0]i[r0](r0)", NULL },
{ SIG_SCI32, 1, MAP_CALL(RestoreGame), "[r0]i[r0]", NULL },
@@ -261,31 +272,73 @@ static const SciKernelMapSubEntry kSave_subops[] = {
// version, subId, function-mapping, signature, workarounds
static const SciKernelMapSubEntry kList_subops[] = {
- { SIG_SCI21, 0, MAP_CALL(NewList), "", NULL },
- { SIG_SCI21, 1, MAP_CALL(DisposeList), "l", NULL },
- { SIG_SCI21, 2, MAP_CALL(NewNode), ".(.)", NULL },
- { SIG_SCI21, 3, MAP_CALL(FirstNode), "[l0]", NULL },
- { SIG_SCI21, 4, MAP_CALL(LastNode), "l", NULL },
- { SIG_SCI21, 5, MAP_CALL(EmptyList), "l", NULL },
- { SIG_SCI21, 6, MAP_CALL(NextNode), "n", NULL },
- { SIG_SCI21, 7, MAP_CALL(PrevNode), "n", NULL },
- { SIG_SCI21, 8, MAP_CALL(NodeValue), "[n0]", NULL },
- { SIG_SCI21, 9, MAP_CALL(AddAfter), "lnn.", NULL },
- { SIG_SCI21, 10, MAP_CALL(AddToFront), "ln.", NULL },
- { SIG_SCI21, 11, MAP_CALL(AddToEnd), "ln(.)", NULL },
- { SIG_SCI21, 12, MAP_CALL(AddBefore), "ln.", NULL },
- { SIG_SCI21, 13, MAP_CALL(MoveToFront), "ln", NULL },
- { SIG_SCI21, 14, MAP_CALL(MoveToEnd), "ln", NULL },
- { SIG_SCI21, 15, MAP_CALL(FindKey), "l.", NULL },
- { SIG_SCI21, 16, MAP_CALL(DeleteKey), "l.", NULL },
- { SIG_SCI21, 17, MAP_CALL(ListAt), "li", NULL },
- { SIG_SCI21, 18, MAP_CALL(ListIndexOf) , "l[io]", NULL },
- { SIG_SCI21, 19, MAP_CALL(ListEachElementDo), "li(.*)", NULL },
- { SIG_SCI21, 20, MAP_CALL(ListFirstTrue), "li(.*)", NULL },
- { SIG_SCI21, 21, MAP_CALL(ListAllTrue), "li(.*)", NULL },
- { SIG_SCI21, 22, MAP_CALL(Sort), "ooo", NULL },
+ { SIG_SINCE_SCI21, 0, MAP_CALL(NewList), "", NULL },
+ { SIG_SINCE_SCI21, 1, MAP_CALL(DisposeList), "l", NULL },
+ { SIG_SINCE_SCI21, 2, MAP_CALL(NewNode), ".(.)", NULL },
+ { SIG_SINCE_SCI21, 3, MAP_CALL(FirstNode), "[l0]", NULL },
+ { SIG_SINCE_SCI21, 4, MAP_CALL(LastNode), "l", NULL },
+ { SIG_SINCE_SCI21, 5, MAP_CALL(EmptyList), "l", NULL },
+ { SIG_SINCE_SCI21, 6, MAP_CALL(NextNode), "n", NULL },
+ { SIG_SINCE_SCI21, 7, MAP_CALL(PrevNode), "n", NULL },
+ { SIG_SINCE_SCI21, 8, MAP_CALL(NodeValue), "[n0]", NULL },
+ { SIG_SINCE_SCI21, 9, MAP_CALL(AddAfter), "lnn.", NULL },
+ { SIG_SINCE_SCI21, 10, MAP_CALL(AddToFront), "ln.", NULL },
+ { SIG_SINCE_SCI21, 11, MAP_CALL(AddToEnd), "ln(.)", NULL },
+ { SIG_SINCE_SCI21, 12, MAP_CALL(AddBefore), "ln.", NULL },
+ { SIG_SINCE_SCI21, 13, MAP_CALL(MoveToFront), "ln", NULL },
+ { SIG_SINCE_SCI21, 14, MAP_CALL(MoveToEnd), "ln", NULL },
+ { SIG_SINCE_SCI21, 15, MAP_CALL(FindKey), "l.", NULL },
+ { SIG_SINCE_SCI21, 16, MAP_CALL(DeleteKey), "l.", NULL },
+ { SIG_SINCE_SCI21, 17, MAP_CALL(ListAt), "li", NULL },
+ { SIG_SINCE_SCI21, 18, MAP_CALL(ListIndexOf) , "l[io]", NULL },
+ { SIG_SINCE_SCI21, 19, MAP_CALL(ListEachElementDo), "li(.*)", NULL },
+ { SIG_SINCE_SCI21, 20, MAP_CALL(ListFirstTrue), "li(.*)", NULL },
+ { SIG_SINCE_SCI21, 21, MAP_CALL(ListAllTrue), "li(.*)", NULL },
+ { SIG_SINCE_SCI21, 22, MAP_CALL(Sort), "ooo", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
+// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kString_subops[] = {
+ { SIG_SCI32, 0, MAP_CALL(StringNew), "i(i)", NULL },
+ { SIG_SCI32, 1, MAP_CALL(StringSize), "[or]", NULL },
+ { SIG_SCI32, 2, MAP_CALL(StringAt), "[or]i", NULL },
+ { SIG_SCI32, 3, MAP_CALL(StringPutAt), "[or]i(i*)", NULL },
+ // StringFree accepts invalid references
+ { SIG_SCI32, 4, MAP_CALL(StringFree), "[or0!]", NULL },
+ { SIG_SCI32, 5, MAP_CALL(StringFill), "[or]ii", NULL },
+ { SIG_SCI32, 6, MAP_CALL(StringCopy), "[or]i[or]ii", NULL },
+ { SIG_SCI32, 7, MAP_CALL(StringCompare), "[or][or](i)", NULL },
+
+ // =SCI2.1 Early and SCI2.1 Middle=
+ { SIG_UNTIL_SCI21MID, 8, MAP_CALL(StringDup), "[or]", NULL },
+ { SIG_UNTIL_SCI21MID, 9, MAP_CALL(StringGetData), "[or]", NULL },
+ { SIG_UNTIL_SCI21MID, 10, MAP_CALL(StringLen), "[or]", NULL },
+ { SIG_UNTIL_SCI21MID, 11, MAP_CALL(StringPrintf), "[or](.*)", NULL },
+ { SIG_UNTIL_SCI21MID, 12, MAP_CALL(StringPrintfBuf), "[or](.*)", NULL },
+ { SIG_UNTIL_SCI21MID, 13, MAP_CALL(StringAtoi), "[or]", NULL },
+ // exact functionality of Trim is unknown atm
+ { SIG_UNTIL_SCI21MID, 14, MAP_CALL(StringTrim), "[or]", NULL },
+ { SIG_UNTIL_SCI21MID, 15, MAP_CALL(StringUpper), "[or]", NULL },
+ { SIG_UNTIL_SCI21MID, 16, MAP_CALL(StringLower), "[or]", NULL },
+ // the following 2 are unknown atm (happen in Phantasmagoria)
+ // possibly translate?
+ { SIG_UNTIL_SCI21MID, 17, MAP_CALL(StringTrn), "[or]", NULL },
+ { SIG_UNTIL_SCI21MID, 18, MAP_CALL(StringTrnExclude), "[or]", NULL },
+
+ // SCI2.1 Late + SCI3 - kStringDup + kStringGetData were removed
+ { SIG_SCI32, 8, MAP_CALL(StringLen), "[or]", NULL },
+ { SIG_SCI32, 9, MAP_CALL(StringPrintf), "[or](.*)", NULL },
+ { SIG_SCI32, 10, MAP_CALL(StringPrintfBuf), "[or](.*)", NULL },
+ { SIG_SCI32, 11, MAP_CALL(StringAtoi), "[or]", NULL },
+ { SIG_SCI32, 12, MAP_CALL(StringTrim), "[or]", NULL },
+ { SIG_SCI32, 13, MAP_CALL(StringUpper), "[or]", NULL },
+ { SIG_SCI32, 14, MAP_CALL(StringLower), "[or]", NULL },
+ { SIG_SCI32, 15, MAP_CALL(StringTrn), "[or]", NULL },
+ { SIG_SCI32, 16, MAP_CALL(StringTrnExclude), "[or]", NULL },
SCI_SUBOPENTRY_TERMINATOR
};
+
#endif
struct SciKernelMapEntry {
@@ -429,7 +482,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL },
{ MAP_CALL(SaveGame), SIG_EVERYWHERE, "[r0]i[r0](r0)", NULL, NULL },
{ MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL },
- { MAP_CALL(SetCursor), SIG_SCI21, SIGFOR_ALL, "i(i)([io])(i*)", NULL, NULL },
+ { MAP_CALL(SetCursor), SIG_SINCE_SCI21, SIGFOR_ALL, "i(i)([io])(i*)", NULL, NULL },
// TODO: SCI2.1 may supply an object optionally (mother goose sci21 right on startup) - find out why
{ MAP_CALL(SetCursor), SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(iiiiii)", NULL, NULL },
{ MAP_CALL(SetCursor), SIG_EVERYWHERE, "i(i)(i)(i)(i)", NULL, kSetCursor_workarounds },
@@ -513,7 +566,7 @@ static SciKernelMapEntry s_kernelMap[] = {
// our garbage collector (i.e. the SCI0-SCI1.1 semantics).
{ "Purge", kFlushResources, SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(SetShowStyle), SIG_EVERYWHERE, "ioiiiii([ri])(i)", NULL, NULL },
- { MAP_CALL(String), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(String), SIG_EVERYWHERE, "(.*)", kString_subops, NULL },
{ MAP_CALL(UpdatePlane), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(ObjectIntersect), SIG_EVERYWHERE, "oo", NULL, NULL },
@@ -570,7 +623,7 @@ static SciKernelMapEntry s_kernelMap[] = {
// SCI2.1 Kernel Functions
{ MAP_CALL(CD), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iioi", NULL, NULL },
- { MAP_CALL(List), SIG_SCI21, SIGFOR_ALL, "(.*)", kList_subops, NULL },
+ { MAP_CALL(List), SIG_SINCE_SCI21, SIGFOR_ALL, "(.*)", kList_subops, NULL },
{ MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL, NULL },
{ MAP_CALL(PlayVMD), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_CALL(Robot), SIG_EVERYWHERE, "(.*)", NULL, NULL },
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index 8e16e0a07a..beaad2628a 100644
--- a/engines/sci/engine/kevent.cpp
+++ b/engines/sci/engine/kevent.cpp
@@ -42,6 +42,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
reg_t obj = argv[1];
SciEvent curEvent;
int modifier_mask = getSciVersion() <= SCI_VERSION_01 ? SCI_KEYMOD_ALL : SCI_KEYMOD_NO_FOOLOCK;
+ uint16 modifiers = 0;
SegManager *segMan = s->_segMan;
Common::Point mousePos;
@@ -58,7 +59,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// In case we use a simulated event we query the current mouse position
mousePos = g_sci->_gfxCursor->getPosition();
#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2_1)
+ if (getSciVersion() >= SCI_VERSION_2_1_EARLY)
g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
#endif
// Limit the mouse cursor position, if necessary
@@ -84,7 +85,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// For a real event we use its associated mouse position
mousePos = curEvent.mousePos;
#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2_1)
+ if (getSciVersion() >= SCI_VERSION_2_1_EARLY)
g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
#endif
// Limit the mouse cursor position, if necessary
@@ -110,6 +111,26 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
writeSelectorValue(segMan, obj, SELECTOR(x), mousePos.x);
writeSelectorValue(segMan, obj, SELECTOR(y), mousePos.y);
+ // Get current keyboard modifiers, only keep relevant bits
+ modifiers = curEvent.modifiers & modifier_mask;
+ if (g_sci->getPlatform() == Common::kPlatformDOS) {
+ // We are supposed to emulate SCI running in DOS
+
+ // We set the higher byte of the modifiers to 02h
+ // Original SCI also did that indirectly, because it asked BIOS for shift status
+ // via AH=0x02 INT16, which then sets the shift flags in AL
+ // AH is supposed to be destroyed in that case and it's not defined that 0x02
+ // is still in it on return. The value of AX was then set into the modifiers selector.
+ // At least one fan-made game (Betrayed Alliance) requires 0x02 to be in the upper byte,
+ // otherwise the darts game (script 111) will not work properly.
+
+ // It seems Sierra fixed this behaviour (effectively bug) in the SCI1 keyboard driver.
+ // SCI32 also resets the upper byte.
+ if (getSciVersion() <= SCI_VERSION_01) {
+ modifiers |= 0x0200;
+ }
+ }
+
//s->_gui->moveCursor(s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y);
switch (curEvent.type) {
@@ -125,7 +146,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
writeSelectorValue(segMan, obj, SELECTOR(message), curEvent.character);
// We only care about the translated character
- writeSelectorValue(segMan, obj, SELECTOR(modifiers), curEvent.modifiers & modifier_mask);
+ writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers);
break;
case SCI_EVENT_MOUSE_RELEASE:
@@ -149,10 +170,11 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
default:
break;
}
+ modifiers |= extra_bits; // add these additional bits to the mix
writeSelectorValue(segMan, obj, SELECTOR(type), curEvent.type);
writeSelectorValue(segMan, obj, SELECTOR(message), 0);
- writeSelectorValue(segMan, obj, SELECTOR(modifiers), (curEvent.modifiers | extra_bits) & modifier_mask);
+ writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers);
s->r_acc = make_reg(0, 1);
}
break;
@@ -161,7 +183,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// Return a null event
writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_NONE);
writeSelectorValue(segMan, obj, SELECTOR(message), 0);
- writeSelectorValue(segMan, obj, SELECTOR(modifiers), curEvent.modifiers & modifier_mask);
+ writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers);
s->r_acc = NULL_REG;
}
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 61ac76d0a7..80bd683dcd 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -258,16 +258,21 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) {
}
debugC(kDebugLevelFile, "kFileIO(open): %s, 0x%x", name.c_str(), mode);
+ if (name.hasPrefix("sciAudio\\")) {
+ // fan-made sciAudio extension, don't create those files and instead return a virtual handle
+ return make_reg(0, VIRTUALFILE_HANDLE_SCIAUDIO);
+ }
+
#ifdef ENABLE_SCI32
if (name == PHANTASMAGORIA_SAVEGAME_INDEX) {
if (s->_virtualIndexFile) {
- return make_reg(0, VIRTUALFILE_HANDLE);
+ return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE);
} else {
Common::String englishName = g_sci->getSciLanguageString(name, K_LANG_ENGLISH);
Common::String wrappedName = g_sci->wrapFilename(englishName);
if (!g_sci->getSaveFileManager()->listSavefiles(wrappedName).empty()) {
s->_virtualIndexFile = new VirtualIndexFile(wrappedName);
- return make_reg(0, VIRTUALFILE_HANDLE);
+ return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE);
}
}
}
@@ -320,7 +325,7 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) {
s->_virtualIndexFile->write("\0", 1);
s->_virtualIndexFile->write("\0", 1); // Spot description (empty)
s->_virtualIndexFile->seek(0, SEEK_SET);
- return make_reg(0, VIRTUALFILE_HANDLE);
+ return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE);
}
}
#endif
@@ -346,12 +351,17 @@ reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) {
uint16 handle = argv[0].toUint16();
#ifdef ENABLE_SCI32
- if (handle == VIRTUALFILE_HANDLE) {
+ if (handle == VIRTUALFILE_HANDLE_SCI32SAVE) {
s->_virtualIndexFile->close();
return SIGNAL_REG;
}
#endif
+ if (handle >= VIRTUALFILE_HANDLE_START) {
+ // it's a virtual handle? ignore it
+ return SIGNAL_REG;
+ }
+
FileHandle *f = getFileFromHandle(s, handle);
if (f) {
f->close();
@@ -373,7 +383,7 @@ reg_t kFileIOReadRaw(EngineState *s, int argc, reg_t *argv) {
debugC(kDebugLevelFile, "kFileIO(readRaw): %d, %d", handle, size);
#ifdef ENABLE_SCI32
- if (handle == VIRTUALFILE_HANDLE) {
+ if (handle == VIRTUALFILE_HANDLE_SCI32SAVE) {
bytesRead = s->_virtualIndexFile->read(buf, size);
} else {
#endif
@@ -403,7 +413,7 @@ reg_t kFileIOWriteRaw(EngineState *s, int argc, reg_t *argv) {
debugC(kDebugLevelFile, "kFileIO(writeRaw): %d, %d", handle, size);
#ifdef ENABLE_SCI32
- if (handle == VIRTUALFILE_HANDLE) {
+ if (handle == VIRTUALFILE_HANDLE_SCI32SAVE) {
s->_virtualIndexFile->write(buf, size);
success = true;
} else {
@@ -480,7 +490,7 @@ reg_t kFileIOReadString(EngineState *s, int argc, reg_t *argv) {
uint32 bytesRead;
#ifdef ENABLE_SCI32
- if (handle == VIRTUALFILE_HANDLE)
+ if (handle == VIRTUALFILE_HANDLE_SCI32SAVE)
bytesRead = s->_virtualIndexFile->readLine(buf, maxsize);
else
#endif
@@ -503,7 +513,7 @@ reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) {
// We skip creating these files, and instead handle the calls
// directly. Since the sciAudio calls are only creating text files,
// this is probably the most straightforward place to handle them.
- if (handle == 0xFFFF && str.hasPrefix("(sciAudio")) {
+ if (handle == VIRTUALFILE_HANDLE_SCIAUDIO) {
Common::List<ExecStack>::const_iterator iter = s->_executionStack.reverse_begin();
iter--; // sciAudio
iter--; // sciAudio child
@@ -512,7 +522,7 @@ reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) {
}
#ifdef ENABLE_SCI32
- if (handle == VIRTUALFILE_HANDLE) {
+ if (handle == VIRTUALFILE_HANDLE_SCI32SAVE) {
s->_virtualIndexFile->write(str.c_str(), str.size());
return NULL_REG;
}
@@ -539,7 +549,7 @@ reg_t kFileIOSeek(EngineState *s, int argc, reg_t *argv) {
debugC(kDebugLevelFile, "kFileIO(seek): %d, %d, %d", handle, offset, whence);
#ifdef ENABLE_SCI32
- if (handle == VIRTUALFILE_HANDLE)
+ if (handle == VIRTUALFILE_HANDLE_SCI32SAVE)
return make_reg(0, s->_virtualIndexFile->seek(offset, whence));
#endif
diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp
index 66590da23f..c0da2daaeb 100644
--- a/engines/sci/engine/klists.cpp
+++ b/engines/sci/engine/klists.cpp
@@ -669,26 +669,44 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) {
// TODO: we need to either merge SCI2 strings and
// arrays together, and in the future merge them with
// the SCI1 strings and arrays in the segment manager
+ bool callStringFunc = false;
if (op == 0) {
// New, check if the target type is 3 (string)
if (argv[2].toUint16() == 3)
- return kString(s, argc, argv);
+ callStringFunc = true;
} else {
if (s->_segMan->getSegmentType(argv[1].getSegment()) == SEG_TYPE_STRING ||
s->_segMan->getSegmentType(argv[1].getSegment()) == SEG_TYPE_SCRIPT) {
- return kString(s, argc, argv);
+ callStringFunc = true;
}
#if 0
if (op == 6) {
if (s->_segMan->getSegmentType(argv[3].getSegment()) == SEG_TYPE_STRING ||
s->_segMan->getSegmentType(argv[3].getSegment()) == SEG_TYPE_SCRIPT) {
- return kString(s, argc, argv);
+ callStringFunc = true;
}
}
#endif
}
+ if (callStringFunc) {
+ Kernel *kernel = g_sci->getKernel();
+ uint16 kernelStringFuncId = kernel->_kernelFunc_StringId;
+ if (kernelStringFuncId) {
+ const KernelFunction *kernelStringFunc = &kernel->_kernelFuncs[kernelStringFuncId];
+
+ if (op < kernelStringFunc->subFunctionCount) {
+ // subfunction-id is valid
+ const KernelSubFunction *kernelStringSubCall = &kernelStringFunc->subFunctions[op];
+ argc--;
+ argv++; // remove subfunction-id from arguments
+ // and call the kString subfunction
+ return kernelStringSubCall->function(s, argc, argv);
+ }
+ }
+ }
+
switch (op) {
case 0: { // New
reg_t arrayHandle;
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
index 448e641b63..1d9dae69b7 100644
--- a/engines/sci/engine/kmisc.cpp
+++ b/engines/sci/engine/kmisc.cpp
@@ -487,7 +487,7 @@ reg_t kMacPlatform(EngineState *s, int argc, reg_t *argv) {
// In SCI1, its usage is still unknown
// In SCI1.1, it's NOP
// In SCI32, it's used for remapping cursor ID's
- if (getSciVersion() >= SCI_VERSION_2_1) // Set Mac cursor remap
+ if (getSciVersion() >= SCI_VERSION_2_1_EARLY) // Set Mac cursor remap
g_sci->_gfxCursor->setMacCursorRemapList(argc - 1, argv + 1);
else if (getSciVersion() != SCI_VERSION_1_1)
warning("Unknown SCI1 kMacPlatform(0) call");
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index 5c271780dd..303de079aa 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -229,7 +229,7 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) {
uint16 address = scr->validateExportFunc(index, true);
// Point to the heap for SCI1.1 - SCI2.1 games
- if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE)
address += scr->getScriptSize();
// Bugfix for the intro speed in PQ2 version 1.002.011.
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index 6a1708d21a..032191e4c1 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -185,7 +185,7 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) {
volume = CLIP<int16>(volume, 0, AUDIO_VOLUME_MAX);
debugC(kDebugLevelSound, "kDoAudio: set volume to %d", volume);
#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2_1) {
+ if (getSciVersion() >= SCI_VERSION_2_1_EARLY) {
int16 volumePrev = mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 2;
volumePrev = CLIP<int16>(volumePrev, 0, AUDIO_VOLUME_MAX);
mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume * 2);
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index eef758a0d9..cd0d6af936 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -674,189 +674,230 @@ reg_t kText(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-reg_t kString(EngineState *s, int argc, reg_t *argv) {
- uint16 op = argv[0].toUint16();
+// TODO: there is an unused second argument, happens at least in LSL6 right during the intro
+reg_t kStringNew(EngineState *s, int argc, reg_t *argv) {
+ reg_t stringHandle;
+ SciString *string = s->_segMan->allocateString(&stringHandle);
+ string->setSize(argv[0].toUint16());
- if (g_sci->_features->detectSci2StringFunctionType() == kSci2StringFunctionNew) {
- if (op >= 8) // Dup, GetData have been removed
- op += 2;
- }
+ // Make sure the first character is a null character
+ if (string->getSize() > 0)
+ string->setValue(0, 0);
- switch (op) {
- case 0: { // New
- reg_t stringHandle;
- SciString *string = s->_segMan->allocateString(&stringHandle);
- string->setSize(argv[1].toUint16());
+ return stringHandle;
+}
- // Make sure the first character is a null character
- if (string->getSize() > 0)
- string->setValue(0, 0);
+reg_t kStringSize(EngineState *s, int argc, reg_t *argv) {
+ return make_reg(0, s->_segMan->getString(argv[0]).size());
+}
- return stringHandle;
- }
- case 1: // Size
- return make_reg(0, s->_segMan->getString(argv[1]).size());
- case 2: { // At (return value at an index)
- // Note that values are put in bytes to avoid sign extension
- if (argv[1].getSegment() == s->_segMan->getStringSegmentId()) {
- SciString *string = s->_segMan->lookupString(argv[1]);
- byte val = string->getRawData()[argv[2].toUint16()];
- return make_reg(0, val);
- } else {
- Common::String string = s->_segMan->getString(argv[1]);
- byte val = string[argv[2].toUint16()];
- return make_reg(0, val);
- }
+// At (return value at an index)
+reg_t kStringAt(EngineState *s, int argc, reg_t *argv) {
+ // Note that values are put in bytes to avoid sign extension
+ if (argv[0].getSegment() == s->_segMan->getStringSegmentId()) {
+ SciString *string = s->_segMan->lookupString(argv[0]);
+ byte val = string->getRawData()[argv[1].toUint16()];
+ return make_reg(0, val);
+ } else {
+ Common::String string = s->_segMan->getString(argv[0]);
+ byte val = string[argv[1].toUint16()];
+ return make_reg(0, val);
}
- case 3: { // Atput (put value at an index)
- SciString *string = s->_segMan->lookupString(argv[1]);
+}
- uint32 index = argv[2].toUint16();
- uint32 count = argc - 3;
+// Atput (put value at an index)
+reg_t kStringPutAt(EngineState *s, int argc, reg_t *argv) {
+ SciString *string = s->_segMan->lookupString(argv[0]);
- if (index + count > 65535)
- break;
+ uint32 index = argv[1].toUint16();
+ uint32 count = argc - 2;
- if (string->getSize() < index + count)
- string->setSize(index + count);
+ if (index + count > 65535)
+ return NULL_REG;
- for (uint16 i = 0; i < count; i++)
- string->setValue(i + index, argv[i + 3].toUint16());
+ if (string->getSize() < index + count)
+ string->setSize(index + count);
- return argv[1]; // We also have to return the handle
- }
- case 4: // Free
- // Freeing of strings is handled by the garbage collector
- return s->r_acc;
- case 5: { // Fill
- SciString *string = s->_segMan->lookupString(argv[1]);
- uint16 index = argv[2].toUint16();
+ for (uint16 i = 0; i < count; i++)
+ string->setValue(i + index, argv[i + 2].toUint16());
+
+ return argv[0]; // We also have to return the handle
+}
+
+reg_t kStringFree(EngineState *s, int argc, reg_t *argv) {
+ // Freeing of strings is handled by the garbage collector
+ return s->r_acc;
+}
+
+reg_t kStringFill(EngineState *s, int argc, reg_t *argv) {
+ SciString *string = s->_segMan->lookupString(argv[0]);
+ uint16 index = argv[1].toUint16();
+
+ // A count of -1 means fill the rest of the array
+ uint16 count = argv[2].toSint16() == -1 ? string->getSize() - index : argv[2].toUint16();
+ uint16 stringSize = string->getSize();
- // A count of -1 means fill the rest of the array
- uint16 count = argv[3].toSint16() == -1 ? string->getSize() - index : argv[3].toUint16();
- uint16 stringSize = string->getSize();
+ if (stringSize < index + count)
+ string->setSize(index + count);
- if (stringSize < index + count)
- string->setSize(index + count);
+ for (uint16 i = 0; i < count; i++)
+ string->setValue(i + index, argv[3].toUint16());
- for (uint16 i = 0; i < count; i++)
- string->setValue(i + index, argv[4].toUint16());
+ return argv[0];
+}
+
+reg_t kStringCopy(EngineState *s, int argc, reg_t *argv) {
+ const char *string2 = 0;
+ uint32 string2Size = 0;
+ Common::String string;
- return argv[1];
+ if (argv[2].getSegment() == s->_segMan->getStringSegmentId()) {
+ SciString *sstr;
+ sstr = s->_segMan->lookupString(argv[2]);
+ string2 = sstr->getRawData();
+ string2Size = sstr->getSize();
+ } else {
+ string = s->_segMan->getString(argv[2]);
+ string2 = string.c_str();
+ string2Size = string.size() + 1;
}
- case 6: { // Cpy
- const char *string2 = 0;
- uint32 string2Size = 0;
- Common::String string;
-
- if (argv[3].getSegment() == s->_segMan->getStringSegmentId()) {
- SciString *sstr;
- sstr = s->_segMan->lookupString(argv[3]);
- string2 = sstr->getRawData();
- string2Size = sstr->getSize();
- } else {
- string = s->_segMan->getString(argv[3]);
- string2 = string.c_str();
- string2Size = string.size() + 1;
+
+ uint32 index1 = argv[1].toUint16();
+ uint32 index2 = argv[3].toUint16();
+
+ if (argv[0] == argv[2]) {
+ // source and destination string are one and the same
+ if (index1 == index2) {
+ // even same index? ignore this call
+ // Happens in KQ7, when starting a chapter
+ return argv[0];
}
+ // TODO: this will crash, when setSize() is triggered later
+ // we need to exactly replicate original interpreter behavior
+ warning("kString(Copy): source is the same as destination string");
+ }
- uint32 index1 = argv[2].toUint16();
- uint32 index2 = argv[4].toUint16();
+ // The original engine ignores bad copies too
+ if (index2 > string2Size)
+ return NULL_REG;
- // The original engine ignores bad copies too
- if (index2 > string2Size)
- break;
+ // A count of -1 means fill the rest of the array
+ uint32 count = argv[4].toSint16() == -1 ? string2Size - index2 + 1 : argv[4].toUint16();
+// reg_t strAddress = argv[0];
- // A count of -1 means fill the rest of the array
- uint32 count = argv[5].toSint16() == -1 ? string2Size - index2 + 1 : argv[5].toUint16();
- reg_t strAddress = argv[1];
+ SciString *string1 = s->_segMan->lookupString(argv[0]);
+ //SciString *string1 = !argv[1].isNull() ? s->_segMan->lookupString(argv[1]) : s->_segMan->allocateString(&strAddress);
- SciString *string1 = s->_segMan->lookupString(argv[1]);
- //SciString *string1 = !argv[1].isNull() ? s->_segMan->lookupString(argv[1]) : s->_segMan->allocateString(&strAddress);
+ if (string1->getSize() < index1 + count)
+ string1->setSize(index1 + count);
- if (string1->getSize() < index1 + count)
- string1->setSize(index1 + count);
+ // Note: We're accessing from c_str() here because the
+ // string's size ignores the trailing 0 and therefore
+ // triggers an assert when doing string2[i + index2].
+ for (uint16 i = 0; i < count; i++)
+ string1->setValue(i + index1, string2[i + index2]);
- // Note: We're accessing from c_str() here because the
- // string's size ignores the trailing 0 and therefore
- // triggers an assert when doing string2[i + index2].
- for (uint16 i = 0; i < count; i++)
- string1->setValue(i + index1, string2[i + index2]);
+ return argv[0];
+}
- return strAddress;
- }
- case 7: { // Cmp
- Common::String string1 = argv[1].isNull() ? "" : s->_segMan->getString(argv[1]);
- Common::String string2 = argv[2].isNull() ? "" : s->_segMan->getString(argv[2]);
-
- if (argc == 4) // Strncmp
- return make_reg(0, strncmp(string1.c_str(), string2.c_str(), argv[3].toUint16()));
- else // Strcmp
- return make_reg(0, strcmp(string1.c_str(), string2.c_str()));
- }
- case 8: { // Dup
- reg_t stringHandle;
+reg_t kStringCompare(EngineState *s, int argc, reg_t *argv) {
+ Common::String string1 = argv[0].isNull() ? "" : s->_segMan->getString(argv[0]);
+ Common::String string2 = argv[1].isNull() ? "" : s->_segMan->getString(argv[1]);
- SciString *dupString = s->_segMan->allocateString(&stringHandle);
+ if (argc == 3) // Strncmp
+ return make_reg(0, strncmp(string1.c_str(), string2.c_str(), argv[2].toUint16()));
+ else // Strcmp
+ return make_reg(0, strcmp(string1.c_str(), string2.c_str()));
+}
- if (argv[1].getSegment() == s->_segMan->getStringSegmentId()) {
- *dupString = *s->_segMan->lookupString(argv[1]);
- } else {
- dupString->fromString(s->_segMan->getString(argv[1]));
- }
+// was removed for SCI2.1 Late+
+reg_t kStringDup(EngineState *s, int argc, reg_t *argv) {
+ reg_t stringHandle;
- return stringHandle;
- }
- case 9: // Getdata
- if (!s->_segMan->isHeapObject(argv[1]))
- return argv[1];
-
- return readSelector(s->_segMan, argv[1], SELECTOR(data));
- case 10: // Stringlen
- return make_reg(0, s->_segMan->strlen(argv[1]));
- case 11: { // Printf
- reg_t stringHandle;
- s->_segMan->allocateString(&stringHandle);
-
- reg_t *adjustedArgs = new reg_t[argc];
- adjustedArgs[0] = stringHandle;
- memcpy(&adjustedArgs[1], argv + 1, (argc - 1) * sizeof(reg_t));
-
- kFormat(s, argc, adjustedArgs);
- delete[] adjustedArgs;
- return stringHandle;
- }
- case 12: // Printf Buf
- return kFormat(s, argc - 1, argv + 1);
- case 13: { // atoi
- Common::String string = s->_segMan->getString(argv[1]);
- return make_reg(0, (uint16)atoi(string.c_str()));
- }
- // New subops in SCI2.1 late / SCI3
- case 14: // unknown
- warning("kString, subop %d", op);
- return NULL_REG;
- case 15: { // upper
- Common::String string = s->_segMan->getString(argv[1]);
+ SciString *dupString = s->_segMan->allocateString(&stringHandle);
- string.toUppercase();
- s->_segMan->strcpy(argv[1], string.c_str());
- return NULL_REG;
+ if (argv[0].getSegment() == s->_segMan->getStringSegmentId()) {
+ *dupString = *s->_segMan->lookupString(argv[0]);
+ } else {
+ dupString->fromString(s->_segMan->getString(argv[0]));
}
- case 16: { // lower
- Common::String string = s->_segMan->getString(argv[1]);
- string.toLowercase();
- s->_segMan->strcpy(argv[1], string.c_str());
- return NULL_REG;
- }
- default:
- error("Unknown kString subop %d", argv[0].toUint16());
- }
+ return stringHandle;
+}
+
+// was removed for SCI2.1 Late+
+reg_t kStringGetData(EngineState *s, int argc, reg_t *argv) {
+ if (!s->_segMan->isHeapObject(argv[0]))
+ return argv[0];
+
+ return readSelector(s->_segMan, argv[0], SELECTOR(data));
+}
+
+reg_t kStringLen(EngineState *s, int argc, reg_t *argv) {
+ return make_reg(0, s->_segMan->strlen(argv[0]));
+}
+
+reg_t kStringPrintf(EngineState *s, int argc, reg_t *argv) {
+ reg_t stringHandle;
+ s->_segMan->allocateString(&stringHandle);
+
+ reg_t *adjustedArgs = new reg_t[argc + 1];
+ adjustedArgs[0] = stringHandle;
+ memcpy(&adjustedArgs[1], argv, argc * sizeof(reg_t));
+
+ kFormat(s, argc + 1, adjustedArgs);
+ delete[] adjustedArgs;
+ return stringHandle;
+}
+
+reg_t kStringPrintfBuf(EngineState *s, int argc, reg_t *argv) {
+ return kFormat(s, argc, argv);
+}
+reg_t kStringAtoi(EngineState *s, int argc, reg_t *argv) {
+ Common::String string = s->_segMan->getString(argv[0]);
+ return make_reg(0, (uint16)atoi(string.c_str()));
+}
+
+reg_t kStringTrim(EngineState *s, int argc, reg_t *argv) {
+ warning("kStringTrim (argc = %d)", argc);
+ return NULL_REG;
+}
+
+reg_t kStringUpper(EngineState *s, int argc, reg_t *argv) {
+ Common::String string = s->_segMan->getString(argv[0]);
+
+ string.toUppercase();
+ s->_segMan->strcpy(argv[0], string.c_str());
+ return NULL_REG;
+}
+
+reg_t kStringLower(EngineState *s, int argc, reg_t *argv) {
+ Common::String string = s->_segMan->getString(argv[0]);
+
+ string.toLowercase();
+ s->_segMan->strcpy(argv[0], string.c_str());
return NULL_REG;
}
+// Possibly kStringTranslate?
+reg_t kStringTrn(EngineState *s, int argc, reg_t *argv) {
+ warning("kStringTrn (argc = %d)", argc);
+ return NULL_REG;
+}
+
+// Possibly kStringTranslateExclude?
+reg_t kStringTrnExclude(EngineState *s, int argc, reg_t *argv) {
+ warning("kStringTrnExclude (argc = %d)", argc);
+ return NULL_REG;
+}
+
+reg_t kString(EngineState *s, int argc, reg_t *argv) {
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
+
#endif
} // End of namespace Sci
diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
index f925111fc9..6920466711 100644
--- a/engines/sci/engine/kvideo.cpp
+++ b/engines/sci/engine/kvideo.cpp
@@ -181,7 +181,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
// for the video, so we'll just play it from there for now.
#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2_1) {
+ if (getSciVersion() >= SCI_VERSION_2_1_EARLY) {
// SCI2.1 always has argv[0] as 1, the rest of the arguments seem to
// follow SCI1.1/2.
if (argv[0].toUint16() != 1)
diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp
index 640175b20a..5300b72b71 100644
--- a/engines/sci/engine/message.cpp
+++ b/engines/sci/engine/message.cpp
@@ -182,7 +182,7 @@ bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &re
#ifdef ENABLE_SCI32
case 5: // v5 seems to be compatible with v4
// SCI32 Mac is different than SCI32 DOS/Win here
- if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2_1)
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2_1_EARLY)
reader = new MessageReaderV4_MacSCI32(res->data, res->size);
else
#endif
diff --git a/engines/sci/engine/object.cpp b/engines/sci/engine/object.cpp
index eeff45163d..0626c084c1 100644
--- a/engines/sci/engine/object.cpp
+++ b/engines/sci/engine/object.cpp
@@ -45,7 +45,7 @@ static bool relocateBlock(Common::Array<reg_t> &block, int block_location, Segme
return false;
}
block[idx].setSegment(segment); // Perform relocation
- if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE)
block[idx].incOffset(scriptSize);
return true;
@@ -63,7 +63,7 @@ void Object::init(byte *buf, reg_t obj_pos, bool initVariables) {
for (int i = 0; i < _methodCount * 2 + 2; ++i) {
_baseMethod.push_back(READ_SCI11ENDIAN_UINT16(data + READ_LE_UINT16(data + kOffsetFunctionArea) + i * 2));
}
- } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
+ } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
_variables.resize(READ_SCI11ENDIAN_UINT16(data + 2));
_baseVars = (const uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 4));
_methodCount = READ_SCI11ENDIAN_UINT16(buf + READ_SCI11ENDIAN_UINT16(data + 6));
@@ -75,7 +75,7 @@ void Object::init(byte *buf, reg_t obj_pos, bool initVariables) {
}
if (initVariables) {
- if (getSciVersion() <= SCI_VERSION_2_1) {
+ if (getSciVersion() <= SCI_VERSION_2_1_LATE) {
for (uint i = 0; i < _variables.size(); i++)
_variables[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(data + (i * 2)));
} else {
@@ -92,7 +92,7 @@ int Object::locateVarSelector(SegManager *segMan, Selector slc) const {
const byte *buf = 0;
uint varnum = 0;
- if (getSciVersion() <= SCI_VERSION_2_1) {
+ if (getSciVersion() <= SCI_VERSION_2_1_LATE) {
const Object *obj = getClass(segMan);
varnum = getSciVersion() <= SCI_VERSION_1_LATE ? getVarCount() : obj->getVariable(1).toUint16();
buf = (const byte *)obj->_baseVars;
diff --git a/engines/sci/engine/object.h b/engines/sci/engine/object.h
index 00fe7c6875..0ae7ed2cab 100644
--- a/engines/sci/engine/object.h
+++ b/engines/sci/engine/object.h
@@ -79,42 +79,42 @@ public:
}
reg_t getSpeciesSelector() const {
- if (getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() < SCI_VERSION_3)
return _variables[_offset];
else // SCI3
return _speciesSelectorSci3;
}
void setSpeciesSelector(reg_t value) {
- if (getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() < SCI_VERSION_3)
_variables[_offset] = value;
else // SCI3
_speciesSelectorSci3 = value;
}
reg_t getSuperClassSelector() const {
- if (getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() < SCI_VERSION_3)
return _variables[_offset + 1];
else // SCI3
return _superClassPosSci3;
}
void setSuperClassSelector(reg_t value) {
- if (getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() < SCI_VERSION_3)
_variables[_offset + 1] = value;
else // SCI3
_superClassPosSci3 = value;
}
reg_t getInfoSelector() const {
- if (getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() < SCI_VERSION_3)
return _variables[_offset + 2];
else // SCI3
return _infoSelectorSci3;
}
void setInfoSelector(reg_t info) {
- if (getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() < SCI_VERSION_3)
_variables[_offset + 2] = info;
else // SCI3
_infoSelectorSci3 = info;
@@ -123,7 +123,7 @@ public:
// No setter for the -info- selector
reg_t getNameSelector() const {
- if (getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() < SCI_VERSION_3)
return _offset + 3 < (uint16)_variables.size() ? _variables[_offset + 3] : NULL_REG;
else // SCI3
return _variables.size() ? _variables[0] : NULL_REG;
@@ -132,7 +132,7 @@ public:
// No setter for the name selector
reg_t getPropDictSelector() const {
- if (getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() < SCI_VERSION_3)
return _variables[2];
else
// This should never occur, this is called from a SCI1.1 - SCI2.1 only function
@@ -140,7 +140,7 @@ public:
}
void setPropDictSelector(reg_t value) {
- if (getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() < SCI_VERSION_3)
_variables[2] = value;
else
// This should never occur, this is called from a SCI1.1 - SCI2.1 only function
@@ -148,14 +148,14 @@ public:
}
reg_t getClassScriptSelector() const {
- if (getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() < SCI_VERSION_3)
return _variables[4];
else // SCI3
return make_reg(0, READ_SCI11ENDIAN_UINT16(_baseObj + 6));
}
void setClassScriptSelector(reg_t value) {
- if (getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() < SCI_VERSION_3)
_variables[4] = value;
else // SCI3
// This should never occur, this is called from a SCI1.1 - SCI2.1 only function
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 93b3a997cc..b464d347bd 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -465,7 +465,7 @@ void Script::syncStringHeap(Common::Serializer &s) {
break;
} while (1);
- } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1){
+ } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE){
// Strings in SCI1.1 come after the object instances
byte *buf = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2;
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 36e33ccfa6..26a7ff5718 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -84,7 +84,7 @@ void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptP
if (getSciVersion() == SCI_VERSION_0_EARLY) {
_bufSize += READ_LE_UINT16(script->data) * 2;
- } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
+ } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
// In SCI1.1 - SCI2.1, the heap was in a separate space from the script. We append
// it to the end of the script, and adjust addressing accordingly.
// However, since we address the heap with a 16-bit pointer, the
@@ -142,7 +142,7 @@ void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptP
assert(_bufSize >= script->size);
memcpy(_buf, script->data, script->size);
- if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
+ if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0);
assert(heap != 0);
@@ -171,7 +171,7 @@ void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptP
_localsOffset = localsBlock - _buf + 4;
_localsCount = (READ_LE_UINT16(_buf + _localsOffset - 2) - 4) >> 1; // half block size
}
- } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
+ } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
if (READ_LE_UINT16(_buf + 1 + 5) > 0) { // does the script have an export table?
_exportTable = (const uint16 *)(_buf + 1 + 5 + 2);
_numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1);
@@ -387,7 +387,7 @@ void Script::identifyOffsets() {
scriptDataLeft -= blockSize;
} while (1);
- } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
+ } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
// Strings in SCI1.1 up to SCI2 come after the object instances
scriptDataPtr = _heapStart;
scriptDataLeft = _heapSize;
@@ -668,7 +668,7 @@ static bool relocateBlock(Common::Array<reg_t> &block, int block_location, Segme
return false;
}
block[idx].setSegment(segment); // Perform relocation
- if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1)
+ if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE)
block[idx].incOffset(scriptSize);
return true;
@@ -702,7 +702,7 @@ void Script::relocateSci0Sci21(reg_t block) {
uint16 heapSize = (uint16)_bufSize;
uint16 heapOffset = 0;
- if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
+ if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
heap = _heapStart;
heapSize = (uint16)_heapSize;
heapOffset = _scriptSize;
@@ -930,7 +930,7 @@ void Script::initializeClasses(SegManager *segMan) {
if (getSciVersion() <= SCI_VERSION_1_LATE) {
seeker = findBlockSCI0(SCI_OBJ_CLASS);
mult = 1;
- } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
+ } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
seeker = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2;
mult = 2;
} else if (getSciVersion() == SCI_VERSION_3) {
@@ -962,7 +962,7 @@ void Script::initializeClasses(SegManager *segMan) {
if (isClass)
species = READ_SCI11ENDIAN_UINT16(seeker + 12);
classpos += 12;
- } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
+ } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
isClass = (READ_SCI11ENDIAN_UINT16(seeker + 14) & kInfoFlagClass); // -info- selector
species = READ_SCI11ENDIAN_UINT16(seeker + 10);
} else if (getSciVersion() == SCI_VERSION_3) {
@@ -1104,7 +1104,7 @@ void Script::initializeObjectsSci3(SegManager *segMan, SegmentId segmentId) {
void Script::initializeObjects(SegManager *segMan, SegmentId segmentId) {
if (getSciVersion() <= SCI_VERSION_1_LATE)
initializeObjectsSci0(segMan, segmentId);
- else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1)
+ else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE)
initializeObjectsSci11(segMan, segmentId);
else if (getSciVersion() == SCI_VERSION_3)
initializeObjectsSci3(segMan, segmentId);
diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp
index 188da3d5a2..8aa1697f07 100644
--- a/engines/sci/engine/static_selectors.cpp
+++ b/engines/sci/engine/static_selectors.cpp
@@ -114,16 +114,16 @@ static const SelectorRemap sciSelectorRemap[] = {
{ SCI_VERSION_1_1, SCI_VERSION_1_1, "cantBeHere", 54 },
// The following are not really needed. They've only been defined to
// ease game debugging.
- { SCI_VERSION_1_1, SCI_VERSION_2_1, "-objID-", 4096 },
- { SCI_VERSION_1_1, SCI_VERSION_2_1, "-size-", 4097 },
- { SCI_VERSION_1_1, SCI_VERSION_2_1, "-propDict-", 4098 },
- { SCI_VERSION_1_1, SCI_VERSION_2_1, "-methDict-", 4099 },
- { SCI_VERSION_1_1, SCI_VERSION_2_1, "-classScript-", 4100 },
- { SCI_VERSION_1_1, SCI_VERSION_2_1, "-script-", 4101 },
- { SCI_VERSION_1_1, SCI_VERSION_2_1, "-super-", 4102 },
+ { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-objID-", 4096 },
+ { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-size-", 4097 },
+ { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-propDict-", 4098 },
+ { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-methDict-", 4099 },
+ { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-classScript-", 4100 },
+ { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-script-", 4101 },
+ { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-super-", 4102 },
//
- { SCI_VERSION_1_1, SCI_VERSION_2_1, "-info-", 4103 },
- { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, 0 }
+ { SCI_VERSION_1_1, SCI_VERSION_2_1_LATE, "-info-", 4103 },
+ { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, 0 }
};
struct ClassReference {
diff --git a/engines/sci/engine/vm_types.cpp b/engines/sci/engine/vm_types.cpp
index 65a82832cc..cf008c45e1 100644
--- a/engines/sci/engine/vm_types.cpp
+++ b/engines/sci/engine/vm_types.cpp
@@ -29,7 +29,7 @@
namespace Sci {
SegmentId reg_t::getSegment() const {
- if (getSciVersion() <= SCI_VERSION_2_1) {
+ if (getSciVersion() < SCI_VERSION_3) {
return _segment;
} else {
// Return the lower 14 bits of the segment
@@ -38,7 +38,7 @@ SegmentId reg_t::getSegment() const {
}
void reg_t::setSegment(SegmentId segment) {
- if (getSciVersion() <= SCI_VERSION_2_1) {
+ if (getSciVersion() < SCI_VERSION_3) {
_segment = segment;
} else {
// Set the lower 14 bits of the segment, and preserve the upper 2 ones for the offset
@@ -47,7 +47,7 @@ void reg_t::setSegment(SegmentId segment) {
}
uint32 reg_t::getOffset() const {
- if (getSciVersion() <= SCI_VERSION_2_1) {
+ if (getSciVersion() < SCI_VERSION_3) {
return _offset;
} else {
// Return the lower 16 bits from the offset, and the 17th and 18th bits from the segment
@@ -56,7 +56,7 @@ uint32 reg_t::getOffset() const {
}
void reg_t::setOffset(uint32 offset) {
- if (getSciVersion() <= SCI_VERSION_2_1) {
+ if (getSciVersion() < SCI_VERSION_3) {
_offset = offset;
} else {
// Store the lower 16 bits in the offset, and the 17th and 18th bits in the segment
diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp
index 3c2285a470..716a366b7c 100644
--- a/engines/sci/graphics/compare.cpp
+++ b/engines/sci/graphics/compare.cpp
@@ -130,7 +130,7 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
#ifdef ENABLE_SCI32
if (view->isSci2Hires())
view->adjustToUpscaledCoordinates(y, x);
- else if (getSciVersion() == SCI_VERSION_2_1)
+ else if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE))
_coordAdjuster->fromScriptToDisplay(y, x);
#endif
@@ -140,7 +140,7 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
if (view->isSci2Hires()) {
view->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
view->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
- } else if (getSciVersion() == SCI_VERSION_2_1) {
+ } else if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE)) {
_coordAdjuster->fromDisplayToScript(celRect.top, celRect.left);
_coordAdjuster->fromDisplayToScript(celRect.bottom, celRect.right);
}
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index ccc362dc37..61aeb00ac3 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -23,7 +23,7 @@
#include "common/algorithm.h"
#include "common/events.h"
#include "common/keyboard.h"
-#include "common/list_intern.h"
+#include "common/list.h"
#include "common/str.h"
#include "common/system.h"
#include "common/textconsole.h"
@@ -727,7 +727,7 @@ void GfxFrameout::kernelFrameout() {
if (view && view->isSci2Hires()) {
view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
view->adjustToUpscaledCoordinates(itemEntry->z, dummyX);
- } else if (getSciVersion() >= SCI_VERSION_2_1) {
+ } else if (getSciVersion() >= SCI_VERSION_2_1_EARLY) {
_coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x);
_coordAdjuster->fromScriptToDisplay(itemEntry->z, dummyX);
}
@@ -782,7 +782,7 @@ void GfxFrameout::kernelFrameout() {
view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right);
g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
- } else if (getSciVersion() >= SCI_VERSION_2_1 && _resMan->detectHires()) {
+ } else if (getSciVersion() >= SCI_VERSION_2_1_EARLY && _resMan->detectHires()) {
_coordAdjuster->fromDisplayToScript(nsRect.top, nsRect.left);
_coordAdjuster->fromDisplayToScript(nsRect.bottom, nsRect.right);
g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp
index 89c9be59f0..b0f2c52791 100644
--- a/engines/sci/graphics/text16.cpp
+++ b/engines/sci/graphics/text16.cpp
@@ -83,8 +83,7 @@ void GfxText16::ClearChar(int16 chr) {
}
// This internal function gets called as soon as a '|' is found in a text. It
-// will process the encountered code and set new font/set color. We only support
-// one-digit codes currently, don't know if multi-digit codes are possible.
+// will process the encountered code and set new font/set color.
// Returns textcode character count.
int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int16 orgPenColor, bool doingDrawing) {
const char *textCode = text;
@@ -99,10 +98,8 @@ int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int1
// c -> sets textColor to current port pen color
// cX -> sets textColor to _textColors[X-1]
curCode = textCode[0];
- curCodeParm = textCode[1];
- if (Common::isDigit(curCodeParm)) {
- curCodeParm -= '0';
- } else {
+ curCodeParm = strtol(textCode+1, NULL, 10);
+ if (!Common::isDigit(textCode[1])) {
curCodeParm = -1;
}
switch (curCode) {
diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp
index da61ecf4c3..2ee18b5c9a 100644
--- a/engines/sci/graphics/view.cpp
+++ b/engines/sci/graphics/view.cpp
@@ -356,7 +356,7 @@ void GfxView::initData(GuiResourceId resourceId) {
for (loopNo = 0; loopNo < _loopCount; loopNo++)
for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++)
_screen->adjustBackUpscaledCoordinates(_loop[loopNo].cel[celNo].scriptWidth, _loop[loopNo].cel[celNo].scriptHeight, _sci2ScaleRes);
- } else if (getSciVersion() == SCI_VERSION_2_1) {
+ } else if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE)) {
for (loopNo = 0; loopNo < _loopCount; loopNo++)
for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++)
_coordAdjuster->fromDisplayToScript(_loop[loopNo].cel[celNo].scriptHeight, _loop[loopNo].cel[celNo].scriptWidth);
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 10740a8b7b..54ef4b3363 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -82,8 +82,12 @@ const char *getSciVersionDesc(SciVersion version) {
return "SCI1.1";
case SCI_VERSION_2:
return "SCI2";
- case SCI_VERSION_2_1:
- return "SCI2.1";
+ case SCI_VERSION_2_1_EARLY:
+ return "Early SCI2.1";
+ case SCI_VERSION_2_1_MIDDLE:
+ return "Middle SCI2.1";
+ case SCI_VERSION_2_1_LATE:
+ return "Late SCI2.1";
case SCI_VERSION_3:
return "SCI3";
default:
@@ -2121,6 +2125,79 @@ ViewType ResourceManager::detectViewType() {
return kViewUnknown;
}
+// to detect selector "wordFail" in LE vocab resource
+static const byte detectSci21EarlySignature[] = {
+ 10, // size of signature
+ 0x08, 0x00, 'w', 'o', 'r', 'd', 'F', 'a', 'i', 'l'
+};
+
+// to detect selector "wordFail" in BE vocab resource (SCI2.1 Early)
+static const byte detectSci21EarlyBESignature[] = {
+ 10, // size of signature
+ 0x00, 0x08, 'w', 'o', 'r', 'd', 'F', 'a', 'i', 'l'
+};
+
+// to detect new kString calling to detect SCI2.1 Late
+static const byte detectSci21NewStringSignature[] = {
+ 8, // size of signature
+ 0x78, // push1
+ 0x78, // push1
+ 0x39, 0x09, // pushi 09
+ 0x59, 0x01, // rest 01
+ 0x43, 0x5c, // callk String
+};
+
+bool ResourceManager::checkResourceDataForSignature(Resource *resource, const byte *signature) {
+ byte signatureSize = *signature;
+ const byte *resourceData = resource->data;
+
+ signature++; // skip over size byte
+ if (signatureSize < 4)
+ error("resource signature is too small, internal error");
+ if (signatureSize > resource->size)
+ return false;
+
+ const uint32 signatureDWord = *((const uint32 *)signature);
+ signature += 4; signatureSize -= 4;
+
+ const uint32 searchLimit = resource->size - signatureSize + 1;
+ uint32 DWordOffset = 0;
+ while (DWordOffset < searchLimit) {
+ if (signatureDWord == READ_UINT32(resourceData + DWordOffset)) {
+ // magic DWORD found, check if the rest matches as well
+ uint32 offset = DWordOffset + 4;
+ uint32 signaturePos = 0;
+ while (signaturePos < signatureSize) {
+ if (resourceData[offset] != signature[signaturePos])
+ break;
+ offset++;
+ signaturePos++;
+ }
+ if (signaturePos >= signatureSize)
+ return true; // signature found
+ }
+ DWordOffset++;
+ }
+ return false;
+}
+
+bool ResourceManager::checkResourceForSignatures(ResourceType resourceType, uint16 resourceNr, const byte *signature1, const byte *signature2) {
+ Resource *resource = findResource(ResourceId(resourceType, resourceNr), false);
+
+ if (resource) {
+ // resource found and loaded, check for signatures
+ if (signature1) {
+ if (checkResourceDataForSignature(resource, signature1))
+ return true;
+ }
+ if (signature2) {
+ if (checkResourceDataForSignature(resource, signature2))
+ return true;
+ }
+ }
+ return false;
+}
+
void ResourceManager::detectSciVersion() {
// We use the view compression to set a preliminary s_sciVersion for the sake of getResourceInfo
// Pretend we have a SCI0 game
@@ -2180,31 +2257,52 @@ void ResourceManager::detectSciVersion() {
// no Mac SCI2 games. Yes, that means that GK1 Mac is SCI2.1 and not SCI2.
// TODO: Decide between SCI2.1 and SCI3
- if (res)
- s_sciVersion = SCI_VERSION_2_1;
- else
+ if (res) {
+ s_sciVersion = SCI_VERSION_2_1_EARLY; // we check for SCI2.1 specifics a bit later
+ } else {
s_sciVersion = SCI_VERSION_1_1;
- return;
+ return;
+ }
}
// Handle SCI32 versions here
- if (_volVersion >= kResVersionSci2) {
- Common::List<ResourceId> heaps = listResources(kResourceTypeHeap);
- bool hasHeapResources = !heaps.empty();
-
- // SCI2.1/3 and SCI1 Late resource maps are the same, except that
- // SCI1 Late resource maps have the resource types or'd with
- // 0x80. We differentiate between SCI2 and SCI2.1/3 based on that.
- if (_mapVersion == kResVersionSci1Late) {
- s_sciVersion = SCI_VERSION_2;
- return;
- } else if (hasHeapResources) {
- s_sciVersion = SCI_VERSION_2_1;
+ if (s_sciVersion != SCI_VERSION_2_1_EARLY) {
+ if (_volVersion >= kResVersionSci2) {
+ Common::List<ResourceId> heaps = listResources(kResourceTypeHeap);
+ bool hasHeapResources = !heaps.empty();
+
+ // SCI2.1/3 and SCI1 Late resource maps are the same, except that
+ // SCI1 Late resource maps have the resource types or'd with
+ // 0x80. We differentiate between SCI2 and SCI2.1/3 based on that.
+ if (_mapVersion == kResVersionSci1Late) {
+ s_sciVersion = SCI_VERSION_2;
+ return;
+ } else if (hasHeapResources) {
+ s_sciVersion = SCI_VERSION_2_1_EARLY; // exact SCI2.1 version is checked a bit later
+ } else {
+ s_sciVersion = SCI_VERSION_3;
+ return;
+ }
+ }
+ }
+
+ if (s_sciVersion == SCI_VERSION_2_1_EARLY) {
+ // we only know that it's SCI2.1, not which exact version it is
+
+ // check, if selector "wordFail" inside vocab 997 exists, if it does it's SCI2.1 Early
+ if ((checkResourceForSignatures(kResourceTypeVocab, 997, detectSci21EarlySignature, detectSci21EarlyBESignature))) {
+ // found -> it is SCI2.1 early
return;
- } else {
- s_sciVersion = SCI_VERSION_3;
+ }
+
+ s_sciVersion = SCI_VERSION_2_1_MIDDLE;
+ if (checkResourceForSignatures(kResourceTypeScript, 64918, detectSci21NewStringSignature, nullptr)) {
+ // new kString call detected, it's SCI2.1 late
+ // TODO: this call seems to be different on Mac
+ s_sciVersion = SCI_VERSION_2_1_LATE;
return;
}
+ return;
}
// Check for transitive SCI1/SCI1.1 games, like PQ1 here
@@ -2537,7 +2635,7 @@ reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) {
int16 offset = !isSci11Mac() ? READ_LE_UINT16(offsetPtr) : READ_BE_UINT16(offsetPtr);
return make_reg(1, offset);
- } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
+ } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
offsetPtr = script->data + 4 + 2 + 2;
// In SCI1.1 - SCI2.1, the heap is appended at the end of the script,
@@ -2565,7 +2663,7 @@ Common::String ResourceManager::findSierraGameId() {
if (getSciVersion() < SCI_VERSION_1_1) {
heap = findResource(ResourceId(kResourceTypeScript, 0), false);
- } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
+ } else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
heap = findResource(ResourceId(kResourceTypeHeap, 0), false);
nameSelector += 5;
} else if (getSciVersion() == SCI_VERSION_3) {
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index ef48998b04..eb5b508254 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -559,6 +559,8 @@ protected:
ViewType detectViewType();
bool hasSci0Voc999();
bool hasSci1Voc900();
+ bool checkResourceDataForSignature(Resource *resource, const byte *signature);
+ bool checkResourceForSignatures(ResourceType resourceType, uint16 resourceNr, const byte *signature1, const byte *signature2);
void detectSciVersion();
};
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index 3a43774492..6869e6379e 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -637,7 +637,7 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
case SCI_VERSION_1_EARLY:
case SCI_VERSION_1_LATE:
- case SCI_VERSION_2_1:
+ case SCI_VERSION_2_1_EARLY:
data = resource->data;
// Count # of tracks
_trackCount = 0;
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 668ad053cc..f1ab65ef98 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -194,12 +194,6 @@ SciEngine::~SciEngine() {
extern void showScummVMDialog(const Common::String &message);
Common::Error SciEngine::run() {
- // Assign default values to the config manager, in case settings are missing
- ConfMan.registerDefault("originalsaveload", "false");
- ConfMan.registerDefault("native_fb01", "false");
- ConfMan.registerDefault("windows_cursors", "false"); // Windows cursors for KQ6 Windows
- ConfMan.registerDefault("silver_cursors", "false"); // Silver cursors for SQ4 CD
-
_resMan = new ResourceManager();
assert(_resMan);
_resMan->addAppropriateSources();
@@ -892,29 +886,79 @@ bool SciEngine::speechAndSubtitlesEnabled() {
}
void SciEngine::syncIngameAudioOptions() {
- // Sync the in-game speech/subtitles settings for SCI1.1 CD games
- if (isCD() && getSciVersion() == SCI_VERSION_1_1) {
- bool subtitlesOn = ConfMan.getBool("subtitles");
- bool speechOn = !ConfMan.getBool("speech_mute");
+ bool useGlobal90 = false;
- if (subtitlesOn && !speechOn) {
- _gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 1); // subtitles
- } else if (!subtitlesOn && speechOn) {
- _gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 2); // speech
- } else if (subtitlesOn && speechOn) {
- // Is it a game that supports simultaneous speech and subtitles?
+ // Sync the in-game speech/subtitles settings for SCI1.1 CD games
+ if (isCD()) {
+ switch (getSciVersion()) {
+ case SCI_VERSION_1_1:
+ // All SCI1.1 CD games use global 90
+ useGlobal90 = true;
+ break;
+#ifdef ENABLE_SCI32
+ case SCI_VERSION_2:
+ case SCI_VERSION_2_1_EARLY:
+ case SCI_VERSION_2_1_MIDDLE:
+ case SCI_VERSION_2_1_LATE:
+ // Only use global 90 for some specific games, not all SCI32 games used this method
switch (_gameId) {
- case GID_SQ4:
- case GID_FREDDYPHARKAS:
- case GID_ECOQUEST:
- case GID_LSL6:
- case GID_LAURABOW2:
- case GID_KQ6:
- _gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 3); // speech + subtitles
+ case GID_KQ7: // SCI2.1
+ case GID_GK1: // SCI2
+ case GID_GK2: // SCI2.1
+ case GID_SQ6: // SCI2.1
+ case GID_TORIN: // SCI2.1
+ case GID_QFG4: // SCI2.1
+ useGlobal90 = true;
break;
+ case GID_LSL6: // SCI2.1
+ // TODO: Uses gameFlags array
+ break;
+ // TODO: Unknown at the moment:
+ // Shivers - seems not to use global 90
+ // Police Quest: SWAT - unable to check
+ // Police Quest 4 - unable to check
+ // Mixed Up Mother Goose - unable to check
+ // Phantasmagoria - seems to use global 90, unable to check for subtitles atm
default:
- // Game does not support speech and subtitles, set it to speech
+ return;
+ }
+ break;
+#endif // ENABLE_SCI32
+ default:
+ return;
+ }
+
+ bool subtitlesOn = ConfMan.getBool("subtitles");
+ bool speechOn = !ConfMan.getBool("speech_mute");
+
+ if (useGlobal90) {
+ if (subtitlesOn && !speechOn) {
+ _gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 1); // subtitles
+ } else if (!subtitlesOn && speechOn) {
_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 2); // speech
+ } else if (subtitlesOn && speechOn) {
+ // Is it a game that supports simultaneous speech and subtitles?
+ switch (_gameId) {
+ case GID_SQ4:
+ case GID_FREDDYPHARKAS:
+ case GID_ECOQUEST:
+ case GID_LSL6:
+ case GID_LAURABOW2:
+ case GID_KQ6:
+#ifdef ENABLE_SCI32
+ // Unsure about Gabriel Knight 2
+ case GID_KQ7: // SCI2.1
+ case GID_GK1: // SCI2
+ case GID_SQ6: // SCI2.1, SQ6 seems to always use subtitles anyway
+ case GID_TORIN: // SCI2.1
+ case GID_QFG4: // SCI2.1
+#endif // ENABLE_SCI32
+ _gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 3); // speech + subtitles
+ break;
+ default:
+ // Game does not support speech and subtitles, set it to speech
+ _gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 2); // speech
+ }
}
}
}
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index c6813aa07c..15034d5e94 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -200,7 +200,9 @@ enum SciVersion {
SCI_VERSION_1_LATE, // Dr. Brain 1, EcoQuest 1, Longbow, PQ3, SQ1, LSL5, KQ5 CD
SCI_VERSION_1_1, // Dr. Brain 2, EcoQuest 1 CD, EcoQuest 2, KQ6, QFG3, SQ4CD, XMAS 1992 and many more
SCI_VERSION_2, // GK1, PQ4 floppy, QFG4 floppy
- SCI_VERSION_2_1, // GK2, KQ7, LSL6 hires, MUMG Deluxe, Phantasmagoria 1, PQ4CD, PQ:SWAT, QFG4CD, Shivers 1, SQ6, Torin
+ SCI_VERSION_2_1_EARLY, // GK2 demo, KQ7, LSL6 hires, PQ4, QFG4 floppy
+ SCI_VERSION_2_1_MIDDLE, // GK2, KQ7, MUMG Deluxe, Phantasmagoria 1, PQ4CD, PQ:SWAT, QFG4CD, Shivers 1, SQ6, Torin
+ SCI_VERSION_2_1_LATE, // demos of LSL7, Lighthouse, RAMA
SCI_VERSION_3 // LSL7, Lighthouse, RAMA, Phantasmagoria 2
};
diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp
index fb9a3f17b9..57f0415285 100644
--- a/engines/sci/sound/audio.cpp
+++ b/engines/sci/sound/audio.cpp
@@ -79,15 +79,23 @@ void AudioPlayer::handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan
Common::String command = segMan->getString(commandReg);
if (command == "play" || command == "playx") {
-#ifdef USE_MAD
reg_t fileNameReg = readSelector(segMan, sciAudioObject, kernel->findSelector("fileName"));
Common::String fileName = segMan->getString(fileNameReg);
- int16 loopCount = (int16)readSelectorValue(segMan, sciAudioObject, kernel->findSelector("loopCount"));
- // When loopCount is -1, we treat it as infinite looping, else no looping is done.
- // This is observed by game scripts, which can set loopCount to all sorts of random values.
+ reg_t loopCountReg = readSelector(segMan, sciAudioObject, kernel->findSelector("loopCount"));
+ Common::String loopCountStr = segMan->getString(loopCountReg);
+ int16 loopCount = atoi(loopCountStr.c_str());
+
// Adjust loopCount for ScummVM's LoopingAudioStream semantics
- loopCount = (loopCount == -1) ? 0 : 1;
+ if (loopCount == -1) {
+ loopCount = 0; // loop endlessly
+ } else if (loopCount >= 0) {
+ // sciAudio loopCount == 0 -> play 1 time -> ScummVM's loopCount should be 1
+ // sciAudio loopCount == 1 -> play 2 times -> ScummVM's loopCount should be 2
+ loopCount++;
+ } else {
+ loopCount = 1; // play once in case the value makes no sense
+ }
// Determine sound type
Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType;
@@ -96,20 +104,51 @@ void AudioPlayer::handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan
else if (fileName.hasPrefix("speech"))
soundType = Audio::Mixer::kSpeechSoundType;
- Common::File *sciAudio = new Common::File();
+ // Determine compression
+ uint32 audioCompressionType = 0;
+ if ((fileName.hasSuffix(".mp3")) || (fileName.hasSuffix(".sciAudio")) || (fileName.hasSuffix(".sciaudio"))) {
+ audioCompressionType = MKTAG('M','P','3',' ');
+ } else if (fileName.hasSuffix(".wav")) {
+ audioCompressionType = MKTAG('W','A','V',' ');
+ } else if (fileName.hasSuffix(".aiff")) {
+ audioCompressionType = MKTAG('A','I','F','F');
+ } else {
+ error("sciAudio: unsupported file type");
+ }
+
+ Common::File *sciAudioFile = new Common::File();
// Replace backwards slashes
for (uint i = 0; i < fileName.size(); i++) {
if (fileName[i] == '\\')
fileName.setChar('/', i);
}
- sciAudio->open("sciAudio/" + fileName);
+ sciAudioFile->open("sciAudio/" + fileName);
+
+ Audio::RewindableAudioStream *audioStream = nullptr;
+
+ switch (audioCompressionType) {
+ case MKTAG('M','P','3',' '):
+#ifdef USE_MAD
+ audioStream = Audio::makeMP3Stream(sciAudioFile, DisposeAfterUse::YES);
+#endif
+ break;
+ case MKTAG('W','A','V',' '):
+ audioStream = Audio::makeWAVStream(sciAudioFile, DisposeAfterUse::YES);
+ break;
+ case MKTAG('A','I','F','F'):
+ audioStream = Audio::makeAIFFStream(sciAudioFile, DisposeAfterUse::YES);
+ break;
+ default:
+ break;
+ }
- Audio::SeekableAudioStream *audioStream = Audio::makeMP3Stream(sciAudio, DisposeAfterUse::YES);
+ if (!audioStream) {
+ error("sciAudio: requested compression not compiled into ScummVM");
+ }
// We only support one audio handle
_mixer->playStream(soundType, &_audioHandle,
Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audioStream, loopCount));
-#endif
} else if (command == "stop") {
_mixer->stopHandle(_audioHandle);
} else {
@@ -217,7 +256,7 @@ static void deDPCM8Nibble(byte *soundBuf, int32 &s, byte b) {
if (b & 8) {
#ifdef ENABLE_SCI32
// SCI2.1 reverses the order of the table values here
- if (getSciVersion() >= SCI_VERSION_2_1)
+ if (getSciVersion() >= SCI_VERSION_2_1_EARLY)
s -= tableDPCM8[b & 7];
else
#endif
diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp
index baf85de74c..aa464cdc19 100644
--- a/engines/sci/sound/drivers/midi.cpp
+++ b/engines/sci/sound/drivers/midi.cpp
@@ -1019,7 +1019,7 @@ int MidiPlayer_Midi::open(ResourceManager *resMan) {
if (!isMt32GmPatch(res->data, res->size)) {
mapMt32ToGm(res->data, res->size);
} else {
- if (getSciVersion() <= SCI_VERSION_2_1) {
+ if (getSciVersion() < SCI_VERSION_3) {
error("MT-32 patch has wrong type");
} else {
// Happens in the SCI3 interactive demo of Lighthouse
diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp
index 9f0d8d150f..21f95f17e0 100644
--- a/engines/sci/sound/midiparser_sci.cpp
+++ b/engines/sci/sound/midiparser_sci.cpp
@@ -717,7 +717,7 @@ bool MidiParser_SCI::processEvent(const EventInfo &info, bool fireEvents) {
break;
case SCI_VERSION_1_EARLY:
case SCI_VERSION_1_LATE:
- case SCI_VERSION_2_1:
+ case SCI_VERSION_2_1_EARLY:
inc = 1;
break;
default:
@@ -862,7 +862,7 @@ void MidiParser_SCI::setMasterVolume(byte masterVolume) {
case SCI_VERSION_1_EARLY:
case SCI_VERSION_1_LATE:
- case SCI_VERSION_2_1:
+ case SCI_VERSION_2_1_EARLY:
// directly set master volume (global volume is merged with channel volumes)
((MidiPlayer *)_driver)->setVolume(masterVolume);
break;
@@ -887,7 +887,7 @@ void MidiParser_SCI::setVolume(byte volume) {
case SCI_VERSION_1_EARLY:
case SCI_VERSION_1_LATE:
- case SCI_VERSION_2_1:
+ case SCI_VERSION_2_1_EARLY:
// Send previous channel volumes again to actually update the volume
for (int i = 0; i < 15; i++)
if (_channelRemap[i] != -1)
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index dca73c3f51..31cf27f7e0 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -73,7 +73,7 @@ void SciMusic::init() {
// Default to MIDI in SCI2.1+ games, as many don't have AdLib support.
// Also, default to MIDI for Windows versions of SCI1.1 games, as their
// soundtrack is written for GM.
- if (getSciVersion() >= SCI_VERSION_2_1 || g_sci->_features->useAltWinGMSound())
+ if (getSciVersion() >= SCI_VERSION_2_1_EARLY || g_sci->_features->useAltWinGMSound())
deviceFlags |= MDT_PREFER_GM;
// Currently our CMS implementation only supports SCI1(.1)
diff --git a/engines/sci/util.cpp b/engines/sci/util.cpp
index 3a9ed9ca69..c72d3beb19 100644
--- a/engines/sci/util.cpp
+++ b/engines/sci/util.cpp
@@ -49,7 +49,7 @@ uint16 READ_SCI11ENDIAN_UINT16(const void *ptr) {
}
uint16 READ_SCI32ENDIAN_UINT16(const void *ptr) {
- if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2_1)
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2_1_EARLY)
return READ_BE_UINT16(ptr);
else
return READ_LE_UINT16(ptr);