SCI32: Add handling for save catalogues
This commit is contained in:
parent
1eb6d90eec
commit
c8516ff9eb
1 changed files with 52 additions and 54 deletions
|
@ -229,6 +229,45 @@ reg_t kGetSavedCD(EngineState *s, int argc, reg_t *argv) {
|
||||||
|
|
||||||
// ---- FileIO operations -----------------------------------------------------
|
// ---- 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) {
|
reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
|
||||||
if (!s)
|
if (!s)
|
||||||
return make_reg(0, getSciVersion());
|
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);
|
return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Torin's autosave system checks for the presence of autosave.cat
|
if (isSaveCatalogue(name)) {
|
||||||
// by opening it. Since we don't use .cat files, we instead check
|
const bool exists = saveCatalogueExists(name);
|
||||||
// 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 (exists) {
|
if (exists) {
|
||||||
// Dummy handle. Torin only checks if this is SIGNAL_REG,
|
// Dummy handle is used to represent the catalogue and ignore any
|
||||||
// and calls kFileIOClose on it.
|
// direct game script writes
|
||||||
return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE);
|
return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE);
|
||||||
} else {
|
} else {
|
||||||
return SIGNAL_REG;
|
return SIGNAL_REG;
|
||||||
|
@ -614,6 +634,12 @@ reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) {
|
||||||
return NULL_REG;
|
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
|
// TODO: It may apparently be worth caching the existence of
|
||||||
// phantsg.dir, and possibly even keeping it open persistently
|
// 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;
|
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()) {
|
if (argv[0].isNull()) {
|
||||||
// Direct call, from a patched Game::save
|
// Direct call, from a patched Game::save
|
||||||
if ((argv[1] != SIGNAL_REG) || (!argv[2].isNull()))
|
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)
|
g_sci->_soundCmd->pauseAll(false); // unpause music (we can't have it paused during save)
|
||||||
if (savegameId < 0)
|
if (savegameId < 0)
|
||||||
return NULL_REG;
|
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 {
|
} else {
|
||||||
// Real call from script
|
// Real call from script
|
||||||
if (argv[2].isNull())
|
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::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
|
||||||
Common::OutSaveFile *out;
|
Common::OutSaveFile *out;
|
||||||
|
|
||||||
if (torinAutosave) {
|
|
||||||
filename = g_sci->wrapFilename(Common::String::format("autosave.%03d", savegameId));
|
|
||||||
}
|
|
||||||
|
|
||||||
out = saveFileMan->openForSaving(filename);
|
out = saveFileMan->openForSaving(filename);
|
||||||
if (!out) {
|
if (!out) {
|
||||||
warning("Error opening savegame \"%s\" for writing", filename.c_str());
|
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);
|
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()) {
|
if (argv[0].isNull()) {
|
||||||
// Direct call, either from launcher or from a patched Game::restore
|
// Direct call, either from launcher or from a patched Game::restore
|
||||||
if (savegameId == -1) {
|
if (savegameId == -1) {
|
||||||
|
@ -935,7 +938,7 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
|
||||||
pausedMusic = true;
|
pausedMusic = true;
|
||||||
}
|
}
|
||||||
// don't adjust ID of the saved game, it's already correct
|
// don't adjust ID of the saved game, it's already correct
|
||||||
} else if (!torinAutosave) {
|
} else {
|
||||||
if (g_sci->getGameId() == GID_JONES) {
|
if (g_sci->getGameId() == GID_JONES) {
|
||||||
// Jones has one save slot only
|
// Jones has one save slot only
|
||||||
savegameId = 0;
|
savegameId = 0;
|
||||||
|
@ -952,9 +955,8 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
|
||||||
s->r_acc = NULL_REG; // signals success
|
s->r_acc = NULL_REG; // signals success
|
||||||
|
|
||||||
Common::Array<SavegameDesc> saves;
|
Common::Array<SavegameDesc> saves;
|
||||||
if (!torinAutosave)
|
listSavegames(saves);
|
||||||
listSavegames(saves);
|
if (findSavegame(saves, savegameId) == -1) {
|
||||||
if (!torinAutosave && findSavegame(saves, savegameId) == -1) {
|
|
||||||
s->r_acc = TRUE_REG;
|
s->r_acc = TRUE_REG;
|
||||||
warning("Savegame ID %d not found", savegameId);
|
warning("Savegame ID %d not found", savegameId);
|
||||||
} else {
|
} else {
|
||||||
|
@ -962,10 +964,6 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
|
||||||
Common::String filename = g_sci->getSavegameName(savegameId);
|
Common::String filename = g_sci->getSavegameName(savegameId);
|
||||||
Common::SeekableReadStream *in;
|
Common::SeekableReadStream *in;
|
||||||
|
|
||||||
if (torinAutosave) {
|
|
||||||
filename = g_sci->wrapFilename(Common::String::format("autosave.%03d", savegameId));
|
|
||||||
}
|
|
||||||
|
|
||||||
in = saveFileMan->openForLoading(filename);
|
in = saveFileMan->openForLoading(filename);
|
||||||
if (in) {
|
if (in) {
|
||||||
// found a savegame file
|
// found a savegame file
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue