aboutsummaryrefslogtreecommitdiff
path: root/engines/zvision/core/save_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/zvision/core/save_manager.cpp')
-rw-r--r--engines/zvision/core/save_manager.cpp186
1 files changed, 119 insertions, 67 deletions
diff --git a/engines/zvision/core/save_manager.cpp b/engines/zvision/core/save_manager.cpp
index e10201e024..9b36824c3b 100644
--- a/engines/zvision/core/save_manager.cpp
+++ b/engines/zvision/core/save_manager.cpp
@@ -42,68 +42,61 @@ const uint32 SaveManager::SAVEGAME_ID = MKTAG('Z', 'E', 'N', 'G');
void SaveManager::saveGame(uint slot, const Common::String &saveName) {
// The games only support 20 slots
- assert(slot <= 1 && slot <= 20);
+ //assert(slot <= 1 && slot <= 20);
Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot));
- // Write out the savegame header
- file->writeUint32BE(SAVEGAME_ID);
-
- // Write version
- file->writeByte(SAVE_VERSION);
+ writeSaveGameHeader(file, saveName);
- // Write savegame name
- file->writeString(saveName);
- file->writeByte(0);
+ _engine->getScriptManager()->serialize(file);
- // We can't call writeGameSaveData because the save menu is actually
- // a room, so writeGameSaveData would save us in the save menu.
- // However, an auto save is performed before each room change, so we
- // can copy the data from there. We can guarantee that an auto save file will
- // exist before this is called because the save menu can only be accessed
- // after the first room (the main menu) has loaded.
- Common::InSaveFile *autoSaveFile = saveFileManager->openForLoading(_engine->generateAutoSaveFileName());
+ file->finalize();
+ delete file;
+}
- // Skip over the header info
- autoSaveFile->readSint32BE(); // SAVEGAME_ID
- autoSaveFile->readByte(); // Version
- autoSaveFile->seek(5, SEEK_CUR); // The string "auto" with terminating NULL
+void SaveManager::saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream) {
+ Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
+ Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot));
- // Read the rest to a buffer
- uint32 size = autoSaveFile->size() - autoSaveFile->pos();
- byte *buffer = new byte[size];
- autoSaveFile->read(buffer, size);
+ writeSaveGameHeader(file, saveName);
- // Then write the buffer to the new file
- file->write(buffer, size);
+ file->write(stream->getData(), stream->size());
- // Cleanup
- delete[] buffer;
file->finalize();
delete file;
}
+void SaveManager::saveGameBuffered(uint slot, const Common::String &saveName) {
+ if (_tempSave) {
+ saveGame(slot, saveName, _tempSave);
+ flushSaveBuffer();
+ }
+}
+
void SaveManager::autoSave() {
Common::OutSaveFile *file = g_system->getSavefileManager()->openForSaving(_engine->generateAutoSaveFileName());
- // Write out the savegame header
- file->writeUint32BE(SAVEGAME_ID);
-
- // Version
- file->writeByte(SAVE_VERSION);
-
- file->writeString("auto");
- file->writeByte(0);
+ writeSaveGameHeader(file, "auto");
- writeSaveGameData(file);
+ _engine->getScriptManager()->serialize(file);
// Cleanup
file->finalize();
delete file;
}
-void SaveManager::writeSaveGameData(Common::OutSaveFile *file) {
+void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName) {
+
+ file->writeUint32BE(SAVEGAME_ID);
+
+ // Write version
+ file->writeByte(SAVE_VERSION);
+
+ // Write savegame name
+ file->writeString(saveName);
+ file->writeByte(0);
+
// Create a thumbnail and save it
Graphics::saveThumbnail(*file);
@@ -115,28 +108,13 @@ void SaveManager::writeSaveGameData(Common::OutSaveFile *file) {
file->writeSint16LE(td.tm_mday);
file->writeSint16LE(td.tm_hour);
file->writeSint16LE(td.tm_min);
-
- ScriptManager *scriptManager = _engine->getScriptManager();
- // Write out the current location
- Location currentLocation = scriptManager->getCurrentLocation();
- file->writeByte(currentLocation.world);
- file->writeByte(currentLocation.room);
- file->writeByte(currentLocation.node);
- file->writeByte(currentLocation.view);
- file->writeUint32LE(currentLocation.offset);
-
- // Write out the current state table values
- scriptManager->serializeStateTable(file);
-
- // Write out any controls needing to save state
- scriptManager->serializeControls(file);
}
Common::Error SaveManager::loadGame(uint slot) {
// The games only support 20 slots
- assert(slot <= 1 && slot <= 20);
+ //assert(slot <= 1 && slot <= 20);
- Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(_engine->generateSaveFileName(slot));
+ Common::SeekableReadStream *saveFile = getSlotFile(slot);
if (saveFile == 0) {
return Common::kPathDoesNotExist;
}
@@ -147,27 +125,60 @@ Common::Error SaveManager::loadGame(uint slot) {
return Common::kUnknownError;
}
- char world = (char)saveFile->readByte();
- char room = (char)saveFile->readByte();
- char node = (char)saveFile->readByte();
- char view = (char)saveFile->readByte();
- uint32 offset = (char)saveFile->readUint32LE();
-
ScriptManager *scriptManager = _engine->getScriptManager();
// Update the state table values
- scriptManager->deserializeStateTable(saveFile);
+ scriptManager->deserialize(saveFile);
+
+ delete saveFile;
+ if (header.thumbnail)
+ delete header.thumbnail;
+
+ return Common::kNoError;
+}
+
+Common::Error SaveManager::loadGame(const Common::String &saveName) {
+ Common::File *saveFile = _engine->getSearchManager()->openFile(saveName);
+ if (saveFile == NULL) {
+ saveFile = new Common::File;
+ if (!saveFile->open(saveName)) {
+ delete saveFile;
+ return Common::kPathDoesNotExist;
+ }
+ }
+
+ // Read the header
+ SaveGameHeader header;
+ if (!readSaveGameHeader(saveFile, header)) {
+ return Common::kUnknownError;
+ }
- // Load the room
- scriptManager->changeLocation(world, room, node, view, offset);
+ ScriptManager *scriptManager = _engine->getScriptManager();
+ // Update the state table values
+ scriptManager->deserialize(saveFile);
- // Update the controls
- scriptManager->deserializeControls(saveFile);
+ delete saveFile;
+ if (header.thumbnail)
+ delete header.thumbnail;
return Common::kNoError;
}
bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header) {
- if (in->readUint32BE() != SAVEGAME_ID) {
+ uint32 tag = in->readUint32BE();
+ // Check if it's original savegame than fill header structure
+ if (tag == MKTAG('Z', 'N', 'S', 'G')) {
+ header.saveYear = 0;
+ header.saveMonth = 0;
+ header.saveDay = 0;
+ header.saveHour = 0;
+ header.saveMinutes = 0;
+ header.saveName = "Original Save";
+ header.thumbnail = NULL;
+ header.version = SAVE_ORIGINAL;
+ in->seek(-4, SEEK_CUR);
+ return true;
+ }
+ if (tag != SAVEGAME_ID) {
warning("File is not a ZVision save file. Aborting load");
return false;
}
@@ -203,4 +214,45 @@ bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &hea
return true;
}
+Common::SeekableReadStream *SaveManager::getSlotFile(uint slot) {
+ Common::SeekableReadStream *saveFile = g_system->getSavefileManager()->openForLoading(_engine->generateSaveFileName(slot));
+ if (saveFile == NULL) {
+ // Try to load standard save file
+ Common::String filename;
+ if (_engine->getGameId() == GID_GRANDINQUISITOR)
+ filename = Common::String::format("inqsav%u.sav", slot);
+ else if (_engine->getGameId() == GID_NEMESIS)
+ filename = Common::String::format("nemsav%u.sav", slot);
+
+ saveFile = _engine->getSearchManager()->openFile(filename);
+ if (saveFile == NULL) {
+ Common::File *tmpFile = new Common::File;
+ if (!tmpFile->open(filename)) {
+ delete tmpFile;
+ } else {
+ saveFile = tmpFile;
+ }
+ }
+
+ }
+
+ return saveFile;
+}
+
+void SaveManager::prepareSaveBuffer() {
+ if (_tempSave)
+ delete _tempSave;
+
+ _tempSave = new Common::MemoryWriteStreamDynamic;
+
+ _engine->getScriptManager()->serialize(_tempSave);
+}
+
+void SaveManager::flushSaveBuffer() {
+ if (_tempSave)
+ delete _tempSave;
+
+ _tempSave = NULL;
+}
+
} // End of namespace ZVision