[Scummvm-git-logs] scummvm master -> f6dd4fa234478978da080bce17f7a5682ff09763
sluicebox
22204938+sluicebox at users.noreply.github.com
Thu Apr 29 16:30:24 UTC 2021
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
f6dd4fa234 SCI: Add option to use KQ5 CD Windows cursors
Commit: f6dd4fa234478978da080bce17f7a5682ff09763
https://github.com/scummvm/scummvm/commit/f6dd4fa234478978da080bce17f7a5682ff09763
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2021-04-29T09:27:13-07:00
Commit Message:
SCI: Add option to use KQ5 CD Windows cursors
Ticket #7800
Changed paths:
engines/sci/detection.cpp
engines/sci/detection.h
engines/sci/detection_tables.h
engines/sci/engine/features.cpp
engines/sci/engine/features.h
engines/sci/engine/savegame.cpp
engines/sci/engine/script_patches.cpp
engines/sci/engine/seg_manager.cpp
engines/sci/engine/seg_manager.h
engines/sci/engine/state.cpp
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 0de4fb193a..69b567634b 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -219,9 +219,9 @@ static const ADExtraGuiOptionsMap optionsList[] = {
}
},
- // KQ6 Windows - windows cursors
+ // KQ5 and KQ6 CD Windows - windows cursors
{
- GAMEOPTION_KQ6_WINDOWS_CURSORS,
+ GAMEOPTION_KQ_WINDOWS_CURSORS,
{
_s("Use Windows cursors"),
_s("Use the Windows cursors (smaller and monochrome) instead of the DOS ones"),
diff --git a/engines/sci/detection.h b/engines/sci/detection.h
index 806e821def..6126961b57 100644
--- a/engines/sci/detection.h
+++ b/engines/sci/detection.h
@@ -30,7 +30,7 @@ namespace Sci {
#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS2
#define GAMEOPTION_MIDI_MODE GUIO_GAMEOPTIONS3
#define GAMEOPTION_JONES_CDAUDIO GUIO_GAMEOPTIONS4
-#define GAMEOPTION_KQ6_WINDOWS_CURSORS GUIO_GAMEOPTIONS5
+#define GAMEOPTION_KQ_WINDOWS_CURSORS GUIO_GAMEOPTIONS5
#define GAMEOPTION_SQ4_SILVER_CURSORS GUIO_GAMEOPTIONS6
#define GAMEOPTION_EGA_UNDITHER GUIO_GAMEOPTIONS7
// HIGH_RESOLUTION_GRAPHICS availability is checked for in SciEngine::run()
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 12bce38c9f..0fb2014a50 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -1632,6 +1632,13 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO_STD16_UNDITHER },
+#define GUIO_KQ5_CD_WINDOWS GUIO6(GUIO_MIDIGM, \
+ GAMEOPTION_PREFER_DIGITAL_SFX, \
+ GAMEOPTION_ORIGINAL_SAVELOAD, \
+ GAMEOPTION_MIDI_MODE, \
+ GAMEOPTION_RGB_RENDERING, \
+ GAMEOPTION_KQ_WINDOWS_CURSORS)
+
// King's Quest 5 - English Amiga (from www.back2roots.org)
// Executable scanning reports "1.004.018"
// SCI interpreter version 1.000.060
@@ -1700,7 +1707,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "449471bfd77be52f18a3773c7f7d843d", 571368},
{"resource.001", 0, "b45a581ff8751e052c7e364f58d3617f", 16800210},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO_STD16_SPEECH_GM },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO_KQ5_CD_WINDOWS },
// King's Quest 5 - English DOS Floppy
// SCI interpreter version 1.000.060
@@ -1969,6 +1976,8 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO_STD16 },
+#undef GUIO_KQ5_CD_WINDOWS
+
#define GUIO_KQ6_DEMO GUIO6(GUIO_NOSPEECH, \
GAMEOPTION_HIGH_RESOLUTION_GRAPHICS, \
GAMEOPTION_PREFER_DIGITAL_SFX, \
@@ -1983,7 +1992,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
GAMEOPTION_RGB_RENDERING)
#define GUIO_KQ6_CD_WINDOWS GUIO7(GUIO_NOASPECT, \
- GAMEOPTION_KQ6_WINDOWS_CURSORS, \
+ GAMEOPTION_KQ_WINDOWS_CURSORS, \
GAMEOPTION_HIGH_RESOLUTION_GRAPHICS, \
GAMEOPTION_PREFER_DIGITAL_SFX, \
GAMEOPTION_ORIGINAL_SAVELOAD, \
@@ -2108,7 +2117,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "233394a5f33b475ae5975e7e9a420865", 8376352},
{"resource.msg", 0, "51ca9f8afc42ef442f6545b3c82a9165", 596121},
AD_LISTEND},
- Common::KO_KOR, Common::kPlatformWindows, ADGF_CD, GUIO5(GUIO_NOASPECT, GAMEOPTION_KQ6_WINDOWS_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_MIDI_MODE) },
+ Common::KO_KOR, Common::kPlatformWindows, ADGF_CD, GUIO5(GUIO_NOASPECT, GAMEOPTION_KQ_WINDOWS_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_MIDI_MODE) },
// King's Quest 6 - English Macintosh Floppy
// VERSION file reports "1.0"
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index 9d7e3f8994..494db51b09 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -45,6 +45,7 @@ GameFeatures::GameFeatures(SegManager *segMan, Kernel *kernel) : _segMan(segMan)
if (!ConfMan.getBool("use_cdaudio"))
_usesCdTrack = false;
_forceDOSTracks = false;
+ _useWindowsCursors = ConfMan.getBool("windows_cursors");
_pseudoMouseAbility = kPseudoMouseAbilityUninitialized;
}
@@ -215,7 +216,14 @@ SciVersion GameFeatures::detectSetCursorType() {
// kSetCursor semantics, otherwise it uses the SCI0 early kSetCursor
// semantics.
if (number == 0)
- _setCursorType = SCI_VERSION_1_1;
+ // KQ5 CD's DOS interpreter contained the new kSetCusor API while
+ // the Windows interpreter contained the old. The scripts tested
+ // the platform to see which version to call.
+ if (g_sci->getGameId() == GID_KQ5 && _useWindowsCursors) {
+ _setCursorType = SCI_VERSION_0_EARLY;
+ } else {
+ _setCursorType = SCI_VERSION_1_1;
+ }
else
_setCursorType = SCI_VERSION_0_EARLY;
}
diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h
index ef6196bc68..42de583b88 100644
--- a/engines/sci/engine/features.h
+++ b/engines/sci/engine/features.h
@@ -258,6 +258,8 @@ public:
*/
void forceDOSTracks() { _forceDOSTracks = true; }
+ bool useWindowsCursors() { return _useWindowsCursors; }
+
/**
* Autodetects, if Pseudo Mouse ability is enabled (different behavior in keyboard driver)
* @return kPseudoMouseAbilityTrue or kPseudoMouseAbilityFalse
@@ -285,6 +287,7 @@ private:
MoveCountType _moveCountType;
bool _usesCdTrack;
bool _forceDOSTracks;
+ bool _useWindowsCursors;
PseudoMouseAbilityType _pseudoMouseAbility;
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index aaabeb99c8..5387d56571 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -1330,6 +1330,20 @@ void gamestate_afterRestoreFixUp(EngineState *s, int savegameId) {
g_sci->_gfxMenu->kernelSetAttribute(1025 >> 8, 1025 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Statistics
g_sci->_gfxMenu->kernelSetAttribute(1026 >> 8, 1026 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Goals
break;
+ case GID_KQ5:
+ // WORKAROUND: We allow users to choose if they want the older KQ5 CD Windows cursors. These
+ // are black and white Cursor resources instead of the color View resources in the DOS version.
+ // This setting affects how KQCursor objects are initialized and might have changed since the
+ // game was saved. The scripts don't expect this since it wasn't an option in the original.
+ // In order for the cursors to correctly use the current setting, we need to clear the "number"
+ // property of every KQCursor when restoring when Windows cursors are disabled.
+ if (g_sci->isCD() && !g_sci->_features->useWindowsCursors()) {
+ Common::Array<reg_t> cursors = s->_segMan->findObjectsBySuperClass("KQCursor");
+ for (uint i = 0; i < cursors.size(); ++i) {
+ writeSelector(s->_segMan, cursors[i], SELECTOR(number), NULL_REG);
+ }
+ }
+ break;
case GID_KQ6:
if (g_sci->isCD()) {
// WORKAROUND:
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index d858e2ca0b..b2685ce5f4 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -4894,12 +4894,12 @@ static const uint16 kq5PatchMultilingualEndingGlitch[] = {
// We replace the global[400] checks with a fixed true. This is toggled with
// enablePatch() below when alternative Windows GM MIDI tracks are used.
//
-// Instead, we could have set global[400], but this has the possibly unwanted
-// side effects of switching to black&white cursors (which also needs complex
-// changes to GameFeatures::detectsetCursorType()) and breaking savegame
-// compatibilty between the DOS and Windows CD versions of KQ5.
+// Global[400] is also used to determine which cursor type to use: color view
+// resources for DOS or old black and white cursor resources for Windows.
+// We set this depending on if the user has used the "windows_cursors" option
+// in the Windows version. That doesn't affect this patch since it removes
+// global[400] from the code.
//
-// TODO: Investigate those side effects more closely.
// Applies to at least: Win CD
// Responsible method: mordOneScript::changeState(1), dragonScript::changeState(1),
// fireScript::changeState() in script 124
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 9d3a504174..904f78c8ec 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -342,6 +342,57 @@ reg_t SegManager::findObjectByName(const Common::String &name, int index) {
return result[index];
}
+Common::Array<reg_t> SegManager::findObjectsBySuperClass(const Common::String &superClassName) {
+ Common::Array<reg_t> result;
+
+ reg_t superClass = findObjectByName(superClassName);
+ if (superClass.isNull()) {
+ return result;
+ }
+
+ // Now all values are available; iterate over all objects.
+ for (uint i = 0; i < _heap.size(); i++) {
+ const SegmentObj *mobj = _heap[i];
+
+ if (!mobj)
+ continue;
+
+ reg_t objpos = make_reg(i, 0);
+
+ if (mobj->getType() == SEG_TYPE_SCRIPT) {
+ // It's a script, scan all objects in it
+ const Script *scr = (const Script *)mobj;
+ const ObjMap &objects = scr->getObjectMap();
+ for (ObjMap::const_iterator it = objects.begin(); it != objects.end(); ++it) {
+ objpos.setOffset(it->_value.getPos().getOffset());
+ Object *object = getObject(objpos);
+ if (object) {
+ if (superClass == object->getSuperClassSelector()) {
+ result.push_back(objpos);
+ }
+ }
+ }
+ } else if (mobj->getType() == SEG_TYPE_CLONES) {
+ // It's clone table, scan all objects in it
+ const CloneTable *ct = (const CloneTable *)mobj;
+ for (uint idx = 0; idx < ct->size(); ++idx) {
+ if (!ct->isValidEntry(idx))
+ continue;
+
+ objpos.setOffset(idx);
+ Object *object = getObject(objpos);
+ if (object) {
+ if (superClass == object->getSuperClassSelector()) {
+ result.push_back(objpos);
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
// return the seg if script_id is valid and in the map, else 0
SegmentId SegManager::getScriptSegment(int script_id) const {
return _scriptSegMap.getValOrDefault(script_id, 0);
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index 3143bfd8c6..32d975e926 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -430,6 +430,11 @@ public:
*/
reg_t findObjectByName(const Common::String &name, int index = -1);
+ /**
+ * Finds the addresses of all objects with the superclass of the given name.
+ */
+ Common::Array<reg_t> findObjectsBySuperClass(const Common::String &superClassName);
+
uint32 classTableSize() const { return _classTable.size(); }
Class getClass(int index) const { return _classTable[index]; }
void setClassOffset(int index, reg_t offset) { _classTable[index].reg = offset; }
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 99864122e5..de1f7d34af 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -23,6 +23,7 @@
#include "sci/sci.h" // for INCLUDE_OLDGFX
#include "sci/debug.h" // for g_debug_sleeptime_factor
+#include "sci/engine/features.h"
#include "sci/engine/file.h"
#include "sci/engine/guest_additions.h"
#include "sci/engine/kernel.h"
@@ -169,6 +170,13 @@ void EngineState::initGlobals() {
variablesSegment[VAR_GLOBAL] = script_000->getLocalsSegment();
variablesBase[VAR_GLOBAL] = variables[VAR_GLOBAL] = script_000->getLocalsBegin();
variablesMax[VAR_GLOBAL] = script_000->getLocalsCount();
+
+ // The KQ5 CD Windows interpreter set global 400 to tell the scripts that the
+ // platform was Windows. The global determines which cursors the scripts use,
+ // so we only set this if the user has chosen to use Windows cursors.
+ if (g_sci->getGameId() == GID_KQ5 && g_sci->isCD()) {
+ variables[VAR_GLOBAL][400].setOffset(g_sci->_features->useWindowsCursors());
+ }
}
uint16 EngineState::currentRoomNumber() const {
More information about the Scummvm-git-logs
mailing list