scummvm/engines/zvision/save_manager.cpp
2013-10-20 18:39:06 +00:00

207 lines
6.2 KiB
C++

/* 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 "zvision/save_manager.h"
#include "zvision/zvision.h"
#include "zvision/script_manager.h"
#include "zvision/render_manager.h"
#include "common/system.h"
#include "graphics/surface.h"
#include "graphics/thumbnail.h"
#include "gui/message.h"
namespace ZVision {
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);
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);
// 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->readByte(); // Version
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();
delete file;
}
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);
writeSaveGameData(file);
// Cleanup
file->finalize();
delete file;
}
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) {
// The games only support 20 slots
assert(slot <= 1 && slot <= 20);
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();
// Update the state table values
scriptManager->deserializeStateTable(saveFile);
// Load the room
scriptManager->changeLocation(world, room, node, view, offset);
// 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 version
header.version = in->readByte();
// Check that the save version isn't newer than this binary
if (header.version > SAVE_VERSION) {
uint tempVersion = header.version;
GUI::MessageDialog dialog(Common::String::format("This save file uses version %u, but this engine only supports up to version %d. You will need an updated version of the engine to use this save file.", tempVersion, SAVE_VERSION), "OK");
dialog.runModal();
}
// 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