[Scummvm-git-logs] scummvm master -> 1f0334ee6b0290465590dd30135e4679615e816e
sluicebox
22204938+sluicebox at users.noreply.github.com
Mon Apr 20 07:30:15 UTC 2020
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
916ce02661 SCI: Factor save game code into functions
12d37a352b SCI32: Implement KQ7/SHIVERS custom Mac saving
1f0334ee6b SCI32: Don't delete planes on restore in all Mac games
Commit: 916ce02661b9f3bef2d98dae667137160fed00ce
https://github.com/scummvm/scummvm/commit/916ce02661b9f3bef2d98dae667137160fed00ce
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2020-04-19T23:33:54-07:00
Commit Message:
SCI: Factor save game code into functions
Factors some common save game code into functions and creates an
overload of GuestAdditions::runSaveRestore that doesn't rely on
SCI memory for returning the description string, all of which will
be used by the custom save/restore kMacPlatform32 subops.
Changed paths:
engines/sci/detection.cpp
engines/sci/engine/file.cpp
engines/sci/engine/file.h
engines/sci/engine/guest_additions.cpp
engines/sci/engine/guest_additions.h
engines/sci/engine/kfile.cpp
engines/sci/engine/savegame.cpp
engines/sci/engine/savegame.h
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 53c1e2e0a5..9c5719ed42 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -938,28 +938,11 @@ Common::Error SciEngine::loadGameState(int slot) {
}
Common::Error SciEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
- Common::String fileName = Common::String::format("%s.%03d", _targetName.c_str(), slot);
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
- Common::OutSaveFile *out = saveFileMan->openForSaving(fileName);
const char *version = "";
- if (!out) {
- warning("Opening savegame \"%s\" for writing failed", fileName.c_str());
- return Common::kWritingFailed;
+ if (gamestate_save(_gamestate, slot, desc, version)) {
+ return Common::kNoError;
}
-
- if (!gamestate_save(_gamestate, out, desc, version)) {
- warning("Saving the game state to '%s' failed", fileName.c_str());
- return Common::kWritingFailed;
- } else {
- out->finalize();
- if (out->err()) {
- warning("Writing the savegame failed");
- return Common::kWritingFailed;
- }
- delete out;
- }
-
- return Common::kNoError;
+ return Common::kWritingFailed;
}
bool SciEngine::canLoadGameStateCurrently() {
diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp
index 8d93269604..e1b727c521 100644
--- a/engines/sci/engine/file.cpp
+++ b/engines/sci/engine/file.cpp
@@ -445,6 +445,24 @@ Common::MemoryReadStream *makeCatalogue(const uint maxNumSaves, const uint gameN
return new Common::MemoryReadStream(data, dataSize, DisposeAfterUse::YES);
}
+
+int shiftSciToScummVMSaveId(int saveId) {
+ if (saveId == kMaxShiftedSaveId) {
+ return 0;
+ } else if (saveId >= 0) {
+ return saveId + kSaveIdShift;
+ }
+ return saveId;
+}
+
+int shiftScummVMToSciSaveId(int saveId) {
+ if (saveId == 0) {
+ return kMaxShiftedSaveId;
+ } else if (saveId > 0) {
+ return saveId - kSaveIdShift;
+ }
+ return saveId;
+}
#endif
FileHandle::FileHandle() : _in(0), _out(0) {
diff --git a/engines/sci/engine/file.h b/engines/sci/engine/file.h
index be6acca88f..1583a25176 100644
--- a/engines/sci/engine/file.h
+++ b/engines/sci/engine/file.h
@@ -177,6 +177,9 @@ bool fillSavegameDesc(const Common::String &filename, SavegameDesc &desc);
* compatible with game scripts' game catalogue readers.
*/
Common::MemoryReadStream *makeCatalogue(const uint maxNumSaves, const uint gameNameSize, const Common::String &fileNamePattern, const bool ramaFormat);
+
+int shiftSciToScummVMSaveId(int saveId);
+int shiftScummVMToSciSaveId(int saveId);
#endif
} // End of namespace Sci
diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp
index a9754afe91..017b41abee 100644
--- a/engines/sci/engine/guest_additions.cpp
+++ b/engines/sci/engine/guest_additions.cpp
@@ -669,12 +669,28 @@ reg_t GuestAdditions::promptSaveRestoreRama(EngineState *s, int argc, reg_t *arg
return make_reg(0, saveIndex);
}
-int GuestAdditions::runSaveRestore(const bool isSave, reg_t outDescription, const int forcedSaveNo) const {
- int saveNo;
+int GuestAdditions::runSaveRestore(const bool isSave, reg_t outDescription, const int forcedSaveId) const {
+ assert(!(isSave && outDescription.isNull()));
+
Common::String descriptionString;
+ int saveId = runSaveRestore(isSave, descriptionString, forcedSaveId);
+
+ if (!outDescription.isNull()) {
+ if (_segMan->isObject(outDescription)) {
+ outDescription = readSelector(_segMan, outDescription, SELECTOR(data));
+ }
+ SciArray &description = *_segMan->lookupArray(outDescription);
+ description.fromString(descriptionString);
+ }
+
+ return saveId;
+}
- if (!isSave && forcedSaveNo != -1) {
- saveNo = forcedSaveNo;
+int GuestAdditions::runSaveRestore(const bool isSave, Common::String &outDescription, const int forcedSaveId) const {
+ int saveId;
+
+ if (!isSave && forcedSaveId != -1) {
+ saveId = forcedSaveId;
} else {
const char *title;
const char *action;
@@ -687,36 +703,23 @@ int GuestAdditions::runSaveRestore(const bool isSave, reg_t outDescription, cons
}
GUI::SaveLoadChooser dialog(title, action, isSave);
- saveNo = dialog.runModalWithCurrentTarget();
- if (saveNo != -1) {
- descriptionString = dialog.getResultString();
- if (descriptionString.empty()) {
- descriptionString = dialog.createDefaultSaveDescription(saveNo - 1);
+ saveId = dialog.runModalWithCurrentTarget();
+ if (saveId != -1) {
+ outDescription = dialog.getResultString();
+ if (outDescription.empty()) {
+ outDescription = dialog.createDefaultSaveDescription(saveId - 1);
}
}
}
- assert(!isSave || !outDescription.isNull());
- if (!outDescription.isNull()) {
- if (_segMan->isObject(outDescription)) {
- outDescription = readSelector(_segMan, outDescription, SELECTOR(data));
- }
- SciArray &description = *_segMan->lookupArray(outDescription);
- description.fromString(descriptionString);
- }
-
// 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. Wrap slot 0 around to kMaxShiftedSaveId so that it remains
// a legal SCI value.
- if (saveNo > 0) {
- saveNo -= kSaveIdShift;
- } else if (saveNo == 0) {
- saveNo = kMaxShiftedSaveId;
- }
+ saveId = shiftScummVMToSciSaveId(saveId);
- return saveNo;
+ return saveId;
}
reg_t GuestAdditions::promptSaveRestoreHoyle5(EngineState *s, int argc, reg_t *argv) const {
diff --git a/engines/sci/engine/guest_additions.h b/engines/sci/engine/guest_additions.h
index cabcc4d620..713695261d 100644
--- a/engines/sci/engine/guest_additions.h
+++ b/engines/sci/engine/guest_additions.h
@@ -269,10 +269,11 @@ public:
* @param isSave If true, the prompt is for saving.
* @param outDescription Will be filled with the save game description.
* Optional for loads, required for saves.
- * @param forcedSaveNo During delayed restore, force the returned save game
- * number to this value.
+ * @param forcedSaveId During delayed restore, force the returned save game
+ * id to this value.
*/
- int runSaveRestore(const bool isSave, const reg_t outDescription, const int forcedSaveNo = -1) const;
+ int runSaveRestore(const bool isSave, const reg_t outDescription, const int forcedSaveId = -1) const;
+ int runSaveRestore(const bool isSave, Common::String &outDescription, const int forcedSaveId = -1) const;
#endif
#pragma mark -
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index b7e2a94a5d..633793100d 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -1151,31 +1151,10 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) {
s->_lastSaveNewId = savegameId;
}
- s->r_acc = NULL_REG;
-
- Common::String filename = g_sci->getSavegameName(savegameId);
- Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
- Common::OutSaveFile *out;
-
- out = saveFileMan->openForSaving(filename);
- if (!out) {
- warning("Error opening savegame \"%s\" for writing", filename.c_str());
- } else {
- if (!gamestate_save(s, out, game_description, version)) {
- warning("Saving the game failed");
- } else {
- s->r_acc = TRUE_REG; // save successful
- }
-
- out->finalize();
- if (out->err()) {
- warning("Writing the savegame failed");
- s->r_acc = NULL_REG; // write failure
- }
- delete out;
+ if (gamestate_save(s, savegameId, game_description, version)) {
+ return TRUE_REG;
}
-
- return s->r_acc;
+ return NULL_REG;
}
reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
@@ -1221,23 +1200,8 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
if (findSavegame(saves, savegameId) == -1) {
s->r_acc = TRUE_REG;
warning("Savegame ID %d not found", savegameId);
- } else {
- Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
- Common::String filename = g_sci->getSavegameName(savegameId);
- Common::SeekableReadStream *in;
-
- in = saveFileMan->openForLoading(filename);
- if (in) {
- // found a savegame file
- gamestate_restore(s, in);
- delete in;
-
- gamestate_afterRestoreFixUp(s, savegameId);
-
- } else {
- s->r_acc = TRUE_REG;
- warning("Savegame #%d not found", savegameId);
- }
+ } else if (!gamestate_restore(s, savegameId)) {
+ s->r_acc = TRUE_REG; // signals failure
}
if (!s->r_acc.isNull()) {
@@ -1370,10 +1334,8 @@ reg_t kSaveGame32(EngineState *s, int argc, reg_t *argv) {
// Autosave slot 1 is a "new game" save
saveNo = kNewGameId;
}
- } else if (saveNo == kMaxShiftedSaveId) {
- saveNo = 0;
} else {
- saveNo += kSaveIdShift;
+ saveNo = shiftSciToScummVMSaveId(saveNo);
}
if (g_sci->getGameId() == GID_PHANTASMAGORIA2 && s->callInStack(g_sci->getGameObject(), SELECTOR(bookMark))) {
@@ -1394,31 +1356,10 @@ reg_t kSaveGame32(EngineState *s, int argc, reg_t *argv) {
s->_segMan->freeArray(autoSaveNameId);
}
- Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
- const Common::String filename = g_sci->getSavegameName(saveNo);
- Common::OutSaveFile *saveStream = saveFileMan->openForSaving(filename);
-
- if (saveStream == nullptr) {
- warning("Error opening savegame \"%s\" for writing", filename.c_str());
- return NULL_REG;
- }
-
- if (!gamestate_save(s, saveStream, saveDescription, gameVersion)) {
- warning("Saving the game failed");
- saveStream->finalize();
- delete saveStream;
- return NULL_REG;
- }
-
- saveStream->finalize();
- if (saveStream->err()) {
- warning("Writing the savegame failed");
- delete saveStream;
- return NULL_REG;
+ if (gamestate_save(s, saveNo, saveDescription, gameVersion)) {
+ return TRUE_REG;
}
-
- delete saveStream;
- return TRUE_REG;
+ return NULL_REG;
}
reg_t kRestoreGame32(EngineState *s, int argc, reg_t *argv) {
@@ -1444,26 +1385,14 @@ reg_t kRestoreGame32(EngineState *s, int argc, reg_t *argv) {
// Autosave slot 1 is a "new game" save
saveNo = kNewGameId;
}
- } else if (saveNo == kMaxShiftedSaveId) {
- saveNo = 0;
} else {
- saveNo += kSaveIdShift;
+ saveNo = shiftSciToScummVMSaveId(saveNo);
}
- Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
- const Common::String filename = g_sci->getSavegameName(saveNo);
- Common::SeekableReadStream *saveStream = saveFileMan->openForLoading(filename);
-
- if (saveStream == nullptr) {
- warning("Savegame #%d not found", saveNo);
- return NULL_REG;
+ if (gamestate_restore(s, saveNo)) {
+ return TRUE_REG;
}
-
- gamestate_restore(s, saveStream);
- delete saveStream;
-
- gamestate_afterRestoreFixUp(s, saveNo);
- return TRUE_REG;
+ return NULL_REG;
}
reg_t kCheckSaveGame32(EngineState *s, int argc, reg_t *argv) {
@@ -1475,10 +1404,8 @@ reg_t kCheckSaveGame32(EngineState *s, int argc, reg_t *argv) {
if (saveNo == 1) {
saveNo = kNewGameId;
}
- } else if (saveNo == kMaxShiftedSaveId) {
- saveNo = 0;
} else {
- saveNo += kSaveIdShift;
+ saveNo = shiftSciToScummVMSaveId(saveNo);
}
SavegameDesc save;
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index b9cd58581a..3308f59027 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -1196,6 +1196,33 @@ void SegManager::reconstructClones() {
#pragma mark -
+bool gamestate_save(EngineState *s, int saveId, const Common::String &savename, const Common::String &version) {
+ Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
+ const Common::String filename = g_sci->getSavegameName(saveId);
+
+ Common::OutSaveFile *saveStream = saveFileMan->openForSaving(filename);
+ if (saveStream == nullptr) {
+ warning("Error opening savegame \"%s\" for writing", filename.c_str());
+ return false;
+ }
+
+ if (!gamestate_save(s, saveStream, savename, version)) {
+ warning("Saving the game failed");
+ saveStream->finalize();
+ delete saveStream;
+ return false;
+ }
+
+ saveStream->finalize();
+ if (saveStream->err()) {
+ warning("Writing the savegame failed");
+ delete saveStream;
+ return false;
+ }
+
+ delete saveStream;
+ return true;
+}
bool gamestate_save(EngineState *s, Common::WriteStream *fh, const Common::String &savename, const Common::String &version) {
Common::Serializer ser(nullptr, fh);
@@ -1345,6 +1372,23 @@ void gamestate_afterRestoreFixUp(EngineState *s, int savegameId) {
}
}
+bool gamestate_restore(EngineState *s, int saveId) {
+ Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
+ const Common::String filename = g_sci->getSavegameName(saveId);
+ Common::SeekableReadStream *saveStream = saveFileMan->openForLoading(filename);
+
+ if (saveStream == nullptr) {
+ warning("Savegame #%d not found", saveId);
+ return false;
+ }
+
+ gamestate_restore(s, saveStream);
+ delete saveStream;
+
+ gamestate_afterRestoreFixUp(s, saveId);
+ return true;
+}
+
void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
SavegameMetadata meta;
diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h
index 76f7cec58a..e8104d4764 100644
--- a/engines/sci/engine/savegame.h
+++ b/engines/sci/engine/savegame.h
@@ -97,22 +97,41 @@ struct SavegameMetadata {
uint8 avatarId;
};
+/**
+* Saves a game state to the hard disk in a portable way.
+* @param s The state to save
+* @param saveId The id of the savegame
+* @param savename The description of the savegame
+* @param version The version string of the game
+* @return true on success, false otherwise
+*/
+bool gamestate_save(EngineState *s, int saveId, const Common::String &savename, const Common::String &version);
+
/**
* Saves a game state to the hard disk in a portable way.
* @param s The state to save
* @param save The stream to save to
* @param savename The description of the savegame
- * @return 0 on success, 1 otherwise
+ * @param version The version string of the game
+ * @return true on success, false otherwise
*/
bool gamestate_save(EngineState *s, Common::WriteStream *save, const Common::String &savename, const Common::String &version);
// does a few fixups right after restoring a saved game
void gamestate_afterRestoreFixUp(EngineState *s, int savegameId);
+/**
+* Restores a game state from a directory.
+* @param s An older state from the same game
+* @param saveId The id of the savegame to restore from
+* @return true on success, false otherwise
+*/
+bool gamestate_restore(EngineState *s, int saveId);
+
/**
* Restores a game state from a directory.
* @param s An older state from the same game
- * @param dirname The subdirectory to restore from
+ * @param save The stream to restore from
*/
void gamestate_restore(EngineState *s, Common::SeekableReadStream *save);
Commit: 12d37a352b74ee9652e83fdb0c71888a4b7aa5cd
https://github.com/scummvm/scummvm/commit/12d37a352b74ee9652e83fdb0c71888a4b7aa5cd
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2020-04-19T23:46:13-07:00
Commit Message:
SCI32: Implement KQ7/SHIVERS custom Mac saving
Implements the custom Mac save and restore kPlatform subops
for KQ7 and Shivers. Still TODO: Mothergoose and Lighthouse.
Changed paths:
engines/sci/engine/guest_additions.cpp
engines/sci/engine/kmisc.cpp
engines/sci/engine/state.cpp
engines/sci/engine/state.h
engines/sci/engine/vm.h
engines/sci/engine/workarounds.cpp
diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp
index 017b41abee..2219c4ee81 100644
--- a/engines/sci/engine/guest_additions.cpp
+++ b/engines/sci/engine/guest_additions.cpp
@@ -25,6 +25,7 @@
#include "common/gui_options.h"
#include "common/savefile.h"
#include "sci/engine/features.h"
+#include "sci/engine/file.h"
#include "sci/engine/guest_additions.h"
#include "sci/engine/kernel.h"
#include "sci/engine/savegame.h"
@@ -789,11 +790,25 @@ bool GuestAdditions::restoreFromLauncher() const {
reg_t args[] = { make_reg(0, _state->_delayedRestoreGameId - kSaveIdShift) };
invokeSelector(g_sci->getGameObject(), SELECTOR(restore), 1, args);
} else {
+ int saveId = _state->_delayedRestoreGameId;
+
// When `Game::restore` is invoked, it will call to `Restore::doit`
// which will automatically return the `_delayedRestoreGameId` instead
// of prompting the user for a save game
invokeSelector(g_sci->getGameObject(), SELECTOR(restore));
+ // initialize KQ7 Mac's global save state by recording the save id
+ // and description. this is necessary for subsequent saves to work
+ // after restoring from launcher.
+ if (g_sci->getGameId() == GID_KQ7 || g_sci->getPlatform() == Common::kPlatformMacintosh) {
+ _state->_kq7MacSaveGameId = saveId;
+
+ SavegameDesc savegameDesc;
+ if (fillSavegameDesc(g_sci->getSavegameName(saveId), savegameDesc)) {
+ _state->_kq7MacSaveGameDescription = savegameDesc.name;
+ }
+ }
+
// The normal save game system resets _delayedRestoreGameId with a
// call to `EngineState::reset`, but RAMA uses a custom save game
// system which does not reset the engine, so we need to clear the
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
index ddd82c124e..fa6f6d5087 100644
--- a/engines/sci/engine/kmisc.cpp
+++ b/engines/sci/engine/kmisc.cpp
@@ -21,6 +21,7 @@
*/
#include "common/config-manager.h"
+#include "common/savefile.h"
#include "common/system.h"
#include "sci/sci.h"
@@ -29,10 +30,15 @@
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
#include "sci/engine/gc.h"
+#ifdef ENABLE_SCI32
+#include "sci/engine/guest_additions.h"
+#endif
+#include "sci/engine/savegame.h"
#include "sci/graphics/cursor.h"
#include "sci/graphics/palette.h"
#ifdef ENABLE_SCI32
#include "sci/graphics/cursor32.h"
+#include "sci/graphics/frameout.h"
#endif
#include "sci/graphics/maciconbar.h"
#include "sci/console.h"
@@ -570,32 +576,118 @@ reg_t kMacPlatform(EngineState *s, int argc, reg_t *argv) {
}
#ifdef ENABLE_SCI32
+// kMacKq7InitializeSave is a subop of kMacPlatform32.
+// KQ7 Mac would display a native Save dialog with the prompt "Who's game?"
+// and store the result in a global variable inside the interpreter
+// for subsequent calls to kMacKq7SaveGame.
+reg_t kMacKq7InitializeSave(EngineState *s) {
+ s->_kq7MacSaveGameId = g_sci->_guestAdditions->runSaveRestore(true, s->_kq7MacSaveGameDescription);
+ s->_kq7MacSaveGameId = shiftSciToScummVMSaveId(s->_kq7MacSaveGameId);
+ return (s->_kq7MacSaveGameId != -1) ? TRUE_REG : NULL_REG;
+}
+
+// kMacKq7SaveGame is a subop of kMacPlatform32.
+// Saves the game using the current save id and description that's set
+// when initializing or restoring a saved game.
+reg_t kMacKq7SaveGame(EngineState *s) {
+ if (s->_kq7MacSaveGameId == -1) {
+ error("kMacKq7SaveGame: save game hasn't been initialized");
+ }
+
+ const reg_t version = s->variables[VAR_GLOBAL][kGlobalVarVersion];
+ const Common::String versionString = s->_segMan->getString(version);
+ if (gamestate_save(s, s->_kq7MacSaveGameId, s->_kq7MacSaveGameDescription, versionString)) {
+ return TRUE_REG;
+ }
+ return NULL_REG;
+}
+
+// kMacKq7RestoreGame is a subop of kMacPlatform32.
+// KQ7 Mac would display a native Open dialog with the prompt "Who's game?"
+// and store the result in a global variable inside the interpreter to
+// use in subsequent calls to kMacKq7SaveGame before restoring.
+reg_t kMacKq7RestoreGame(EngineState *s) {
+ s->_kq7MacSaveGameId = g_sci->_guestAdditions->runSaveRestore(false, s->_kq7MacSaveGameDescription);
+ s->_kq7MacSaveGameId = shiftSciToScummVMSaveId(s->_kq7MacSaveGameId);
+ if (s->_kq7MacSaveGameId == -1) {
+ return NULL_REG;
+ }
+
+ // gamestate_restore() resets s->_kq7MacSaveGameId and
+ // s->_kq7MacSaveGameDescription so save and restore them.
+ int kq7MacSaveGameId = s->_kq7MacSaveGameId;
+ Common::String kq7MacSaveGameDescription = s->_kq7MacSaveGameDescription;
+ bool success = gamestate_restore(s, s->_kq7MacSaveGameId);
+ s->_kq7MacSaveGameId = kq7MacSaveGameId;
+ s->_kq7MacSaveGameDescription = kq7MacSaveGameDescription;
+
+ return success ? TRUE_REG : NULL_REG;
+}
+
+// kMacShiversInitializeSave is a subop of kMacPlatform32.
+reg_t kMacShiversInitializeSave(EngineState *s, int argc, reg_t *argv) {
+ return TRUE_REG; // NULL_REG if i/o errors
+}
+
+// kMacShiversSaveGame is a subop of kMacPlatform32.
+reg_t kMacShiversSaveGame(EngineState *s, int argc, reg_t *argv) {
+ g_sci->_gfxFrameout->kernelFrameOut(true); // see kSaveGame32
+
+ const int saveId = shiftSciToScummVMSaveId(argv[1].toUint16());
+ const Common::String description = s->_segMan->getString(argv[2]);
+ const reg_t version = s->variables[VAR_GLOBAL][kGlobalVarVersion];
+ const Common::String versionString = s->_segMan->getString(version);
+ if (gamestate_save(s, saveId, description, versionString)) {
+ return TRUE_REG;
+ }
+ return NULL_REG;
+}
+
+// kMacShiversRestoreGame is a subop of kMacPlatform32.
+reg_t kMacShiversRestoreGame(EngineState *s, int argc, reg_t *argv) {
+ const int saveId = shiftSciToScummVMSaveId(argv[1].toUint16());
+ if (gamestate_restore(s, saveId)) {
+ return TRUE_REG;
+ }
+ return NULL_REG;
+}
+
reg_t kMacPlatform32(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
case 0: // build cursor view map
g_sci->_gfxCursor32->setMacCursorRemapList(argc - 1, argv + 1);
- break;
+ return s->r_acc;
case 1: // compact/purge mac memory
case 2: // hands-off/hands-on for mac menus
- break;
+ return s->r_acc;
- // TODO: Save game handling in KQ7, Shivers, and Lighthouse.
- // - KQ7 uses all three with no parameters; the interpreter would
- // remember the current save file.
- // - Shivers uses all three but passes parameters in a similar
- // manner as the normal kSave\kRestore calls.
- // - Lighthouse goes insane and only uses subop 3 but adds sub-subops
- // which appear to do the three operations.
- // Temporarily stubbing these out with success values so that KQ7 can start.
- case 3: // initialize save game file
- warning("Unimplemented kMacPlatform32(%d): Initialize save game file", argv[0].toUint16());
- return TRUE_REG;
- case 4: // save game
- warning("Unimplemented kMacPlatform32(%d): Save game", argv[0].toUint16());
- return TRUE_REG;
- case 5: // restore game
- warning("Unimplemented kMacPlatform32(%d): Restore game", argv[0].toUint16());
+ // Subops 3-5 are used for custom saving and restoring but they
+ // changed completely between each game that uses them.
+ //
+ // KQ7: 3-5 with no parameters
+ // Shivers: 3-5 with parameters
+ // Lighthouse: 3 with sub-subops: -1, 0, and 1 (TODO)
+ case 3:
+ if (argc == 1) {
+ return kMacKq7InitializeSave(s);
+ } else if (argc == 3) {
+ return kMacShiversInitializeSave(s, argc - 1, argv + 1);
+ }
+ break;
+ case 4:
+ if (argc == 1) {
+ return kMacKq7SaveGame(s);
+ } else if (argc == 4) {
+ return kMacShiversSaveGame(s, argc - 1, argv + 1);
+ }
+ break;
+ case 5:
+ if (argc == 1) {
+ return kMacKq7RestoreGame(s);
+ } else if (argc == 3) {
+ return kMacShiversRestoreGame(s, argc - 1, argv + 1);
+ }
break;
// TODO: Mother Goose save game handling
@@ -605,18 +697,18 @@ reg_t kMacPlatform32(EngineState *s, int argc, reg_t *argv) {
case 9:
case 10:
case 11:
- error("Unimplemented kMacPlatform32(%d) save game operation", argv[0].toUint16());
break;
// TODO: Phantasmagoria music volume adjustment [ 0-15 ]
case 12:
warning("Unimplemented kMacPlatform32(%d): Set volume: %d", argv[0].toUint16(), argv[1].toUint16());
- break;
+ return s->r_acc;
default:
- error("Unknown kMacPlatform32(%d)", argv[0].toUint16());
+ break;
}
+ error("Unknown kMacPlatform32(%d)", argv[0].toUint16());
return s->r_acc;
}
#endif
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 5bb1343839..6648458bd7 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -88,6 +88,9 @@ void EngineState::reset(bool isRestoring) {
_delayedRestoreGameId = -1;
+ _kq7MacSaveGameId = -1;
+ _kq7MacSaveGameDescription.clear();
+
executionStackBase = 0;
_executionStackPosChanged = false;
stack_base = 0;
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index a783f09d82..46161a3187 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -136,6 +136,10 @@ public:
// see detection.cpp / SciEngine::loadGameState()
int _delayedRestoreGameId; // the saved game id, that it supposed to get restored (triggered by ScummVM menu)
+ // see kmisc.cpp / kMacPlatform32
+ int _kq7MacSaveGameId; // the saved game id to use when saving (might not exist yet)
+ Common::String _kq7MacSaveGameDescription; // description to use when saving game
+
uint _chosenQfGImportItem; // Remembers the item selected in QfG import rooms
bool _cursorWorkaroundActive; // Refer to GfxCursor::setPosition()
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index c80070409b..f1af11a249 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -149,6 +149,7 @@ enum GlobalVar {
kGlobalVarPreviousRoomNo = 12,
kGlobalVarNewRoomNo = 13,
kGlobalVarScore = 15,
+ kGlobalVarVersion = 27,
kGlobalVarGK2MusicVolume = 76, // 0 to 127
kGlobalVarPhant2SecondaryVolume = 76, // 0 to 127
kGlobalVarFastCast = 84, // SCI16
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index a921833708..7050edbf9c 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -446,6 +446,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_KQ7, 2450, 2450, 0, "maliciaComes", "handleEvent", NULL, 0, 0, { WORKAROUND_FAKE, 0 } }, // when malicia appears at the southeast exit of the main chamber near the end of chapter 2
{ GID_KQ7, 5300, 5302, 0, "putOnMask", "handleEvent", NULL, 0, 0, { WORKAROUND_FAKE, 0 } }, // in chapter 3, after using the mask on Valanice, click the jackalope hair in inventory - bug Trac#9759
{ GID_KQ7, 6060, 64964, 0, "DPath", "init", NULL, 1, 1, { WORKAROUND_FAKE, 0 } }, // after entering the harp crystal in chapter 5
+ { GID_KQ7, -1, 64994, -1, "Game", "restore", NULL, 0, 0, { WORKAROUND_FAKE, 0 } }, // when restoring from ScummVM launcher in Mac version
{ GID_LAURABOW, 37, 0, 0, "CB1", "doit", NULL, 1, 1, { WORKAROUND_FAKE, 0 } }, // when going up the stairs - bug #5084
{ GID_LAURABOW, -1, 967, 0, "myIcon", "cycle", NULL, 1, 1, { WORKAROUND_FAKE, 0 } }, // having any portrait conversation coming up - initial bug #4971
{ GID_LAURABOW2, -1, 24, 0, "gcWin", "open", NULL, 5, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu
Commit: 1f0334ee6b0290465590dd30135e4679615e816e
https://github.com/scummvm/scummvm/commit/1f0334ee6b0290465590dd30135e4679615e816e
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2020-04-20T00:19:38-07:00
Commit Message:
SCI32: Don't delete planes on restore in all Mac games
Changed paths:
engines/sci/graphics/frameout.cpp
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 0c7f0dee8e..9dc76a9b60 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -348,7 +348,17 @@ void GfxFrameout::deletePlane(Plane &planeToFind) {
void GfxFrameout::deletePlanesForMacRestore() {
// SCI32 PC games delete planes and screen items from
// their Game:restore script before calling kRestore.
- // In Mac this work was moved into the interpreter.
+ // In Mac this work was moved into the interpreter
+ // for some games, while others added it back to
+ // Game:restore or used their own scripts that took
+ // care of this in both PC and Mac versions.
+ if (!(g_sci->getGameId() == GID_GK1 ||
+ g_sci->getGameId() == GID_PQ4 ||
+ g_sci->getGameId() == GID_LSL6 ||
+ g_sci->getGameId() == GID_KQ7)) {
+ return;
+ }
+
for (PlaneList::size_type i = 0; i < _planes.size(); ) {
Plane *plane = _planes[i];
More information about the Scummvm-git-logs
mailing list