citra-emu
/
citra-canary
Archived
1
0
Fork 0

Show save/load errors to the user

This commit is contained in:
Hamish Milne 2020-04-12 23:12:15 +01:00
parent 915c426dc9
commit d53e94db88
4 changed files with 34 additions and 39 deletions

View File

@ -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 =

View File

@ -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;
} }

View File

@ -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
}; };

View File

@ -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