From 401b34bf4505e9d43596a8e9c8c4322c1e6d96a5 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 1 Jul 2016 14:57:03 +0200 Subject: SCI32: Support Torin's autosave system Torin has two sets of saves: autosave.### and torinsg.###, both with their own slots and .cat file. The autosave system uses autosave.000 and autosave.001. It also checks the presence of autosave.cat to determine if it should show the chapter selection menu on startup. --- engines/sci/engine/kfile.cpp | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'engines/sci/engine') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 4508a481a0..bb86e693f2 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -688,7 +688,7 @@ reg_t kSave(EngineState *s, int argc, reg_t *argv) { #endif reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { - Common::String game_id; + Common::String game_id = !argv[0].isNull() ? s->_segMan->getString(argv[0]) : ""; int16 virtualId = argv[1].toSint16(); int16 savegameId = -1; Common::String game_description; @@ -703,6 +703,13 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } + // Torin has two sets of saves: autosave.### and torinsg.###, both with + // their own slots and .cat file. + // The autosave system uses autosave.000 and autosave.001. + // It also checks the presence of autosave.cat to determine if it should + // show the chapter selection menu on startup. + bool torinAutosave = g_sci->getGameId() == GID_TORIN && game_id == "Autosave"; + if (argv[0].isNull()) { // Direct call, from a patched Game::save if ((argv[1] != SIGNAL_REG) || (!argv[2].isNull())) @@ -722,9 +729,15 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { if (savegameId < 0) return NULL_REG; + } else if (torinAutosave) { + if (argv[2].isNull()) + error("kSaveGame: called with description being NULL"); + game_description = s->_segMan->getString(argv[2]); + savegameId = virtualId; + + debug(3, "kSaveGame(%s,%d,%s,%s) [Torin autosave]", game_id.c_str(), virtualId, game_description.c_str(), version.c_str()); } else { // Real call from script - game_id = s->_segMan->getString(argv[0]); if (argv[2].isNull()) error("kSaveGame: called with description being NULL"); game_description = s->_segMan->getString(argv[2]); @@ -798,6 +811,10 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); Common::OutSaveFile *out; + if (torinAutosave) { + filename = g_sci->wrapFilename(Common::String::format("autosave.%03d", savegameId)); + } + out = saveFileMan->openForSaving(filename); if (!out) { warning("Error opening savegame \"%s\" for writing", filename.c_str()); @@ -816,6 +833,14 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { delete out; } + if (torinAutosave && !s->r_acc.isNull()) { + // Create autosave.cat so that the game can detect the presence + // of autosaves. + Common::WriteStream *t; + t = saveFileMan->openForSaving(g_sci->wrapFilename("autosave.cat")); + delete t; + } + return s->r_acc; } @@ -826,6 +851,10 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savegameId); + + // See comment in kSaveGame + bool torinAutosave = g_sci->getGameId() == GID_TORIN && game_id == "Autosave"; + if (argv[0].isNull()) { // Direct call, either from launcher or from a patched Game::restore if (savegameId == -1) { @@ -841,7 +870,7 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { pausedMusic = true; } // don't adjust ID of the saved game, it's already correct - } else { + } else if (!torinAutosave) { if (g_sci->getGameId() == GID_JONES) { // Jones has one save slot only savegameId = 0; @@ -858,8 +887,9 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { s->r_acc = NULL_REG; // signals success Common::Array saves; - listSavegames(saves); - if (findSavegame(saves, savegameId) == -1) { + if (!torinAutosave) + listSavegames(saves); + if (!torinAutosave && findSavegame(saves, savegameId) == -1) { s->r_acc = TRUE_REG; warning("Savegame ID %d not found", savegameId); } else { @@ -867,6 +897,10 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { Common::String filename = g_sci->getSavegameName(savegameId); Common::SeekableReadStream *in; + if (torinAutosave) { + filename = g_sci->wrapFilename(Common::String::format("autosave.%03d", savegameId)); + } + in = saveFileMan->openForLoading(filename); if (in) { // found a savegame file -- cgit v1.2.3 From 6d9ed09897e859c95caadf0b6d0139e49d2c0e03 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 11 Aug 2016 19:29:34 +0200 Subject: SCI32: Don't use autosave.cat in Torin --- engines/sci/engine/kfile.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'engines/sci/engine') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index bb86e693f2..3bcadd143c 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -251,6 +251,25 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { return SIGNAL_REG; } + // Torin's autosave system checks for the presence of autosave.cat + // by opening it. Since we don't use .cat files, we instead check + // for autosave.000 or autosave.001. + // + // This has the added benefit of not detecting an SSCI autosave.cat + // accompanying SSCI autosave files that we wouldn't be able to load. + if (g_sci->getGameId() == GID_TORIN && name == "autosave.cat") { + Common::String pattern = g_sci->wrapFilename("autosave.###"); + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + bool exists = !saveFileMan->listSavefiles(pattern).empty(); + if (exists) { + // Dummy handle. Torin only checks if this is SIGNAL_REG, + // and calls kFileIOClose on it. + return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE); + } else { + return SIGNAL_REG; + } + } + if (name.empty()) { // Happens many times during KQ1 (e.g. when typing something) debugC(kDebugLevelFile, "Attempted to open a file with an empty filename"); @@ -707,7 +726,7 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { // their own slots and .cat file. // The autosave system uses autosave.000 and autosave.001. // It also checks the presence of autosave.cat to determine if it should - // show the chapter selection menu on startup. + // show the chapter selection menu on startup. (See kFileIOOpen.) bool torinAutosave = g_sci->getGameId() == GID_TORIN && game_id == "Autosave"; if (argv[0].isNull()) { @@ -833,14 +852,6 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { delete out; } - if (torinAutosave && !s->r_acc.isNull()) { - // Create autosave.cat so that the game can detect the presence - // of autosaves. - Common::WriteStream *t; - t = saveFileMan->openForSaving(g_sci->wrapFilename("autosave.cat")); - delete t; - } - return s->r_acc; } -- cgit v1.2.3