Clear out state before deserialization - fixes many crashes.

This commit is contained in:
Hamish Milne 2020-04-01 22:06:22 +01:00
parent f156fdd332
commit 5b6ee9a6ab
5 changed files with 24 additions and 9 deletions

View file

@ -132,7 +132,9 @@ void OpenGLWindow::Present() {
return; return;
context->makeCurrent(this); context->makeCurrent(this);
VideoCore::g_renderer->TryPresent(100); if (VideoCore::g_renderer) {
VideoCore::g_renderer->TryPresent(100);
}
context->swapBuffers(this); context->swapBuffers(this);
auto f = context->versionFunctions<QOpenGLFunctions_3_3_Core>(); auto f = context->versionFunctions<QOpenGLFunctions_3_3_Core>();
f->glFinish(); f->glFinish();

View file

@ -12,7 +12,7 @@ namespace boost::serialization {
template <class Archive, class T> template <class Archive, class T>
void save(Archive& ar, const boost::icl::interval_set<T>& set, const unsigned int file_version) { void save(Archive& ar, const boost::icl::interval_set<T>& set, const unsigned int file_version) {
ar << static_cast<u64>(set.size()); ar << static_cast<u64>(set.iterative_size());
for (auto& v : set) { for (auto& v : set) {
ar << v; ar << v;
} }
@ -24,9 +24,9 @@ void load(Archive& ar, boost::icl::interval_set<T>& set, const unsigned int file
ar >> count; ar >> count;
set.clear(); set.clear();
for (u64 i = 0; i < count; i++) { for (u64 i = 0; i < count; i++) {
T value{}; typename boost::icl::interval_set<T>::interval_type value{};
ar >> value; ar >> value;
set.insert(value); set.add(value);
} }
} }

View file

@ -478,7 +478,7 @@ void System::RegisterImageInterface(std::shared_ptr<Frontend::ImageInterface> im
registered_image_interface = std::move(image_interface); registered_image_interface = std::move(image_interface);
} }
void System::Shutdown() { void System::Shutdown(bool is_deserializing) {
// Log last frame performance stats // Log last frame performance stats
const auto perf_results = GetAndResetPerfStats(); const auto perf_results = GetAndResetPerfStats();
telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed", telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed",
@ -494,17 +494,19 @@ void System::Shutdown() {
GDBStub::Shutdown(); GDBStub::Shutdown();
VideoCore::Shutdown(); VideoCore::Shutdown();
HW::Shutdown(); HW::Shutdown();
if (!is_deserializing) {
perf_stats.reset();
cheat_engine.reset();
app_loader.reset();
}
telemetry_session.reset(); telemetry_session.reset();
perf_stats.reset();
rpc_server.reset(); rpc_server.reset();
cheat_engine.reset();
archive_manager.reset(); archive_manager.reset();
service_manager.reset(); service_manager.reset();
dsp_core.reset(); dsp_core.reset();
cpu_cores.clear(); cpu_cores.clear();
kernel.reset(); kernel.reset();
timing.reset(); timing.reset();
app_loader.reset();
if (video_dumper->IsDumping()) { if (video_dumper->IsDumping()) {
video_dumper->StopDumping(); video_dumper->StopDumping();
@ -565,6 +567,7 @@ void System::serialize(Archive& ar, const unsigned int file_version) {
// This needs to be set from somewhere - might as well be here! // This needs to be set from somewhere - might as well be here!
if (Archive::is_loading::value) { if (Archive::is_loading::value) {
Service::GSP::SetGlobalModule(*this); Service::GSP::SetGlobalModule(*this);
memory->SetDSP(*dsp_core);
} }
} }

View file

@ -113,7 +113,7 @@ public:
ResultStatus SingleStep(); ResultStatus SingleStep();
/// Shutdown the emulated system. /// Shutdown the emulated system.
void Shutdown(); void Shutdown(bool is_deserializing = false);
/// Shutdown and then load again /// Shutdown and then load again
void Reset(); void Reset();

View file

@ -8,6 +8,7 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/scm_rev.h" #include "common/scm_rev.h"
#include "common/zstd_compression.h" #include "common/zstd_compression.h"
#include "core/cheats/cheats.h"
#include "core/core.h" #include "core/core.h"
#include "core/savestate.h" #include "core/savestate.h"
#include "video_core/video_core.h" #include "video_core/video_core.h"
@ -158,6 +159,15 @@ void System::LoadState(u32 slot) {
std::ios_base::binary}; std::ios_base::binary};
decompressed.clear(); decompressed.clear();
// When loading, we want to make sure any lingering state gets cleared out before we begin.
// Shutdown, but persist a few things between loads...
Shutdown(true);
// Re-initialize everything like it was before
auto system_mode = this->app_loader->LoadKernelSystemMode();
auto n3ds_mode = this->app_loader->LoadKernelN3dsMode();
Init(*m_emu_window, *system_mode.first, *n3ds_mode.first);
try { try {
{ {