From 10f450917cc484242893322aeb966cec67d6fd68 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Tue, 13 Sep 2016 10:32:41 -0500 Subject: SCI32: Implement kSave for standard-save SCI32 games Games with custom save code (KQ7, MGDX, PQ:SWAT, Shivers) are not fully supported yet. --- engines/sci/engine/kernel.h | 13 ++++++------- engines/sci/engine/kernel_tables.h | 22 +++++++++++----------- engines/sci/engine/kfile.cpp | 33 ++++++++++++++++++++++----------- 3 files changed, 39 insertions(+), 29 deletions(-) (limited to 'engines/sci') 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(); -- cgit v1.2.3