Show save/load errors to the user
This commit is contained in:
parent
915c426dc9
commit
d53e94db88
|
@ -2079,6 +2079,9 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
|
||||||
|
|
||||||
title = tr("System Archive Not Found");
|
title = tr("System Archive Not Found");
|
||||||
status_message = tr("System Archive Missing");
|
status_message = tr("System Archive Missing");
|
||||||
|
} else if (result == Core::System::ResultStatus::ErrorSavestate) {
|
||||||
|
title = tr("Save/load Error");
|
||||||
|
message = QString::fromStdString(details);
|
||||||
} else {
|
} else {
|
||||||
title = tr("Fatal Error");
|
title = tr("Fatal Error");
|
||||||
message =
|
message =
|
||||||
|
|
|
@ -107,15 +107,27 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
|
||||||
return ResultStatus::ShutdownRequested;
|
return ResultStatus::ShutdownRequested;
|
||||||
case Signal::Load: {
|
case Signal::Load: {
|
||||||
LOG_INFO(Core, "Begin load");
|
LOG_INFO(Core, "Begin load");
|
||||||
|
try {
|
||||||
System::LoadState(param);
|
System::LoadState(param);
|
||||||
LOG_INFO(Core, "Load completed");
|
LOG_INFO(Core, "Load completed");
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
LOG_ERROR(Core, "Error loading: {}", e.what());
|
||||||
|
status_details = e.what();
|
||||||
|
return ResultStatus::ErrorSavestate;
|
||||||
|
}
|
||||||
frame_limiter.WaitOnce();
|
frame_limiter.WaitOnce();
|
||||||
return ResultStatus::Success;
|
return ResultStatus::Success;
|
||||||
}
|
}
|
||||||
case Signal::Save: {
|
case Signal::Save: {
|
||||||
LOG_INFO(Core, "Begin save");
|
LOG_INFO(Core, "Begin save");
|
||||||
|
try {
|
||||||
System::SaveState(param);
|
System::SaveState(param);
|
||||||
LOG_INFO(Core, "Save completed");
|
LOG_INFO(Core, "Save completed");
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
LOG_ERROR(Core, "Error saving: {}", e.what());
|
||||||
|
status_details = e.what();
|
||||||
|
return ResultStatus::ErrorSavestate;
|
||||||
|
}
|
||||||
frame_limiter.WaitOnce();
|
frame_limiter.WaitOnce();
|
||||||
return ResultStatus::Success;
|
return ResultStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@ public:
|
||||||
/// generic drivers installed
|
/// generic drivers installed
|
||||||
ErrorVideoCore_ErrorBelowGL33, ///< Error in the video core due to the user not having
|
ErrorVideoCore_ErrorBelowGL33, ///< Error in the video core due to the user not having
|
||||||
/// OpenGL 3.3 or higher
|
/// OpenGL 3.3 or higher
|
||||||
|
ErrorSavestate, ///< Error saving or loading
|
||||||
ShutdownRequested, ///< Emulated program requested a system shutdown
|
ShutdownRequested, ///< Emulated program requested a system shutdown
|
||||||
ErrorUnknown ///< Any other error
|
ErrorUnknown ///< Any other error
|
||||||
};
|
};
|
||||||
|
|
|
@ -90,26 +90,22 @@ std::vector<SaveStateInfo> ListSaveStates(u64 program_id) {
|
||||||
|
|
||||||
void System::SaveState(u32 slot) const {
|
void System::SaveState(u32 slot) const {
|
||||||
std::ostringstream sstream{std::ios_base::binary};
|
std::ostringstream sstream{std::ios_base::binary};
|
||||||
try {
|
// Serialize
|
||||||
oarchive oa{sstream};
|
oarchive oa{sstream};
|
||||||
oa&* this;
|
oa&* this;
|
||||||
} catch (const std::exception& e) {
|
|
||||||
LOG_ERROR(Core, "Error saving: {}", e.what());
|
|
||||||
}
|
|
||||||
const std::string& str{sstream.str()};
|
const std::string& str{sstream.str()};
|
||||||
auto buffer = Common::Compression::CompressDataZSTDDefault(
|
auto buffer = Common::Compression::CompressDataZSTDDefault(
|
||||||
reinterpret_cast<const u8*>(str.data()), str.size());
|
reinterpret_cast<const u8*>(str.data()), str.size());
|
||||||
|
|
||||||
const auto path = GetSaveStatePath(title_id, slot);
|
const auto path = GetSaveStatePath(title_id, slot);
|
||||||
if (!FileUtil::CreateFullPath(path)) {
|
if (!FileUtil::CreateFullPath(path)) {
|
||||||
LOG_ERROR(Core, "Could not create path {}", path);
|
throw std::runtime_error("Could not create path " + path);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileUtil::IOFile file(path, "wb");
|
FileUtil::IOFile file(path, "wb");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
LOG_ERROR(Core, "Could not open file {}", path);
|
throw std::runtime_error("Could not open file " + path);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSTHeader header{};
|
CSTHeader header{};
|
||||||
|
@ -123,41 +119,27 @@ void System::SaveState(u32 slot) const {
|
||||||
std::chrono::system_clock::now().time_since_epoch())
|
std::chrono::system_clock::now().time_since_epoch())
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
if (file.WriteBytes(&header, sizeof(header)) != sizeof(header)) {
|
if (file.WriteBytes(&header, sizeof(header)) != sizeof(header) ||
|
||||||
LOG_ERROR(Core, "Could not write to file {}", path);
|
file.WriteBytes(buffer.data(), buffer.size()) != buffer.size()) {
|
||||||
return;
|
throw std::runtime_error("Could not write to file " + path);
|
||||||
}
|
|
||||||
if (file.WriteBytes(buffer.data(), buffer.size()) != buffer.size()) {
|
|
||||||
LOG_ERROR(Core, "Could not write to file {}", path);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::LoadState(u32 slot) {
|
void System::LoadState(u32 slot) {
|
||||||
if (Network::GetRoomMember().lock()->IsConnected()) {
|
if (Network::GetRoomMember().lock()->IsConnected()) {
|
||||||
LOG_ERROR(Core, "Unable to load while connected to multiplayer");
|
throw std::runtime_error("Unable to load while connected to multiplayer");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto path = GetSaveStatePath(title_id, slot);
|
const auto path = GetSaveStatePath(title_id, slot);
|
||||||
if (!FileUtil::Exists(path)) {
|
|
||||||
LOG_ERROR(Core, "File not exist {}", path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<u8> decompressed;
|
std::vector<u8> decompressed;
|
||||||
{
|
{
|
||||||
std::vector<u8> buffer(FileUtil::GetSize(path) - sizeof(CSTHeader));
|
std::vector<u8> buffer(FileUtil::GetSize(path) - sizeof(CSTHeader));
|
||||||
|
|
||||||
FileUtil::IOFile file(path, "rb");
|
FileUtil::IOFile file(path, "rb");
|
||||||
if (!file) {
|
|
||||||
LOG_ERROR(Core, "Could not open file {}", path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
file.Seek(sizeof(CSTHeader), SEEK_SET); // Skip header
|
file.Seek(sizeof(CSTHeader), SEEK_SET); // Skip header
|
||||||
if (file.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) {
|
if (file.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) {
|
||||||
LOG_ERROR(Core, "Could not read from file {}", path);
|
throw std::runtime_error("Could not read from file at " + path);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
decompressed = Common::Compression::DecompressDataZSTD(buffer);
|
decompressed = Common::Compression::DecompressDataZSTD(buffer);
|
||||||
}
|
}
|
||||||
|
@ -166,12 +148,9 @@ void System::LoadState(u32 slot) {
|
||||||
std::ios_base::binary};
|
std::ios_base::binary};
|
||||||
decompressed.clear();
|
decompressed.clear();
|
||||||
|
|
||||||
try {
|
// Deserialize
|
||||||
iarchive ia{sstream};
|
iarchive ia{sstream};
|
||||||
ia&* this;
|
ia&* this;
|
||||||
} catch (const std::exception& e) {
|
|
||||||
LOG_ERROR(Core, "Error loading: {}", e.what());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
Reference in New Issue