aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/kfile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/kfile.cpp')
-rw-r--r--engines/sci/engine/kfile.cpp105
1 files changed, 82 insertions, 23 deletions
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 4508a481a0..e8b9d0461d 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -40,6 +40,9 @@
#include "sci/engine/savegame.h"
#include "sci/sound/audio.h"
#include "sci/console.h"
+#ifdef ENABLE_SCI32
+#include "sci/resource.h"
+#endif
namespace Sci {
@@ -196,26 +199,25 @@ reg_t kValidPath(EngineState *s, int argc, reg_t *argv) {
#ifdef ENABLE_SCI32
reg_t kCD(EngineState *s, int argc, reg_t *argv) {
- // TODO: Stub
- switch (argv[0].toUint16()) {
- case 0:
- if (argc == 1) {
- // Check if a disc is in the drive
- return TRUE_REG;
- } else {
- // Check if the specified disc is in the drive
- // and return the current disc number. We just
- // return the requested disc number.
- return argv[1];
- }
- case 1:
- // Return the current CD number
- return make_reg(0, 1);
- default:
- warning("CD(%d)", argv[0].toUint16());
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
+
+reg_t kCheckCD(EngineState *s, int argc, reg_t *argv) {
+ const int16 cdNo = argc > 0 ? argv[0].toSint16() : 0;
+
+ if (cdNo) {
+ g_sci->getResMan()->findDisc(cdNo);
}
- return NULL_REG;
+ return make_reg(0, g_sci->getResMan()->getCurrentDiscNo());
+}
+
+reg_t kGetSavedCD(EngineState *s, int argc, reg_t *argv) {
+ // TODO: This is wrong, CD number needs to be available prior to
+ // the save game being loaded
+ return make_reg(0, g_sci->getResMan()->getCurrentDiscNo());
}
#endif
@@ -251,6 +253,28 @@ 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.
+ //
+ // The same logic is being followed for torinsg.cat - this shows
+ // the "Open..." button when continuing a game.
+ //
+ // 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" || name == "torinsg.cat")) {
+ Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
+ const Common::String pattern = (name == "autosave.cat") ? g_sci->wrapFilename("autosave.###") : g_sci->getSavegamePattern();
+ 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");
@@ -608,6 +632,15 @@ reg_t kFileIORename(EngineState *s, int argc, reg_t *argv) {
Common::String oldName = s->_segMan->getString(argv[0]);
Common::String newName = s->_segMan->getString(argv[1]);
+ // We don't fully implement all cases that could occur here, and
+ // assume the file to be renamed is a wrapped filename.
+ // Known usage: In Phant1 and KQ7 while deleting savegames.
+ // The scripts rewrite the dir file as a temporary file, and then
+ // rename it to the actual dir file.
+
+ oldName = g_sci->wrapFilename(oldName);
+ newName = g_sci->wrapFilename(newName);
+
// SCI1.1 returns 0 on success and a DOS error code on fail. SCI32
// returns -1 on fail. We just return -1 for all versions.
if (g_sci->getSaveFileManager()->renameSavefile(oldName, newName))
@@ -688,7 +721,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 +736,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. (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()))
@@ -722,9 +762,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 +844,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());
@@ -826,6 +876,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 +895,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 +912,9 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
s->r_acc = NULL_REG; // signals success
Common::Array<SavegameDesc> 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 +922,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