aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorColin Snover2016-09-13 10:32:41 -0500
committerColin Snover2016-09-29 19:39:16 -0500
commit10f450917cc484242893322aeb966cec67d6fd68 (patch)
tree8e30fc77d9770fec2d468360d4f77683acdb2674 /engines/sci
parenta22bfb0db22487537254dcb2e83dc02dc484d1fa (diff)
downloadscummvm-rg350-10f450917cc484242893322aeb966cec67d6fd68.tar.gz
scummvm-rg350-10f450917cc484242893322aeb966cec67d6fd68.tar.bz2
scummvm-rg350-10f450917cc484242893322aeb966cec67d6fd68.zip
SCI32: Implement kSave for standard-save SCI32 games
Games with custom save code (KQ7, MGDX, PQ:SWAT, Shivers) are not fully supported yet.
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/engine/kernel.h13
-rw-r--r--engines/sci/engine/kernel_tables.h22
-rw-r--r--engines/sci/engine/kfile.cpp33
3 files changed, 39 insertions, 29 deletions
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index e1ec5c0dde..05e15daab4 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -484,11 +484,12 @@ reg_t kShowMovieWinPlayUntilEvent(EngineState *s, int argc, reg_t *argv);
reg_t kShowMovieWinInitDouble(EngineState *s, int argc, reg_t *argv);
reg_t kSave(EngineState *s, int argc, reg_t *argv);
-reg_t kSaveSave32(EngineState *s, int argc, reg_t *argv);
-reg_t kSaveRestore32(EngineState *s, int argc, reg_t *argv);
-reg_t kSaveList32(EngineState *s, int argc, reg_t *argv);
-reg_t kSaveCheck32(EngineState *s, int argc, reg_t *argv);
-reg_t kSaveMakeFileName32(EngineState *s, int argc, reg_t *argv);
+reg_t kSaveGame32(EngineState *s, int argc, reg_t *argv);
+reg_t kRestoreGame32(EngineState *s, int argc, reg_t *argv);
+reg_t kGetSaveFiles32(EngineState *s, int argc, reg_t *argv);
+reg_t kCheckSaveGame32(EngineState *s, int argc, reg_t *argv);
+reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv);
+reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv);
reg_t kSetHotRectangles(EngineState *s, int argc, reg_t *argv);
reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv);
@@ -591,8 +592,6 @@ reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv);
reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv);
reg_t kEditText(EngineState *s, int argc, reg_t *argv);
-reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv);
-reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv);
reg_t kSetScroll(EngineState *s, int argc, reg_t *argv);
reg_t kPaletteSetFromResource32(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index 7244262b9d..c74b3ae1fb 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -351,18 +351,18 @@ static const SciKernelMapSubEntry kPalCycle_subops[] = {
// version, subId, function-mapping, signature, workarounds
static const SciKernelMapSubEntry kSave_subops[] = {
- { SIG_SCI32, 0, MAP_CALL(SaveSave32), "rir[r0]", NULL },
- { SIG_SCI32, 1, MAP_CALL(SaveRestore32), "ri[r0]", NULL },
+ { SIG_SCI32, 0, MAP_CALL(SaveGame32), "rir[r0]", NULL },
+ { SIG_SCI32, 1, MAP_CALL(RestoreGame32), "ri[r0]", NULL },
// System script 64994 in several SCI2.1mid games (KQ7 2.00b, Phant1,
// PQ:SWAT, SQ6, Torin) calls GetSaveDir with an extra unused argument, and
// it is easier to just handle it here than to bother with creating
// workarounds
{ SIG_SCI32, 2, MAP_CALL(GetSaveDir), "(r)", NULL },
- { SIG_SCI32, 3, MAP_CALL(SaveCheck32), "ri[r0]", NULL },
+ { SIG_SCI32, 3, MAP_CALL(CheckSaveGame32), "ri[r0]", NULL },
// Subop 4 hasn't been encountered yet
- { SIG_SCI32, 5, MAP_CALL(SaveList32), "rrr", NULL },
+ { SIG_SCI32, 5, MAP_CALL(GetSaveFiles32), "rrr", NULL },
{ SIG_SCI32, 6, MAP_CALL(MakeSaveCatName), "rr", NULL },
- { SIG_SCI32, 7, MAP_CALL(SaveMakeFileName32), "rri", NULL },
+ { SIG_SCI32, 7, MAP_CALL(MakeSaveFileName), "rri", NULL },
{ SIG_SCI32, 8, MAP_EMPTY(GameIsRestarting), ".*", NULL },
SCI_SUBOPENTRY_TERMINATOR
};
@@ -633,7 +633,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(CheckFreeSpace), SIG_SCI11, SIGFOR_ALL, "r(i)", NULL, NULL },
{ MAP_CALL(CheckFreeSpace), SIG_SCI16, SIGFOR_ALL, "r", NULL, NULL },
#ifdef ENABLE_SCI32
- { "CheckSaveGame", kSaveCheck32, SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "ri[r0]", NULL, NULL },
+ { "CheckSaveGame", kCheckSaveGame32, SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "ri[r0]", NULL, NULL },
#endif
{ MAP_CALL(CheckSaveGame), SIG_SCI16, SIGFOR_ALL, ".*", NULL, NULL },
{ MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL },
@@ -690,7 +690,7 @@ static SciKernelMapEntry s_kernelMap[] = {
#endif
{ MAP_CALL(GetSaveDir), SIG_SCI16, SIGFOR_ALL, "", NULL, NULL },
#ifdef ENABLE_SCI32
- { "GetSaveFiles", kSaveList32, SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "rrr", NULL, NULL },
+ { "GetSaveFiles", kGetSaveFiles32, SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "rrr", NULL, NULL },
#endif
{ MAP_CALL(GetSaveFiles), SIG_EVERYWHERE, "rrr", NULL, NULL },
{ MAP_CALL(GetTime), SIG_EVERYWHERE, "(i)", NULL, NULL },
@@ -754,12 +754,12 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL },
{ MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL, NULL },
#ifdef ENABLE_SCI32
- { "RestoreGame", kSaveRestore32, SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "ri[r0]", NULL, NULL },
+ { "RestoreGame", kRestoreGame32, SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "ri[r0]", NULL, NULL },
#endif
{ MAP_CALL(RestoreGame), SIG_EVERYWHERE, "[r0]i[r0]", NULL, NULL },
{ MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL },
#ifdef ENABLE_SCI32
- { "SaveGame", kSaveSave32, SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "rir[r0]", NULL, NULL },
+ { "SaveGame", kSaveGame32, SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "rir[r0]", NULL, NULL },
#endif
{ MAP_CALL(SaveGame), SIG_SCI16, SIGFOR_ALL, "[r0]i[r0](r0)", NULL, NULL },
{ MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL },
@@ -870,8 +870,8 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(ObjectIntersect), SIG_EVERYWHERE, "oo", NULL, NULL },
{ MAP_CALL(EditText), SIG_EVERYWHERE, "o", NULL, NULL },
- { MAP_CALL(MakeSaveCatName), SIG_EVERYWHERE, "rr", NULL, NULL },
- { "MakeSaveFileName", kSaveMakeFileName32, SIG_UNTIL_SCI21MID, SIGFOR_ALL, "rri", NULL, NULL },
+ { MAP_CALL(MakeSaveCatName), SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "rr", NULL, NULL },
+ { MAP_CALL(MakeSaveFileName), SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "rri", NULL, NULL },
{ MAP_CALL(SetScroll), SIG_EVERYWHERE, "oiiii(i)(i)", NULL, NULL },
{ MAP_CALL(PalCycle), SIG_EVERYWHERE, "(.*)", kPalCycle_subops, NULL },
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 797cd5d570..41aa16b16f 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -256,6 +256,12 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) {
return SIGNAL_REG;
}
+#ifdef ENABLE_SCI32
+ // See kMakeSaveCatName
+ if (name == "fake.cat") {
+ 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.
@@ -285,6 +291,7 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) {
return SIGNAL_REG;
}
}
+#endif
if (name.empty()) {
// Happens many times during KQ1 (e.g. when typing something)
@@ -1039,7 +1046,7 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) {
}
#ifdef ENABLE_SCI32
-reg_t kSaveSave32(EngineState *s, int argc, reg_t *argv) {
+reg_t kSaveGame32(EngineState *s, int argc, reg_t *argv) {
const Common::String gameName = s->_segMan->getString(argv[0]);
int16 saveNo = argv[1].toSint16();
const Common::String saveDescription = s->_segMan->getString(argv[2]);
@@ -1111,7 +1118,7 @@ reg_t kSaveSave32(EngineState *s, int argc, reg_t *argv) {
return TRUE_REG;
}
-reg_t kSaveRestore32(EngineState *s, int argc, reg_t *argv) {
+reg_t kRestoreGame32(EngineState *s, int argc, reg_t *argv) {
const Common::String gameName = s->_segMan->getString(argv[0]);
int16 saveNo = argv[1].toSint16();
const Common::String gameVersion = argv[2].isNull() ? "" : s->_segMan->getString(argv[2]);
@@ -1141,7 +1148,7 @@ reg_t kSaveRestore32(EngineState *s, int argc, reg_t *argv) {
return TRUE_REG;
}
-reg_t kSaveCheck32(EngineState *s, int argc, reg_t *argv) {
+reg_t kCheckSaveGame32(EngineState *s, int argc, reg_t *argv) {
const Common::String gameName = s->_segMan->getString(argv[0]);
int16 saveNo = argv[1].toSint16();
const Common::String gameVersion = argv[2].isNull() ? "" : s->_segMan->getString(argv[2]);
@@ -1168,7 +1175,7 @@ reg_t kSaveCheck32(EngineState *s, int argc, reg_t *argv) {
return TRUE_REG;
}
-reg_t kSaveList32(EngineState *s, int argc, reg_t *argv) {
+reg_t kGetSaveFiles32(EngineState *s, int argc, reg_t *argv) {
// argv[0] is gameName, used in SSCI as the name of the save game catalogue
// but unused here since ScummVM does not support multiple catalogues
SciArray &descriptions = *s->_segMan->lookupArray(argv[1]);
@@ -1179,8 +1186,8 @@ reg_t kSaveList32(EngineState *s, int argc, reg_t *argv) {
// Normally SSCI limits to 20 games per directory, but ScummVM allows more
// than that
- descriptions.resize(SCI_MAX_SAVENAME_LENGTH * saves.size() + 1);
- saveIds.resize(saves.size());
+ descriptions.resize(SCI_MAX_SAVENAME_LENGTH * saves.size() + 1, true);
+ saveIds.resize(saves.size(), true);
for (uint i = 0; i < saves.size(); ++i) {
const SavegameDesc &save = saves[i];
@@ -1189,18 +1196,22 @@ reg_t kSaveList32(EngineState *s, int argc, reg_t *argv) {
saveIds.int16At(i) = save.id;
}
+ descriptions.charAt(SCI_MAX_SAVENAME_LENGTH * saves.size()) = '\0';
+
return make_reg(0, saves.size());
}
reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv) {
- // Normally, this creates the name of the save catalogue/directory to save into.
- // First parameter is the string to save the result into. Second is a string
- // with game parameters. We don't have a use for this at all, as we have our own
- // savegame directory management, thus we always return an empty string.
+ // ScummVM does not use SCI catalogues for save games, but game scripts try
+ // to write out catalogues manually after a save game is deleted, so we need
+ // to be able to identify and ignore these IO operations by always giving
+ // back a fixed catalogue name and then ignoring it in kFileIO
+ SciArray &outCatName = *s->_segMan->lookupArray(argv[0]);
+ outCatName.fromString("fake.cat");
return argv[0];
}
-reg_t kSaveMakeFileName32(EngineState *s, int argc, reg_t *argv) {
+reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv) {
SciArray &outFileName = *s->_segMan->lookupArray(argv[0]);
// argv[1] is the game name, which is not used by ScummVM
int16 saveNo = argv[2].toSint16();