aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorColin Snover2017-02-05 12:08:56 -0600
committerColin Snover2017-04-22 13:01:35 -0500
commit6f75bed90cdf36878f26cc1e091483efcc8091c8 (patch)
treedcbd8600f5a4ae2a8558ef395702c426698cc57e /engines/sci
parent4c0f2a37384df0ba14f55f223f47a26f208d0199 (diff)
downloadscummvm-rg350-6f75bed90cdf36878f26cc1e091483efcc8091c8.tar.gz
scummvm-rg350-6f75bed90cdf36878f26cc1e091483efcc8091c8.tar.bz2
scummvm-rg350-6f75bed90cdf36878f26cc1e091483efcc8091c8.zip
SCI32: Remove original save/load option from games without ScummVM save integration
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/detection_tables.h13
-rw-r--r--engines/sci/engine/guest_additions.cpp92
-rw-r--r--engines/sci/engine/guest_additions.h4
-rw-r--r--engines/sci/engine/kernel_tables.h2
-rw-r--r--engines/sci/engine/savegame.cpp6
5 files changed, 98 insertions, 19 deletions
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index c37dd4fffb..82d3bddc3b 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -1814,10 +1814,9 @@ static const struct ADGameDescription SciGameDescriptions[] = {
GUIO_LINKMUSICTOSFX, \
GUIO_LINKSPEECHTOSFX, \
GUIO_NOASPECT)
-#define GUIO_KQ7 GUIO4(GUIO_NOASPECT, \
+#define GUIO_KQ7 GUIO3(GUIO_NOASPECT, \
GUIO_LINKMUSICTOSFX, \
- GUIO_LINKSPEECHTOSFX, \
- GAMEOPTION_ORIGINAL_SAVELOAD)
+ GUIO_LINKSPEECHTOSFX)
// King's Quest 7 - English Windows (from the King's Quest Collection)
// Executable scanning reports "2.100.002", VERSION file reports "1.4"
@@ -2887,7 +2886,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
#define GUIO_MOTHERGOOSEHIRES GUIO4(GUIO_NOSUBTITLES, \
GUIO_NOASPECT, \
GUIO_LINKSPEECHTOSFX, \
- GAMEOPTION_ORIGINAL_SAVELOAD)
+ GUIO_NOLAUNCHLOAD)
// Mixed-Up Mother Goose Deluxe - English Windows/DOS CD (supplied by markcoolio in bug report #2723810)
// Executable scanning reports "2.100.002"
@@ -3414,12 +3413,11 @@ static const struct ADGameDescription SciGameDescriptions[] = {
GUIO_LINKSPEECHTOSFX, \
GUIO_NOASPECT, \
GUIO_NOLAUNCHLOAD)
-#define GUIO_PQSWAT GUIO7(GUIO_NOSUBTITLES, \
+#define GUIO_PQSWAT GUIO6(GUIO_NOSUBTITLES, \
GUIO_NOMIDI, \
GUIO_LINKMUSICTOSFX, \
GUIO_LINKSPEECHTOSFX, \
GUIO_NOASPECT, \
- GAMEOPTION_ORIGINAL_SAVELOAD, \
GAMEOPTION_ENABLE_BLACK_LINED_VIDEO)
// Police Quest: SWAT - English DOS/Windows Demo (from jvprat)
@@ -3946,11 +3944,10 @@ static const struct ADGameDescription SciGameDescriptions[] = {
GUIO_LINKSPEECHTOSFX, \
GUIO_LINKMUSICTOSFX, \
GUIO_NOASPECT)
-#define GUIO_SHIVERS GUIO6(GUIO_NOMIDI, \
+#define GUIO_SHIVERS GUIO5(GUIO_NOMIDI, \
GUIO_LINKSPEECHTOSFX, \
GUIO_LINKMUSICTOSFX, \
GUIO_NOASPECT, \
- GAMEOPTION_ORIGINAL_SAVELOAD, \
GAMEOPTION_ENABLE_BLACK_LINED_VIDEO)
// Shivers - English Windows (from jvprat)
diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp
index 8ac780ac17..57de4e3680 100644
--- a/engines/sci/engine/guest_additions.cpp
+++ b/engines/sci/engine/guest_additions.cpp
@@ -210,14 +210,20 @@ void GuestAdditions::kDoSoundSetVolumeHook(const reg_t soundObj, const int16 vol
}
void GuestAdditions::instantiateScriptHook(Script &script) const {
- if (getSciVersion() < SCI_VERSION_2) {
+ if (getSciVersion() < SCI_VERSION_2 || ConfMan.getBool("originalsaveload")) {
return;
}
- // 64990 is the system script containing SRDialog. This script is normally
- // used by the main Game object, but it is not loaded immediately, so we
- // wait for it to be loaded before patching it
- if (!ConfMan.getBool("originalsaveload") && script.getScriptNumber() == 64990) {
+ if (g_sci->getGameId() == GID_TORIN && script.getScriptNumber() == 64866) {
+ patchGameSaveRestoreTorin(script);
+ } else if (script.getScriptNumber() == 64990) {
+ // 64990 is the system script containing SRDialog. This script is used
+ // by the main Game object, but it is not loaded immediately, so we wait
+ // for it to be loaded before patching it. Attempting to preload this
+ // script early for patching will cause the order of entries in the
+ // segment table to change (versus save games that are not patched),
+ // breaking persistent objects (like the control panel in SQ6) which
+ // require reg_ts created during game startup to always be the same
patchGameSaveRestoreSCI32(script);
}
}
@@ -347,8 +353,38 @@ void GuestAdditions::patchGameSaveRestoreSCI32(Script &script) const {
}
}
+static const byte SRTorinPatch[] = {
+ 0x38, 0x8d, 0x00, // pushi $8d (new)
+ 0x76, // push0
+ 0x51, 0x0f, // class $f (Str)
+ 0x4a, 0x04, 0x00, // send 4
+ 0xa3, 0x01, // sal 1
+ 0x76, // push0
+ 0x59, 0x01, // &rest 1
+ 0x43, kScummVMSaveLoadId, 0x00, 0x00, // callk kScummVMSaveLoad, 0
+ 0x48 // ret
+};
+
+void GuestAdditions::patchGameSaveRestoreTorin(Script &script) const {
+ const uint16 address = script.validateExportFunc(2, true);
+ byte *patchPtr = const_cast<byte *>(script.getBuf(address));
+ memcpy(patchPtr, SRTorinPatch, sizeof(SRTorinPatch));
+ if (g_sci->isBE()) {
+ SWAP(patchPtr[1], patchPtr[2]);
+ SWAP(patchPtr[8], patchPtr[9]);
+ }
+}
+
reg_t GuestAdditions::kScummVMSaveLoad(EngineState *s, int argc, reg_t *argv) const {
- const bool isSave = (bool)argv[0].toSint16();
+ if (g_sci->getGameId() == GID_TORIN) {
+ return promptSaveRestoreTorin(s, argc, argv);
+ }
+
+ return promptSaveRestoreDefault(s, argc, argv);
+}
+
+reg_t GuestAdditions::promptSaveRestoreDefault(EngineState *s, int argc, reg_t *argv) const {
+ const bool isSave = (argc > 0);
int saveNo;
if (isSave) {
@@ -356,10 +392,10 @@ reg_t GuestAdditions::kScummVMSaveLoad(EngineState *s, int argc, reg_t *argv) co
saveNo = dialog.runModalWithCurrentTarget();
if (saveNo != -1) {
reg_t descriptionId;
- if (_segMan->isObject(argv[1])) {
- descriptionId = readSelector(_segMan, argv[1], SELECTOR(data));
+ if (_segMan->isObject(argv[0])) {
+ descriptionId = readSelector(_segMan, argv[0], SELECTOR(data));
} else {
- descriptionId = argv[1];
+ descriptionId = argv[0];
}
SciArray &description = *_segMan->lookupArray(descriptionId);
description.fromString(dialog.getResultString());
@@ -380,6 +416,44 @@ reg_t GuestAdditions::kScummVMSaveLoad(EngineState *s, int argc, reg_t *argv) co
return make_reg(0, saveNo);
}
+
+reg_t GuestAdditions::promptSaveRestoreTorin(EngineState *s, int argc, reg_t *argv) const {
+ const bool isSave = (argc > 0 && (bool)argv[0].toSint16());
+ int saveNo;
+
+ if (isSave) {
+ GUI::SaveLoadChooser dialog(_("Save game:"), _("Save"), true);
+ saveNo = dialog.runModalWithCurrentTarget();
+ if (saveNo != -1) {
+ reg_t descriptionId = s->variables[VAR_LOCAL][1];
+ reg_t dataId;
+ SciArray &description = *_segMan->allocateArray(kArrayTypeString, 0, &dataId);
+ description.fromString(dialog.getResultString());
+ writeSelector(_segMan, descriptionId, SELECTOR(data), dataId);
+ }
+ } else {
+ GUI::SaveLoadChooser dialog(_("Restore game:"), _("Restore"), false);
+ saveNo = dialog.runModalWithCurrentTarget();
+ }
+
+ if (saveNo > 0) {
+ // The autosave slot in ScummVM takes up slot 0, but in SCI the first
+ // non-autosave save game number needs to be 0, so reduce the save
+ // number here to match what would come from the normal SCI save/restore
+ // dialog. There is additional special code for handling the autosave
+ // game inside of kRestoreGame32.
+ --saveNo;
+ }
+
+ if (saveNo != -1) {
+ assert(s->variablesMax[VAR_LOCAL] > 2);
+ s->variables[VAR_LOCAL][2] = make_reg(0, saveNo);
+ s->variables[VAR_LOCAL][3] = make_reg(0, isSave ? 1 : 0);
+ }
+
+ return make_reg(0, saveNo != -1);
+}
+
#endif
#pragma mark -
diff --git a/engines/sci/engine/guest_additions.h b/engines/sci/engine/guest_additions.h
index ebb328c901..f9c1691445 100644
--- a/engines/sci/engine/guest_additions.h
+++ b/engines/sci/engine/guest_additions.h
@@ -148,6 +148,10 @@ public:
private:
void patchGameSaveRestoreSCI32(Script &script) const;
+ void patchGameSaveRestoreTorin(Script &script) const;
+
+ reg_t promptSaveRestoreDefault(EngineState *s, int argc, reg_t *argv) const;
+ reg_t promptSaveRestoreTorin(EngineState *s, int argc, reg_t *argv) const;
#endif
#pragma mark -
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index f075da3005..7e3f4a8bff 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -783,7 +783,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL },
#ifdef ENABLE_SCI32
{ "SaveGame", kSaveGame32, SIG_THRU_SCI21EARLY, SIGFOR_ALL, "ri[r0][r0]", NULL, NULL },
- { MAP_CALL(ScummVMSaveLoad), SIG_SCI32, SIGFOR_ALL, "i([ro])", NULL, NULL },
+ { MAP_CALL(ScummVMSaveLoad), SIG_SCI32, SIGFOR_ALL, "([iro])([ro0])", NULL, NULL },
#endif
{ MAP_CALL(SaveGame), SIG_SCI16, SIGFOR_ALL, "[r0]i[r0](r0)", NULL, NULL },
{ MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL },
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index d7fe009c9a..17bdebc76d 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -48,6 +48,7 @@
#include "sci/sound/music.h"
#ifdef ENABLE_SCI32
+#include "sci/engine/guest_additions.h"
#include "sci/graphics/cursor32.h"
#include "sci/graphics/frameout.h"
#include "sci/graphics/palette32.h"
@@ -256,7 +257,6 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
ObjMap objects = scr->getObjectMap();
for (ObjMap::iterator it = objects.begin(); it != objects.end(); ++it)
it->_value.syncBaseObject(SciSpan<const byte>(scr->getBuf(it->_value.getPos().getOffset()), scr->getBufSize() - it->_value.getPos().getOffset()));
-
}
// Sync the script's string heap
@@ -297,6 +297,10 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
}
}
}
+
+ if (s.isLoading() && pass == passes) {
+ g_sci->_guestAdditions->instantiateScriptHook(*scr);
+ }
}
}
}