aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/features.h11
-rw-r--r--engines/sci/engine/kernel.h1
-rw-r--r--engines/sci/engine/kernel_tables.h1
-rw-r--r--engines/sci/engine/kstring.cpp12
-rw-r--r--engines/sci/engine/kvideo.cpp5
-rw-r--r--engines/sci/engine/message.cpp12
-rw-r--r--engines/sci/engine/message.h2
-rw-r--r--engines/sci/engine/savegame.cpp25
-rw-r--r--engines/sci/engine/script_patches.cpp19
-rw-r--r--engines/sci/engine/segment.h13
-rw-r--r--engines/sci/engine/workarounds.cpp16
-rw-r--r--engines/sci/engine/workarounds.h1
12 files changed, 84 insertions, 34 deletions
diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h
index 15c80a7277..36b0d06360 100644
--- a/engines/sci/engine/features.h
+++ b/engines/sci/engine/features.h
@@ -117,6 +117,17 @@ public:
inline bool hasNewPaletteCode() const {
return getSciVersion() >= SCI_VERSION_2_1_MIDDLE || g_sci->getGameId() == GID_KQ7;
}
+
+ inline bool VMDOpenStopsAudio() const {
+ // Of the games that use VMDs:
+ // Yes: Phant1, Shivers, Torin
+ // No: SQ6
+ // TODO: Optional extra flag to kPlayVMD which defaults to Yes: PQ:SWAT
+ // TODO: SCI3, GK2 (GK2's VMD code is closer to SCI3 than SCI21)
+ return getSciVersion() == SCI_VERSION_2_1_MIDDLE &&
+ g_sci->getGameId() != GID_SQ6 &&
+ g_sci->getGameId() != GID_GK2;
+ }
#endif
/**
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index cce9a223d3..03c8a673a8 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -466,6 +466,7 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv);
reg_t kPlayVMDOpen(EngineState *s, int argc, reg_t *argv);
reg_t kPlayVMDInit(EngineState *s, int argc, reg_t *argv);
reg_t kPlayVMDClose(EngineState *s, int argc, reg_t *argv);
+reg_t kPlayVMDIgnorePalettes(EngineState *s, int argc, reg_t *argv);
reg_t kPlayVMDGetStatus(EngineState *s, int argc, reg_t *argv);
reg_t kPlayVMDPlayUntilEvent(EngineState *s, int argc, reg_t *argv);
reg_t kPlayVMDShowCursor(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index 6e88112992..8093147cb4 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -466,6 +466,7 @@ static const SciKernelMapSubEntry kPlayVMD_subops[] = {
{ SIG_SINCE_SCI21, 0, MAP_CALL(PlayVMDOpen), "r(i)(i)", NULL },
{ SIG_SINCE_SCI21, 1, MAP_CALL(PlayVMDInit), "ii(i)(i)(ii)", NULL },
{ SIG_SINCE_SCI21, 6, MAP_CALL(PlayVMDClose), "", NULL },
+ { SIG_SINCE_SCI21, 7, MAP_CALL(PlayVMDIgnorePalettes), "", NULL },
{ SIG_SINCE_SCI21, 10, MAP_CALL(PlayVMDGetStatus), "", NULL },
{ SIG_SINCE_SCI21, 14, MAP_CALL(PlayVMDPlayUntilEvent), "i(i)(i)", NULL },
{ SIG_SINCE_SCI21, 16, MAP_CALL(PlayVMDShowCursor), "i", NULL },
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 6ec61343b0..74c1f99778 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -733,11 +733,12 @@ namespace {
}
bool isSignedType(const char type) {
- return type == 'd' || type == 'i';
+ // For whatever reason, %d ends up being treated as unsigned in SSCI
+ return type == 'i';
}
bool isUnsignedType(const char type) {
- return strchr("uxXoc", type);
+ return strchr("duxXoc", type);
}
bool isStringType(const char type) {
@@ -805,8 +806,11 @@ Common::String format(const Common::String &source, int argc, const reg_t *argv)
continue;
}
- assert(argIndex < argc);
- out += readPlaceholder(in, argv[argIndex++]);
+ if (argIndex < argc) {
+ out += readPlaceholder(in, argv[argIndex++]);
+ } else {
+ out += readPlaceholder(in, NULL_REG);
+ }
} else {
out += *in++;
}
diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
index 83a02883af..11378d7647 100644
--- a/engines/sci/engine/kvideo.cpp
+++ b/engines/sci/engine/kvideo.cpp
@@ -428,6 +428,11 @@ reg_t kPlayVMDClose(EngineState *s, int argc, reg_t *argv) {
return make_reg(0, g_sci->_video32->getVMDPlayer().close());
}
+reg_t kPlayVMDIgnorePalettes(EngineState *s, int argc, reg_t *argv) {
+ g_sci->_video32->getVMDPlayer().ignorePalettes();
+ return s->r_acc;
+}
+
reg_t kPlayVMDGetStatus(EngineState *s, int argc, reg_t *argv) {
return make_reg(0, g_sci->_video32->getVMDPlayer().getStatus());
}
diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp
index b0615b4213..26ab9b47a5 100644
--- a/engines/sci/engine/message.cpp
+++ b/engines/sci/engine/message.cpp
@@ -333,12 +333,14 @@ void MessageState::popCursorStack() {
error("Message: attempt to pop from empty stack");
}
-int MessageState::hexDigitToInt(char h) {
+int MessageState::hexDigitToWrongInt(char h) {
+ // Hex digits above 9 are incorrectly interpreted by SSCI as 11-16 instead
+ // of 10-15 because of a never-fixed typo
if ((h >= 'A') && (h <= 'F'))
- return h - 'A' + 10;
+ return h - 'A' + 11;
if ((h >= 'a') && (h <= 'f'))
- return h - 'a' + 10;
+ return h - 'a' + 11;
if ((h >= '0') && (h <= '9'))
return h - '0';
@@ -355,8 +357,8 @@ bool MessageState::stringHex(Common::String &outStr, const Common::String &inStr
if (index + 2 >= inStr.size())
return false;
- int digit1 = hexDigitToInt(inStr[index + 1]);
- int digit2 = hexDigitToInt(inStr[index + 2]);
+ int digit1 = hexDigitToWrongInt(inStr[index + 1]);
+ int digit2 = hexDigitToWrongInt(inStr[index + 2]);
// Check for hex
if ((digit1 == -1) || (digit2 == -1))
diff --git a/engines/sci/engine/message.h b/engines/sci/engine/message.h
index ff76534d2d..5847e4767e 100644
--- a/engines/sci/engine/message.h
+++ b/engines/sci/engine/message.h
@@ -73,7 +73,7 @@ private:
bool getRecord(CursorStack &stack, bool recurse, MessageRecord &record);
void outputString(reg_t buf, const Common::String &str);
Common::String processString(const char *s);
- int hexDigitToInt(char h);
+ int hexDigitToWrongInt(char h);
bool stringHex(Common::String &outStr, const Common::String &inStr, uint &index);
bool stringLit(Common::String &outStr, const Common::String &inStr, uint &index);
bool stringStage(Common::String &outStr, const Common::String &inStr, uint &index);
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 2e4da46b70..720f6783ee 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -643,20 +643,33 @@ void SoundCommandParser::reconstructPlayList() {
_music->_mutex.unlock();
for (MusicList::iterator i = songs.begin(); i != songs.end(); ++i) {
- initSoundResource(*i);
+ MusicEntry *entry = *i;
+ initSoundResource(entry);
- if ((*i)->status == kSoundPlaying) {
+#ifdef ENABLE_SCI32
+ if (_soundVersion >= SCI_VERSION_2_1_EARLY && entry->isSample) {
+ const reg_t &soundObj = entry->soundObj;
+
+ if ((int)readSelectorValue(_segMan, soundObj, SELECTOR(loop)) != -1 &&
+ readSelector(_segMan, soundObj, SELECTOR(handle)) != NULL_REG) {
+
+ writeSelector(_segMan, soundObj, SELECTOR(handle), NULL_REG);
+ processPlaySound(soundObj, entry->playBed);
+ }
+ } else
+#endif
+ if (entry->status == kSoundPlaying) {
// WORKAROUND: PQ3 (German?) scripts can set volume negative in the
// sound object directly without going through DoSound.
// Since we re-read this selector when re-playing the sound after loading,
// this will lead to unexpected behaviour. As a workaround we
// sync the sound object's selectors here. (See bug #5501)
- writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(loop), (*i)->loop);
- writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(priority), (*i)->priority);
+ writeSelectorValue(_segMan, entry->soundObj, SELECTOR(loop), entry->loop);
+ writeSelectorValue(_segMan, entry->soundObj, SELECTOR(priority), entry->priority);
if (_soundVersion >= SCI_VERSION_1_EARLY)
- writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(vol), (*i)->volume);
+ writeSelectorValue(_segMan, entry->soundObj, SELECTOR(vol), entry->volume);
- processPlaySound((*i)->soundObj, (*i)->playBed);
+ processPlaySound(entry->soundObj, entry->playBed);
}
}
}
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 5ac4b758ba..5f3370bad5 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -2190,8 +2190,27 @@ static const SciScriptPatcherEntry larry6Signatures[] = {
#pragma mark -
#pragma mark Leisure Suit Larry 6 Hires
+// When entering room 270 (diving board) from room 230, a typo in the game
+// script means that `setScale` is called accidentally instead of `setScaler`.
+// In SSCI this did not do much because the first argument happened to be
+// smaller than the y-position of `ego`, but in ScummVM the first argument is
+// larger and so a debug message "y value less than vanishingY" is displayed.
+static const uint16 larry6HiresSignatureSetScale[] = {
+ SIG_MAGICDWORD,
+ 0x38, SIG_UINT16(0x14b), // pushi 014b (setScale)
+ 0x38, SIG_UINT16(0x05), // pushi 0005
+ 0x51, 0x2c, // class 2c (Scaler)
+ SIG_END
+};
+
+static const uint16 larry6HiresPatchSetScale[] = {
+ 0x38, SIG_UINT16(0x14f), // pushi 014f (setScaler)
+ PATCH_END
+};
+
// script, description, signature patch
static const SciScriptPatcherEntry larry6HiresSignatures[] = {
+ { true, 270, "fix incorrect setScale call", 1, larry6HiresSignatureSetScale, larry6HiresPatchSetScale },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature1, sci2NumSavesPatch1 },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature2, sci2NumSavesPatch2 },
{ true, 64990, "disable change directory button", 1, sci2ChangeDirSignature, sci2ChangeDirPatch },
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index 361c1cb895..e8f0be3a79 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -552,8 +552,17 @@ public:
case kArrayTypeID:
return ((reg_t *)_data)[index];
case kArrayTypeByte:
- case kArrayTypeString:
- return make_reg(0, ((byte *)_data)[index]);
+ case kArrayTypeString: {
+ int16 value;
+
+ if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
+ value = ((int8 *)_data)[index];
+ } else {
+ value = ((uint8 *)_data)[index];
+ }
+
+ return make_reg(0, value);
+ }
default:
error("Invalid array type %d", _type);
}
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index dabf79a54b..4e9c59b225 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -399,6 +399,7 @@ const SciWorkaroundEntry kAbs_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround
const SciWorkaroundEntry kArraySetElements_workarounds[] = {
+ { GID_GK1, 302, 64918, 0, "Str", "callKernel", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when erasing a letter on the wall in St Louis Cemetery
{ GID_PHANTASMAGORIA,902, 64918, 0, "Str", "callKernel", NULL, 0, { WORKAROUND_FAKE, 0 } }, // tries to set an element of a string array to the ego object when starting a new game and selecting a chapter above 1
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -684,21 +685,6 @@ const SciWorkaroundEntry kNewWindow_workarounds[] = {
};
// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround
-const SciWorkaroundEntry kNumCels_workarounds[] = {
- { GID_GK1, 460, 64998, -1, "GKEgo", "lastCel", NULL, -1, { WORKAROUND_FAKE, 5 } }, // when Gabriel clicks "ask" on the bartender from a distance
- { GID_GK1, 808, 64998, -1, "sDJEnters", "changeState", NULL, -1, { WORKAROUND_FAKE, 6 } }, //
- { GID_GK2, 470, 64998, -1, "pLookieLoos", "lastCel", NULL, -1, { WORKAROUND_FAKE, 50 } }, // random background movement in the crime scene in Munich city centre
- { GID_GK2, 470, 64998, -1, "pNewsCrew", "lastCel", NULL, -1, { WORKAROUND_FAKE, 18 } }, // random background movement in the crime scene in Munich city centre
- { GID_GK2, 470, 64998, -1, "pLeberGroup", "lastCel", NULL, -1, { WORKAROUND_FAKE, 22 } }, // random background movement in the crime scene in Munich city centre
- { GID_SQ6, 270, 64998, -1, "offWorld", "lastCel", NULL, -1, { WORKAROUND_FAKE, 3 } }, // when exiting the kidnapping room
- { GID_SQ6, 320, 64998, -1, "wandererB", "lastCel", NULL, -1, { WORKAROUND_FAKE, 8 } }, // random background movement on Polysorbate LX street 3
- { GID_SQ6, 340, 64998, -1, "wandererB", "lastCel", NULL, -1, { WORKAROUND_FAKE, 8 } }, // random background movement on Polysorbate LX street 1
- { GID_SQ6, 530, 64998, -1, "monitors", "lastCel", NULL, -1, { WORKAROUND_FAKE, 5 } }, // random background movement during cutscene
- { GID_SQ6, 680, 64998, -1, "ego", "lastCel", NULL, -1, { WORKAROUND_FAKE, 44 } }, // when double-clicking hand icon on blockage
- SCI_WORKAROUNDENTRY_TERMINATOR
-};
-
-// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround
const SciWorkaroundEntry kPalVarySetPercent_workarounds[] = {
{ GID_GK1, 370, 370, 0, "graceComeOut", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // there's an extra parameter in GK1, when changing chapters. This extra parameter seems to be a bug or just unimplemented functionality, as there's no visible change from the original in the chapter change room
SCI_WORKAROUNDENTRY_TERMINATOR
diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h
index c50a7fb04e..2d72ae5811 100644
--- a/engines/sci/engine/workarounds.h
+++ b/engines/sci/engine/workarounds.h
@@ -85,7 +85,6 @@ extern const SciWorkaroundEntry kIsObject_workarounds[];
extern const SciWorkaroundEntry kMemory_workarounds[];
extern const SciWorkaroundEntry kMoveCursor_workarounds[];
extern const SciWorkaroundEntry kNewWindow_workarounds[];
-extern const SciWorkaroundEntry kNumCels_workarounds[];
extern const SciWorkaroundEntry kPalVarySetPercent_workarounds[];
extern const SciWorkaroundEntry kRandom_workarounds[];
extern const SciWorkaroundEntry kReadNumber_workarounds[];