mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-16 14:50:17 +00:00
207 lines
6.2 KiB
C++
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
|