From c8516ff9ebc7480c2303b4ab2c151b46444e1911 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Thu, 15 Sep 2016 09:02:55 -0500 Subject: SCI32: Add handling for save catalogues --- engines/sci/engine/kfile.cpp | 106 +++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 50560be7d1..cfb829bab2 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -229,6 +229,45 @@ reg_t kGetSavedCD(EngineState *s, int argc, reg_t *argv) { // ---- FileIO operations ----------------------------------------------------- +#ifdef ENABLE_SCI32 +static bool isSaveCatalogue(const Common::String &name) { + return name == "autosave.cat" || name.hasSuffix("sg.cat"); +} + +// SCI32 save game scripts check for, and write directly to, the save game +// catalogue. Since ScummVM does not use these catalogues, when looking for a +// catalogue, we instead check for save games within ScummVM that are logically +// equivalent to the behaviour of SSCI. +static bool saveCatalogueExists(const Common::String &name) { + bool exists = false; + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + + // There will always be one save game in some games, the "new game" + // game, which should be ignored when deciding if there are any save + // games available + uint numPermanentSaves; + switch (g_sci->getGameId()) { + case GID_TORIN: + case GID_LSL7: + case GID_LIGHTHOUSE: + numPermanentSaves = 1; + break; + default: + numPermanentSaves = 0; + break; + } + + // Torin uses autosave.cat; LSL7 uses autosvsg.cat + if (name == "autosave.cat" || name == "autosvsg.cat") { + exists = !saveFileMan->listSavefiles(g_sci->getSavegameName(0)).empty(); + } else { + exists = saveFileMan->listSavefiles(g_sci->getSavegamePattern()).size() > numPermanentSaves; + } + + return exists; +} +#endif + reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { if (!s) return make_reg(0, getSciVersion()); @@ -264,30 +303,11 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE); } - // 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 the autosave game. - // - // Similar logic is needed for torinsg.cat - this shows the "Open..." button - // when continuing a game if it exists. - // - // TODO: Other games with autosave built in should be included here - if (g_sci->getGameId() == GID_TORIN && (name == "autosave.cat" || name == "torinsg.cat")) { - Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); - - bool exists; - if (name == "autosave.cat") { - exists = !saveFileMan->listSavefiles(g_sci->getSavegameName(0)).empty(); - } else { - // There will always be one save game in Torin, the "new game" game, - // which should be ignored when deciding if there are any save games - // to open - exists = saveFileMan->listSavefiles(g_sci->getSavegamePattern()).size() > 1; - } - + if (isSaveCatalogue(name)) { + const bool exists = saveCatalogueExists(name); if (exists) { - // Dummy handle. Torin only checks if this is SIGNAL_REG, - // and calls kFileIOClose on it. + // Dummy handle is used to represent the catalogue and ignore any + // direct game script writes return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE); } else { return SIGNAL_REG; @@ -614,6 +634,12 @@ reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } +#ifdef ENABLE_SCI32 + if (isSaveCatalogue(name)) { + return saveCatalogueExists(name) ? TRUE_REG : NULL_REG; + } +#endif + // TODO: It may apparently be worth caching the existence of // phantsg.dir, and possibly even keeping it open persistently @@ -776,13 +802,6 @@ 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. (See kFileIOOpen.) - 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())) @@ -801,14 +820,6 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { g_sci->_soundCmd->pauseAll(false); // unpause music (we can't have it paused during save) 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 if (argv[2].isNull()) @@ -884,10 +895,6 @@ 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()); @@ -916,10 +923,6 @@ 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) { @@ -935,7 +938,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 if (!torinAutosave) { + } else { if (g_sci->getGameId() == GID_JONES) { // Jones has one save slot only savegameId = 0; @@ -952,9 +955,8 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { s->r_acc = NULL_REG; // signals success Common::Array saves; - if (!torinAutosave) - listSavegames(saves); - if (!torinAutosave && findSavegame(saves, savegameId) == -1) { + listSavegames(saves); + if (findSavegame(saves, savegameId) == -1) { s->r_acc = TRUE_REG; warning("Savegame ID %d not found", savegameId); } else { @@ -962,10 +964,6 @@ 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