diff options
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/engine/kernel_tables.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/kfile.cpp | 124 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 19 |
3 files changed, 87 insertions, 58 deletions
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 53853e29b3..a9b38efeef 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -414,7 +414,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "[r0]i[r0]", NULL, NULL }, { MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL }, - { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rir(r)", NULL, NULL }, + { MAP_CALL(SaveGame), SIG_EVERYWHERE, "[r0]i[r0](r)", NULL, NULL }, { MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL }, { MAP_CALL(SetCursor), SIG_SCI21, SIGFOR_ALL, "i(i)([io])(i*)", NULL, NULL }, // TODO: SCI2.1 may supply an object optionally (mother goose sci21 right on startup) - find out why diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 629efd905a..bb08a0edd4 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -551,81 +551,111 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) { } reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { - Common::String game_id = s->_segMan->getString(argv[0]); - int16 virtualId = argv[1].toSint16(); - Common::String game_description = s->_segMan->getString(argv[2]); + Common::String game_id; + int16 virtualId = argv[1].toSint16(); + int16 savegameId = -1; + Common::String game_description; Common::String version; + bool pausedMusic = false; + if (argc > 3) version = s->_segMan->getString(argv[3]); - debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), virtualId, game_description.c_str(), version.c_str()); - // We check here, we don't want to delete a users save in case we are within a kernel function if (s->executionStackBase) { warning("kSaveGame - won't save from within kernel function"); return NULL_REG; } - Common::Array<SavegameDesc> saves; - listSavegames(saves); - - int16 savegameId; - if ((virtualId >= SAVEGAMEID_OFFICIALRANGE_START) && (virtualId <= SAVEGAMEID_OFFICIALRANGE_END)) { - // savegameId is an actual Id, so search for it just to make sure - savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; - if (findSavegame(saves, savegameId) == -1) + if (argv[0].isNull()) { + // Direct call, from a patched Game::save + if ((argv[1] != SIGNAL_REG) || (!argv[2].isNull())) + error("kSaveGame: assumed patched call isn't accurate"); + + // we are supposed to show a dialog for the user and let him choose where to save + g_sci->_soundCmd->pauseAll(true); // pause music + const EnginePlugin *plugin = NULL; + EngineMan.findGame(g_sci->getGameIdStr(), &plugin); + GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save"); + dialog->setSaveMode(true); + savegameId = dialog->runModal(plugin, ConfMan.getActiveDomainName()); + game_description = dialog->getResultString(); + delete dialog; + if (savegameId < 0) { + g_sci->_soundCmd->pauseAll(false); // unpause music return NULL_REG; - } else if (virtualId < SAVEGAMEID_OFFICIALRANGE_START) { - // virtualId is low, we assume that scripts expect us to create new slot - if (virtualId == s->_lastSaveVirtualId) { - // if last virtual id is the same as this one, we assume that caller wants to overwrite last save - savegameId = s->_lastSaveNewId; - } else { - uint savegameNr; - // savegameId is in lower range, scripts expect us to create a new slot - for (savegameId = 0; savegameId < SAVEGAMEID_OFFICIALRANGE_START; savegameId++) { - for (savegameNr = 0; savegameNr < saves.size(); savegameNr++) { - if (savegameId == saves[savegameNr].id) + } + pausedMusic = true; + + } 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]); + + debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), virtualId, game_description.c_str(), version.c_str()); + + Common::Array<SavegameDesc> saves; + listSavegames(saves); + + if ((virtualId >= SAVEGAMEID_OFFICIALRANGE_START) && (virtualId <= SAVEGAMEID_OFFICIALRANGE_END)) { + // savegameId is an actual Id, so search for it just to make sure + savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; + if (findSavegame(saves, savegameId) == -1) + return NULL_REG; + } else if (virtualId < SAVEGAMEID_OFFICIALRANGE_START) { + // virtualId is low, we assume that scripts expect us to create new slot + if (virtualId == s->_lastSaveVirtualId) { + // if last virtual id is the same as this one, we assume that caller wants to overwrite last save + savegameId = s->_lastSaveNewId; + } else { + uint savegameNr; + // savegameId is in lower range, scripts expect us to create a new slot + for (savegameId = 0; savegameId < SAVEGAMEID_OFFICIALRANGE_START; savegameId++) { + for (savegameNr = 0; savegameNr < saves.size(); savegameNr++) { + if (savegameId == saves[savegameNr].id) + break; + } + if (savegameNr == saves.size()) break; } - if (savegameNr == saves.size()) - break; + if (savegameId == SAVEGAMEID_OFFICIALRANGE_START) + error("kSavegame: no more savegame slots available"); } - if (savegameId == SAVEGAMEID_OFFICIALRANGE_START) - error("kSavegame: no more savegame slots available"); + } else { + error("kSaveGame: invalid savegameId used"); } - } else { - error("kSaveGame: invalid savegameId used"); + + // Save in case caller wants to overwrite last newly created save + s->_lastSaveVirtualId = virtualId; + s->_lastSaveNewId = savegameId; } - // Save in case caller wants to overwrite last newly created save - s->_lastSaveVirtualId = virtualId; - s->_lastSaveNewId = savegameId; + s->r_acc = NULL_REG; Common::String filename = g_sci->getSavegameName(savegameId); Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); Common::OutSaveFile *out; if (!(out = saveFileMan->openForSaving(filename))) { warning("Error opening savegame \"%s\" for writing", filename.c_str()); - s->r_acc = NULL_REG; - return NULL_REG; - } - - if (!gamestate_save(s, out, game_description.c_str(), version.c_str())) { - warning("Saving the game failed."); - s->r_acc = NULL_REG; } else { - out->finalize(); - if (out->err()) { - delete out; - warning("Writing the savegame failed."); - s->r_acc = NULL_REG; + if (!gamestate_save(s, out, game_description.c_str(), version.c_str())) { + warning("Saving the game failed."); } else { + out->finalize(); + if (out->err()) { + warning("Writing the savegame failed."); + } else { + s->r_acc = TRUE_REG; // success + } delete out; - s->r_acc = make_reg(0, 1); } } + if (pausedMusic) + g_sci->_soundCmd->pauseAll(false); // unpause music + return s->r_acc; } @@ -637,7 +667,7 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savegameId); if (argv[0].isNull()) { - // Direct call, either from launcher or from a patched Game::restore call + // Direct call, either from launcher or from a patched Game::restore if (savegameId == -1) { // we are supposed to show a dialog for the user and let him choose a saved game g_sci->_soundCmd->pauseAll(true); // pause music diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 2f71a716da..9ed6a6932b 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -330,12 +330,12 @@ Common::Error SciEngine::run() { return Common::kNoError; } -static byte patchGameRestore[] = { +static byte patchGameRestoreSave[] = { 0x39, 0x03, // pushi 03 0x76, // push0 0x38, 0xff, 0xff, // pushi -1 0x76, // push0 - 0x43, 0xff, 0x06, // call kRestoreGame (will get fixed directly) + 0x43, 0xff, 0x06, // call kRestoreGame/kSaveGame (will get fixed directly) 0x48, // ret }; @@ -381,12 +381,6 @@ void SciEngine::patchGameSaveRestore(SegManager *segMan) { scriptRestorePtr = script->getBuf(methodAddress.offset); break; } - if (methodName == "save") { - methodAddress = gameSuperObject->getFunction(methodNr); - Script *script = segMan->getScript(methodAddress.segment); - scriptSavePtr = script->getBuf(methodAddress.offset); - break; - } } switch (_gameId) { @@ -399,10 +393,15 @@ void SciEngine::patchGameSaveRestore(SegManager *segMan) { if (scriptRestorePtr) { // Now patch in our code byte *patchPtr = const_cast<byte *>(scriptRestorePtr); - memcpy(patchPtr, patchGameRestore, sizeof(patchGameRestore)); + memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave)); patchPtr[8] = kernelIdRestore; } - // Saving is not yet patched + //if (scriptSavePtr) { + // // Now patch in our code + // byte *patchPtr = const_cast<byte *>(scriptSavePtr); + // memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave)); + // patchPtr[8] = kernelIdSave; + //} } bool SciEngine::initGame() { |