From f2ee9baec7f8ce5f634a9a1752c3a81aebb6f379 Mon Sep 17 00:00:00 2001 From: Steveice10 <1269164+Steveice10@users.noreply.github.com> Date: Fri, 5 Jan 2024 12:07:28 -0800 Subject: [PATCH] core: Eliminate more uses of Core::System::GetInstance(). (#7313) --- src/audio_core/hle/hle.cpp | 6 - src/audio_core/hle/hle.h | 4 - src/audio_core/input_details.cpp | 12 +- src/audio_core/input_details.h | 6 +- src/core/core.cpp | 8 +- src/core/file_sys/plugin_3gx.cpp | 8 +- src/core/file_sys/plugin_3gx.h | 6 +- src/core/frontend/applets/default_applets.cpp | 2 +- src/core/frontend/applets/swkbd.cpp | 4 +- src/core/frontend/applets/swkbd.h | 8 ++ src/core/hle/applets/applet.cpp | 90 -------------- src/core/hle/applets/applet.h | 31 +---- src/core/hle/applets/erreula.cpp | 2 +- src/core/hle/applets/erreula.h | 6 +- src/core/hle/applets/mii_selector.cpp | 4 +- src/core/hle/applets/mii_selector.h | 6 +- src/core/hle/applets/mint.cpp | 2 +- src/core/hle/applets/mint.h | 6 +- src/core/hle/applets/swkbd.cpp | 4 +- src/core/hle/applets/swkbd.h | 6 +- src/core/hle/service/ac/ac.cpp | 12 +- src/core/hle/service/ac/ac.h | 10 +- src/core/hle/service/am/am.cpp | 35 ++++-- src/core/hle/service/am/am.h | 28 ++--- src/core/hle/service/apt/applet_manager.cpp | 110 +++++++++++++++--- src/core/hle/service/apt/applet_manager.h | 13 ++- src/core/hle/service/apt/apt.cpp | 3 +- src/core/hle/service/cam/y2r_u.cpp | 4 +- src/core/hle/service/gsp/gsp_gpu.cpp | 13 ++- src/core/hle/service/mic/mic_u.cpp | 5 +- src/core/hle/service/plgldr/plgldr.cpp | 49 ++++++-- src/core/hle/service/plgldr/plgldr.h | 48 +++----- src/core/hle/service/ptm/ptm.cpp | 15 ++- src/core/hle/service/ptm/ptm.h | 13 ++- src/core/hle/service/sm/srv.cpp | 2 +- src/core/loader/3dsx.cpp | 17 ++- src/core/loader/3dsx.h | 4 +- src/core/loader/elf.cpp | 14 +-- src/core/loader/elf.h | 4 +- src/core/loader/loader.cpp | 14 ++- src/core/loader/loader.h | 4 +- src/core/loader/ncch.cpp | 5 +- src/core/loader/ncch.h | 4 +- src/core/memory.cpp | 93 ++++++++------- src/core/memory.h | 4 +- src/video_core/gpu.cpp | 57 ++++----- src/video_core/gpu.h | 2 + 47 files changed, 416 insertions(+), 387 deletions(-) diff --git a/src/audio_core/hle/hle.cpp b/src/audio_core/hle/hle.cpp index 89bb8a5f4..9d5277504 100644 --- a/src/audio_core/hle/hle.cpp +++ b/src/audio_core/hle/hle.cpp @@ -24,16 +24,10 @@ #include "core/core.h" #include "core/core_timing.h" -SERIALIZE_EXPORT_IMPL(AudioCore::DspHle) - using InterruptType = Service::DSP::InterruptType; namespace AudioCore { -DspHle::DspHle() - : DspHle(Core::System::GetInstance(), Core::System::GetInstance().Memory(), - Core::System::GetInstance().CoreTiming()) {} - DspHle::DspHle(Core::System& system) : DspHle(system, system.Memory(), system.CoreTiming()) {} template diff --git a/src/audio_core/hle/hle.h b/src/audio_core/hle/hle.h index 6e9ec106f..2ee4421e7 100644 --- a/src/audio_core/hle/hle.h +++ b/src/audio_core/hle/hle.h @@ -50,13 +50,9 @@ private: friend struct Impl; std::unique_ptr impl; - DspHle(); - template void serialize(Archive& ar, const unsigned int); friend class boost::serialization::access; }; } // namespace AudioCore - -BOOST_CLASS_EXPORT_KEY(AudioCore::DspHle) diff --git a/src/audio_core/input_details.cpp b/src/audio_core/input_details.cpp index d6b2dc5c9..e98310d31 100644 --- a/src/audio_core/input_details.cpp +++ b/src/audio_core/input_details.cpp @@ -24,8 +24,8 @@ namespace { constexpr std::array input_details = { #ifdef HAVE_CUBEB InputDetails{InputType::Cubeb, "Real Device (Cubeb)", true, - [](std::string_view device_id) -> std::unique_ptr { - if (!Core::System::GetInstance().HasMicPermission()) { + [](Core::System& system, std::string_view device_id) -> std::unique_ptr { + if (!system.HasMicPermission()) { LOG_WARNING(Audio, "Microphone permission denied, falling back to null input."); return std::make_unique(); @@ -36,8 +36,8 @@ constexpr std::array input_details = { #endif #ifdef HAVE_OPENAL InputDetails{InputType::OpenAL, "Real Device (OpenAL)", true, - [](std::string_view device_id) -> std::unique_ptr { - if (!Core::System::GetInstance().HasMicPermission()) { + [](Core::System& system, std::string_view device_id) -> std::unique_ptr { + if (!system.HasMicPermission()) { LOG_WARNING(Audio, "Microphone permission denied, falling back to null input."); return std::make_unique(); @@ -47,12 +47,12 @@ constexpr std::array input_details = { &ListOpenALInputDevices}, #endif InputDetails{InputType::Static, "Static Noise", false, - [](std::string_view device_id) -> std::unique_ptr { + [](Core::System& system, std::string_view device_id) -> std::unique_ptr { return std::make_unique(); }, [] { return std::vector{"Static Noise"}; }}, InputDetails{InputType::Null, "None", false, - [](std::string_view device_id) -> std::unique_ptr { + [](Core::System& system, std::string_view device_id) -> std::unique_ptr { return std::make_unique(); }, [] { return std::vector{"None"}; }}, diff --git a/src/audio_core/input_details.h b/src/audio_core/input_details.h index f1be87572..a091dfe6c 100644 --- a/src/audio_core/input_details.h +++ b/src/audio_core/input_details.h @@ -10,6 +10,10 @@ #include #include "common/common_types.h" +namespace Core { +class System; +} + namespace AudioCore { class Input; @@ -23,7 +27,7 @@ enum class InputType : u32 { }; struct InputDetails { - using FactoryFn = std::unique_ptr (*)(std::string_view device_id); + using FactoryFn = std::unique_ptr (*)(Core::System& system, std::string_view device_id); using ListDevicesFn = std::vector (*)(); /// Type of this input. diff --git a/src/core/core.cpp b/src/core/core.cpp index 56211d979..ad6f0ae56 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -666,9 +666,11 @@ void System::ApplySettings() { Service::MIC::ReloadMic(*this); } - Service::PLGLDR::PLG_LDR::SetEnabled(Settings::values.plugin_loader_enabled.GetValue()); - Service::PLGLDR::PLG_LDR::SetAllowGameChangeState( - Settings::values.allow_plugin_loader.GetValue()); + auto plg_ldr = Service::PLGLDR::GetService(*this); + if (plg_ldr) { + plg_ldr->SetEnabled(Settings::values.plugin_loader_enabled.GetValue()); + plg_ldr->SetAllowGameChangeState(Settings::values.allow_plugin_loader.GetValue()); + } } template diff --git a/src/core/file_sys/plugin_3gx.cpp b/src/core/file_sys/plugin_3gx.cpp index 839bd8f80..89d29aa9b 100644 --- a/src/core/file_sys/plugin_3gx.cpp +++ b/src/core/file_sys/plugin_3gx.cpp @@ -65,7 +65,7 @@ static bool ReadSection(std::vector& data_out, FileUtil::IOFile& file, std:: Loader::ResultStatus FileSys::Plugin3GXLoader::Load( Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Kernel::Process& process, - Kernel::KernelSystem& kernel) { + Kernel::KernelSystem& kernel, Service::PLGLDR::PLG_LDR& plg_ldr) { FileUtil::IOFile file(plg_context.plugin_path, "rb"); if (!file.IsOpen()) { LOG_ERROR(Service_PLGLDR, "Failed to load 3GX plugin. Not found: {}", @@ -158,12 +158,12 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Load( return Loader::ResultStatus::Error; } - return Map(plg_context, process, kernel); + return Map(plg_context, process, kernel, plg_ldr); } Loader::ResultStatus FileSys::Plugin3GXLoader::Map( Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Kernel::Process& process, - Kernel::KernelSystem& kernel) { + Kernel::KernelSystem& kernel, Service::PLGLDR::PLG_LDR& plg_ldr) { // Verify exe load checksum function is available if (exe_load_func.empty() && plg_context.load_exe_func.empty()) { @@ -195,7 +195,7 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Map( return Loader::ResultStatus::ErrorMemoryAllocationFailed; } auto backing_memory_fb = kernel.memory.GetFCRAMRef(*offset_fb); - Service::PLGLDR::PLG_LDR::SetPluginFBAddr(Memory::FCRAM_PADDR + *offset_fb); + plg_ldr.SetPluginFBAddr(Memory::FCRAM_PADDR + *offset_fb); std::fill(backing_memory_fb.GetPtr(), backing_memory_fb.GetPtr() + _3GX_fb_size, 0); auto vma_heap_fb = process.vm_manager.MapBackingMemory( diff --git a/src/core/file_sys/plugin_3gx.h b/src/core/file_sys/plugin_3gx.h index d4c2650e1..f718841fc 100644 --- a/src/core/file_sys/plugin_3gx.h +++ b/src/core/file_sys/plugin_3gx.h @@ -43,7 +43,8 @@ class FileBackend; class Plugin3GXLoader { public: Loader::ResultStatus Load(Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, - Kernel::Process& process, Kernel::KernelSystem& kernel); + Kernel::Process& process, Kernel::KernelSystem& kernel, + Service::PLGLDR::PLG_LDR& plg_ldr); struct PluginHeader { u32_le magic; @@ -68,7 +69,8 @@ public: private: Loader::ResultStatus Map(Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, - Kernel::Process& process, Kernel::KernelSystem& kernel); + Kernel::Process& process, Kernel::KernelSystem& kernel, + Service::PLGLDR::PLG_LDR& plg_ldr); static constexpr size_t bootloader_memory_size = 0x1000; static void MapBootloader(Kernel::Process& process, Kernel::KernelSystem& kernel, diff --git a/src/core/frontend/applets/default_applets.cpp b/src/core/frontend/applets/default_applets.cpp index 3b67e97f8..2feabd6e1 100644 --- a/src/core/frontend/applets/default_applets.cpp +++ b/src/core/frontend/applets/default_applets.cpp @@ -9,7 +9,7 @@ namespace Frontend { void RegisterDefaultApplets(Core::System& system) { - system.RegisterSoftwareKeyboard(std::make_shared()); + system.RegisterSoftwareKeyboard(std::make_shared(system)); system.RegisterMiiSelector(std::make_shared()); } } // namespace Frontend diff --git a/src/core/frontend/applets/swkbd.cpp b/src/core/frontend/applets/swkbd.cpp index 51f21cda6..07c25eae3 100644 --- a/src/core/frontend/applets/swkbd.cpp +++ b/src/core/frontend/applets/swkbd.cpp @@ -144,10 +144,12 @@ const KeyboardData& SoftwareKeyboard::ReceiveData() { return data; } +DefaultKeyboard::DefaultKeyboard(Core::System& system_) : system(system_) {} + void DefaultKeyboard::Execute(const Frontend::KeyboardConfig& config_) { SoftwareKeyboard::Execute(config_); - auto cfg = Service::CFG::GetModule(Core::System::GetInstance()); + auto cfg = Service::CFG::GetModule(system); std::string username = Common::UTF16ToUTF8(cfg->GetUsername()); switch (this->config.button_config) { case ButtonConfig::None: diff --git a/src/core/frontend/applets/swkbd.h b/src/core/frontend/applets/swkbd.h index 8e3ae3e8b..82a1a2edb 100644 --- a/src/core/frontend/applets/swkbd.h +++ b/src/core/frontend/applets/swkbd.h @@ -8,6 +8,10 @@ #include #include "common/assert.h" +namespace Core { +class System; +} + namespace Frontend { enum class AcceptedInput { @@ -137,8 +141,12 @@ protected: class DefaultKeyboard final : public SoftwareKeyboard { public: + explicit DefaultKeyboard(Core::System& system_); void Execute(const KeyboardConfig& config) override; void ShowError(const std::string& error) override; + +private: + Core::System& system; }; } // namespace Frontend diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp index 0e07080cf..f237898e6 100644 --- a/src/core/hle/applets/applet.cpp +++ b/src/core/hle/applets/applet.cpp @@ -5,97 +5,16 @@ #include #include #include -#include #include #include "common/assert.h" #include "common/common_types.h" #include "core/core.h" #include "core/core_timing.h" #include "core/hle/applets/applet.h" -#include "core/hle/applets/erreula.h" -#include "core/hle/applets/mii_selector.h" -#include "core/hle/applets/mint.h" -#include "core/hle/applets/swkbd.h" #include "core/hle/result.h" namespace HLE::Applets { -static std::unordered_map> applets; -/// The CoreTiming event identifier for the Applet update callback. -static Core::TimingEventType* applet_update_event = nullptr; -/// The interval at which the Applet update callback will be called, 16.6ms -static const u64 applet_update_interval_us = 16666; - -Result Applet::Create(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, - const std::shared_ptr& manager) { - switch (id) { - case Service::APT::AppletId::SoftwareKeyboard1: - case Service::APT::AppletId::SoftwareKeyboard2: - applets[id] = std::make_shared(id, parent, preload, manager); - break; - case Service::APT::AppletId::Ed1: - case Service::APT::AppletId::Ed2: - applets[id] = std::make_shared(id, parent, preload, manager); - break; - case Service::APT::AppletId::Error: - case Service::APT::AppletId::Error2: - applets[id] = std::make_shared(id, parent, preload, manager); - break; - case Service::APT::AppletId::Mint: - case Service::APT::AppletId::Mint2: - applets[id] = std::make_shared(id, parent, preload, manager); - break; - default: - LOG_ERROR(Service_APT, "Could not create applet {}", id); - // TODO(Subv): Find the right error code - return Result(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported, - ErrorLevel::Permanent); - } - - Service::APT::AppletAttributes attributes; - attributes.applet_pos.Assign(Service::APT::AppletPos::AutoLibrary); - attributes.is_home_menu.Assign(false); - const auto lock_handle_data = manager->GetLockHandle(attributes); - - manager->Initialize(id, lock_handle_data->corrected_attributes); - manager->Enable(lock_handle_data->corrected_attributes); - if (preload) { - manager->FinishPreloadingLibraryApplet(id); - } - - // Schedule the update event - Core::System::GetInstance().CoreTiming().ScheduleEvent( - usToCycles(applet_update_interval_us), applet_update_event, static_cast(id)); - return ResultSuccess; -} - -std::shared_ptr Applet::Get(Service::APT::AppletId id) { - auto itr = applets.find(id); - if (itr != applets.end()) - return itr->second; - return nullptr; -} - -/// Handles updating the current Applet every time it's called. -static void AppletUpdateEvent(u64 applet_id, s64 cycles_late) { - const auto id = static_cast(applet_id); - const auto applet = Applet::Get(id); - ASSERT_MSG(applet != nullptr, "Applet doesn't exist! applet_id={:08X}", id); - - if (applet->IsActive()) { - applet->Update(); - } - - // If the applet is still running after the last update, reschedule the event - if (applet->IsRunning()) { - Core::System::GetInstance().CoreTiming().ScheduleEvent( - usToCycles(applet_update_interval_us) - cycles_late, applet_update_event, applet_id); - } else { - // Otherwise the applet has terminated, in which case we should clean it up - applets[id] = nullptr; - } -} - bool Applet::IsRunning() const { return is_running; } @@ -140,13 +59,4 @@ void Applet::CloseApplet(std::shared_ptr object, const std::vect is_running = false; } -void Init() { - // Register the applet update callback - applet_update_event = Core::System::GetInstance().CoreTiming().RegisterEvent( - "HLE Applet Update Event", AppletUpdateEvent); -} - -void Shutdown() { - Core::System::GetInstance().CoreTiming().RemoveEvent(applet_update_event); -} } // namespace HLE::Applets diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h index 39aeca58a..d6e26c8a4 100644 --- a/src/core/hle/applets/applet.h +++ b/src/core/hle/applets/applet.h @@ -14,24 +14,6 @@ class Applet { public: virtual ~Applet() = default; - /** - * Creates an instance of the Applet subclass identified by the parameter. - * and stores it in a global map. - * @param id Id of the applet to create. - * @param parent Id of the applet's parent. - * @param preload Whether the applet is being preloaded. - * @returns Result Whether the operation was successful or not. - */ - static Result Create(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, - const std::shared_ptr& manager); - - /** - * Retrieves the Applet instance identified by the specified id. - * @param id Id of the Applet to retrieve. - * @returns Requested Applet or nullptr if not found. - */ - static std::shared_ptr Get(Service::APT::AppletId id); - /** * Handles a parameter from the application. * @param parameter Parameter data to handle. @@ -55,9 +37,9 @@ public: virtual void Update() = 0; protected: - Applet(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, - std::weak_ptr manager) - : id(id), parent(parent), preload(preload), manager(std::move(manager)) {} + Applet(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent, + bool preload, std::weak_ptr manager) + : system(system), id(id), parent(parent), preload(preload), manager(std::move(manager)) {} /** * Handles a parameter from the application. @@ -79,6 +61,8 @@ protected: */ virtual Result Finalize() = 0; + Core::System& system; + Service::APT::AppletId id; ///< Id of this Applet Service::APT::AppletId parent; ///< Id of this Applet's parent bool preload; ///< Whether the Applet is being preloaded. @@ -97,9 +81,4 @@ private: std::weak_ptr manager; }; -/// Initializes the HLE applets -void Init(); - -/// Shuts down the HLE applets -void Shutdown(); } // namespace HLE::Applets diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp index e8b7798ac..5d0fc6e35 100644 --- a/src/core/hle/applets/erreula.cpp +++ b/src/core/hle/applets/erreula.cpp @@ -28,7 +28,7 @@ Result ErrEula::ReceiveParameterImpl(const Service::APT::MessageParameter& param // TODO: allocated memory never released using Kernel::MemoryPermission; // Create a SharedMemory that directly points to this heap block. - framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet( + framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet( 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, "ErrEula Memory"); diff --git a/src/core/hle/applets/erreula.h b/src/core/hle/applets/erreula.h index c47bb99ef..ba5dbb6e0 100644 --- a/src/core/hle/applets/erreula.h +++ b/src/core/hle/applets/erreula.h @@ -11,9 +11,9 @@ namespace HLE::Applets { class ErrEula final : public Applet { public: - explicit ErrEula(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, - std::weak_ptr manager) - : Applet(id, parent, preload, std::move(manager)) {} + explicit ErrEula(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent, + bool preload, std::weak_ptr manager) + : Applet(system, id, parent, preload, std::move(manager)) {} Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; Result Start(const Service::APT::MessageParameter& parameter) override; diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp index 5e2d0bf6a..c2145d888 100644 --- a/src/core/hle/applets/mii_selector.cpp +++ b/src/core/hle/applets/mii_selector.cpp @@ -35,7 +35,7 @@ Result MiiSelector::ReceiveParameterImpl(const Service::APT::MessageParameter& p using Kernel::MemoryPermission; // Create a SharedMemory that directly points to this heap block. - framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet( + framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet( 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, "MiiSelector Memory"); @@ -57,7 +57,7 @@ Result MiiSelector::Start(const Service::APT::MessageParameter& parameter) { std::memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); using namespace Frontend; - frontend_applet = Core::System::GetInstance().GetMiiSelector(); + frontend_applet = system.GetMiiSelector(); ASSERT(frontend_applet); MiiSelectorConfig frontend_config = ToFrontendConfig(config); diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h index 40662795d..4ee263f36 100644 --- a/src/core/hle/applets/mii_selector.h +++ b/src/core/hle/applets/mii_selector.h @@ -62,9 +62,9 @@ ASSERT_REG_POSITION(guest_mii_name, 0x6C); class MiiSelector final : public Applet { public: - MiiSelector(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, - std::weak_ptr manager) - : Applet(id, parent, preload, std::move(manager)) {} + MiiSelector(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent, + bool preload, std::weak_ptr manager) + : Applet(system, id, parent, preload, std::move(manager)) {} Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; Result Start(const Service::APT::MessageParameter& parameter) override; diff --git a/src/core/hle/applets/mint.cpp b/src/core/hle/applets/mint.cpp index f8a632e12..3e3613128 100644 --- a/src/core/hle/applets/mint.cpp +++ b/src/core/hle/applets/mint.cpp @@ -28,7 +28,7 @@ Result Mint::ReceiveParameterImpl(const Service::APT::MessageParameter& paramete // TODO: allocated memory never released using Kernel::MemoryPermission; // Create a SharedMemory that directly points to this heap block. - framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet( + framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet( 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, "Mint Memory"); diff --git a/src/core/hle/applets/mint.h b/src/core/hle/applets/mint.h index bffa972ab..4ee32110f 100644 --- a/src/core/hle/applets/mint.h +++ b/src/core/hle/applets/mint.h @@ -11,9 +11,9 @@ namespace HLE::Applets { class Mint final : public Applet { public: - explicit Mint(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, - std::weak_ptr manager) - : Applet(id, parent, preload, std::move(manager)) {} + explicit Mint(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent, + bool preload, std::weak_ptr manager) + : Applet(system, id, parent, preload, std::move(manager)) {} Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; Result Start(const Service::APT::MessageParameter& parameter) override; diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp index 556060779..c4aceb10f 100644 --- a/src/core/hle/applets/swkbd.cpp +++ b/src/core/hle/applets/swkbd.cpp @@ -32,7 +32,7 @@ Result SoftwareKeyboard::ReceiveParameterImpl(Service::APT::MessageParameter con using Kernel::MemoryPermission; // Create a SharedMemory that directly points to this heap block. - framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet( + framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet( 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, "SoftwareKeyboard Memory"); @@ -99,7 +99,7 @@ Result SoftwareKeyboard::Start(Service::APT::MessageParameter const& parameter) DrawScreenKeyboard(); using namespace Frontend; - frontend_applet = Core::System::GetInstance().GetSoftwareKeyboard(); + frontend_applet = system.GetSoftwareKeyboard(); ASSERT(frontend_applet); frontend_applet->Execute(ToFrontendConfig(config)); diff --git a/src/core/hle/applets/swkbd.h b/src/core/hle/applets/swkbd.h index 10a906728..f6847aaca 100644 --- a/src/core/hle/applets/swkbd.h +++ b/src/core/hle/applets/swkbd.h @@ -175,9 +175,9 @@ static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config class SoftwareKeyboard final : public Applet { public: - SoftwareKeyboard(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, - std::weak_ptr manager) - : Applet(id, parent, preload, std::move(manager)) {} + SoftwareKeyboard(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent, + bool preload, std::weak_ptr manager) + : Applet(system, id, parent, preload, std::move(manager)) {} Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; Result Start(const Service::APT::MessageParameter& parameter) override; diff --git a/src/core/hle/service/ac/ac.cpp b/src/core/hle/service/ac/ac.cpp index 62d226ec5..a71903028 100644 --- a/src/core/hle/service/ac/ac.cpp +++ b/src/core/hle/service/ac/ac.cpp @@ -20,6 +20,9 @@ #include "core/hle/service/soc/soc_u.h" #include "core/memory.h" +SERIALIZE_EXPORT_IMPL(Service::AC::Module) +SERVICE_CONSTRUCT_IMPL(Service::AC::Module) + namespace Service::AC { void Module::Interface::CreateDefaultConfig(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); @@ -96,7 +99,7 @@ void Module::Interface::GetWifiStatus(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); bool can_reach_internet = false; - std::shared_ptr socu_module = SOC::GetService(Core::System::GetInstance()); + std::shared_ptr socu_module = SOC::GetService(ac->system); if (socu_module) { can_reach_internet = socu_module->GetDefaultInterfaceInfo().has_value(); } @@ -194,11 +197,13 @@ Module::Interface::Interface(std::shared_ptr ac, const char* name, u32 m void InstallInterfaces(Core::System& system) { auto& service_manager = system.ServiceManager(); - auto ac = std::make_shared(); + auto ac = std::make_shared(system); std::make_shared(ac)->InstallAsService(service_manager); std::make_shared(ac)->InstallAsService(service_manager); } +Module::Module(Core::System& system_) : system(system_) {} + template void Module::serialize(Archive& ar, const unsigned int) { ar& ac_connected; @@ -207,7 +212,6 @@ void Module::serialize(Archive& ar, const unsigned int) { ar& disconnect_event; // default_config is never written to } +SERIALIZE_IMPL(Module) } // namespace Service::AC - -SERIALIZE_IMPL(Service::AC::Module) diff --git a/src/core/hle/service/ac/ac.h b/src/core/hle/service/ac/ac.h index 38761150b..2b0d2e5ce 100644 --- a/src/core/hle/service/ac/ac.h +++ b/src/core/hle/service/ac/ac.h @@ -19,6 +19,9 @@ class Event; namespace Service::AC { class Module final { public: + explicit Module(Core::System& system_); + ~Module() = default; + class Interface : public ServiceFramework { public: Interface(std::shared_ptr ac, const char* name, u32 max_session); @@ -169,11 +172,16 @@ protected: std::shared_ptr disconnect_event; private: + 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::AC + +BOOST_CLASS_EXPORT_KEY(Service::AC::Module) +SERVICE_CONSTRUCT(Service::AC::Module) diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 0b3b93f62..a741e3488 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -9,6 +9,7 @@ #include #include #include "common/alignment.h" +#include "common/archives.h" #include "common/common_paths.h" #include "common/file_util.h" #include "common/logging/log.h" @@ -33,6 +34,9 @@ #include "core/loader/smdh.h" #include "core/nus_download.h" +SERIALIZE_EXPORT_IMPL(Service::AM::Module) +SERVICE_CONSTRUCT_IMPL(Service::AM::Module) + namespace Service::AM { constexpr u16 PLATFORM_CTR = 0x0004; @@ -81,8 +85,9 @@ public: std::vector::Decryption> content; }; -CIAFile::CIAFile(Service::FS::MediaType media_type) - : media_type(media_type), decryption_state(std::make_unique()) {} +CIAFile::CIAFile(Core::System& system_, Service::FS::MediaType media_type) + : system(system_), media_type(media_type), + decryption_state(std::make_unique()) {} CIAFile::~CIAFile() { Close(); @@ -361,8 +366,7 @@ bool CIAFile::Close() const { // are closed. std::string to_delete = GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index); - if (!(Core::System::GetInstance().IsPoweredOn() && - Core::System::GetInstance().SetSelfDelete(to_delete))) { + if (!system.IsPoweredOn() || !system.SetSelfDelete(to_delete)) { FileUtil::Delete(to_delete); } } @@ -425,6 +429,7 @@ InstallStatus InstallCIA(const std::string& path, FileSys::CIAContainer container; if (container.Load(path) == Loader::ResultStatus::Success) { Service::AM::CIAFile installFile( + Core::System::GetInstance(), Service::AM::GetTitleMediaType(container.GetTitleMetadata().GetTitleID())); bool title_key_available = container.GetTicket().GetTitleKey().has_value(); @@ -502,7 +507,7 @@ InstallStatus InstallCIA(const std::string& path, InstallStatus InstallFromNus(u64 title_id, int version) { LOG_DEBUG(Service_AM, "Downloading {:X}", title_id); - CIAFile install_file{GetTitleMediaType(title_id)}; + CIAFile install_file{Core::System::GetInstance(), GetTitleMediaType(title_id)}; std::string path = fmt::format("/ccs/download/{:016X}/tmd", title_id); if (version != -1) { @@ -1327,7 +1332,7 @@ void Module::Interface::BeginImportProgram(Kernel::HLERequestContext& ctx) { // Citra will store contents out to sdmc/nand const FileSys::Path cia_path = {}; auto file = std::make_shared( - am->kernel, std::make_unique(media_type), cia_path); + am->system.Kernel(), std::make_unique(am->system, media_type), cia_path); am->cia_installing = true; @@ -1354,7 +1359,7 @@ void Module::Interface::BeginImportProgramTemporarily(Kernel::HLERequestContext& // contents out to sdmc/nand const FileSys::Path cia_path = {}; auto file = std::make_shared( - am->kernel, std::make_unique(FS::MediaType::NAND), cia_path); + am->system.Kernel(), std::make_unique(am->system, FS::MediaType::NAND), cia_path); am->cia_installing = true; @@ -1769,8 +1774,8 @@ void Module::Interface::BeginImportTicket(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); // Create our TicketFile handle for the app to write to - auto file = std::make_shared(am->kernel, std::make_unique(), - FileSys::Path{}); + auto file = std::make_shared( + am->system.Kernel(), std::make_unique(), FileSys::Path{}); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); rb.Push(ResultSuccess); // No error @@ -1789,13 +1794,19 @@ void Module::Interface::EndImportTicket(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); } -Module::Module(Core::System& system) : kernel(system.Kernel()) { +template +void Module::serialize(Archive& ar, const unsigned int) { + ar& cia_installing; + ar& am_title_list; + ar& system_updater_mutex; +} +SERIALIZE_IMPL(Module) + +Module::Module(Core::System& system) : system(system) { ScanForAllTitles(); system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex"); } -Module::Module(Kernel::KernelSystem& kernel) : kernel(kernel) {} - Module::~Module() = default; void InstallInterfaces(Core::System& system) { diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index fed2228a6..09fe9dc87 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -11,7 +11,6 @@ #include #include #include -#include #include "common/common_types.h" #include "common/construct.h" #include "common/swap.h" @@ -80,7 +79,7 @@ using ProgressCallback = void(std::size_t, std::size_t); // A file handled returned for CIAs to be written into and subsequently installed. class CIAFile final : public FileSys::FileBackend { public: - explicit CIAFile(Service::FS::MediaType media_type); + explicit CIAFile(Core::System& system_, Service::FS::MediaType media_type); ~CIAFile(); ResultVal Read(u64 offset, std::size_t length, u8* buffer) const override; @@ -95,6 +94,8 @@ public: void Flush() const override; private: + Core::System& system; + // Whether it's installing an update, and what step of installation it is at bool is_update = false; CIAInstallState install_state = CIAInstallState::InstallStarted; @@ -706,8 +707,6 @@ public: }; private: - explicit Module(Kernel::KernelSystem& kernel); - /** * Scans the for titles in a storage medium for listing. * @param media_type the storage medium to scan @@ -719,27 +718,13 @@ private: */ void ScanForAllTitles(); - Kernel::KernelSystem& kernel; + Core::System& system; bool cia_installing = false; std::array, 3> am_title_list; std::shared_ptr system_updater_mutex; template - void serialize(Archive& ar, const unsigned int) { - ar& cia_installing; - ar& am_title_list; - ar& system_updater_mutex; - } - - template - static void load_construct(Archive& ar, Module* t, const unsigned int file_version) { - ::new (t) Module(Core::Global()); - } - - template - void save_construct(Archive& ar, const unsigned int file_version) const {} - - friend class ::construct_access; + void serialize(Archive& ar, const unsigned int); friend class boost::serialization::access; }; @@ -747,4 +732,5 @@ void InstallInterfaces(Core::System& system); } // namespace Service::AM -BOOST_SERIALIZATION_CONSTRUCT(Service::AM::Module); +BOOST_CLASS_EXPORT_KEY(Service::AM::Module) +SERVICE_CONSTRUCT(Service::AM::Module) diff --git a/src/core/hle/service/apt/applet_manager.cpp b/src/core/hle/service/apt/applet_manager.cpp index f8cf43d0e..f4fb3df76 100644 --- a/src/core/hle/service/apt/applet_manager.cpp +++ b/src/core/hle/service/apt/applet_manager.cpp @@ -8,6 +8,10 @@ #include "core/core.h" #include "core/frontend/input.h" #include "core/hle/applets/applet.h" +#include "core/hle/applets/erreula.h" +#include "core/hle/applets/mii_selector.h" +#include "core/hle/applets/mint.h" +#include "core/hle/applets/swkbd.h" #include "core/hle/service/am/am.h" #include "core/hle/service/apt/applet_manager.h" #include "core/hle/service/apt/errors.h" @@ -22,6 +26,8 @@ namespace Service::APT { /// The interval at which the home button update callback will be called, 16.6ms static constexpr u64 button_update_interval_us = 16666; +/// The interval at which the HLE Applet update callback will be called, 16.6ms. +static constexpr u64 hle_applet_update_interval_us = 16666; struct AppletTitleData { // There are two possible applet ids for each applet. @@ -222,8 +228,8 @@ void AppletManager::CancelAndSendParameter(const MessageParameter& parameter) { parameter.sender_id, parameter.destination_id, parameter.signal, parameter.buffer.size()); // If the applet is being HLEd, send directly to the applet. - if (auto dest_applet = HLE::Applets::Applet::Get(parameter.destination_id)) { - dest_applet->ReceiveParameter(parameter); + if (hle_applets.contains(parameter.destination_id)) { + hle_applets[parameter.destination_id]->ReceiveParameter(parameter); } else { // Otherwise, send the parameter the LLE way. next_parameter = parameter; @@ -497,6 +503,52 @@ void AppletManager::SendNotificationToAll(Notification notification) { } } +Result AppletManager::CreateHLEApplet(AppletId id, AppletId parent, bool preload) { + switch (id) { + case AppletId::SoftwareKeyboard1: + case AppletId::SoftwareKeyboard2: + hle_applets[id] = std::make_shared( + system, id, parent, preload, shared_from_this()); + break; + case AppletId::Ed1: + case AppletId::Ed2: + hle_applets[id] = std::make_shared(system, id, parent, preload, + shared_from_this()); + break; + case AppletId::Error: + case AppletId::Error2: + hle_applets[id] = std::make_shared(system, id, parent, preload, + shared_from_this()); + break; + case AppletId::Mint: + case AppletId::Mint2: + hle_applets[id] = + std::make_shared(system, id, parent, preload, shared_from_this()); + break; + default: + LOG_ERROR(Service_APT, "Could not create applet {}", id); + // TODO(Subv): Find the right error code + return Result(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported, + ErrorLevel::Permanent); + } + + AppletAttributes attributes; + attributes.applet_pos.Assign(AppletPos::AutoLibrary); + attributes.is_home_menu.Assign(false); + const auto lock_handle_data = GetLockHandle(attributes); + + Initialize(id, lock_handle_data->corrected_attributes); + Enable(lock_handle_data->corrected_attributes); + if (preload) { + FinishPreloadingLibraryApplet(id); + } + + // Schedule the update event + system.CoreTiming().ScheduleEvent(usToCycles(hle_applet_update_interval_us), + hle_applet_update_event, static_cast(id)); + return ResultSuccess; +} + Result AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) { // The real APT service returns an error if there's a pending APT parameter when this function // is called. @@ -523,14 +575,13 @@ Result AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) { } // If we weren't able to load the native applet title, try to fallback to an HLE implementation. - auto applet = HLE::Applets::Applet::Get(applet_id); - if (applet) { - LOG_WARNING(Service_APT, "applet has already been started id={:03X}", applet_id); + if (hle_applets.contains(applet_id)) { + LOG_WARNING(Service_APT, "Applet has already been started id={:03X}", applet_id); return ResultSuccess; } else { auto parent = GetAppletSlotId(last_library_launcher_slot); LOG_DEBUG(Service_APT, "Creating HLE applet {:03X} with parent {:03X}", applet_id, parent); - return HLE::Applets::Applet::Create(applet_id, parent, false, shared_from_this()); + return CreateHLEApplet(applet_id, parent, false); } } @@ -551,14 +602,13 @@ Result AppletManager::PreloadLibraryApplet(AppletId applet_id) { } // If we weren't able to load the native applet title, try to fallback to an HLE implementation. - auto applet = HLE::Applets::Applet::Get(applet_id); - if (applet) { - LOG_WARNING(Service_APT, "applet has already been started id={:08X}", applet_id); + if (hle_applets.contains(applet_id)) { + LOG_WARNING(Service_APT, "Applet has already been started id={:08X}", applet_id); return ResultSuccess; } else { auto parent = GetAppletSlotId(last_library_launcher_slot); LOG_DEBUG(Service_APT, "Creating HLE applet {:03X} with parent {:03X}", applet_id, parent); - return HLE::Applets::Applet::Create(applet_id, parent, true, shared_from_this()); + return CreateHLEApplet(applet_id, parent, true); } } @@ -1387,8 +1437,8 @@ static void CaptureFrameBuffer(Core::System& system, u32 capture_offset, VAddr s return; } - Memory::RasterizerFlushVirtualRegion(src, GSP::FRAMEBUFFER_WIDTH * height * bpp, - Memory::FlushMode::Flush); + system.Memory().RasterizerFlushVirtualRegion(src, GSP::FRAMEBUFFER_WIDTH * height * bpp, + Memory::FlushMode::Flush); // Address in VRAM that APT copies framebuffer captures to. constexpr VAddr screen_capture_base_vaddr = Memory::VRAM_VADDR + 0x500000; @@ -1416,8 +1466,8 @@ static void CaptureFrameBuffer(Core::System& system, u32 capture_offset, VAddr s } } - Memory::RasterizerFlushVirtualRegion(dst_vaddr, GSP::FRAMEBUFFER_WIDTH_POW2 * height * bpp, - Memory::FlushMode::Invalidate); + system.Memory().RasterizerFlushVirtualRegion( + dst_vaddr, GSP::FRAMEBUFFER_WIDTH_POW2 * height * bpp, Memory::FlushMode::Invalidate); } void AppletManager::CaptureFrameBuffers() { @@ -1441,6 +1491,30 @@ void AppletManager::LoadInputDevices() { Settings::values.current_input_profile.buttons[Settings::NativeButton::Power]); } +/// Handles updating the current Applet every time it's called. +void AppletManager::HLEAppletUpdateEvent(std::uintptr_t user_data, s64 cycles_late) { + const auto id = static_cast(user_data); + if (!hle_applets.contains(id)) { + // Dead applet, exit event loop. + LOG_WARNING(Service_APT, "Attempted to update dead applet id={:03X}", id); + return; + } + + const auto applet = hle_applets[id]; + if (applet->IsActive()) { + applet->Update(); + } + + // If the applet is still running after the last update, reschedule the event + if (applet->IsRunning()) { + system.CoreTiming().ScheduleEvent(usToCycles(hle_applet_update_interval_us) - cycles_late, + hle_applet_update_event, user_data); + } else { + // Otherwise the applet has terminated, in which case we should clean it up + hle_applets[id] = nullptr; + } +} + void AppletManager::ButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late) { if (is_device_reload_pending.exchange(false)) { LoadInputDevices(); @@ -1485,7 +1559,10 @@ AppletManager::AppletManager(Core::System& system) : system(system) { slot_data.parameter_event = system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "APT:Parameter"); } - HLE::Applets::Init(); + hle_applet_update_event = system.CoreTiming().RegisterEvent( + "HLE Applet Update Event", [this](std::uintptr_t user_data, s64 cycles_late) { + HLEAppletUpdateEvent(user_data, cycles_late); + }); button_update_event = system.CoreTiming().RegisterEvent( "APT Button Update Event", [this](std::uintptr_t user_data, s64 cycles_late) { ButtonUpdateEvent(user_data, cycles_late); @@ -1494,7 +1571,8 @@ AppletManager::AppletManager(Core::System& system) : system(system) { } AppletManager::~AppletManager() { - HLE::Applets::Shutdown(); + system.CoreTiming().RemoveEvent(hle_applet_update_event); + system.CoreTiming().RemoveEvent(button_update_event); } void AppletManager::ReloadInputDevices() { diff --git a/src/core/hle/service/apt/applet_manager.h b/src/core/hle/service/apt/applet_manager.h index 9b5a1056d..2c4d0879e 100644 --- a/src/core/hle/service/apt/applet_manager.h +++ b/src/core/hle/service/apt/applet_manager.h @@ -23,6 +23,10 @@ namespace Core { class System; } +namespace HLE::Applets { +class Applet; +} + namespace Service::APT { /// Signals used by APT functions @@ -291,7 +295,6 @@ public: ResultVal InquireNotification(AppletId app_id); Result SendNotification(Notification notification); - void SendNotificationToAll(Notification notification); Result PrepareToStartLibraryApplet(AppletId applet_id); Result PreloadLibraryApplet(AppletId applet_id); @@ -481,6 +484,9 @@ private: // It also affects the results of APT:GetTargetPlatform and APT:GetApplicationRunningMode. bool new_3ds_mode_blocked = false; + std::unordered_map> hle_applets; + Core::TimingEventType* hle_applet_update_event; + Core::TimingEventType* button_update_event; std::atomic is_device_reload_pending{true}; std::unique_ptr home_button; @@ -506,10 +512,15 @@ private: /// otherwise it queues for sending when the application registers itself with APT::Enable. void SendApplicationParameterAfterRegistration(const MessageParameter& parameter); + void SendNotificationToAll(Notification notification); + void EnsureHomeMenuLoaded(); void CaptureFrameBuffers(); + Result CreateHLEApplet(AppletId id, AppletId parent, bool preload); + void HLEAppletUpdateEvent(std::uintptr_t user_data, s64 cycles_late); + void LoadInputDevices(); void ButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late); diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index eba748ae7..a3befffd8 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -1133,8 +1133,7 @@ void Module::APTInterface::GetProgramId(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); rb.Push(ResultSuccess); - auto fs_user = - Core::System::GetInstance().ServiceManager().GetService("fs:USER"); + auto fs_user = apt->system.ServiceManager().GetService("fs:USER"); ASSERT_MSG(fs_user != nullptr, "fs:USER service is missing."); auto program_info_result = fs_user->GetProgramLaunchInfo(process_id); diff --git a/src/core/hle/service/cam/y2r_u.cpp b/src/core/hle/service/cam/y2r_u.cpp index bca0439f7..266cf2e92 100644 --- a/src/core/hle/service/cam/y2r_u.cpp +++ b/src/core/hle/service/cam/y2r_u.cpp @@ -517,8 +517,8 @@ void Y2R_U::StartConversion(Kernel::HLERequestContext& ctx) { // dst_image_size would seem to be perfect for this, but it doesn't include the gap :( u32 total_output_size = conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); - Memory::RasterizerFlushVirtualRegion(conversion.dst.address, total_output_size, - Memory::FlushMode::FlushAndInvalidate); + system.Memory().RasterizerFlushVirtualRegion(conversion.dst.address, total_output_size, + Memory::FlushMode::FlushAndInvalidate); HW::Y2R::PerformConversion(system.Memory(), conversion); diff --git a/src/core/hle/service/gsp/gsp_gpu.cpp b/src/core/hle/service/gsp/gsp_gpu.cpp index d2c7d8438..374bbe3c6 100644 --- a/src/core/hle/service/gsp/gsp_gpu.cpp +++ b/src/core/hle/service/gsp/gsp_gpu.cpp @@ -477,9 +477,10 @@ static void CopyFrameBuffer(Core::System& system, VAddr dst, VAddr src, u32 stri return; } - Memory::RasterizerFlushVirtualRegion(src, stride * lines, Memory::FlushMode::Flush); + system.Memory().RasterizerFlushVirtualRegion(src, stride * lines, Memory::FlushMode::Flush); std::memcpy(dst_ptr, src_ptr, stride * lines); - Memory::RasterizerFlushVirtualRegion(dst, stride * lines, Memory::FlushMode::Invalidate); + system.Memory().RasterizerFlushVirtualRegion(dst, stride * lines, + Memory::FlushMode::Invalidate); } void GSP_GPU::SaveVramSysArea(Kernel::HLERequestContext& ctx) { @@ -497,8 +498,8 @@ void GSP_GPU::SaveVramSysArea(Kernel::HLERequestContext& ctx) { LOG_INFO(Service_GSP, "called"); // TODO: This should also save LCD register state. - Memory::RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE, - Memory::FlushMode::Flush); + system.Memory().RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE, + Memory::FlushMode::Flush); const auto vram = system.Memory().GetPointer(Memory::VRAM_VADDR); saved_vram.emplace(std::vector(Memory::VRAM_SIZE)); std::memcpy(saved_vram.get().data(), vram, Memory::VRAM_SIZE); @@ -548,8 +549,8 @@ void GSP_GPU::RestoreVramSysArea(Kernel::HLERequestContext& ctx) { // TODO: This should also restore LCD register state. auto vram = system.Memory().GetPointer(Memory::VRAM_VADDR); std::memcpy(vram, saved_vram.get().data(), Memory::VRAM_SIZE); - Memory::RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE, - Memory::FlushMode::Invalidate); + system.Memory().RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE, + Memory::FlushMode::Invalidate); } IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); diff --git a/src/core/hle/service/mic/mic_u.cpp b/src/core/hle/service/mic/mic_u.cpp index 0d6de542c..1ed15cd25 100644 --- a/src/core/hle/service/mic/mic_u.cpp +++ b/src/core/hle/service/mic/mic_u.cpp @@ -135,7 +135,7 @@ private: }; struct MIC_U::Impl { - explicit Impl(Core::System& system) : timing(system.CoreTiming()) { + explicit Impl(Core::System& system) : system(system), timing(system.CoreTiming()) { buffer_full_event = system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event"); buffer_write_event = timing.RegisterEvent( @@ -376,7 +376,7 @@ struct MIC_U::Impl { } mic = AudioCore::GetInputDetails(Settings::values.input_type.GetValue()) - .create_input(Settings::values.input_device.GetValue()); + .create_input(system, Settings::values.input_device.GetValue()); if (was_sampling) { StartSampling(); } @@ -392,6 +392,7 @@ struct MIC_U::Impl { bool allow_shell_closed = false; bool clamp = false; std::unique_ptr mic; + Core::System& system; Core::Timing& timing; State state{}; Encoding encoding{}; diff --git a/src/core/hle/service/plgldr/plgldr.cpp b/src/core/hle/service/plgldr/plgldr.cpp index 5955946d0..7fb929cc0 100644 --- a/src/core/hle/service/plgldr/plgldr.cpp +++ b/src/core/hle/service/plgldr/plgldr.cpp @@ -36,15 +36,13 @@ #include "core/loader/loader.h" SERIALIZE_EXPORT_IMPL(Service::PLGLDR::PLG_LDR) +SERVICE_CONSTRUCT_IMPL(Service::PLGLDR::PLG_LDR) namespace Service::PLGLDR { -const Kernel::CoreVersion PLG_LDR::plgldr_version = Kernel::CoreVersion(1, 0, 0); -PLG_LDR::PluginLoaderContext PLG_LDR::plgldr_context; -bool PLG_LDR::allow_game_change = true; -PAddr PLG_LDR::plugin_fb_addr = 0; +static const Kernel::CoreVersion plgldr_version = Kernel::CoreVersion(1, 0, 0); -PLG_LDR::PLG_LDR() : ServiceFramework{"plg:ldr", 1} { +PLG_LDR::PLG_LDR(Core::System& system_) : ServiceFramework{"plg:ldr", 1}, system(system_) { static const FunctionInfo functions[] = { // clang-format off {0x0001, nullptr, "LoadPlugin"}, @@ -67,6 +65,33 @@ PLG_LDR::PLG_LDR() : ServiceFramework{"plg:ldr", 1} { plgldr_context.plugin_loaded = false; } +template +void PLG_LDR::PluginLoaderContext::serialize(Archive& ar, const unsigned int) { + ar& is_enabled; + ar& plugin_loaded; + ar& is_default_path; + ar& plugin_path; + ar& use_user_load_parameters; + ar& user_load_parameters; + ar& plg_event; + ar& plg_reply; + ar& memory_changed_handle; + ar& is_exe_load_function_set; + ar& exe_load_checksum; + ar& load_exe_func; + ar& load_exe_args; +} +SERIALIZE_IMPL(PLG_LDR::PluginLoaderContext) + +template +void PLG_LDR::serialize(Archive& ar, const unsigned int) { + ar& boost::serialization::base_object(*this); + ar& plgldr_context; + ar& plugin_fb_addr; + ar& allow_game_change; +} +SERIALIZE_IMPL(PLG_LDR) + void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kernel) { if (!plgldr_context.is_enabled || plgldr_context.plugin_loaded) { return; @@ -91,7 +116,7 @@ void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kerne std::string(plgldr_context.user_load_parameters.path + 1); plgldr_context.is_default_path = false; plgldr_context.plugin_path = plugin_file; - plugin_loader.Load(plgldr_context, process, kernel); + plugin_loader.Load(plgldr_context, process, kernel, *this); } else { const std::string plugin_root = FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "luma/plugins/"; @@ -103,7 +128,7 @@ void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kerne if (!child.isDirectory && child.physicalName.ends_with(".3gx")) { plgldr_context.is_default_path = false; plgldr_context.plugin_path = child.physicalName; - if (plugin_loader.Load(plgldr_context, process, kernel) == + if (plugin_loader.Load(plgldr_context, process, kernel, *this) == Loader::ResultStatus::Success) { return; } @@ -114,7 +139,7 @@ void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kerne if (FileUtil::Exists(default_path)) { plgldr_context.is_default_path = true; plgldr_context.plugin_path = default_path; - plugin_loader.Load(plgldr_context, process, kernel); + plugin_loader.Load(plgldr_context, process, kernel, *this); } } } @@ -134,9 +159,9 @@ ResultVal PLG_LDR::GetMemoryChangedHandle(Kernel::KernelSystem& return plgldr_context.memory_changed_handle; } - std::shared_ptr evt = kernel.CreateEvent( - Kernel::ResetType::OneShot, - fmt::format("event-{:08x}", Core::System::GetInstance().GetRunningCore().GetReg(14))); + std::shared_ptr evt = + kernel.CreateEvent(Kernel::ResetType::OneShot, + fmt::format("event-{:08x}", system.GetRunningCore().GetReg(14))); R_TRY(kernel.GetCurrentProcess()->handle_table.Create( std::addressof(plgldr_context.memory_changed_handle), std::move(evt))); return plgldr_context.memory_changed_handle; @@ -274,7 +299,7 @@ std::shared_ptr GetService(Core::System& system) { } void InstallInterfaces(Core::System& system) { - std::make_shared()->InstallAsNamedPort(system.Kernel()); + std::make_shared(system)->InstallAsNamedPort(system.Kernel()); } } // namespace Service::PLGLDR diff --git a/src/core/hle/service/plgldr/plgldr.h b/src/core/hle/service/plgldr/plgldr.h index 0780db564..23d44f38e 100644 --- a/src/core/hle/service/plgldr/plgldr.h +++ b/src/core/hle/service/plgldr/plgldr.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include "core/hle/service/service.h" namespace Core { @@ -70,25 +70,11 @@ public: u32_le load_exe_args[4] = {0}; template - void serialize(Archive& ar, const unsigned int) { - ar& is_enabled; - ar& plugin_loaded; - ar& is_default_path; - ar& plugin_path; - ar& use_user_load_parameters; - ar& user_load_parameters; - ar& plg_event; - ar& plg_reply; - ar& memory_changed_handle; - ar& is_exe_load_function_set; - ar& exe_load_checksum; - ar& load_exe_func; - ar& load_exe_args; - } + void serialize(Archive& ar, const unsigned int); friend class boost::serialization::access; }; - PLG_LDR(); + PLG_LDR(Core::System& system_); ~PLG_LDR() {} void OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kernel); @@ -96,31 +82,31 @@ public: ResultVal GetMemoryChangedHandle(Kernel::KernelSystem& kernel); void OnMemoryChanged(Kernel::Process& process, Kernel::KernelSystem& kernel); - static void SetEnabled(bool enabled) { + void SetEnabled(bool enabled) { plgldr_context.is_enabled = enabled; } - static bool GetEnabled() { + bool GetEnabled() { return plgldr_context.is_enabled; } - static void SetAllowGameChangeState(bool allow) { + void SetAllowGameChangeState(bool allow) { allow_game_change = allow; } - static bool GetAllowGameChangeState() { + bool GetAllowGameChangeState() { return allow_game_change; } - static void SetPluginFBAddr(PAddr addr) { + void SetPluginFBAddr(PAddr addr) { plugin_fb_addr = addr; } - static PAddr GetPluginFBAddr() { + PAddr GetPluginFBAddr() { return plugin_fb_addr; } private: - static const Kernel::CoreVersion plgldr_version; + Core::System& system; - static PluginLoaderContext plgldr_context; - static PAddr plugin_fb_addr; - static bool allow_game_change; + PluginLoaderContext plgldr_context; + PAddr plugin_fb_addr = 0; + bool allow_game_change = true; void IsEnabled(Kernel::HLERequestContext& ctx); void SetEnabled(Kernel::HLERequestContext& ctx); @@ -131,12 +117,7 @@ private: void GetPluginPath(Kernel::HLERequestContext& ctx); template - void serialize(Archive& ar, const unsigned int) { - ar& boost::serialization::base_object(*this); - ar& plgldr_context; - ar& plugin_fb_addr; - ar& allow_game_change; - } + void serialize(Archive& ar, const unsigned int); friend class boost::serialization::access; }; @@ -147,3 +128,4 @@ void InstallInterfaces(Core::System& system); } // namespace Service::PLGLDR BOOST_CLASS_EXPORT_KEY(Service::PLGLDR::PLG_LDR) +SERVICE_CONSTRUCT(Service::PLGLDR::PLG_LDR) diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index 577c2ad50..6f609182b 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -20,6 +20,7 @@ #include "core/hle/service/ptm/ptm_u.h" SERIALIZE_EXPORT_IMPL(Service::PTM::Module) +SERVICE_CONSTRUCT_IMPL(Service::PTM::Module) namespace Service::PTM { @@ -136,7 +137,7 @@ void Module::Interface::CheckNew3DS(Kernel::HLERequestContext& ctx) { void Module::Interface::GetSystemTime(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); - auto& share_page = Core::System::GetInstance().Kernel().GetSharedPageHandler(); + auto& share_page = ptm->system.Kernel().GetSharedPageHandler(); const u64 console_time = share_page.GetSystemTimeSince2000(); IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); @@ -207,7 +208,7 @@ static GameCoin ReadGameCoinData() { return gamecoin_data; } -Module::Module() { +Module::Module(Core::System& system_) : system(system_) { // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't // exist const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); @@ -221,6 +222,14 @@ Module::Module() { } } +template +void Module::serialize(Archive& ar, const unsigned int) { + ar& shell_open; + ar& battery_is_charging; + ar& pedometer_is_counting; +} +SERIALIZE_IMPL(Module) + u16 Module::GetPlayCoins() { return ReadGameCoinData().total_coins; } @@ -238,7 +247,7 @@ Module::Interface::Interface(std::shared_ptr ptm, const char* name, u32 void InstallInterfaces(Core::System& system) { auto& service_manager = system.ServiceManager(); - auto ptm = std::make_shared(); + auto ptm = std::make_shared(system); std::make_shared(ptm)->InstallAsService(service_manager); std::make_shared(ptm)->InstallAsService(service_manager); std::make_shared(ptm)->InstallAsService(service_manager); diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h index 83298f02a..2e3e5af55 100644 --- a/src/core/hle/service/ptm/ptm.h +++ b/src/core/hle/service/ptm/ptm.h @@ -47,7 +47,9 @@ void CheckNew3DS(IPC::RequestBuilder& rb); class Module final { public: - Module(); + explicit Module(Core::System& system_); + ~Module() = default; + static u16 GetPlayCoins(); static void SetPlayCoins(u16 play_coins); @@ -150,16 +152,14 @@ public: }; private: + Core::System& system; + bool shell_open = true; bool battery_is_charging = true; bool pedometer_is_counting = false; template - void serialize(Archive& ar, const unsigned int) { - ar& shell_open; - ar& battery_is_charging; - ar& pedometer_is_counting; - } + void serialize(Archive& ar, const unsigned int); friend class boost::serialization::access; }; @@ -168,3 +168,4 @@ void InstallInterfaces(Core::System& system); } // namespace Service::PTM BOOST_CLASS_EXPORT_KEY(Service::PTM::Module) +SERVICE_CONSTRUCT(Service::PTM::Module) diff --git a/src/core/hle/service/sm/srv.cpp b/src/core/hle/service/sm/srv.cpp index f42c5cb1a..97d563771 100644 --- a/src/core/hle/service/sm/srv.cpp +++ b/src/core/hle/service/sm/srv.cpp @@ -249,7 +249,7 @@ void SRV::PublishToSubscriber(Kernel::HLERequestContext& ctx) { // console. Normally, this is handled by NS. If notification handling is properly implemented, // this piece of code should be removed, and handled by subscribing from NS instead. if (notification_id == 0x203) { - Core::System::GetInstance().RequestShutdown(); + system.RequestShutdown(); } else { LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x{:X}, flags={}", notification_id, flags); diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index d235783a9..c839a414c 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -94,7 +94,7 @@ static u32 TranslateAddr(u32 addr, const THREEloadinfo* loadinfo, u32* offsets) using Kernel::CodeSet; -static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, +static THREEDSX_Error Load3DSXFile(Core::System& system, FileUtil::IOFile& file, u32 base_addr, std::shared_ptr* out_codeset) { if (!file.IsOpen()) return ERROR_FILE; @@ -222,7 +222,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, } // Create the CodeSet - std::shared_ptr code_set = Core::System::GetInstance().Kernel().CreateCodeSet("", 0); + std::shared_ptr code_set = system.Kernel().CreateCodeSet("", 0); code_set->CodeSegment().offset = loadinfo.seg_ptrs[0] - program_image.data(); code_set->CodeSegment().addr = loadinfo.seg_addrs[0]; @@ -268,25 +268,24 @@ ResultStatus AppLoader_THREEDSX::Load(std::shared_ptr& process) return ResultStatus::Error; std::shared_ptr codeset; - if (Load3DSXFile(file, Memory::PROCESS_IMAGE_VADDR, &codeset) != ERROR_NONE) + if (Load3DSXFile(system, file, Memory::PROCESS_IMAGE_VADDR, &codeset) != ERROR_NONE) return ResultStatus::Error; codeset->name = filename; - process = Core::System::GetInstance().Kernel().CreateProcess(std::move(codeset)); + process = system.Kernel().CreateProcess(std::move(codeset)); process->Set3dsxKernelCaps(); // Attach the default resource limit (APPLICATION) to the process - process->resource_limit = Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory( - Kernel::ResourceLimitCategory::Application); + process->resource_limit = + system.Kernel().ResourceLimit().GetForCategory(Kernel::ResourceLimitCategory::Application); // On real HW this is done with FS:Reg, but we can be lazy - auto fs_user = - Core::System::GetInstance().ServiceManager().GetService("fs:USER"); + auto fs_user = system.ServiceManager().GetService("fs:USER"); fs_user->RegisterProgramInfo(process->GetObjectId(), process->codeset->program_id, filepath); process->Run(48, Kernel::DEFAULT_STACK_SIZE); - Core::System::GetInstance().ArchiveManager().RegisterSelfNCCH(*this); + system.ArchiveManager().RegisterSelfNCCH(*this); is_loaded = true; return ResultStatus::Success; diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h index 9a1f2081f..27432e9fd 100644 --- a/src/core/loader/3dsx.h +++ b/src/core/loader/3dsx.h @@ -14,9 +14,9 @@ namespace Loader { /// Loads an 3DSX file class AppLoader_THREEDSX final : public AppLoader { public: - AppLoader_THREEDSX(FileUtil::IOFile&& file, const std::string& filename, + AppLoader_THREEDSX(Core::System& system_, FileUtil::IOFile&& file, const std::string& filename, const std::string& filepath) - : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {} + : AppLoader(system_, std::move(file)), filename(std::move(filename)), filepath(filepath) {} /** * Returns the type of the file diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index dded22498..30b98e483 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -199,7 +199,7 @@ public: u32 GetFlags() const { return (u32)(header->e_flags); } - std::shared_ptr LoadInto(u32 vaddr); + std::shared_ptr LoadInto(Core::System& system, u32 vaddr); int GetNumSegments() const { return (int)(header->e_phnum); @@ -262,7 +262,7 @@ const char* ElfReader::GetSectionName(int section) const { return nullptr; } -std::shared_ptr ElfReader::LoadInto(u32 vaddr) { +std::shared_ptr ElfReader::LoadInto(Core::System& system, u32 vaddr) { LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx); // Should we relocate? @@ -290,7 +290,7 @@ std::shared_ptr ElfReader::LoadInto(u32 vaddr) { std::vector program_image(total_image_size); std::size_t current_image_position = 0; - std::shared_ptr codeset = Core::System::GetInstance().Kernel().CreateCodeSet("", 0); + std::shared_ptr codeset = system.Kernel().CreateCodeSet("", 0); for (unsigned int i = 0; i < header->e_phnum; ++i) { Elf32_Phdr* p = &segments[i]; @@ -380,15 +380,15 @@ ResultStatus AppLoader_ELF::Load(std::shared_ptr& process) { return ResultStatus::Error; ElfReader elf_reader(&buffer[0]); - std::shared_ptr codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR); + std::shared_ptr codeset = elf_reader.LoadInto(system, Memory::PROCESS_IMAGE_VADDR); codeset->name = filename; - process = Core::System::GetInstance().Kernel().CreateProcess(std::move(codeset)); + process = system.Kernel().CreateProcess(std::move(codeset)); process->Set3dsxKernelCaps(); // Attach the default resource limit (APPLICATION) to the process - process->resource_limit = Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory( - Kernel::ResourceLimitCategory::Application); + process->resource_limit = + system.Kernel().ResourceLimit().GetForCategory(Kernel::ResourceLimitCategory::Application); process->Run(48, Kernel::DEFAULT_STACK_SIZE); diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index 5ad927761..ad5799d14 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h @@ -14,8 +14,8 @@ namespace Loader { /// Loads an ELF/AXF file class AppLoader_ELF final : public AppLoader { public: - AppLoader_ELF(FileUtil::IOFile&& file, std::string filename) - : AppLoader(std::move(file)), filename(std::move(filename)) {} + AppLoader_ELF(Core::System& system_, FileUtil::IOFile&& file, std::string filename) + : AppLoader(system_, std::move(file)), filename(std::move(filename)) {} /** * Returns the type of the file diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 30dd1d9a2..b282d0a24 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -6,6 +6,7 @@ #include #include "common/logging/log.h" #include "common/string_util.h" +#include "core/core.h" #include "core/hle/kernel/process.h" #include "core/loader/3dsx.h" #include "core/loader/elf.h" @@ -89,23 +90,23 @@ const char* GetFileTypeString(FileType type) { * @param filepath the file full path (with name) * @return std::unique_ptr a pointer to a loader object; nullptr for unsupported type */ -static std::unique_ptr GetFileLoader(FileUtil::IOFile&& file, FileType type, - const std::string& filename, +static std::unique_ptr GetFileLoader(Core::System& system, FileUtil::IOFile&& file, + FileType type, const std::string& filename, const std::string& filepath) { switch (type) { // 3DSX file format. case FileType::THREEDSX: - return std::make_unique(std::move(file), filename, filepath); + return std::make_unique(system, std::move(file), filename, filepath); // Standard ELF file format. case FileType::ELF: - return std::make_unique(std::move(file), filename); + return std::make_unique(system, std::move(file), filename); // NCCH/NCSD container formats. case FileType::CXI: case FileType::CCI: - return std::make_unique(std::move(file), filepath); + return std::make_unique(system, std::move(file), filepath); default: return nullptr; @@ -133,7 +134,8 @@ std::unique_ptr GetLoader(const std::string& filename) { LOG_DEBUG(Loader, "Loading file {} as {}...", filename, GetFileTypeString(type)); - return GetFileLoader(std::move(file), type, filename_filename, filename); + auto& system = Core::System::GetInstance(); + return GetFileLoader(system, std::move(file), type, filename_filename, filename); } } // namespace Loader diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index deee7c230..fd76e1cb6 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -82,7 +82,8 @@ constexpr u32 MakeMagic(char a, char b, char c, char d) { /// Interface for loading an application class AppLoader : NonCopyable { public: - explicit AppLoader(FileUtil::IOFile&& file) : file(std::move(file)) {} + explicit AppLoader(Core::System& system_, FileUtil::IOFile&& file) + : system(system_), file(std::move(file)) {} virtual ~AppLoader() {} /** @@ -253,6 +254,7 @@ public: } protected: + Core::System& system; FileUtil::IOFile file; bool is_loaded = false; }; diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 5bbe85944..695a612f4 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -113,8 +113,7 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr& process) std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( (const char*)overlay_ncch->exheader_header.codeset_info.name, 8); - std::shared_ptr codeset = - Core::System::GetInstance().Kernel().CreateCodeSet(process_name, program_id); + std::shared_ptr codeset = system.Kernel().CreateCodeSet(process_name, program_id); codeset->CodeSegment().offset = 0; codeset->CodeSegment().addr = overlay_ncch->exheader_header.codeset_info.text.address; @@ -148,7 +147,6 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr& process) codeset->entrypoint = codeset->CodeSegment().addr; codeset->memory = std::move(code); - auto& system = Core::System::GetInstance(); process = system.Kernel().CreateProcess(std::move(codeset)); // Attach a resource limit to the process based on the resource limit category @@ -276,7 +274,6 @@ ResultStatus AppLoader_NCCH::Load(std::shared_ptr& process) { overlay_ncch = &update_ncch; } - auto& system = Core::System::GetInstance(); system.TelemetrySession().AddField(Common::Telemetry::FieldType::Session, "ProgramId", program_id); diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index 57ec25c5b..099644b75 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h @@ -15,8 +15,8 @@ namespace Loader { /// Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI) class AppLoader_NCCH final : public AppLoader { public: - AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath) - : AppLoader(std::move(file)), base_ncch(filepath), overlay_ncch(&base_ncch), + AppLoader_NCCH(Core::System& system_, FileUtil::IOFile&& file, const std::string& filepath) + : AppLoader(system_, std::move(file)), base_ncch(filepath), overlay_ncch(&base_ncch), filepath(filepath) {} /** diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 0f2ef021d..fa616b9ed 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -264,14 +264,55 @@ public: return {vram_mem, addr - VRAM_VADDR}; } if (addr >= PLUGIN_3GX_FB_VADDR && addr < PLUGIN_3GX_FB_VADDR_END) { - return {fcram_mem, addr - PLUGIN_3GX_FB_VADDR + - Service::PLGLDR::PLG_LDR::GetPluginFBAddr() - FCRAM_PADDR}; + auto plg_ldr = Service::PLGLDR::GetService(system); + if (plg_ldr) { + return {fcram_mem, + addr - PLUGIN_3GX_FB_VADDR + plg_ldr->GetPluginFBAddr() - FCRAM_PADDR}; + } } UNREACHABLE(); return MemoryRef{}; } + void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) { + const VAddr end = start + size; + + auto CheckRegion = [&](VAddr region_start, VAddr region_end, PAddr paddr_region_start) { + if (start >= region_end || end <= region_start) { + // No overlap with region + return; + } + + auto& renderer = system.GPU().Renderer(); + VAddr overlap_start = std::max(start, region_start); + VAddr overlap_end = std::min(end, region_end); + PAddr physical_start = paddr_region_start + (overlap_start - region_start); + u32 overlap_size = overlap_end - overlap_start; + + auto* rasterizer = renderer.Rasterizer(); + switch (mode) { + case FlushMode::Flush: + rasterizer->FlushRegion(physical_start, overlap_size); + break; + case FlushMode::Invalidate: + rasterizer->InvalidateRegion(physical_start, overlap_size); + break; + case FlushMode::FlushAndInvalidate: + rasterizer->FlushAndInvalidateRegion(physical_start, overlap_size); + break; + } + }; + + CheckRegion(LINEAR_HEAP_VADDR, LINEAR_HEAP_VADDR_END, FCRAM_PADDR); + CheckRegion(NEW_LINEAR_HEAP_VADDR, NEW_LINEAR_HEAP_VADDR_END, FCRAM_PADDR); + CheckRegion(VRAM_VADDR, VRAM_VADDR_END, VRAM_PADDR); + auto plg_ldr = Service::PLGLDR::GetService(system); + if (plg_ldr && plg_ldr->GetPluginFBAddr()) { + CheckRegion(PLUGIN_3GX_FB_VADDR, PLUGIN_3GX_FB_VADDR_END, plg_ldr->GetPluginFBAddr()); + } + } + private: friend class boost::serialization::access; template @@ -345,41 +386,8 @@ std::shared_ptr MemorySystem::GetCurrentPageTable() const { return impl->current_page_table; } -void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) { - const VAddr end = start + size; - - auto CheckRegion = [&](VAddr region_start, VAddr region_end, PAddr paddr_region_start) { - if (start >= region_end || end <= region_start) { - // No overlap with region - return; - } - - auto& renderer = Core::System::GetInstance().GPU().Renderer(); - VAddr overlap_start = std::max(start, region_start); - VAddr overlap_end = std::min(end, region_end); - PAddr physical_start = paddr_region_start + (overlap_start - region_start); - u32 overlap_size = overlap_end - overlap_start; - - auto* rasterizer = renderer.Rasterizer(); - switch (mode) { - case FlushMode::Flush: - rasterizer->FlushRegion(physical_start, overlap_size); - break; - case FlushMode::Invalidate: - rasterizer->InvalidateRegion(physical_start, overlap_size); - break; - case FlushMode::FlushAndInvalidate: - rasterizer->FlushAndInvalidateRegion(physical_start, overlap_size); - break; - } - }; - - CheckRegion(LINEAR_HEAP_VADDR, LINEAR_HEAP_VADDR_END, FCRAM_PADDR); - CheckRegion(NEW_LINEAR_HEAP_VADDR, NEW_LINEAR_HEAP_VADDR_END, FCRAM_PADDR); - CheckRegion(VRAM_VADDR, VRAM_VADDR_END, VRAM_PADDR); - if (Service::PLGLDR::PLG_LDR::GetPluginFBAddr()) - CheckRegion(PLUGIN_3GX_FB_VADDR, PLUGIN_3GX_FB_VADDR_END, - Service::PLGLDR::PLG_LDR::GetPluginFBAddr()); +void MemorySystem::RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) { + impl->RasterizerFlushVirtualRegion(start, size, mode); } void MemorySystem::MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, @@ -683,16 +691,19 @@ std::vector MemorySystem::PhysicalToVirtualAddressForRasterizer(PAddr add if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { return {addr - VRAM_PADDR + VRAM_VADDR}; } - if (addr >= Service::PLGLDR::PLG_LDR::GetPluginFBAddr() && - addr < Service::PLGLDR::PLG_LDR::GetPluginFBAddr() + PLUGIN_3GX_FB_SIZE) { - return {addr - Service::PLGLDR::PLG_LDR::GetPluginFBAddr() + PLUGIN_3GX_FB_VADDR}; - } if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { return {addr - FCRAM_PADDR + LINEAR_HEAP_VADDR, addr - FCRAM_PADDR + NEW_LINEAR_HEAP_VADDR}; } if (addr >= FCRAM_PADDR_END && addr < FCRAM_N3DS_PADDR_END) { return {addr - FCRAM_PADDR + NEW_LINEAR_HEAP_VADDR}; } + auto plg_ldr = Service::PLGLDR::GetService(impl->system); + if (plg_ldr) { + auto fb_addr = plg_ldr->GetPluginFBAddr(); + if (addr >= fb_addr && addr < fb_addr + PLUGIN_3GX_FB_SIZE) { + return {addr - fb_addr + PLUGIN_3GX_FB_VADDR}; + } + } // While the physical <-> virtual mapping is 1:1 for the regions supported by the cache, // some games (like Pokemon Super Mystery Dungeon) will try to use textures that go beyond // the end address of VRAM, causing the Virtual->Physical translation to fail when flushing diff --git a/src/core/memory.h b/src/core/memory.h index 24ece022a..3aaf09bbe 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -235,8 +235,6 @@ enum class FlushMode { FlushAndInvalidate, }; -void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); - class MemorySystem { public: explicit MemorySystem(Core::System& system); @@ -553,6 +551,8 @@ public: void SetDSP(AudioCore::DspInterface& dsp); + void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); + private: template T Read(const VAddr vaddr); diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index a77e8b1dd..3def26757 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -22,28 +22,6 @@ namespace VideoCore { constexpr VAddr VADDR_LCD = 0x1ED02000; constexpr VAddr VADDR_GPU = 0x1EF00000; -static PAddr VirtualToPhysicalAddress(VAddr addr) { - if (addr == 0) { - return 0; - } - - if (addr >= Memory::VRAM_VADDR && addr <= Memory::VRAM_VADDR_END) { - return addr - Memory::VRAM_VADDR + Memory::VRAM_PADDR; - } - if (addr >= Memory::LINEAR_HEAP_VADDR && addr <= Memory::LINEAR_HEAP_VADDR_END) { - return addr - Memory::LINEAR_HEAP_VADDR + Memory::FCRAM_PADDR; - } - if (addr >= Memory::NEW_LINEAR_HEAP_VADDR && addr <= Memory::NEW_LINEAR_HEAP_VADDR_END) { - return addr - Memory::NEW_LINEAR_HEAP_VADDR + Memory::FCRAM_PADDR; - } - if (addr >= Memory::PLUGIN_3GX_FB_VADDR && addr <= Memory::PLUGIN_3GX_FB_VADDR_END) { - return addr - Memory::PLUGIN_3GX_FB_VADDR + Service::PLGLDR::PLG_LDR::GetPluginFBAddr(); - } - - LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x{:08X}", addr); - return addr; -} - MICROPROFILE_DEFINE(GPU_DisplayTransfer, "GPU", "DisplayTransfer", MP_RGB(100, 100, 255)); MICROPROFILE_DEFINE(GPU_CmdlistProcessing, "GPU", "Cmdlist Processing", MP_RGB(100, 255, 100)); @@ -84,6 +62,31 @@ GPU::GPU(Core::System& system, Frontend::EmuWindow& emu_window, GPU::~GPU() = default; +PAddr GPU::VirtualToPhysicalAddress(VAddr addr) { + if (addr == 0) { + return 0; + } + + if (addr >= Memory::VRAM_VADDR && addr <= Memory::VRAM_VADDR_END) { + return addr - Memory::VRAM_VADDR + Memory::VRAM_PADDR; + } + if (addr >= Memory::LINEAR_HEAP_VADDR && addr <= Memory::LINEAR_HEAP_VADDR_END) { + return addr - Memory::LINEAR_HEAP_VADDR + Memory::FCRAM_PADDR; + } + if (addr >= Memory::NEW_LINEAR_HEAP_VADDR && addr <= Memory::NEW_LINEAR_HEAP_VADDR_END) { + return addr - Memory::NEW_LINEAR_HEAP_VADDR + Memory::FCRAM_PADDR; + } + if (addr >= Memory::PLUGIN_3GX_FB_VADDR && addr <= Memory::PLUGIN_3GX_FB_VADDR_END) { + auto plg_ldr = Service::PLGLDR::GetService(impl->system); + if (plg_ldr) { + return addr - Memory::PLUGIN_3GX_FB_VADDR + plg_ldr->GetPluginFBAddr(); + } + } + + LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x{:08X}", addr); + return addr; +} + void GPU::SetInterruptHandler(Service::GSP::InterruptHandler handler) { impl->signal_interrupt = handler; impl->pica.SetInterruptHandler(handler); @@ -107,11 +110,11 @@ void GPU::Execute(const Service::GSP::Command& command) { switch (command.id) { case CommandId::RequestDma: { - Memory::RasterizerFlushVirtualRegion(command.dma_request.source_address, - command.dma_request.size, Memory::FlushMode::Flush); - Memory::RasterizerFlushVirtualRegion(command.dma_request.dest_address, - command.dma_request.size, - Memory::FlushMode::Invalidate); + impl->system.Memory().RasterizerFlushVirtualRegion( + command.dma_request.source_address, command.dma_request.size, Memory::FlushMode::Flush); + impl->system.Memory().RasterizerFlushVirtualRegion(command.dma_request.dest_address, + command.dma_request.size, + Memory::FlushMode::Invalidate); // TODO(Subv): These memory accesses should not go through the application's memory mapping. // They should go through the GSP module's memory mapping. diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 4b29bb431..c5dd2c868 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -108,6 +108,8 @@ private: private: struct Impl; std::unique_ptr impl; + + PAddr VirtualToPhysicalAddress(VAddr addr); }; } // namespace VideoCore