Show save/load errors to the user
This commit is contained in:
		@@ -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");
 | 
				
			||||||
        System::LoadState(param);
 | 
					        try {
 | 
				
			||||||
        LOG_INFO(Core, "Load completed");
 | 
					            System::LoadState(param);
 | 
				
			||||||
 | 
					            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");
 | 
				
			||||||
        System::SaveState(param);
 | 
					        try {
 | 
				
			||||||
        LOG_INFO(Core, "Save completed");
 | 
					            System::SaveState(param);
 | 
				
			||||||
 | 
					            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
	
	Block a user