2015-07-01 23:17:14 -04:00
|
|
|
#include "stdafx.h"
|
2017-05-06 15:27:48 -04:00
|
|
|
#include "../Utilities/FolderUtilities.h"
|
|
|
|
#include "../Utilities/ZipWriter.h"
|
|
|
|
#include "../Utilities/ZipReader.h"
|
2015-07-01 23:17:14 -04:00
|
|
|
#include "SaveStateManager.h"
|
|
|
|
#include "MessageManager.h"
|
|
|
|
#include "Console.h"
|
2016-01-16 09:25:34 -05:00
|
|
|
#include "EmulationSettings.h"
|
2017-05-06 15:27:48 -04:00
|
|
|
#include "VideoDecoder.h"
|
2015-07-01 23:17:14 -04:00
|
|
|
|
2016-06-02 23:56:11 -04:00
|
|
|
const uint32_t SaveStateManager::FileFormatVersion;
|
2016-12-11 10:56:23 -05:00
|
|
|
atomic<uint32_t> SaveStateManager::_lastIndex(1);
|
2016-06-02 23:56:11 -04:00
|
|
|
|
2015-07-11 08:27:22 -04:00
|
|
|
string SaveStateManager::GetStateFilepath(int stateIndex)
|
2015-07-01 23:17:14 -04:00
|
|
|
{
|
2015-07-11 08:27:22 -04:00
|
|
|
string folder = FolderUtilities::GetSaveStateFolder();
|
2016-06-17 20:53:05 -04:00
|
|
|
string filename = FolderUtilities::GetFilename(Console::GetRomName(), false) + "_" + std::to_string(stateIndex) + ".mst";
|
2015-07-01 23:17:14 -04:00
|
|
|
return FolderUtilities::CombinePath(folder, filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t SaveStateManager::GetStateInfo(int stateIndex)
|
|
|
|
{
|
2015-07-11 08:27:22 -04:00
|
|
|
string filepath = SaveStateManager::GetStateFilepath(stateIndex);
|
2015-07-01 23:17:14 -04:00
|
|
|
ifstream file(filepath, ios::in | ios::binary);
|
|
|
|
|
|
|
|
if(file) {
|
|
|
|
file.close();
|
|
|
|
return FolderUtilities::GetFileModificationTime(filepath);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-02 19:36:37 -04:00
|
|
|
void SaveStateManager::MoveToNextSlot()
|
|
|
|
{
|
|
|
|
_lastIndex = (_lastIndex % MaxIndex) + 1;
|
|
|
|
MessageManager::DisplayMessage("SaveStates", "SaveStateSlotSelected", std::to_string(_lastIndex));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveStateManager::MoveToPreviousSlot()
|
|
|
|
{
|
|
|
|
_lastIndex = (_lastIndex == 1 ? SaveStateManager::MaxIndex : (_lastIndex - 1));
|
|
|
|
MessageManager::DisplayMessage("SaveStates", "SaveStateSlotSelected", std::to_string(_lastIndex));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveStateManager::SaveState()
|
|
|
|
{
|
|
|
|
SaveState(_lastIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SaveStateManager::LoadState()
|
|
|
|
{
|
|
|
|
return LoadState(_lastIndex);
|
|
|
|
}
|
|
|
|
|
2017-05-06 15:27:48 -04:00
|
|
|
void SaveStateManager::SaveState(ostream &stream)
|
|
|
|
{
|
|
|
|
Console::Pause();
|
|
|
|
|
|
|
|
uint32_t emuVersion = EmulationSettings::GetMesenVersion();
|
|
|
|
stream.write("MST", 3);
|
|
|
|
stream.write((char*)&emuVersion, sizeof(emuVersion));
|
|
|
|
stream.write((char*)&SaveStateManager::FileFormatVersion, sizeof(uint32_t));
|
|
|
|
|
|
|
|
Console::SaveState(stream);
|
|
|
|
Console::Resume();
|
|
|
|
}
|
|
|
|
|
2016-08-31 20:54:38 -04:00
|
|
|
void SaveStateManager::SaveState(int stateIndex, bool displayMessage)
|
2015-07-01 23:17:14 -04:00
|
|
|
{
|
2015-07-11 08:27:22 -04:00
|
|
|
string filepath = SaveStateManager::GetStateFilepath(stateIndex);
|
2015-07-01 23:17:14 -04:00
|
|
|
ofstream file(filepath, ios::out | ios::binary);
|
|
|
|
|
|
|
|
if(file) {
|
2016-09-02 19:36:37 -04:00
|
|
|
_lastIndex = stateIndex;
|
2017-05-06 15:27:48 -04:00
|
|
|
SaveState(file);
|
|
|
|
file.close();
|
2016-09-02 19:36:37 -04:00
|
|
|
|
2017-05-06 15:27:48 -04:00
|
|
|
if(displayMessage) {
|
|
|
|
MessageManager::DisplayMessage("SaveStates", "SaveStateSaved", std::to_string(stateIndex));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-01-16 09:25:34 -05:00
|
|
|
|
2017-05-06 15:27:48 -04:00
|
|
|
bool SaveStateManager::LoadState(istream &stream)
|
|
|
|
{
|
|
|
|
char header[3];
|
|
|
|
stream.read(header, 3);
|
|
|
|
if(memcmp(header, "MST", 3) == 0) {
|
|
|
|
uint32_t emuVersion, fileFormatVersion;
|
|
|
|
|
|
|
|
stream.read((char*)&emuVersion, sizeof(emuVersion));
|
|
|
|
if(emuVersion > EmulationSettings::GetMesenVersion()) {
|
|
|
|
MessageManager::DisplayMessage("SaveStates", "SaveStateNewerVersion");
|
|
|
|
return false;
|
|
|
|
}
|
2016-01-16 09:25:34 -05:00
|
|
|
|
2017-05-06 15:27:48 -04:00
|
|
|
stream.read((char*)&fileFormatVersion, sizeof(fileFormatVersion));
|
|
|
|
if(fileFormatVersion != SaveStateManager::FileFormatVersion) {
|
|
|
|
MessageManager::DisplayMessage("SaveStates", "SaveStateIncompatibleVersion"); // , std::to_string(stateIndex));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Console::Pause();
|
|
|
|
Console::LoadState(stream);
|
2015-07-01 23:17:14 -04:00
|
|
|
Console::Resume();
|
2016-08-31 20:54:38 -04:00
|
|
|
|
2017-05-06 15:27:48 -04:00
|
|
|
return true;
|
2015-07-01 23:17:14 -04:00
|
|
|
}
|
2017-05-06 15:27:48 -04:00
|
|
|
|
|
|
|
return false;
|
2015-07-01 23:17:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SaveStateManager::LoadState(int stateIndex)
|
|
|
|
{
|
2015-07-11 08:27:22 -04:00
|
|
|
string filepath = SaveStateManager::GetStateFilepath(stateIndex);
|
2015-07-01 23:17:14 -04:00
|
|
|
ifstream file(filepath, ios::in | ios::binary);
|
2016-01-16 09:25:34 -05:00
|
|
|
bool result = false;
|
2015-07-01 23:17:14 -04:00
|
|
|
|
|
|
|
if(file) {
|
2017-05-06 15:27:48 -04:00
|
|
|
if(LoadState(file)) {
|
2016-09-02 19:36:37 -04:00
|
|
|
_lastIndex = stateIndex;
|
2016-09-02 20:10:50 -04:00
|
|
|
MessageManager::DisplayMessage("SaveStates", "SaveStateLoaded", std::to_string(stateIndex));
|
2016-01-16 09:25:34 -05:00
|
|
|
result = true;
|
2016-02-07 20:07:19 -05:00
|
|
|
} else {
|
2016-09-02 20:10:50 -04:00
|
|
|
MessageManager::DisplayMessage("SaveStates", "SaveStateInvalidFile");
|
2016-01-16 09:25:34 -05:00
|
|
|
}
|
2015-07-01 23:17:14 -04:00
|
|
|
file.close();
|
2016-01-16 09:25:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if(!result) {
|
2016-09-02 20:10:50 -04:00
|
|
|
MessageManager::DisplayMessage("SaveStates", "SaveStateEmpty");
|
2015-07-01 23:17:14 -04:00
|
|
|
}
|
|
|
|
|
2016-01-16 09:25:34 -05:00
|
|
|
return result;
|
2017-05-06 15:27:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void SaveStateManager::SaveRecentGame(string romName, string romPath, string patchPath, int32_t archiveFileIndex)
|
|
|
|
{
|
|
|
|
if(!EmulationSettings::CheckFlag(EmulationFlags::ConsoleMode) && Console::GetRomFormat() != RomFormat::Nsf) {
|
|
|
|
string filename = FolderUtilities::GetFilename(Console::GetRomName(), false) + ".rgd";
|
|
|
|
ZipWriter writer(FolderUtilities::CombinePath(FolderUtilities::GetRecentGamesFolder(), filename));
|
|
|
|
|
|
|
|
std::stringstream pngStream;
|
|
|
|
VideoDecoder::GetInstance()->TakeScreenshot(pngStream);
|
|
|
|
writer.AddFile(pngStream, "Screenshot.png");
|
|
|
|
|
|
|
|
std::stringstream stateStream;
|
|
|
|
SaveStateManager::SaveState(stateStream);
|
|
|
|
writer.AddFile(stateStream, "Savestate.mst");
|
|
|
|
|
|
|
|
std::stringstream romInfoStream;
|
|
|
|
romInfoStream << romName << std::endl;
|
|
|
|
romInfoStream << romPath << std::endl;
|
|
|
|
romInfoStream << patchPath << std::endl;
|
|
|
|
romInfoStream << std::to_string(archiveFileIndex) << std::endl;
|
|
|
|
writer.AddFile(romInfoStream, "RomInfo.txt");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveStateManager::LoadRecentGame(string filename)
|
|
|
|
{
|
|
|
|
ZipReader reader;
|
|
|
|
reader.LoadArchive(filename);
|
|
|
|
|
|
|
|
std::stringstream romInfoStream = reader.GetStream("RomInfo.txt");
|
|
|
|
std::stringstream stateStream = reader.GetStream("Savestate.mst");
|
|
|
|
|
|
|
|
string romName, romPath, patchPath, archiveIndex;
|
|
|
|
std::getline(romInfoStream, romName);
|
|
|
|
std::getline(romInfoStream, romPath);
|
|
|
|
std::getline(romInfoStream, patchPath);
|
|
|
|
std::getline(romInfoStream, archiveIndex);
|
|
|
|
|
|
|
|
Console::Pause();
|
|
|
|
try {
|
|
|
|
Console::LoadROM(romPath, nullptr, std::stoi(archiveIndex.c_str()), patchPath);
|
|
|
|
SaveStateManager::LoadState(stateStream);
|
|
|
|
} catch(std::exception ex) {
|
|
|
|
Console::GetInstance()->Stop();
|
|
|
|
}
|
|
|
|
Console::Resume();
|
2015-07-01 23:17:14 -04:00
|
|
|
}
|