Skip to content

Commit

Permalink
ZVISION: Refactor of save functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Marisa-Chan committed Mar 5, 2014
1 parent eb9061e commit 2a4e9a6
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 83 deletions.
157 changes: 95 additions & 62 deletions engines/zvision/save_manager.cpp
Expand Up @@ -42,68 +42,54 @@ 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::autoSave() {
Common::OutSaveFile *file = g_system->getSavefileManager()->openForSaving(_engine->generateAutoSaveFileName());

// Write out the savegame header
file->writeUint32BE(SAVEGAME_ID);

// Version
file->writeByte(SAVE_VERSION);
writeSaveGameHeader(file, "auto");

file->writeString("auto");
file->writeByte(0);

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);

Expand All @@ -115,26 +101,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);

}

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;
}
Expand All @@ -145,24 +118,59 @@ 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->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;
}

ScriptManager *scriptManager = _engine->getScriptManager();
// Update the state table values
scriptManager->deserializeStateTable(saveFile);
scriptManager->deserialize(saveFile);

// Load the room
scriptManager->changeLocation(world, room, node, view, offset);
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();
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;
}
Expand Down Expand Up @@ -198,4 +206,29 @@ 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 standart save file
Common::String filename;
if (_engine->getGameId() == GID_GRANDINQUISITOR)
filename.format("inqsav%u.sav", slot);
else if (_engine->getGameId() == GID_NEMESIS)
filename.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;
}

} // End of namespace ZVision
9 changes: 7 additions & 2 deletions engines/zvision/save_manager.h
Expand Up @@ -24,6 +24,7 @@
#define ZVISION_SAVE_MANAGER_H

#include "common/savefile.h"
#include "common/memstream.h"

namespace Common {
class String;
Expand Down Expand Up @@ -54,6 +55,7 @@ class SaveManager {
static const uint32 SAVEGAME_ID;

enum {
SAVE_ORIGINAL = 0,
SAVE_VERSION = 1
};

Expand All @@ -73,17 +75,20 @@ class SaveManager {
* @param saveName The internal name for this save. This is NOT the name of the actual save file.
*/
void saveGame(uint slot, const Common::String &saveName);
void saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream);
/**
* Loads the state data from the save file that slot references. Uses
* ZVision::generateSaveFileName(slot) to get the save file name.
*
* @param slot The save slot to load. Must be [1, 20]
*/
Common::Error loadGame(uint slot);
Common::Error loadGame(const Common::String &saveName);

Common::SeekableReadStream *getSlotFile(uint slot);
bool readSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &header);
private:
void writeSaveGameData(Common::OutSaveFile *file);
bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header);
void writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName);
};

} // End of namespace ZVision
Expand Down

0 comments on commit 2a4e9a6

Please sign in to comment.