From 0409013e6dd59e1f2348c89a7122b5a21f6202cc Mon Sep 17 00:00:00 2001 From: PabloMK7 Date: Wed, 12 Mar 2025 00:05:39 +0100 Subject: [PATCH] Various savestate bugfixes --- .../features/settings/model/BooleanSetting.kt | 10 ++- .../settings/ui/SettingsFragmentPresenter.kt | 19 ++++++ src/android/app/src/main/jni/default_ini.h | 11 +++- .../app/src/main/res/values/strings.xml | 4 ++ .../configuration/configure_debug.cpp | 4 ++ src/citra_qt/configuration/configure_debug.ui | 10 +++ src/citra_sdl/config.cpp | 4 +- src/common/archives.h | 7 +- src/common/logging/filter.cpp | 3 +- src/common/logging/types.h | 3 +- src/common/settings.h | 1 + src/core/core.cpp | 65 ++++++++++++++++--- src/core/core.h | 18 +++++ src/core/file_sys/archive_extsavedata.cpp | 10 ++- src/core/file_sys/disk_archive.h | 4 +- src/core/hle/kernel/hle_ipc.cpp | 6 +- src/core/hle/kernel/hle_ipc.h | 36 +++++----- src/core/hle/kernel/kernel.h | 20 +++++- src/core/hle/kernel/thread.cpp | 15 ++++- src/core/hle/kernel/thread.h | 10 ++- src/core/hle/service/ac/ac.cpp | 3 +- src/core/hle/service/act/act.cpp | 16 ++++- src/core/hle/service/act/act.h | 13 +++- src/core/hle/service/am/am.cpp | 1 + src/core/hle/service/apt/apt.cpp | 3 +- src/core/hle/service/boss/boss.cpp | 3 +- src/core/hle/service/cam/cam.cpp | 3 +- src/core/hle/service/cecd/cecd.cpp | 3 +- src/core/hle/service/cfg/cfg.cpp | 1 + src/core/hle/service/csnd/csnd_snd.h | 4 +- src/core/hle/service/dsp/dsp_dsp.h | 3 +- src/core/hle/service/frd/frd.h | 3 +- src/core/hle/service/fs/fs_user.cpp | 1 + src/core/hle/service/gsp/gsp_gpu.cpp | 3 +- src/core/hle/service/hid/hid.cpp | 3 +- src/core/hle/service/http/http_c.h | 3 +- src/core/hle/service/ir/ir_rst.cpp | 3 +- src/core/hle/service/ir/ir_user.cpp | 3 +- src/core/hle/service/ldr_ro/ldr_ro.h | 3 +- src/core/hle/service/mic/mic_u.cpp | 3 +- src/core/hle/service/ndm/ndm_u.h | 3 +- src/core/hle/service/news/news.cpp | 3 +- src/core/hle/service/nfc/nfc.cpp | 3 +- src/core/hle/service/nim/nim_u.h | 3 +- src/core/hle/service/nwm/nwm_uds.cpp | 1 + src/core/hle/service/plgldr/plgldr.cpp | 3 +- src/core/hle/service/ptm/ptm.cpp | 1 + src/core/hle/service/service.cpp | 18 ++++- src/core/hle/service/service.h | 4 +- src/core/hle/service/sm/sm.h | 4 +- src/core/hle/service/sm/srv.cpp | 3 +- src/core/hle/service/soc/soc_u.h | 3 +- 52 files changed, 318 insertions(+), 69 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt index 4e5481d7c..793f028f7 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt @@ -1,4 +1,4 @@ -// Copyright 2023 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -15,7 +15,9 @@ enum class BooleanSetting( ALLOW_PLUGIN_LOADER("allow_plugin_loader", Settings.SECTION_SYSTEM, true), SWAP_SCREEN("swap_screen", Settings.SECTION_LAYOUT, false), INSTANT_DEBUG_LOG("instant_debug_log", Settings.SECTION_DEBUG, false), - CUSTOM_LAYOUT("custom_layout",Settings.SECTION_LAYOUT,false); + CUSTOM_LAYOUT("custom_layout",Settings.SECTION_LAYOUT,false), + DELAY_START_LLE_MODULES("delay_start_for_lle_modules", Settings.SECTION_DEBUG, true), + DETERMINISTIC_ASYNC_OPERATIONS("deterministic_async_operations", Settings.SECTION_DEBUG, false); override var boolean: Boolean = defaultValue @@ -36,7 +38,9 @@ enum class BooleanSetting( private val NOT_RUNTIME_EDITABLE = listOf( PLUGIN_LOADER, ALLOW_PLUGIN_LOADER, - ASYNC_SHADERS + ASYNC_SHADERS, + DELAY_START_LLE_MODULES, + DETERMINISTIC_ASYNC_OPERATIONS, ) fun from(key: String): BooleanSetting? = diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index 31401567f..3f1b98088 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -1360,6 +1360,25 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) BooleanSetting.INSTANT_DEBUG_LOG.defaultValue ) ) + add( + SwitchSetting( + BooleanSetting.DELAY_START_LLE_MODULES, + R.string.delay_start_lle_modules, + R.string.delay_start_lle_modules_desc, + BooleanSetting.DELAY_START_LLE_MODULES.key, + BooleanSetting.DELAY_START_LLE_MODULES.defaultValue + ) + ) + add( + SwitchSetting( + BooleanSetting.DETERMINISTIC_ASYNC_OPERATIONS, + R.string.deterministic_async_operations, + R.string.deterministic_async_operations_desc, + BooleanSetting.DETERMINISTIC_ASYNC_OPERATIONS.key, + BooleanSetting.DETERMINISTIC_ASYNC_OPERATIONS.defaultValue + ) + ) + } } diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h index 5c802856e..b60dde668 100644 --- a/src/android/app/src/main/jni/default_ini.h +++ b/src/android/app/src/main/jni/default_ini.h @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -413,6 +413,15 @@ gdbstub_port=24689 # Immediately commits the debug log to file. Use this if Azahar crashes and the log output is being cut. instant_debug_log = +# Delay the start of apps when LLE modules are enabled +# 0: Off, 1 (default): On +delay_start_for_lle_modules = + +# Force deterministic async operations +# Only needed for debugging, makes performance worse if enabled +# 0: Off (default), 1: On +deterministic_async_operations = + # To LLE a service module add "LLE\=true" [WebService] diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 5495a2a23..b48cc1499 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -781,5 +781,9 @@ Immediately commits the debug log to file. Use this if Azahar crashes and the log output is being cut. Disable Right Eye Render Greatly improves performance in some applications, but can cause flickering in others. + Delay start with LLE modules + Delays the start of the app when LLE modules are enabled + Deterministic Async Operations + Makes async operations deterministic for debugging. Enabling this may cause freezes. diff --git a/src/citra_qt/configuration/configure_debug.cpp b/src/citra_qt/configuration/configure_debug.cpp index c1410002a..3fa9205f6 100644 --- a/src/citra_qt/configuration/configure_debug.cpp +++ b/src/citra_qt/configuration/configure_debug.cpp @@ -102,6 +102,8 @@ void ConfigureDebug::SetConfiguration() { ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue()); ui->delay_start_for_lle_modules->setChecked( Settings::values.delay_start_for_lle_modules.GetValue()); + ui->deterministic_async_operations->setChecked( + Settings::values.deterministic_async_operations.GetValue()); ui->toggle_renderer_debug->setChecked(Settings::values.renderer_debug.GetValue()); ui->toggle_dump_command_buffers->setChecked(Settings::values.dump_command_buffers.GetValue()); @@ -137,6 +139,8 @@ void ConfigureDebug::ApplyConfiguration() { Common::Log::SetRegexFilter(Settings::values.log_regex_filter.GetValue()); Settings::values.use_cpu_jit = ui->toggle_cpu_jit->isChecked(); Settings::values.delay_start_for_lle_modules = ui->delay_start_for_lle_modules->isChecked(); + Settings::values.deterministic_async_operations = + ui->deterministic_async_operations->isChecked(); Settings::values.renderer_debug = ui->toggle_renderer_debug->isChecked(); Settings::values.dump_command_buffers = ui->toggle_dump_command_buffers->isChecked(); Settings::values.instant_debug_log = ui->instant_debug_log->isChecked(); diff --git a/src/citra_qt/configuration/configure_debug.ui b/src/citra_qt/configuration/configure_debug.ui index 07a41f3ae..d6a0bdc0f 100644 --- a/src/citra_qt/configuration/configure_debug.ui +++ b/src/citra_qt/configuration/configure_debug.ui @@ -259,6 +259,16 @@ + + + + Force deterministic async operations + + + <html><head/><body><p>Forces all async operations to run on the main thread, making them deterministic. Do not enable if you don't know what you are doing.</p></body></html> + + + diff --git a/src/citra_sdl/config.cpp b/src/citra_sdl/config.cpp index adb55b4c6..3db076fab 100644 --- a/src/citra_sdl/config.cpp +++ b/src/citra_sdl/config.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -328,6 +328,8 @@ void SdlConfig::ReadValues() { // Miscellaneous ReadSetting("Miscellaneous", Settings::values.log_filter); ReadSetting("Miscellaneous", Settings::values.log_regex_filter); + ReadSetting("Miscellaneous", Settings::values.delay_start_for_lle_modules); + ReadSetting("Miscellaneous", Settings::values.deterministic_async_operations); // Apply the log_filter setting as the logger has already been initialized // and doesn't pick up the filter on its own. diff --git a/src/common/archives.h b/src/common/archives.h index b9f4330bd..4e7dc7e75 100644 --- a/src/common/archives.h +++ b/src/common/archives.h @@ -1,4 +1,4 @@ -// Copyright 2020 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -19,3 +19,8 @@ using oarchive = boost::archive::binary_oarchive; BOOST_CLASS_EXPORT_IMPLEMENT(A) \ BOOST_SERIALIZATION_REGISTER_ARCHIVE(iarchive) \ BOOST_SERIALIZATION_REGISTER_ARCHIVE(oarchive) + +#define DEBUG_SERIALIZATION_POINT \ + do { \ + LOG_DEBUG(Savestate, ""); \ + } while (0) diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index fbeb6d69f..fe905dfe7 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -74,6 +74,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Core, Timing) \ SUB(Core, Cheats) \ CLS(Config) \ + CLS(Savestate) \ CLS(Debug) \ SUB(Debug, Emulated) \ SUB(Debug, GPU) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index ea912ee57..215bdbb3f 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -1,4 +1,4 @@ -// Copyright 2023 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -39,6 +39,7 @@ enum class Class : u8 { Core_Timing, ///< CoreTiming functions Core_Cheats, ///< Cheat functions Config, ///< Emulator configuration + Savestate, ///< Savestates Debug, ///< Debugging tools Debug_Emulated, ///< Debug messages from the emulated programs Debug_GPU, ///< GPU debugging tools diff --git a/src/common/settings.h b/src/common/settings.h index e484c1cd2..b3351085c 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -451,6 +451,7 @@ struct Values { SwitchableSetting cpu_clock_percentage{100, 5, 400, "cpu_clock_percentage"}; SwitchableSetting is_new_3ds{true, "is_new_3ds"}; SwitchableSetting lle_applets{false, "lle_applets"}; + SwitchableSetting deterministic_async_operations{false, "deterministic_async_operations"}; // Data Storage Setting use_virtual_sd{true, "use_virtual_sd"}; diff --git a/src/core/core.cpp b/src/core/core.cpp index 78f82eadd..31579acac 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -121,7 +121,35 @@ System::ResultStatus System::RunLoop(bool tight_loop) { case Signal::Shutdown: return ResultStatus::ShutdownRequested; case Signal::Load: { - const u32 slot = param; + if (save_state_request_status != SaveStateStatus::NONE) { + LOG_ERROR(Core, "A pending save state operation has not finished yet"); + status_details = "A pending save state operation has not finished yet"; + return ResultStatus::ErrorSavestate; + } + save_state_slot = param; + save_state_request_time = std::chrono::steady_clock::now(); + save_state_request_status = SaveStateStatus::LOADING; + break; + } + case Signal::Save: { + if (save_state_request_status != SaveStateStatus::NONE) { + LOG_ERROR(Core, "A pending save state operation has not finished yet"); + status_details = "A pending save state operation has not finished yet"; + return ResultStatus::ErrorSavestate; + } + save_state_slot = param; + save_state_request_time = std::chrono::steady_clock::now(); + save_state_request_status = SaveStateStatus::SAVING; + break; + } + default: + break; + } + + if (save_state_request_status == SaveStateStatus::LOADING && kernel.get() && + !kernel->AreAsyncOperationsPending()) { + const u32 slot = save_state_slot; + save_state_request_status = SaveStateStatus::NONE; LOG_INFO(Core, "Begin load of slot {}", slot); try { System::LoadState(slot); @@ -133,9 +161,10 @@ System::ResultStatus System::RunLoop(bool tight_loop) { } frame_limiter.WaitOnce(); return ResultStatus::Success; - } - case Signal::Save: { - const u32 slot = param; + } else if (save_state_request_status == SaveStateStatus::SAVING && kernel.get() && + !kernel->AreAsyncOperationsPending()) { + save_state_request_status = SaveStateStatus::NONE; + const u32 slot = save_state_slot; LOG_INFO(Core, "Begin save to slot {}", slot); try { System::SaveState(slot); @@ -147,9 +176,13 @@ System::ResultStatus System::RunLoop(bool tight_loop) { } frame_limiter.WaitOnce(); return ResultStatus::Success; - } - default: - break; + } else if (save_state_request_status != SaveStateStatus::NONE && + (std::chrono::steady_clock::now() - save_state_request_time) > + std::chrono::seconds(5)) { + save_state_request_status = SaveStateStatus::NONE; + LOG_ERROR(Core, "Cannot perform save state operation due to pending async operations"); + status_details = "Cannot perform save state operation due to pending async operations"; + return ResultStatus::ErrorSavestate; } // All cores should have executed the same amount of ticks. If this is not the case an event was @@ -476,7 +509,7 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, archive_manager = std::make_unique(*this); HW::AES::InitKeys(); - Service::Init(*this, !app_loader->DoingInitialSetup()); + Service::Init(*this, lle_modules, !app_loader->DoingInitialSetup()); GDBStub::DeferStart(); if (!registered_image_interface) { @@ -598,6 +631,7 @@ void System::Shutdown(bool is_deserializing) { gpu.reset(); if (!is_deserializing) { + lle_modules.clear(); GDBStub::Shutdown(); perf_stats.reset(); app_loader.reset(); @@ -720,12 +754,25 @@ bool System::IsInitialSetup() { template void System::serialize(Archive& ar, const unsigned int file_version) { + if (Archive::is_loading::value) { + save_state_status = SaveStateStatus::LOADING; + } else { + save_state_status = SaveStateStatus::SAVING; + } + u32 num_cores; if (Archive::is_saving::value) { num_cores = this->GetNumCores(); } ar & num_cores; + // TODO(PabloMK7): Figure out why this is the case + if (!lle_modules.empty()) { + throw std::runtime_error("Savestates are not supported with LLE modules enabled"); + } + + ar & lle_modules; + if (Archive::is_loading::value) { // When loading, we want to make sure any lingering state gets cleared out before we begin. // Shutdown, but persist a few things between loads... @@ -775,6 +822,8 @@ void System::serialize(Archive& ar, const unsigned int file_version) { gpu->SetInterruptHandler( [gsp](Service::GSP::InterruptId interrupt_id) { gsp->SignalInterrupt(interrupt_id); }); } + + save_state_status = SaveStateStatus::NONE; } SERIALIZE_IMPL(System) diff --git a/src/core/core.h b/src/core/core.h index 5c0e14a9c..4ed8ff326 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include #include @@ -345,6 +346,16 @@ public: (mic_permission_granted = mic_permission_func()); } + enum class SaveStateStatus { + NONE, + LOADING, + SAVING, + }; + + SaveStateStatus GetSaveStateStatus() { + return save_state_status; + } + void SaveState(u32 slot) const; void LoadState(u32 slot); @@ -440,6 +451,11 @@ private: std::atomic_bool is_powered_on{}; + SaveStateStatus save_state_status = SaveStateStatus::NONE; + SaveStateStatus save_state_request_status = SaveStateStatus::NONE; + u32 save_state_slot = 0; + std::chrono::steady_clock::time_point save_state_request_time{}; + ResultStatus status = ResultStatus::Success; std::string status_details = ""; /// Saved variables for reset @@ -460,6 +476,8 @@ private: boost::optional restore_deliver_arg; boost::optional restore_plugin_context; + std::vector lle_modules; + friend class boost::serialization::access; template void serialize(Archive& ar, const unsigned int file_version); diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp index 4e9ea6ef8..6107cefe3 100644 --- a/src/core/file_sys/archive_extsavedata.cpp +++ b/src/core/file_sys/archive_extsavedata.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -54,7 +54,14 @@ public: } private: + FixSizeDiskFile() : DiskFile() {}; u64 size{}; + template + void serialize(Archive& ar, const unsigned int) { + ar& boost::serialization::base_object(*this); + ar & size; + } + friend class boost::serialization::access; }; class ExtSaveDataDelayGenerator : public DelayGenerator { @@ -424,5 +431,6 @@ ResultVal ArchiveFactory_ExtSaveData::GetFormatInfo(const Pat } } // namespace FileSys +BOOST_CLASS_EXPORT(FileSys::FixSizeDiskFile) SERIALIZE_EXPORT_IMPL(FileSys::ExtSaveDataDelayGenerator) SERIALIZE_EXPORT_IMPL(FileSys::ExtSaveDataArchive) diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h index 0e44cb997..d823f5272 100644 --- a/src/core/file_sys/disk_archive.h +++ b/src/core/file_sys/disk_archive.h @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -44,9 +44,9 @@ protected: Mode mode; std::unique_ptr file; -private: DiskFile() = default; +private: template void serialize(Archive& ar, const unsigned int) { ar& boost::serialization::base_object(*this); diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 9aa204cd4..fe82b39b7 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -1,4 +1,4 @@ -// Copyright 2017 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -56,6 +56,10 @@ public: cmd_buff.size() * sizeof(u32)); } + bool SupportsSerialization() { + return !callback.get() || callback->SupportsSerialization(); + } + private: ThreadCallback() = default; std::shared_ptr callback{}; diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 5bbf8fcf1..1b3b8c93e 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -1,4 +1,4 @@ -// Copyright 2017 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -15,6 +15,7 @@ #include #include "common/common_types.h" #include "common/serialization/boost_small_vector.hpp" +#include "common/settings.h" #include "common/swap.h" #include "core/hle/ipc.h" #include "core/hle/kernel/object.h" @@ -231,6 +232,9 @@ public: virtual ~WakeupCallback() = default; virtual void WakeUp(std::shared_ptr thread, HLERequestContext& context, ThreadWakeupReason reason) = 0; + virtual bool SupportsSerialization() { + return true; + } private: template @@ -257,28 +261,26 @@ private: template class AsyncWakeUpCallback : public WakeupCallback { public: - explicit AsyncWakeUpCallback(ResultFunctor res_functor, std::future fut) - : functor(res_functor) { + explicit AsyncWakeUpCallback(KernelSystem& kernel, ResultFunctor res_functor, + std::future fut) + : kernel(kernel), functor(res_functor) { future = std::move(fut); } void WakeUp(std::shared_ptr thread, Kernel::HLERequestContext& ctx, - Kernel::ThreadWakeupReason reason) { + Kernel::ThreadWakeupReason reason) override { functor(ctx); + kernel.ReportAsyncState(false); + } + + bool SupportsSerialization() override { + return false; } private: + KernelSystem& kernel; ResultFunctor functor; std::future future; - - template - void serialize(Archive& ar, const unsigned int) { - if (!Archive::is_loading::value && future.valid()) { - future.wait(); - } - ar & functor; - } - friend class boost::serialization::access; }; public: @@ -300,11 +302,12 @@ public: void RunAsync(AsyncFunctor async_section, ResultFunctor result_function, bool really_async = true) { - if (really_async) { + if (!Settings::values.deterministic_async_operations && really_async) { + kernel.ReportAsyncState(true); this->SleepClientThread( "RunAsync", std::chrono::nanoseconds(-1), std::make_shared>( - result_function, + kernel, result_function, std::move(std::async(std::launch::async, [this, async_section] { s64 sleep_for = async_section(*this); this->thread->WakeAfterDelay(sleep_for, true); @@ -313,8 +316,9 @@ public: } else { s64 sleep_for = async_section(*this); if (sleep_for > 0) { + kernel.ReportAsyncState(true); auto parallel_wakeup = std::make_shared>( - result_function, std::move(std::future())); + kernel, result_function, std::move(std::future())); this->SleepClientThread("RunAsync", std::chrono::nanoseconds(sleep_for), parallel_wakeup); } else { diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 8a30abe59..5704cdda0 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -1,4 +1,8 @@ -// Copyright 2014 Citra Emulator Project / PPSSPP Project +// Copyright Citra Emulator Project / Azahar Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +// PPSSPP Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -346,6 +350,18 @@ public: return main_thread_extended_sleep; } + void ReportAsyncState(bool state) { + if (state) { + pending_async_operations++; + } else { + pending_async_operations--; + } + } + + bool AreAsyncOperationsPending() { + return pending_async_operations != 0; + } + private: void MemoryInit(MemoryMode memory_mode, New3dsMemoryMode n3ds_mode, u64 override_init_time); @@ -354,6 +370,8 @@ private: std::unique_ptr resource_limits; std::atomic next_object_id{0}; + std::atomic pending_async_operations{}; + // Note: keep the member order below in order to perform correct destruction. // Thread manager is destructed before process list in order to Stop threads and clear thread // info from their parent processes first. Timer manager is destructed after process list diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index f8084f5ab..0170cef3d 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project / PPSSPP Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -59,6 +59,19 @@ void Thread::serialize(Archive& ar, const unsigned int file_version) { ar & wait_objects; ar & wait_address; ar & name; + if (Archive::is_loading::value) { + bool serialize_blocked; + ar & serialize_blocked; + if (!serialize_blocked) { + ar & wakeup_callback; + } + } else { + bool serialize_blocked = wakeup_callback.get() && !wakeup_callback->SupportsSerialization(); + ar & serialize_blocked; + if (!serialize_blocked) { + ar & wakeup_callback; + } + } ar & wakeup_callback; } SERIALIZE_IMPL(Thread) diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 65b1cd7e6..09291d567 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -1,4 +1,8 @@ -// Copyright 2014 Citra Emulator Project / PPSSPP Project +// Copyright Citra Emulator Project / Azahar Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +// PPSSPP Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -67,6 +71,10 @@ public: virtual void WakeUp(ThreadWakeupReason reason, std::shared_ptr thread, std::shared_ptr object) = 0; + virtual bool SupportsSerialization() { + return true; + } + private: template void serialize(Archive& ar, const unsigned int); diff --git a/src/core/hle/service/ac/ac.cpp b/src/core/hle/service/ac/ac.cpp index 7495ce711..f719d919d 100644 --- a/src/core/hle/service/ac/ac.cpp +++ b/src/core/hle/service/ac/ac.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -206,6 +206,7 @@ Module::Module(Core::System& system_) : system(system_) {} template void Module::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar & ac_connected; ar & close_event; ar & connect_event; diff --git a/src/core/hle/service/act/act.cpp b/src/core/hle/service/act/act.cpp index 46c4b62bc..d70e62901 100644 --- a/src/core/hle/service/act/act.cpp +++ b/src/core/hle/service/act/act.cpp @@ -1,7 +1,8 @@ -// Copyright 2016 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/archives.h" #include "core/core.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/shared_memory.h" @@ -10,8 +11,13 @@ #include "core/hle/service/act/act_errors.h" #include "core/hle/service/act/act_u.h" +SERIALIZE_EXPORT_IMPL(Service::ACT::Module) +SERVICE_CONSTRUCT_IMPL(Service::ACT::Module) + namespace Service::ACT { +Module::Module(Core::System& system_) : system(system_) {} + Module::Interface::Interface(std::shared_ptr act, const char* name) : ServiceFramework(name, 3), act(std::move(act)) {} @@ -59,9 +65,15 @@ void Module::Interface::GetAccountInfo(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } +template +void Module::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; +} +SERIALIZE_IMPL(Module) + void InstallInterfaces(Core::System& system) { auto& service_manager = system.ServiceManager(); - auto act = std::make_shared(); + auto act = std::make_shared(system); std::make_shared(act)->InstallAsService(service_manager); std::make_shared(act)->InstallAsService(service_manager); } diff --git a/src/core/hle/service/act/act.h b/src/core/hle/service/act/act.h index ec9f954bb..9d8ce6011 100644 --- a/src/core/hle/service/act/act.h +++ b/src/core/hle/service/act/act.h @@ -1,4 +1,4 @@ -// Copyright 2016 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -15,6 +15,9 @@ namespace Service::ACT { /// Initializes all ACT services class Module final { public: + explicit Module(Core::System& system_); + ~Module() = default; + class Interface : public ServiceFramework { public: Interface(std::shared_ptr act, const char* name); @@ -62,11 +65,17 @@ public: }; private: + [[maybe_unused]] + Core::System& system; + template - void serialize(Archive& ar, const unsigned int file_version) {} + void serialize(Archive& ar, const unsigned int); friend class boost::serialization::access; }; void InstallInterfaces(Core::System& system); } // namespace Service::ACT + +BOOST_CLASS_EXPORT_KEY(Service::ACT::Module) +SERVICE_CONSTRUCT(Service::ACT::Module) \ No newline at end of file diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index fe693e7e9..0f5911b3c 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -3764,6 +3764,7 @@ void Module::Interface::Sign(Kernel::HLERequestContext& ctx) { template void Module::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar & cia_installing; ar & force_old_device_id; ar & force_new_device_id; diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 4c2cbbd09..39aa3f5df 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -41,6 +41,7 @@ namespace Service::APT { template void Module::serialize(Archive& ar, const unsigned int file_version) { + DEBUG_SERIALIZATION_POINT; ar & shared_font_mem; ar & shared_font_loaded; ar & shared_font_relocated; diff --git a/src/core/hle/service/boss/boss.cpp b/src/core/hle/service/boss/boss.cpp index dcc064fcf..94ffbd3e1 100644 --- a/src/core/hle/service/boss/boss.cpp +++ b/src/core/hle/service/boss/boss.cpp @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -19,6 +19,7 @@ namespace Service::BOSS { template void Module::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar & task_finish_event; ar & new_arrival_flag; ar & ns_data_new_flag; diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp index cec48add4..3001d357b 100644 --- a/src/core/hle/service/cam/cam.cpp +++ b/src/core/hle/service/cam/cam.cpp @@ -1,4 +1,4 @@ -// Copyright Citra Emulator Project / Lime3DS Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -26,6 +26,7 @@ namespace Service::CAM { template void Module::serialize(Archive& ar, const unsigned int file_version) { + DEBUG_SERIALIZATION_POINT; ar & cameras; ar & ports; ar & is_camera_reload_pending; diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp index 510b4fa86..92ae92fb7 100644 --- a/src/core/hle/service/cecd/cecd.cpp +++ b/src/core/hle/service/cecd/cecd.cpp @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -35,6 +35,7 @@ namespace Service::CECD { template void Module::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar & cecd_system_save_data_archive; ar & cecinfo_event; ar & cecinfosys_event; diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index e3c0fc033..2af087fdc 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -38,6 +38,7 @@ namespace Service::CFG { template void Module::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar & cfg_config_file_buffer; ar & cfg_system_save_data_archive; ar & mac_address; diff --git a/src/core/hle/service/csnd/csnd_snd.h b/src/core/hle/service/csnd/csnd_snd.h index c4e960777..381e8416f 100644 --- a/src/core/hle/service/csnd/csnd_snd.h +++ b/src/core/hle/service/csnd/csnd_snd.h @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -7,6 +7,7 @@ #include #include #include +#include "common/archives.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/service/service.h" @@ -257,6 +258,7 @@ private: template void serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & mutex; ar & shared_memory; diff --git a/src/core/hle/service/dsp/dsp_dsp.h b/src/core/hle/service/dsp/dsp_dsp.h index e47b2bf85..d1b1bfe01 100644 --- a/src/core/hle/service/dsp/dsp_dsp.h +++ b/src/core/hle/service/dsp/dsp_dsp.h @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -269,6 +269,7 @@ private: template void serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & semaphore_event; ar & preset_semaphore; diff --git a/src/core/hle/service/frd/frd.h b/src/core/hle/service/frd/frd.h index 3e19e17f3..663176838 100644 --- a/src/core/hle/service/frd/frd.h +++ b/src/core/hle/service/frd/frd.h @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -271,6 +271,7 @@ private: template void serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar & my_friend_key; ar & my_presence; ar & logged_in; diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index df824e0bb..99390cd40 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -1885,6 +1885,7 @@ FS_USER::FS_USER(Core::System& system) } template void Service::FS::FS_USER::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & priority; ar & secure_value_backend; diff --git a/src/core/hle/service/gsp/gsp_gpu.cpp b/src/core/hle/service/gsp/gsp_gpu.cpp index 5e3e5e420..8f07c22e6 100644 --- a/src/core/hle/service/gsp/gsp_gpu.cpp +++ b/src/core/hle/service/gsp/gsp_gpu.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -716,6 +716,7 @@ SessionData* GSP_GPU::FindRegisteredThreadData(u32 thread_id) { template void GSP_GPU::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & shared_memory; ar & active_thread_id; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index ca81128da..81b833f34 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -32,6 +32,7 @@ namespace Service::HID { template void Module::serialize(Archive& ar, const unsigned int file_version) { + DEBUG_SERIALIZATION_POINT; ar & shared_mem; ar & event_pad_or_touch_1; ar & event_pad_or_touch_2; diff --git a/src/core/hle/service/http/http_c.h b/src/core/hle/service/http/http_c.h index 90ecd5b66..28f7c4795 100644 --- a/src/core/hle/service/http/http_c.h +++ b/src/core/hle/service/http/http_c.h @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -904,6 +904,7 @@ private: // NOTE: Serialization of the HTTP service is on a 'best effort' basis. // There is a very good chance that saving/loading during a network connection will break, // regardless! + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & ClCertA.certificate; ar & ClCertA.private_key; diff --git a/src/core/hle/service/ir/ir_rst.cpp b/src/core/hle/service/ir/ir_rst.cpp index fbe340181..aca655e7f 100644 --- a/src/core/hle/service/ir/ir_rst.cpp +++ b/src/core/hle/service/ir/ir_rst.cpp @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -22,6 +22,7 @@ namespace Service::IR { template void IR_RST::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & update_event; ar & shared_memory; diff --git a/src/core/hle/service/ir/ir_user.cpp b/src/core/hle/service/ir/ir_user.cpp index 2c29d855a..705fe60c6 100644 --- a/src/core/hle/service/ir/ir_user.cpp +++ b/src/core/hle/service/ir/ir_user.cpp @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -25,6 +25,7 @@ namespace Service::IR { template void IR_USER::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & conn_status_event; ar & send_event; diff --git a/src/core/hle/service/ldr_ro/ldr_ro.h b/src/core/hle/service/ldr_ro/ldr_ro.h index eb00f55e3..85c721524 100644 --- a/src/core/hle/service/ldr_ro/ldr_ro.h +++ b/src/core/hle/service/ldr_ro/ldr_ro.h @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -164,6 +164,7 @@ private: private: template void serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); } friend class boost::serialization::access; diff --git a/src/core/hle/service/mic/mic_u.cpp b/src/core/hle/service/mic/mic_u.cpp index 4363b3ab1..d15c077bd 100644 --- a/src/core/hle/service/mic/mic_u.cpp +++ b/src/core/hle/service/mic/mic_u.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -25,6 +25,7 @@ namespace Service::MIC { template void MIC_U::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar&* impl.get(); } diff --git a/src/core/hle/service/ndm/ndm_u.h b/src/core/hle/service/ndm/ndm_u.h index 3270e78c3..213b621aa 100644 --- a/src/core/hle/service/ndm/ndm_u.h +++ b/src/core/hle/service/ndm/ndm_u.h @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -274,6 +274,7 @@ private: template void serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & daemon_bit_mask; ar & default_daemon_bit_mask; diff --git a/src/core/hle/service/news/news.cpp b/src/core/hle/service/news/news.cpp index 4eb051061..0f04d13d2 100644 --- a/src/core/hle/service/news/news.cpp +++ b/src/core/hle/service/news/news.cpp @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -45,6 +45,7 @@ constexpr std::array news_system_savedata_id{ template void Module::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar & db; ar & notification_ids; ar & automatic_sync_flag; diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp index 528ec84bc..758f403f0 100644 --- a/src/core/hle/service/nfc/nfc.cpp +++ b/src/core/hle/service/nfc/nfc.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -16,6 +16,7 @@ namespace Service::NFC { template void Module::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar & nfc_mode; ar & device; } diff --git a/src/core/hle/service/nim/nim_u.h b/src/core/hle/service/nim/nim_u.h index 667a25b26..1beb32ce0 100644 --- a/src/core/hle/service/nim/nim_u.h +++ b/src/core/hle/service/nim/nim_u.h @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -532,6 +532,7 @@ private: template void serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & nim_system_update_event_for_menu; ar & nim_system_update_event_for_news; diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp index 830e1ffc7..3a08ffbee 100644 --- a/src/core/hle/service/nwm/nwm_uds.cpp +++ b/src/core/hle/service/nwm/nwm_uds.cpp @@ -33,6 +33,7 @@ namespace Service::NWM { template void NWM_UDS::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & node_map; ar & connection_event; diff --git a/src/core/hle/service/plgldr/plgldr.cpp b/src/core/hle/service/plgldr/plgldr.cpp index 85ac3ecab..d619a0d0d 100644 --- a/src/core/hle/service/plgldr/plgldr.cpp +++ b/src/core/hle/service/plgldr/plgldr.cpp @@ -1,4 +1,4 @@ -// Copyright 2022 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -85,6 +85,7 @@ SERIALIZE_IMPL(PLG_LDR::PluginLoaderContext) template void PLG_LDR::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & plgldr_context; } diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index 950c1ccb6..1cdb64c88 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -225,6 +225,7 @@ Module::Module(Core::System& system_) : system(system_) { template void Module::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar & shell_open; ar & battery_is_charging; ar & pedometer_is_counting; diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 68e1bfa47..025f566dc 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -220,13 +220,27 @@ static bool AttemptLLE(const ServiceModuleInfo& service_module) { } /// Initialize ServiceManager -void Init(Core::System& core, bool allow_lle) { +void Init(Core::System& core, std::vector& lle_modules, bool allow_lle) { SM::ServiceManager::InstallInterfaces(core); core.Kernel().SetAppMainThreadExtendedSleep(false); bool lle_module_present = false; for (const auto& service_module : service_module_map) { - const bool has_lle = allow_lle && AttemptLLE(service_module); + if (core.GetSaveStateStatus() == Core::System::SaveStateStatus::LOADING && + std::find(lle_modules.begin(), lle_modules.end(), service_module.title_id) != + lle_modules.end()) { + // The system module has already been loaded before, do not attempt to load again as the + // process, threads, etc are already serialized in the kernel structures. + lle_module_present |= true; + continue; + } + + const bool has_lle = allow_lle && + core.GetSaveStateStatus() != Core::System::SaveStateStatus::LOADING && + AttemptLLE(service_module); + if (has_lle) { + lle_modules.push_back(service_module.title_id); + } if (!has_lle && service_module.init_function != nullptr) { service_module.init_function(core); } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 51a2b200e..d61633cf6 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -12,6 +12,7 @@ #include #include #include +#include "common/archives.h" #include "common/common_types.h" #include "common/construct.h" #include "core/hle/kernel/hle_ipc.h" @@ -183,7 +184,7 @@ private: }; /// Initialize ServiceManager -void Init(Core::System& system, bool allow_lle); +void Init(Core::System& system, std::vector& lle_modules, bool allow_lle); struct ServiceModuleInfo { std::string name; @@ -218,6 +219,7 @@ extern const std::array service_module_map; #define SERVICE_SERIALIZATION_SIMPLE \ template \ void serialize(Archive& ar, const unsigned int) { \ + DEBUG_SERIALIZATION_POINT; \ ar& boost::serialization::base_object(*this); \ } \ friend class boost::serialization::access; diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index fd86ff198..b304a4406 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h @@ -1,4 +1,4 @@ -// Copyright 2017 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -89,11 +89,13 @@ private: template void save(Archive& ar, const unsigned int file_version) const { + DEBUG_SERIALIZATION_POINT; ar << registered_services; } template void load(Archive& ar, const unsigned int file_version) { + DEBUG_SERIALIZATION_POINT; ar >> registered_services; registered_services_inverse.clear(); for (const auto& pair : registered_services) { diff --git a/src/core/hle/service/sm/srv.cpp b/src/core/hle/service/sm/srv.cpp index 8463cd40c..84e7f734f 100644 --- a/src/core/hle/service/sm/srv.cpp +++ b/src/core/hle/service/sm/srv.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -31,6 +31,7 @@ namespace Service::SM { template void SRV::serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & notification_semaphore; ar & get_service_handle_delayed_map; diff --git a/src/core/hle/service/soc/soc_u.h b/src/core/hle/service/soc/soc_u.h index 015aefeb5..071305833 100644 --- a/src/core/hle/service/soc/soc_u.h +++ b/src/core/hle/service/soc/soc_u.h @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -169,6 +169,7 @@ private: template void serialize(Archive& ar, const unsigned int) { + DEBUG_SERIALIZATION_POINT; ar& boost::serialization::base_object(*this); ar & created_sockets; ar & initialized_processes;