diff options
Diffstat (limited to 'engines/sci/engine')
-rw-r--r-- | engines/sci/engine/features.h | 11 | ||||
-rw-r--r-- | engines/sci/engine/kernel.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/kernel_tables.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/kstring.cpp | 12 | ||||
-rw-r--r-- | engines/sci/engine/kvideo.cpp | 5 | ||||
-rw-r--r-- | engines/sci/engine/message.cpp | 12 | ||||
-rw-r--r-- | engines/sci/engine/message.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 25 | ||||
-rw-r--r-- | engines/sci/engine/script_patches.cpp | 19 | ||||
-rw-r--r-- | engines/sci/engine/segment.h | 13 | ||||
-rw-r--r-- | engines/sci/engine/workarounds.cpp | 16 | ||||
-rw-r--r-- | engines/sci/engine/workarounds.h | 1 |
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[]; |