/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "common/scummsys.h" #include "common/system.h" #include "graphics/surface.h" #include "graphics/thumbnail.h" #include "zvision/save_manager.h" #include "zvision/zvision.h" #include "zvision/script_manager.h" namespace ZVision { const uint32 SaveManager::SAVEGAME_ID = MKTAG('Z', 'E', 'N', 'G'); void SaveManager::saveGame(uint slot, const Common::String &saveName) { Common::SaveFileManager *saveFileManager = g_system->getSavefileManager(); Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot)); // Write out the savegame header file->writeUint32BE(SAVEGAME_ID); // Write savegame name file->writeString(saveName); file->writeByte(0); // 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()); // Skip over the header info autoSaveFile->readSint32BE(); // SAVEGAME_ID autoSaveFile->seek(5, SEEK_CUR); // The string "auto" with terminating NULL // Read the rest to a buffer uint32 size = autoSaveFile->size() - autoSaveFile->pos(); byte *buffer = new byte[size]; autoSaveFile->read(buffer, size); // Then write the buffer to the new file file->write(buffer, size); // Cleanup delete[] buffer; file->finalize(); } void SaveManager::autoSave() { Common::OutSaveFile *file = g_system->getSavefileManager()->openForSaving(_engine->generateAutoSaveFileName()); // Write out the savegame header file->writeUint32BE(SAVEGAME_ID); file->writeString("auto"); file->writeByte(0); writeSaveGameData(file); file->finalize(); } void SaveManager::writeSaveGameData(Common::OutSaveFile *file) { // Create a thumbnail and save it Graphics::saveThumbnail(*file); // Write out the save date/time TimeDate td; g_system->getTimeAndDate(td); file->writeSint16LE(td.tm_year + 1900); file->writeSint16LE(td.tm_mon + 1); 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) { Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(_engine->generateSaveFileName(slot)); if (saveFile == 0) { return Common::kPathDoesNotExist; } // Read the header SaveGameHeader header; if (!readSaveGameHeader(saveFile, header)) { 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(); // Load the room scriptManager->changeLocation(world, room, node, view, offset); // Update the state table values scriptManager->deserializeStateTable(saveFile); // Update the controls scriptManager->deserializeControls(saveFile); return Common::kNoError; } bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header) { if (in->readUint32BE() != SAVEGAME_ID) { warning("File is not a ZVision save file. Aborting load"); return false; } // Read in the save name header.saveName.clear(); char ch; while ((ch = (char)in->readByte()) != '\0') header.saveName += ch; // Get the thumbnail header.thumbnail = Graphics::loadThumbnail(*in); if (!header.thumbnail) return false; // Read in save date/time header.saveYear = in->readSint16LE(); header.saveMonth = in->readSint16LE(); header.saveDay = in->readSint16LE(); header.saveHour = in->readSint16LE(); header.saveMinutes = in->readSint16LE(); return true; } } // End of namespace ZVision