/** * DoRestore */ static bool DoRestore() { Common::InSaveFile *f = _vm->getSaveFileMan()->openForLoading(g_savedFiles[g_RestoreGameNumber].name); if (f == NULL) { return false; } Common::Serializer s(f, 0); SaveGameHeader hdr; if (!syncSaveGameHeader(s, hdr)) { delete f; // Invalid header, or savegame too new -> skip it return false; } DoSync(s); uint32 id = f->readSint32LE(); if (id != (uint32)0xFEEDFACE) error("Incompatible saved game"); bool failed = (f->eos() || f->err()); delete f; if (failed) { GUI::MessageDialog dialog(_("Failed to load game state from file.")); dialog.runModal(); } return !failed; }
/** * Compute a list of all available saved game files. * Store the file details, ordered by time, in savedFiles[] and return * the number of files found. */ int getList(Common::SaveFileManager *saveFileMan, const Common::String &target) { // No change since last call? // TODO/FIXME: Just always reload this data? Be careful about slow downs!!! if (!g_NeedLoad) return g_numSfiles; int i; const Common::String pattern = target + ".???"; Common::StringArray files = saveFileMan->listSavefiles(pattern); g_numSfiles = 0; for (Common::StringArray::const_iterator file = files.begin(); file != files.end(); ++file) { if (g_numSfiles >= MAX_SAVED_FILES) break; const Common::String &fname = *file; Common::InSaveFile *f = saveFileMan->openForLoading(fname); if (f == NULL) { continue; } // Try to load save game header Common::Serializer s(f, 0); SaveGameHeader hdr; bool validHeader = syncSaveGameHeader(s, hdr); delete f; if (!validHeader) { continue; // Invalid header, or savegame too new -> skip it // TODO: In SCUMM, we still show an entry for the save, but with description // "incompatible version". } i = g_numSfiles; #ifndef DISABLE_SAVEGAME_SORTING for (i = 0; i < g_numSfiles; i++) { if (cmpTimeDate(hdr.dateTime, g_savedFiles[i].dateTime) > 0) { Common::copy_backward(&g_savedFiles[i], &g_savedFiles[g_numSfiles], &g_savedFiles[g_numSfiles + 1]); break; } } #endif Common::strlcpy(g_savedFiles[i].name, fname.c_str(), FNAMELEN); Common::strlcpy(g_savedFiles[i].desc, hdr.desc, SG_DESC_LEN); g_savedFiles[i].dateTime = hdr.dateTime; ++g_numSfiles; } // Next getList() needn't do its stuff again g_NeedLoad = false; return g_numSfiles; }
/** * DoSave */ static void DoSave() { Common::OutSaveFile *f; const char *fname; // Next getList() must do its stuff again NeedLoad = true; if (SaveSceneName == NULL) SaveSceneName = NewName(); if (SaveSceneDesc[0] == 0) SaveSceneDesc = "unnamed"; fname = SaveSceneName; f = _vm->getSaveFileMan()->openForSaving(fname); Common::Serializer s(0, f); if (f == NULL) goto save_failure; // Write out a savegame header SaveGameHeader hdr; hdr.id = SAVEGAME_ID; hdr.size = SAVEGAME_HEADER_SIZE; hdr.ver = CURRENT_VER; memcpy(hdr.desc, SaveSceneDesc, SG_DESC_LEN); hdr.desc[SG_DESC_LEN - 1] = 0; g_system->getTimeAndDate(hdr.dateTime); if (!syncSaveGameHeader(s, hdr) || f->err()) { goto save_failure; } DoSync(s); // Write out the special Id for Discworld savegames f->writeUint32LE(0xFEEDFACE); if (f->err()) goto save_failure; f->finalize(); delete f; return; save_failure: if (f) { delete f; _vm->getSaveFileMan()->removeSavefile(fname); } GUI::MessageDialog dialog("Failed to save game state to file."); dialog.runModal(); }
/** * DoRestore */ static bool DoRestore() { Common::InSaveFile *f = _vm->getSaveFileMan()->openForLoading(g_savedFiles[g_RestoreGameNumber].name); if (f == NULL) { return false; } Common::Serializer s(f, 0); SaveGameHeader hdr; if (!syncSaveGameHeader(s, hdr)) { delete f; // Invalid header, or savegame too new -> skip it return false; } // Load in the data. For older savegame versions, we potentially need to load the data twice, once // for pre 1.5 savegames, and if that fails, a second time for 1.5 savegames int numInterpreters = hdr.numInterpreters; int32 currentPos = f->pos(); for (int tryNumber = 0; tryNumber < ((hdr.ver >= 2) ? 1 : 2); ++tryNumber) { // If it's the second loop iteration, try with the 1.5 savegame number of interpreter contexts if (tryNumber == 1) { f->seek(currentPos); numInterpreters = 80; } // Load the savegame data if (DoSync(s, numInterpreters)) // Data load was successful (or likely), so break out of loop break; } uint32 id = f->readSint32LE(); if (id != (uint32)0xFEEDFACE) error("Incompatible saved game"); bool failed = (f->eos() || f->err()); delete f; if (failed) { GUI::MessageDialog dialog(_("Failed to load game state from file.")); dialog.runModal(); } return !failed; }
/** * DoSave */ static void DoSave() { Common::OutSaveFile *f; char tmpName[FNAMELEN]; // Next getList() must do its stuff again g_NeedLoad = true; if (g_SaveSceneName == NULL) { // Generate a new unique save name int i; int ano = 1; // Allocated number while (1) { Common::String fname = _vm->getSavegameFilename(ano); strcpy(tmpName, fname.c_str()); for (i = 0; i < g_numSfiles; i++) if (!strcmp(g_savedFiles[i].name, tmpName)) break; if (i == g_numSfiles) break; ano++; } g_SaveSceneName = tmpName; } if (g_SaveSceneDesc[0] == 0) g_SaveSceneDesc = "unnamed"; f = _vm->getSaveFileMan()->openForSaving(g_SaveSceneName); Common::Serializer s(0, f); if (f == NULL) { SaveFailure(f); return; } // Write out a savegame header SaveGameHeader hdr; hdr.id = SAVEGAME_ID; hdr.size = SAVEGAME_HEADER_SIZE; hdr.ver = CURRENT_VER; memcpy(hdr.desc, g_SaveSceneDesc, SG_DESC_LEN); hdr.desc[SG_DESC_LEN - 1] = 0; g_system->getTimeAndDate(hdr.dateTime); hdr.scnFlag = _vm->getFeatures() & GF_SCNFILES; hdr.language = _vm->_config->_language; if (!syncSaveGameHeader(s, hdr) || f->err()) { SaveFailure(f); return; } DoSync(s, hdr.numInterpreters); // Write out the special Id for Discworld savegames f->writeUint32LE(0xFEEDFACE); if (f->err()) { SaveFailure(f); return; } f->finalize(); delete f; g_SaveSceneName = NULL; // Invalidate save name }
/** * DoSave */ static void DoSave() { Common::OutSaveFile *f; char tmpName[FNAMELEN]; // Next getList() must do its stuff again NeedLoad = true; if (SaveSceneName == NULL) { // Generate a new unique save name int i; int ano = 1; // Allocated number while (1) { Common::String fname = _vm->getSavegameFilename(ano); strcpy(tmpName, fname.c_str()); for (i = 0; i < numSfiles; i++) if (!strcmp(savedFiles[i].name, tmpName)) break; if (i == numSfiles) break; ano++; } SaveSceneName = tmpName; } if (SaveSceneDesc[0] == 0) SaveSceneDesc = "unnamed"; f = _vm->getSaveFileMan()->openForSaving(SaveSceneName); Common::Serializer s(0, f); if (f == NULL) goto save_failure; // Write out a savegame header SaveGameHeader hdr; hdr.id = SAVEGAME_ID; hdr.size = SAVEGAME_HEADER_SIZE; hdr.ver = CURRENT_VER; memcpy(hdr.desc, SaveSceneDesc, SG_DESC_LEN); hdr.desc[SG_DESC_LEN - 1] = 0; g_system->getTimeAndDate(hdr.dateTime); if (!syncSaveGameHeader(s, hdr) || f->err()) { goto save_failure; } DoSync(s); // Write out the special Id for Discworld savegames f->writeUint32LE(0xFEEDFACE); if (f->err()) goto save_failure; f->finalize(); delete f; SaveSceneName = NULL; // Invalidate save name return; save_failure: if (f) { delete f; _vm->getSaveFileMan()->removeSavefile(SaveSceneName); SaveSceneName = NULL; // Invalidate save name } GUI::MessageDialog dialog("Failed to save game state to file."); dialog.runModal(); }