mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	core: Eliminate more uses of Core::System::GetInstance(). (#7313)
This commit is contained in:
		
							parent
							
								
									8e2037b3ff
								
							
						
					
					
						commit
						f2ee9baec7
					
				
					 47 changed files with 416 additions and 387 deletions
				
			
		|  | @ -24,16 +24,10 @@ | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| 
 | 
 | ||||||
| SERIALIZE_EXPORT_IMPL(AudioCore::DspHle) |  | ||||||
| 
 |  | ||||||
| using InterruptType = Service::DSP::InterruptType; | using InterruptType = Service::DSP::InterruptType; | ||||||
| 
 | 
 | ||||||
| namespace AudioCore { | 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()) {} | DspHle::DspHle(Core::System& system) : DspHle(system, system.Memory(), system.CoreTiming()) {} | ||||||
| 
 | 
 | ||||||
| template <class Archive> | template <class Archive> | ||||||
|  |  | ||||||
|  | @ -50,13 +50,9 @@ private: | ||||||
|     friend struct Impl; |     friend struct Impl; | ||||||
|     std::unique_ptr<Impl> impl; |     std::unique_ptr<Impl> impl; | ||||||
| 
 | 
 | ||||||
|     DspHle(); |  | ||||||
| 
 |  | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|     void serialize(Archive& ar, const unsigned int); |     void serialize(Archive& ar, const unsigned int); | ||||||
|     friend class boost::serialization::access; |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace AudioCore
 | } // namespace AudioCore
 | ||||||
| 
 |  | ||||||
| BOOST_CLASS_EXPORT_KEY(AudioCore::DspHle) |  | ||||||
|  |  | ||||||
|  | @ -24,8 +24,8 @@ namespace { | ||||||
| constexpr std::array input_details = { | constexpr std::array input_details = { | ||||||
| #ifdef HAVE_CUBEB | #ifdef HAVE_CUBEB | ||||||
|     InputDetails{InputType::Cubeb, "Real Device (Cubeb)", true, |     InputDetails{InputType::Cubeb, "Real Device (Cubeb)", true, | ||||||
|                  [](std::string_view device_id) -> std::unique_ptr<Input> { |                  [](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> { | ||||||
|                      if (!Core::System::GetInstance().HasMicPermission()) { |                      if (!system.HasMicPermission()) { | ||||||
|                          LOG_WARNING(Audio, |                          LOG_WARNING(Audio, | ||||||
|                                      "Microphone permission denied, falling back to null input."); |                                      "Microphone permission denied, falling back to null input."); | ||||||
|                          return std::make_unique<NullInput>(); |                          return std::make_unique<NullInput>(); | ||||||
|  | @ -36,8 +36,8 @@ constexpr std::array input_details = { | ||||||
| #endif | #endif | ||||||
| #ifdef HAVE_OPENAL | #ifdef HAVE_OPENAL | ||||||
|     InputDetails{InputType::OpenAL, "Real Device (OpenAL)", true, |     InputDetails{InputType::OpenAL, "Real Device (OpenAL)", true, | ||||||
|                  [](std::string_view device_id) -> std::unique_ptr<Input> { |                  [](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> { | ||||||
|                      if (!Core::System::GetInstance().HasMicPermission()) { |                      if (!system.HasMicPermission()) { | ||||||
|                          LOG_WARNING(Audio, |                          LOG_WARNING(Audio, | ||||||
|                                      "Microphone permission denied, falling back to null input."); |                                      "Microphone permission denied, falling back to null input."); | ||||||
|                          return std::make_unique<NullInput>(); |                          return std::make_unique<NullInput>(); | ||||||
|  | @ -47,12 +47,12 @@ constexpr std::array input_details = { | ||||||
|                  &ListOpenALInputDevices}, |                  &ListOpenALInputDevices}, | ||||||
| #endif | #endif | ||||||
|     InputDetails{InputType::Static, "Static Noise", false, |     InputDetails{InputType::Static, "Static Noise", false, | ||||||
|                  [](std::string_view device_id) -> std::unique_ptr<Input> { |                  [](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> { | ||||||
|                      return std::make_unique<StaticInput>(); |                      return std::make_unique<StaticInput>(); | ||||||
|                  }, |                  }, | ||||||
|                  [] { return std::vector<std::string>{"Static Noise"}; }}, |                  [] { return std::vector<std::string>{"Static Noise"}; }}, | ||||||
|     InputDetails{InputType::Null, "None", false, |     InputDetails{InputType::Null, "None", false, | ||||||
|                  [](std::string_view device_id) -> std::unique_ptr<Input> { |                  [](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> { | ||||||
|                      return std::make_unique<NullInput>(); |                      return std::make_unique<NullInput>(); | ||||||
|                  }, |                  }, | ||||||
|                  [] { return std::vector<std::string>{"None"}; }}, |                  [] { return std::vector<std::string>{"None"}; }}, | ||||||
|  |  | ||||||
|  | @ -10,6 +10,10 @@ | ||||||
| #include <vector> | #include <vector> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
|  | namespace Core { | ||||||
|  | class System; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| namespace AudioCore { | namespace AudioCore { | ||||||
| 
 | 
 | ||||||
| class Input; | class Input; | ||||||
|  | @ -23,7 +27,7 @@ enum class InputType : u32 { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct InputDetails { | struct InputDetails { | ||||||
|     using FactoryFn = std::unique_ptr<Input> (*)(std::string_view device_id); |     using FactoryFn = std::unique_ptr<Input> (*)(Core::System& system, std::string_view device_id); | ||||||
|     using ListDevicesFn = std::vector<std::string> (*)(); |     using ListDevicesFn = std::vector<std::string> (*)(); | ||||||
| 
 | 
 | ||||||
|     /// Type of this input.
 |     /// Type of this input.
 | ||||||
|  |  | ||||||
|  | @ -666,9 +666,11 @@ void System::ApplySettings() { | ||||||
|         Service::MIC::ReloadMic(*this); |         Service::MIC::ReloadMic(*this); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Service::PLGLDR::PLG_LDR::SetEnabled(Settings::values.plugin_loader_enabled.GetValue()); |     auto plg_ldr = Service::PLGLDR::GetService(*this); | ||||||
|     Service::PLGLDR::PLG_LDR::SetAllowGameChangeState( |     if (plg_ldr) { | ||||||
|         Settings::values.allow_plugin_loader.GetValue()); |         plg_ldr->SetEnabled(Settings::values.plugin_loader_enabled.GetValue()); | ||||||
|  |         plg_ldr->SetAllowGameChangeState(Settings::values.allow_plugin_loader.GetValue()); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <class Archive> | template <class Archive> | ||||||
|  |  | ||||||
|  | @ -65,7 +65,7 @@ static bool ReadSection(std::vector<u8>& data_out, FileUtil::IOFile& file, std:: | ||||||
| 
 | 
 | ||||||
| Loader::ResultStatus FileSys::Plugin3GXLoader::Load( | Loader::ResultStatus FileSys::Plugin3GXLoader::Load( | ||||||
|     Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Kernel::Process& process, |     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"); |     FileUtil::IOFile file(plg_context.plugin_path, "rb"); | ||||||
|     if (!file.IsOpen()) { |     if (!file.IsOpen()) { | ||||||
|         LOG_ERROR(Service_PLGLDR, "Failed to load 3GX plugin. Not found: {}", |         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 Loader::ResultStatus::Error; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return Map(plg_context, process, kernel); |     return Map(plg_context, process, kernel, plg_ldr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Loader::ResultStatus FileSys::Plugin3GXLoader::Map( | Loader::ResultStatus FileSys::Plugin3GXLoader::Map( | ||||||
|     Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Kernel::Process& process, |     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
 |     // Verify exe load checksum function is available
 | ||||||
|     if (exe_load_func.empty() && plg_context.load_exe_func.empty()) { |     if (exe_load_func.empty() && plg_context.load_exe_func.empty()) { | ||||||
|  | @ -195,7 +195,7 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Map( | ||||||
|         return Loader::ResultStatus::ErrorMemoryAllocationFailed; |         return Loader::ResultStatus::ErrorMemoryAllocationFailed; | ||||||
|     } |     } | ||||||
|     auto backing_memory_fb = kernel.memory.GetFCRAMRef(*offset_fb); |     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); |     std::fill(backing_memory_fb.GetPtr(), backing_memory_fb.GetPtr() + _3GX_fb_size, 0); | ||||||
| 
 | 
 | ||||||
|     auto vma_heap_fb = process.vm_manager.MapBackingMemory( |     auto vma_heap_fb = process.vm_manager.MapBackingMemory( | ||||||
|  |  | ||||||
|  | @ -43,7 +43,8 @@ class FileBackend; | ||||||
| class Plugin3GXLoader { | class Plugin3GXLoader { | ||||||
| public: | public: | ||||||
|     Loader::ResultStatus Load(Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, |     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 { |     struct PluginHeader { | ||||||
|         u32_le magic; |         u32_le magic; | ||||||
|  | @ -68,7 +69,8 @@ public: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Loader::ResultStatus Map(Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, |     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 constexpr size_t bootloader_memory_size = 0x1000; | ||||||
|     static void MapBootloader(Kernel::Process& process, Kernel::KernelSystem& kernel, |     static void MapBootloader(Kernel::Process& process, Kernel::KernelSystem& kernel, | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ | ||||||
| 
 | 
 | ||||||
| namespace Frontend { | namespace Frontend { | ||||||
| void RegisterDefaultApplets(Core::System& system) { | void RegisterDefaultApplets(Core::System& system) { | ||||||
|     system.RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>()); |     system.RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>(system)); | ||||||
|     system.RegisterMiiSelector(std::make_shared<DefaultMiiSelector>()); |     system.RegisterMiiSelector(std::make_shared<DefaultMiiSelector>()); | ||||||
| } | } | ||||||
| } // namespace Frontend
 | } // namespace Frontend
 | ||||||
|  |  | ||||||
|  | @ -144,10 +144,12 @@ const KeyboardData& SoftwareKeyboard::ReceiveData() { | ||||||
|     return data; |     return data; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | DefaultKeyboard::DefaultKeyboard(Core::System& system_) : system(system_) {} | ||||||
|  | 
 | ||||||
| void DefaultKeyboard::Execute(const Frontend::KeyboardConfig& config_) { | void DefaultKeyboard::Execute(const Frontend::KeyboardConfig& config_) { | ||||||
|     SoftwareKeyboard::Execute(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()); |     std::string username = Common::UTF16ToUTF8(cfg->GetUsername()); | ||||||
|     switch (this->config.button_config) { |     switch (this->config.button_config) { | ||||||
|     case ButtonConfig::None: |     case ButtonConfig::None: | ||||||
|  |  | ||||||
|  | @ -8,6 +8,10 @@ | ||||||
| #include <vector> | #include <vector> | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| 
 | 
 | ||||||
|  | namespace Core { | ||||||
|  | class System; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| namespace Frontend { | namespace Frontend { | ||||||
| 
 | 
 | ||||||
| enum class AcceptedInput { | enum class AcceptedInput { | ||||||
|  | @ -137,8 +141,12 @@ protected: | ||||||
| 
 | 
 | ||||||
| class DefaultKeyboard final : public SoftwareKeyboard { | class DefaultKeyboard final : public SoftwareKeyboard { | ||||||
| public: | public: | ||||||
|  |     explicit DefaultKeyboard(Core::System& system_); | ||||||
|     void Execute(const KeyboardConfig& config) override; |     void Execute(const KeyboardConfig& config) override; | ||||||
|     void ShowError(const std::string& error) override; |     void ShowError(const std::string& error) override; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     Core::System& system; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Frontend
 | } // namespace Frontend
 | ||||||
|  |  | ||||||
|  | @ -5,97 +5,16 @@ | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <type_traits> | #include <type_traits> | ||||||
| #include <unordered_map> |  | ||||||
| #include <utility> | #include <utility> | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/hle/applets/applet.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" | #include "core/hle/result.h" | ||||||
| 
 | 
 | ||||||
| namespace HLE::Applets { | namespace HLE::Applets { | ||||||
| 
 | 
 | ||||||
| static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> 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<Service::APT::AppletManager>& manager) { |  | ||||||
|     switch (id) { |  | ||||||
|     case Service::APT::AppletId::SoftwareKeyboard1: |  | ||||||
|     case Service::APT::AppletId::SoftwareKeyboard2: |  | ||||||
|         applets[id] = std::make_shared<SoftwareKeyboard>(id, parent, preload, manager); |  | ||||||
|         break; |  | ||||||
|     case Service::APT::AppletId::Ed1: |  | ||||||
|     case Service::APT::AppletId::Ed2: |  | ||||||
|         applets[id] = std::make_shared<MiiSelector>(id, parent, preload, manager); |  | ||||||
|         break; |  | ||||||
|     case Service::APT::AppletId::Error: |  | ||||||
|     case Service::APT::AppletId::Error2: |  | ||||||
|         applets[id] = std::make_shared<ErrEula>(id, parent, preload, manager); |  | ||||||
|         break; |  | ||||||
|     case Service::APT::AppletId::Mint: |  | ||||||
|     case Service::APT::AppletId::Mint2: |  | ||||||
|         applets[id] = std::make_shared<Mint>(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<u64>(id)); |  | ||||||
|     return ResultSuccess; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::shared_ptr<Applet> 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<Service::APT::AppletId>(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 { | bool Applet::IsRunning() const { | ||||||
|     return is_running; |     return is_running; | ||||||
| } | } | ||||||
|  | @ -140,13 +59,4 @@ void Applet::CloseApplet(std::shared_ptr<Kernel::Object> object, const std::vect | ||||||
|     is_running = false; |     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
 | } // namespace HLE::Applets
 | ||||||
|  |  | ||||||
|  | @ -14,24 +14,6 @@ class Applet { | ||||||
| public: | public: | ||||||
|     virtual ~Applet() = default; |     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<Service::APT::AppletManager>& 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<Applet> Get(Service::APT::AppletId id); |  | ||||||
| 
 |  | ||||||
|     /**
 |     /**
 | ||||||
|      * Handles a parameter from the application. |      * Handles a parameter from the application. | ||||||
|      * @param parameter Parameter data to handle. |      * @param parameter Parameter data to handle. | ||||||
|  | @ -55,9 +37,9 @@ public: | ||||||
|     virtual void Update() = 0; |     virtual void Update() = 0; | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     Applet(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, |     Applet(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent, | ||||||
|            std::weak_ptr<Service::APT::AppletManager> manager) |            bool preload, std::weak_ptr<Service::APT::AppletManager> manager) | ||||||
|         : id(id), parent(parent), preload(preload), manager(std::move(manager)) {} |         : system(system), id(id), parent(parent), preload(preload), manager(std::move(manager)) {} | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Handles a parameter from the application. |      * Handles a parameter from the application. | ||||||
|  | @ -79,6 +61,8 @@ protected: | ||||||
|      */ |      */ | ||||||
|     virtual Result Finalize() = 0; |     virtual Result Finalize() = 0; | ||||||
| 
 | 
 | ||||||
|  |     Core::System& system; | ||||||
|  | 
 | ||||||
|     Service::APT::AppletId id;                    ///< Id of this Applet
 |     Service::APT::AppletId id;                    ///< Id of this Applet
 | ||||||
|     Service::APT::AppletId parent;                ///< Id of this Applet's parent
 |     Service::APT::AppletId parent;                ///< Id of this Applet's parent
 | ||||||
|     bool preload;                                 ///< Whether the Applet is being preloaded.
 |     bool preload;                                 ///< Whether the Applet is being preloaded.
 | ||||||
|  | @ -97,9 +81,4 @@ private: | ||||||
|     std::weak_ptr<Service::APT::AppletManager> manager; |     std::weak_ptr<Service::APT::AppletManager> manager; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// Initializes the HLE applets
 |  | ||||||
| void Init(); |  | ||||||
| 
 |  | ||||||
| /// Shuts down the HLE applets
 |  | ||||||
| void Shutdown(); |  | ||||||
| } // namespace HLE::Applets
 | } // namespace HLE::Applets
 | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ Result ErrEula::ReceiveParameterImpl(const Service::APT::MessageParameter& param | ||||||
|     // TODO: allocated memory never released
 |     // TODO: allocated memory never released
 | ||||||
|     using Kernel::MemoryPermission; |     using Kernel::MemoryPermission; | ||||||
|     // Create a SharedMemory that directly points to this heap block.
 |     // 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, |         0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, | ||||||
|         "ErrEula Memory"); |         "ErrEula Memory"); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,9 +11,9 @@ namespace HLE::Applets { | ||||||
| 
 | 
 | ||||||
| class ErrEula final : public Applet { | class ErrEula final : public Applet { | ||||||
| public: | public: | ||||||
|     explicit ErrEula(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, |     explicit ErrEula(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent, | ||||||
|                      std::weak_ptr<Service::APT::AppletManager> manager) |                      bool preload, std::weak_ptr<Service::APT::AppletManager> manager) | ||||||
|         : Applet(id, parent, preload, std::move(manager)) {} |         : Applet(system, id, parent, preload, std::move(manager)) {} | ||||||
| 
 | 
 | ||||||
|     Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; |     Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; | ||||||
|     Result Start(const Service::APT::MessageParameter& parameter) override; |     Result Start(const Service::APT::MessageParameter& parameter) override; | ||||||
|  |  | ||||||
|  | @ -35,7 +35,7 @@ Result MiiSelector::ReceiveParameterImpl(const Service::APT::MessageParameter& p | ||||||
| 
 | 
 | ||||||
|     using Kernel::MemoryPermission; |     using Kernel::MemoryPermission; | ||||||
|     // Create a SharedMemory that directly points to this heap block.
 |     // 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, |         0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, | ||||||
|         "MiiSelector Memory"); |         "MiiSelector Memory"); | ||||||
| 
 | 
 | ||||||
|  | @ -57,7 +57,7 @@ Result MiiSelector::Start(const Service::APT::MessageParameter& parameter) { | ||||||
|     std::memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); |     std::memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); | ||||||
| 
 | 
 | ||||||
|     using namespace Frontend; |     using namespace Frontend; | ||||||
|     frontend_applet = Core::System::GetInstance().GetMiiSelector(); |     frontend_applet = system.GetMiiSelector(); | ||||||
|     ASSERT(frontend_applet); |     ASSERT(frontend_applet); | ||||||
| 
 | 
 | ||||||
|     MiiSelectorConfig frontend_config = ToFrontendConfig(config); |     MiiSelectorConfig frontend_config = ToFrontendConfig(config); | ||||||
|  |  | ||||||
|  | @ -62,9 +62,9 @@ ASSERT_REG_POSITION(guest_mii_name, 0x6C); | ||||||
| 
 | 
 | ||||||
| class MiiSelector final : public Applet { | class MiiSelector final : public Applet { | ||||||
| public: | public: | ||||||
|     MiiSelector(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, |     MiiSelector(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent, | ||||||
|                 std::weak_ptr<Service::APT::AppletManager> manager) |                 bool preload, std::weak_ptr<Service::APT::AppletManager> manager) | ||||||
|         : Applet(id, parent, preload, std::move(manager)) {} |         : Applet(system, id, parent, preload, std::move(manager)) {} | ||||||
| 
 | 
 | ||||||
|     Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; |     Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; | ||||||
|     Result Start(const Service::APT::MessageParameter& parameter) override; |     Result Start(const Service::APT::MessageParameter& parameter) override; | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ Result Mint::ReceiveParameterImpl(const Service::APT::MessageParameter& paramete | ||||||
|     // TODO: allocated memory never released
 |     // TODO: allocated memory never released
 | ||||||
|     using Kernel::MemoryPermission; |     using Kernel::MemoryPermission; | ||||||
|     // Create a SharedMemory that directly points to this heap block.
 |     // 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, |         0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, | ||||||
|         "Mint Memory"); |         "Mint Memory"); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,9 +11,9 @@ namespace HLE::Applets { | ||||||
| 
 | 
 | ||||||
| class Mint final : public Applet { | class Mint final : public Applet { | ||||||
| public: | public: | ||||||
|     explicit Mint(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, |     explicit Mint(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent, | ||||||
|                   std::weak_ptr<Service::APT::AppletManager> manager) |                   bool preload, std::weak_ptr<Service::APT::AppletManager> manager) | ||||||
|         : Applet(id, parent, preload, std::move(manager)) {} |         : Applet(system, id, parent, preload, std::move(manager)) {} | ||||||
| 
 | 
 | ||||||
|     Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; |     Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; | ||||||
|     Result Start(const Service::APT::MessageParameter& parameter) override; |     Result Start(const Service::APT::MessageParameter& parameter) override; | ||||||
|  |  | ||||||
|  | @ -32,7 +32,7 @@ Result SoftwareKeyboard::ReceiveParameterImpl(Service::APT::MessageParameter con | ||||||
| 
 | 
 | ||||||
|         using Kernel::MemoryPermission; |         using Kernel::MemoryPermission; | ||||||
|         // Create a SharedMemory that directly points to this heap block.
 |         // 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, |             0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, | ||||||
|             "SoftwareKeyboard Memory"); |             "SoftwareKeyboard Memory"); | ||||||
| 
 | 
 | ||||||
|  | @ -99,7 +99,7 @@ Result SoftwareKeyboard::Start(Service::APT::MessageParameter const& parameter) | ||||||
|     DrawScreenKeyboard(); |     DrawScreenKeyboard(); | ||||||
| 
 | 
 | ||||||
|     using namespace Frontend; |     using namespace Frontend; | ||||||
|     frontend_applet = Core::System::GetInstance().GetSoftwareKeyboard(); |     frontend_applet = system.GetSoftwareKeyboard(); | ||||||
|     ASSERT(frontend_applet); |     ASSERT(frontend_applet); | ||||||
| 
 | 
 | ||||||
|     frontend_applet->Execute(ToFrontendConfig(config)); |     frontend_applet->Execute(ToFrontendConfig(config)); | ||||||
|  |  | ||||||
|  | @ -175,9 +175,9 @@ static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config | ||||||
| 
 | 
 | ||||||
| class SoftwareKeyboard final : public Applet { | class SoftwareKeyboard final : public Applet { | ||||||
| public: | public: | ||||||
|     SoftwareKeyboard(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, |     SoftwareKeyboard(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent, | ||||||
|                      std::weak_ptr<Service::APT::AppletManager> manager) |                      bool preload, std::weak_ptr<Service::APT::AppletManager> manager) | ||||||
|         : Applet(id, parent, preload, std::move(manager)) {} |         : Applet(system, id, parent, preload, std::move(manager)) {} | ||||||
| 
 | 
 | ||||||
|     Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; |     Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; | ||||||
|     Result Start(const Service::APT::MessageParameter& parameter) override; |     Result Start(const Service::APT::MessageParameter& parameter) override; | ||||||
|  |  | ||||||
|  | @ -20,6 +20,9 @@ | ||||||
| #include "core/hle/service/soc/soc_u.h" | #include "core/hle/service/soc/soc_u.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| 
 | 
 | ||||||
|  | SERIALIZE_EXPORT_IMPL(Service::AC::Module) | ||||||
|  | SERVICE_CONSTRUCT_IMPL(Service::AC::Module) | ||||||
|  | 
 | ||||||
| namespace Service::AC { | namespace Service::AC { | ||||||
| void Module::Interface::CreateDefaultConfig(Kernel::HLERequestContext& ctx) { | void Module::Interface::CreateDefaultConfig(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(ctx); |     IPC::RequestParser rp(ctx); | ||||||
|  | @ -96,7 +99,7 @@ void Module::Interface::GetWifiStatus(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(ctx); |     IPC::RequestParser rp(ctx); | ||||||
|     bool can_reach_internet = false; |     bool can_reach_internet = false; | ||||||
| 
 | 
 | ||||||
|     std::shared_ptr<SOC::SOC_U> socu_module = SOC::GetService(Core::System::GetInstance()); |     std::shared_ptr<SOC::SOC_U> socu_module = SOC::GetService(ac->system); | ||||||
|     if (socu_module) { |     if (socu_module) { | ||||||
|         can_reach_internet = socu_module->GetDefaultInterfaceInfo().has_value(); |         can_reach_internet = socu_module->GetDefaultInterfaceInfo().has_value(); | ||||||
|     } |     } | ||||||
|  | @ -194,11 +197,13 @@ Module::Interface::Interface(std::shared_ptr<Module> ac, const char* name, u32 m | ||||||
| 
 | 
 | ||||||
| void InstallInterfaces(Core::System& system) { | void InstallInterfaces(Core::System& system) { | ||||||
|     auto& service_manager = system.ServiceManager(); |     auto& service_manager = system.ServiceManager(); | ||||||
|     auto ac = std::make_shared<Module>(); |     auto ac = std::make_shared<Module>(system); | ||||||
|     std::make_shared<AC_I>(ac)->InstallAsService(service_manager); |     std::make_shared<AC_I>(ac)->InstallAsService(service_manager); | ||||||
|     std::make_shared<AC_U>(ac)->InstallAsService(service_manager); |     std::make_shared<AC_U>(ac)->InstallAsService(service_manager); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Module::Module(Core::System& system_) : system(system_) {} | ||||||
|  | 
 | ||||||
| template <class Archive> | template <class Archive> | ||||||
| void Module::serialize(Archive& ar, const unsigned int) { | void Module::serialize(Archive& ar, const unsigned int) { | ||||||
|     ar& ac_connected; |     ar& ac_connected; | ||||||
|  | @ -207,7 +212,6 @@ void Module::serialize(Archive& ar, const unsigned int) { | ||||||
|     ar& disconnect_event; |     ar& disconnect_event; | ||||||
|     // default_config is never written to
 |     // default_config is never written to
 | ||||||
| } | } | ||||||
|  | SERIALIZE_IMPL(Module) | ||||||
| 
 | 
 | ||||||
| } // namespace Service::AC
 | } // namespace Service::AC
 | ||||||
| 
 |  | ||||||
| SERIALIZE_IMPL(Service::AC::Module) |  | ||||||
|  |  | ||||||
|  | @ -19,6 +19,9 @@ class Event; | ||||||
| namespace Service::AC { | namespace Service::AC { | ||||||
| class Module final { | class Module final { | ||||||
| public: | public: | ||||||
|  |     explicit Module(Core::System& system_); | ||||||
|  |     ~Module() = default; | ||||||
|  | 
 | ||||||
|     class Interface : public ServiceFramework<Interface> { |     class Interface : public ServiceFramework<Interface> { | ||||||
|     public: |     public: | ||||||
|         Interface(std::shared_ptr<Module> ac, const char* name, u32 max_session); |         Interface(std::shared_ptr<Module> ac, const char* name, u32 max_session); | ||||||
|  | @ -169,11 +172,16 @@ protected: | ||||||
|     std::shared_ptr<Kernel::Event> disconnect_event; |     std::shared_ptr<Kernel::Event> disconnect_event; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     Core::System& system; | ||||||
|  | 
 | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|     void serialize(Archive& ar, const unsigned int file_version); |     void serialize(Archive& ar, const unsigned int); | ||||||
|     friend class boost::serialization::access; |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void InstallInterfaces(Core::System& system); | void InstallInterfaces(Core::System& system); | ||||||
| 
 | 
 | ||||||
| } // namespace Service::AC
 | } // namespace Service::AC
 | ||||||
|  | 
 | ||||||
|  | BOOST_CLASS_EXPORT_KEY(Service::AC::Module) | ||||||
|  | SERVICE_CONSTRUCT(Service::AC::Module) | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| #include <cryptopp/modes.h> | #include <cryptopp/modes.h> | ||||||
| #include <fmt/format.h> | #include <fmt/format.h> | ||||||
| #include "common/alignment.h" | #include "common/alignment.h" | ||||||
|  | #include "common/archives.h" | ||||||
| #include "common/common_paths.h" | #include "common/common_paths.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | @ -33,6 +34,9 @@ | ||||||
| #include "core/loader/smdh.h" | #include "core/loader/smdh.h" | ||||||
| #include "core/nus_download.h" | #include "core/nus_download.h" | ||||||
| 
 | 
 | ||||||
|  | SERIALIZE_EXPORT_IMPL(Service::AM::Module) | ||||||
|  | SERVICE_CONSTRUCT_IMPL(Service::AM::Module) | ||||||
|  | 
 | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
| 
 | 
 | ||||||
| constexpr u16 PLATFORM_CTR = 0x0004; | constexpr u16 PLATFORM_CTR = 0x0004; | ||||||
|  | @ -81,8 +85,9 @@ public: | ||||||
|     std::vector<CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption> content; |     std::vector<CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption> content; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| CIAFile::CIAFile(Service::FS::MediaType media_type) | CIAFile::CIAFile(Core::System& system_, Service::FS::MediaType media_type) | ||||||
|     : media_type(media_type), decryption_state(std::make_unique<DecryptionState>()) {} |     : system(system_), media_type(media_type), | ||||||
|  |       decryption_state(std::make_unique<DecryptionState>()) {} | ||||||
| 
 | 
 | ||||||
| CIAFile::~CIAFile() { | CIAFile::~CIAFile() { | ||||||
|     Close(); |     Close(); | ||||||
|  | @ -361,8 +366,7 @@ bool CIAFile::Close() const { | ||||||
|             // are closed.
 |             // are closed.
 | ||||||
|             std::string to_delete = |             std::string to_delete = | ||||||
|                 GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index); |                 GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index); | ||||||
|             if (!(Core::System::GetInstance().IsPoweredOn() && |             if (!system.IsPoweredOn() || !system.SetSelfDelete(to_delete)) { | ||||||
|                   Core::System::GetInstance().SetSelfDelete(to_delete))) { |  | ||||||
|                 FileUtil::Delete(to_delete); |                 FileUtil::Delete(to_delete); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -425,6 +429,7 @@ InstallStatus InstallCIA(const std::string& path, | ||||||
|     FileSys::CIAContainer container; |     FileSys::CIAContainer container; | ||||||
|     if (container.Load(path) == Loader::ResultStatus::Success) { |     if (container.Load(path) == Loader::ResultStatus::Success) { | ||||||
|         Service::AM::CIAFile installFile( |         Service::AM::CIAFile installFile( | ||||||
|  |             Core::System::GetInstance(), | ||||||
|             Service::AM::GetTitleMediaType(container.GetTitleMetadata().GetTitleID())); |             Service::AM::GetTitleMediaType(container.GetTitleMetadata().GetTitleID())); | ||||||
| 
 | 
 | ||||||
|         bool title_key_available = container.GetTicket().GetTitleKey().has_value(); |         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) { | InstallStatus InstallFromNus(u64 title_id, int version) { | ||||||
|     LOG_DEBUG(Service_AM, "Downloading {:X}", title_id); |     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); |     std::string path = fmt::format("/ccs/download/{:016X}/tmd", title_id); | ||||||
|     if (version != -1) { |     if (version != -1) { | ||||||
|  | @ -1327,7 +1332,7 @@ void Module::Interface::BeginImportProgram(Kernel::HLERequestContext& ctx) { | ||||||
|     // Citra will store contents out to sdmc/nand
 |     // Citra will store contents out to sdmc/nand
 | ||||||
|     const FileSys::Path cia_path = {}; |     const FileSys::Path cia_path = {}; | ||||||
|     auto file = std::make_shared<Service::FS::File>( |     auto file = std::make_shared<Service::FS::File>( | ||||||
|         am->kernel, std::make_unique<CIAFile>(media_type), cia_path); |         am->system.Kernel(), std::make_unique<CIAFile>(am->system, media_type), cia_path); | ||||||
| 
 | 
 | ||||||
|     am->cia_installing = true; |     am->cia_installing = true; | ||||||
| 
 | 
 | ||||||
|  | @ -1354,7 +1359,7 @@ void Module::Interface::BeginImportProgramTemporarily(Kernel::HLERequestContext& | ||||||
|     // contents out to sdmc/nand
 |     // contents out to sdmc/nand
 | ||||||
|     const FileSys::Path cia_path = {}; |     const FileSys::Path cia_path = {}; | ||||||
|     auto file = std::make_shared<Service::FS::File>( |     auto file = std::make_shared<Service::FS::File>( | ||||||
|         am->kernel, std::make_unique<CIAFile>(FS::MediaType::NAND), cia_path); |         am->system.Kernel(), std::make_unique<CIAFile>(am->system, FS::MediaType::NAND), cia_path); | ||||||
| 
 | 
 | ||||||
|     am->cia_installing = true; |     am->cia_installing = true; | ||||||
| 
 | 
 | ||||||
|  | @ -1769,8 +1774,8 @@ void Module::Interface::BeginImportTicket(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(ctx); |     IPC::RequestParser rp(ctx); | ||||||
| 
 | 
 | ||||||
|     // Create our TicketFile handle for the app to write to
 |     // Create our TicketFile handle for the app to write to
 | ||||||
|     auto file = std::make_shared<Service::FS::File>(am->kernel, std::make_unique<TicketFile>(), |     auto file = std::make_shared<Service::FS::File>( | ||||||
|                                                     FileSys::Path{}); |         am->system.Kernel(), std::make_unique<TicketFile>(), FileSys::Path{}); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     rb.Push(ResultSuccess); // No error
 |     rb.Push(ResultSuccess); // No error
 | ||||||
|  | @ -1789,13 +1794,19 @@ void Module::Interface::EndImportTicket(Kernel::HLERequestContext& ctx) { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called"); |     LOG_WARNING(Service_AM, "(STUBBED) called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Module::Module(Core::System& system) : kernel(system.Kernel()) { | template <class Archive> | ||||||
|  | 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(); |     ScanForAllTitles(); | ||||||
|     system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex"); |     system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Module::Module(Kernel::KernelSystem& kernel) : kernel(kernel) {} |  | ||||||
| 
 |  | ||||||
| Module::~Module() = default; | Module::~Module() = default; | ||||||
| 
 | 
 | ||||||
| void InstallInterfaces(Core::System& system) { | void InstallInterfaces(Core::System& system) { | ||||||
|  |  | ||||||
|  | @ -11,7 +11,6 @@ | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <boost/serialization/array.hpp> | #include <boost/serialization/array.hpp> | ||||||
| #include <boost/serialization/shared_ptr.hpp> | #include <boost/serialization/shared_ptr.hpp> | ||||||
| #include <boost/serialization/vector.hpp> |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/construct.h" | #include "common/construct.h" | ||||||
| #include "common/swap.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.
 | // A file handled returned for CIAs to be written into and subsequently installed.
 | ||||||
| class CIAFile final : public FileSys::FileBackend { | class CIAFile final : public FileSys::FileBackend { | ||||||
| public: | public: | ||||||
|     explicit CIAFile(Service::FS::MediaType media_type); |     explicit CIAFile(Core::System& system_, Service::FS::MediaType media_type); | ||||||
|     ~CIAFile(); |     ~CIAFile(); | ||||||
| 
 | 
 | ||||||
|     ResultVal<std::size_t> Read(u64 offset, std::size_t length, u8* buffer) const override; |     ResultVal<std::size_t> Read(u64 offset, std::size_t length, u8* buffer) const override; | ||||||
|  | @ -95,6 +94,8 @@ public: | ||||||
|     void Flush() const override; |     void Flush() const override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     Core::System& system; | ||||||
|  | 
 | ||||||
|     // Whether it's installing an update, and what step of installation it is at
 |     // Whether it's installing an update, and what step of installation it is at
 | ||||||
|     bool is_update = false; |     bool is_update = false; | ||||||
|     CIAInstallState install_state = CIAInstallState::InstallStarted; |     CIAInstallState install_state = CIAInstallState::InstallStarted; | ||||||
|  | @ -706,8 +707,6 @@ public: | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     explicit Module(Kernel::KernelSystem& kernel); |  | ||||||
| 
 |  | ||||||
|     /**
 |     /**
 | ||||||
|      * Scans the for titles in a storage medium for listing. |      * Scans the for titles in a storage medium for listing. | ||||||
|      * @param media_type the storage medium to scan |      * @param media_type the storage medium to scan | ||||||
|  | @ -719,27 +718,13 @@ private: | ||||||
|      */ |      */ | ||||||
|     void ScanForAllTitles(); |     void ScanForAllTitles(); | ||||||
| 
 | 
 | ||||||
|     Kernel::KernelSystem& kernel; |     Core::System& system; | ||||||
|     bool cia_installing = false; |     bool cia_installing = false; | ||||||
|     std::array<std::vector<u64_le>, 3> am_title_list; |     std::array<std::vector<u64_le>, 3> am_title_list; | ||||||
|     std::shared_ptr<Kernel::Mutex> system_updater_mutex; |     std::shared_ptr<Kernel::Mutex> system_updater_mutex; | ||||||
| 
 | 
 | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|     void serialize(Archive& ar, const unsigned int) { |     void serialize(Archive& ar, const unsigned int); | ||||||
|         ar& cia_installing; |  | ||||||
|         ar& am_title_list; |  | ||||||
|         ar& system_updater_mutex; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     template <class Archive> |  | ||||||
|     static void load_construct(Archive& ar, Module* t, const unsigned int file_version) { |  | ||||||
|         ::new (t) Module(Core::Global<Kernel::KernelSystem>()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     template <class Archive> |  | ||||||
|     void save_construct(Archive& ar, const unsigned int file_version) const {} |  | ||||||
| 
 |  | ||||||
|     friend class ::construct_access; |  | ||||||
|     friend class boost::serialization::access; |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -747,4 +732,5 @@ void InstallInterfaces(Core::System& system); | ||||||
| 
 | 
 | ||||||
| } // namespace Service::AM
 | } // namespace Service::AM
 | ||||||
| 
 | 
 | ||||||
| BOOST_SERIALIZATION_CONSTRUCT(Service::AM::Module); | BOOST_CLASS_EXPORT_KEY(Service::AM::Module) | ||||||
|  | SERVICE_CONSTRUCT(Service::AM::Module) | ||||||
|  |  | ||||||
|  | @ -8,6 +8,10 @@ | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/frontend/input.h" | #include "core/frontend/input.h" | ||||||
| #include "core/hle/applets/applet.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/am/am.h" | ||||||
| #include "core/hle/service/apt/applet_manager.h" | #include "core/hle/service/apt/applet_manager.h" | ||||||
| #include "core/hle/service/apt/errors.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
 | /// The interval at which the home button update callback will be called, 16.6ms
 | ||||||
| static constexpr u64 button_update_interval_us = 16666; | 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 { | struct AppletTitleData { | ||||||
|     // There are two possible applet ids for each applet.
 |     // 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()); |         parameter.sender_id, parameter.destination_id, parameter.signal, parameter.buffer.size()); | ||||||
| 
 | 
 | ||||||
|     // If the applet is being HLEd, send directly to the applet.
 |     // If the applet is being HLEd, send directly to the applet.
 | ||||||
|     if (auto dest_applet = HLE::Applets::Applet::Get(parameter.destination_id)) { |     if (hle_applets.contains(parameter.destination_id)) { | ||||||
|         dest_applet->ReceiveParameter(parameter); |         hle_applets[parameter.destination_id]->ReceiveParameter(parameter); | ||||||
|     } else { |     } else { | ||||||
|         // Otherwise, send the parameter the LLE way.
 |         // Otherwise, send the parameter the LLE way.
 | ||||||
|         next_parameter = parameter; |         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<HLE::Applets::SoftwareKeyboard>( | ||||||
|  |             system, id, parent, preload, shared_from_this()); | ||||||
|  |         break; | ||||||
|  |     case AppletId::Ed1: | ||||||
|  |     case AppletId::Ed2: | ||||||
|  |         hle_applets[id] = std::make_shared<HLE::Applets::MiiSelector>(system, id, parent, preload, | ||||||
|  |                                                                       shared_from_this()); | ||||||
|  |         break; | ||||||
|  |     case AppletId::Error: | ||||||
|  |     case AppletId::Error2: | ||||||
|  |         hle_applets[id] = std::make_shared<HLE::Applets::ErrEula>(system, id, parent, preload, | ||||||
|  |                                                                   shared_from_this()); | ||||||
|  |         break; | ||||||
|  |     case AppletId::Mint: | ||||||
|  |     case AppletId::Mint2: | ||||||
|  |         hle_applets[id] = | ||||||
|  |             std::make_shared<HLE::Applets::Mint>(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<u64>(id)); | ||||||
|  |     return ResultSuccess; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Result AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) { | Result AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) { | ||||||
|     // The real APT service returns an error if there's a pending APT parameter when this function
 |     // The real APT service returns an error if there's a pending APT parameter when this function
 | ||||||
|     // is called.
 |     // 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.
 |     // 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 (hle_applets.contains(applet_id)) { | ||||||
|     if (applet) { |         LOG_WARNING(Service_APT, "Applet has already been started id={:03X}", applet_id); | ||||||
|         LOG_WARNING(Service_APT, "applet has already been started id={:03X}", applet_id); |  | ||||||
|         return ResultSuccess; |         return ResultSuccess; | ||||||
|     } else { |     } else { | ||||||
|         auto parent = GetAppletSlotId(last_library_launcher_slot); |         auto parent = GetAppletSlotId(last_library_launcher_slot); | ||||||
|         LOG_DEBUG(Service_APT, "Creating HLE applet {:03X} with parent {:03X}", applet_id, parent); |         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.
 |     // 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 (hle_applets.contains(applet_id)) { | ||||||
|     if (applet) { |         LOG_WARNING(Service_APT, "Applet has already been started id={:08X}", applet_id); | ||||||
|         LOG_WARNING(Service_APT, "applet has already been started id={:08X}", applet_id); |  | ||||||
|         return ResultSuccess; |         return ResultSuccess; | ||||||
|     } else { |     } else { | ||||||
|         auto parent = GetAppletSlotId(last_library_launcher_slot); |         auto parent = GetAppletSlotId(last_library_launcher_slot); | ||||||
|         LOG_DEBUG(Service_APT, "Creating HLE applet {:03X} with parent {:03X}", applet_id, parent); |         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,7 +1437,7 @@ static void CaptureFrameBuffer(Core::System& system, u32 capture_offset, VAddr s | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Memory::RasterizerFlushVirtualRegion(src, GSP::FRAMEBUFFER_WIDTH * height * bpp, |     system.Memory().RasterizerFlushVirtualRegion(src, GSP::FRAMEBUFFER_WIDTH * height * bpp, | ||||||
|                                                  Memory::FlushMode::Flush); |                                                  Memory::FlushMode::Flush); | ||||||
| 
 | 
 | ||||||
|     // Address in VRAM that APT copies framebuffer captures to.
 |     // Address in VRAM that APT copies framebuffer captures to.
 | ||||||
|  | @ -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, |     system.Memory().RasterizerFlushVirtualRegion( | ||||||
|                                          Memory::FlushMode::Invalidate); |         dst_vaddr, GSP::FRAMEBUFFER_WIDTH_POW2 * height * bpp, Memory::FlushMode::Invalidate); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void AppletManager::CaptureFrameBuffers() { | void AppletManager::CaptureFrameBuffers() { | ||||||
|  | @ -1441,6 +1491,30 @@ void AppletManager::LoadInputDevices() { | ||||||
|         Settings::values.current_input_profile.buttons[Settings::NativeButton::Power]); |         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<AppletId>(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) { | void AppletManager::ButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late) { | ||||||
|     if (is_device_reload_pending.exchange(false)) { |     if (is_device_reload_pending.exchange(false)) { | ||||||
|         LoadInputDevices(); |         LoadInputDevices(); | ||||||
|  | @ -1485,7 +1559,10 @@ AppletManager::AppletManager(Core::System& system) : system(system) { | ||||||
|         slot_data.parameter_event = |         slot_data.parameter_event = | ||||||
|             system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "APT:Parameter"); |             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( |     button_update_event = system.CoreTiming().RegisterEvent( | ||||||
|         "APT Button Update Event", [this](std::uintptr_t user_data, s64 cycles_late) { |         "APT Button Update Event", [this](std::uintptr_t user_data, s64 cycles_late) { | ||||||
|             ButtonUpdateEvent(user_data, cycles_late); |             ButtonUpdateEvent(user_data, cycles_late); | ||||||
|  | @ -1494,7 +1571,8 @@ AppletManager::AppletManager(Core::System& system) : system(system) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| AppletManager::~AppletManager() { | AppletManager::~AppletManager() { | ||||||
|     HLE::Applets::Shutdown(); |     system.CoreTiming().RemoveEvent(hle_applet_update_event); | ||||||
|  |     system.CoreTiming().RemoveEvent(button_update_event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void AppletManager::ReloadInputDevices() { | void AppletManager::ReloadInputDevices() { | ||||||
|  |  | ||||||
|  | @ -23,6 +23,10 @@ namespace Core { | ||||||
| class System; | class System; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | namespace HLE::Applets { | ||||||
|  | class Applet; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| namespace Service::APT { | namespace Service::APT { | ||||||
| 
 | 
 | ||||||
| /// Signals used by APT functions
 | /// Signals used by APT functions
 | ||||||
|  | @ -291,7 +295,6 @@ public: | ||||||
| 
 | 
 | ||||||
|     ResultVal<Notification> InquireNotification(AppletId app_id); |     ResultVal<Notification> InquireNotification(AppletId app_id); | ||||||
|     Result SendNotification(Notification notification); |     Result SendNotification(Notification notification); | ||||||
|     void SendNotificationToAll(Notification notification); |  | ||||||
| 
 | 
 | ||||||
|     Result PrepareToStartLibraryApplet(AppletId applet_id); |     Result PrepareToStartLibraryApplet(AppletId applet_id); | ||||||
|     Result PreloadLibraryApplet(AppletId applet_id); |     Result PreloadLibraryApplet(AppletId applet_id); | ||||||
|  | @ -481,6 +484,9 @@ private: | ||||||
|     // It also affects the results of APT:GetTargetPlatform and APT:GetApplicationRunningMode.
 |     // It also affects the results of APT:GetTargetPlatform and APT:GetApplicationRunningMode.
 | ||||||
|     bool new_3ds_mode_blocked = false; |     bool new_3ds_mode_blocked = false; | ||||||
| 
 | 
 | ||||||
|  |     std::unordered_map<AppletId, std::shared_ptr<HLE::Applets::Applet>> hle_applets; | ||||||
|  |     Core::TimingEventType* hle_applet_update_event; | ||||||
|  | 
 | ||||||
|     Core::TimingEventType* button_update_event; |     Core::TimingEventType* button_update_event; | ||||||
|     std::atomic<bool> is_device_reload_pending{true}; |     std::atomic<bool> is_device_reload_pending{true}; | ||||||
|     std::unique_ptr<Input::ButtonDevice> home_button; |     std::unique_ptr<Input::ButtonDevice> home_button; | ||||||
|  | @ -506,10 +512,15 @@ private: | ||||||
|     /// otherwise it queues for sending when the application registers itself with APT::Enable.
 |     /// otherwise it queues for sending when the application registers itself with APT::Enable.
 | ||||||
|     void SendApplicationParameterAfterRegistration(const MessageParameter& parameter); |     void SendApplicationParameterAfterRegistration(const MessageParameter& parameter); | ||||||
| 
 | 
 | ||||||
|  |     void SendNotificationToAll(Notification notification); | ||||||
|  | 
 | ||||||
|     void EnsureHomeMenuLoaded(); |     void EnsureHomeMenuLoaded(); | ||||||
| 
 | 
 | ||||||
|     void CaptureFrameBuffers(); |     void CaptureFrameBuffers(); | ||||||
| 
 | 
 | ||||||
|  |     Result CreateHLEApplet(AppletId id, AppletId parent, bool preload); | ||||||
|  |     void HLEAppletUpdateEvent(std::uintptr_t user_data, s64 cycles_late); | ||||||
|  | 
 | ||||||
|     void LoadInputDevices(); |     void LoadInputDevices(); | ||||||
|     void ButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late); |     void ButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1133,8 +1133,7 @@ void Module::APTInterface::GetProgramId(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(ResultSuccess); | ||||||
| 
 | 
 | ||||||
|     auto fs_user = |     auto fs_user = apt->system.ServiceManager().GetService<Service::FS::FS_USER>("fs:USER"); | ||||||
|         Core::System::GetInstance().ServiceManager().GetService<Service::FS::FS_USER>("fs:USER"); |  | ||||||
|     ASSERT_MSG(fs_user != nullptr, "fs:USER service is missing."); |     ASSERT_MSG(fs_user != nullptr, "fs:USER service is missing."); | ||||||
| 
 | 
 | ||||||
|     auto program_info_result = fs_user->GetProgramLaunchInfo(process_id); |     auto program_info_result = fs_user->GetProgramLaunchInfo(process_id); | ||||||
|  |  | ||||||
|  | @ -517,7 +517,7 @@ void Y2R_U::StartConversion(Kernel::HLERequestContext& ctx) { | ||||||
|     // dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
 |     // dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
 | ||||||
|     u32 total_output_size = |     u32 total_output_size = | ||||||
|         conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); |         conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); | ||||||
|     Memory::RasterizerFlushVirtualRegion(conversion.dst.address, total_output_size, |     system.Memory().RasterizerFlushVirtualRegion(conversion.dst.address, total_output_size, | ||||||
|                                                  Memory::FlushMode::FlushAndInvalidate); |                                                  Memory::FlushMode::FlushAndInvalidate); | ||||||
| 
 | 
 | ||||||
|     HW::Y2R::PerformConversion(system.Memory(), conversion); |     HW::Y2R::PerformConversion(system.Memory(), conversion); | ||||||
|  |  | ||||||
|  | @ -477,9 +477,10 @@ static void CopyFrameBuffer(Core::System& system, VAddr dst, VAddr src, u32 stri | ||||||
|         return; |         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); |     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) { | void GSP_GPU::SaveVramSysArea(Kernel::HLERequestContext& ctx) { | ||||||
|  | @ -497,7 +498,7 @@ void GSP_GPU::SaveVramSysArea(Kernel::HLERequestContext& ctx) { | ||||||
|     LOG_INFO(Service_GSP, "called"); |     LOG_INFO(Service_GSP, "called"); | ||||||
| 
 | 
 | ||||||
|     // TODO: This should also save LCD register state.
 |     // TODO: This should also save LCD register state.
 | ||||||
|     Memory::RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE, |     system.Memory().RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE, | ||||||
|                                                  Memory::FlushMode::Flush); |                                                  Memory::FlushMode::Flush); | ||||||
|     const auto vram = system.Memory().GetPointer(Memory::VRAM_VADDR); |     const auto vram = system.Memory().GetPointer(Memory::VRAM_VADDR); | ||||||
|     saved_vram.emplace(std::vector<u8>(Memory::VRAM_SIZE)); |     saved_vram.emplace(std::vector<u8>(Memory::VRAM_SIZE)); | ||||||
|  | @ -548,7 +549,7 @@ void GSP_GPU::RestoreVramSysArea(Kernel::HLERequestContext& ctx) { | ||||||
|         // TODO: This should also restore LCD register state.
 |         // TODO: This should also restore LCD register state.
 | ||||||
|         auto vram = system.Memory().GetPointer(Memory::VRAM_VADDR); |         auto vram = system.Memory().GetPointer(Memory::VRAM_VADDR); | ||||||
|         std::memcpy(vram, saved_vram.get().data(), Memory::VRAM_SIZE); |         std::memcpy(vram, saved_vram.get().data(), Memory::VRAM_SIZE); | ||||||
|         Memory::RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE, |         system.Memory().RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE, | ||||||
|                                                      Memory::FlushMode::Invalidate); |                                                      Memory::FlushMode::Invalidate); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -135,7 +135,7 @@ private: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct MIC_U::Impl { | 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 = |         buffer_full_event = | ||||||
|             system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event"); |             system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event"); | ||||||
|         buffer_write_event = timing.RegisterEvent( |         buffer_write_event = timing.RegisterEvent( | ||||||
|  | @ -376,7 +376,7 @@ struct MIC_U::Impl { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         mic = AudioCore::GetInputDetails(Settings::values.input_type.GetValue()) |         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) { |         if (was_sampling) { | ||||||
|             StartSampling(); |             StartSampling(); | ||||||
|         } |         } | ||||||
|  | @ -392,6 +392,7 @@ struct MIC_U::Impl { | ||||||
|     bool allow_shell_closed = false; |     bool allow_shell_closed = false; | ||||||
|     bool clamp = false; |     bool clamp = false; | ||||||
|     std::unique_ptr<AudioCore::Input> mic; |     std::unique_ptr<AudioCore::Input> mic; | ||||||
|  |     Core::System& system; | ||||||
|     Core::Timing& timing; |     Core::Timing& timing; | ||||||
|     State state{}; |     State state{}; | ||||||
|     Encoding encoding{}; |     Encoding encoding{}; | ||||||
|  |  | ||||||
|  | @ -36,15 +36,13 @@ | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
| SERIALIZE_EXPORT_IMPL(Service::PLGLDR::PLG_LDR) | SERIALIZE_EXPORT_IMPL(Service::PLGLDR::PLG_LDR) | ||||||
|  | SERVICE_CONSTRUCT_IMPL(Service::PLGLDR::PLG_LDR) | ||||||
| 
 | 
 | ||||||
| namespace Service::PLGLDR { | namespace Service::PLGLDR { | ||||||
| 
 | 
 | ||||||
| const Kernel::CoreVersion PLG_LDR::plgldr_version = Kernel::CoreVersion(1, 0, 0); | static const Kernel::CoreVersion 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; |  | ||||||
| 
 | 
 | ||||||
| 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[] = { |     static const FunctionInfo functions[] = { | ||||||
|         // clang-format off
 |         // clang-format off
 | ||||||
|         {0x0001, nullptr, "LoadPlugin"}, |         {0x0001, nullptr, "LoadPlugin"}, | ||||||
|  | @ -67,6 +65,33 @@ PLG_LDR::PLG_LDR() : ServiceFramework{"plg:ldr", 1} { | ||||||
|     plgldr_context.plugin_loaded = false; |     plgldr_context.plugin_loaded = false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template <class Archive> | ||||||
|  | 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 <class Archive> | ||||||
|  | void PLG_LDR::serialize(Archive& ar, const unsigned int) { | ||||||
|  |     ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*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) { | void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kernel) { | ||||||
|     if (!plgldr_context.is_enabled || plgldr_context.plugin_loaded) { |     if (!plgldr_context.is_enabled || plgldr_context.plugin_loaded) { | ||||||
|         return; |         return; | ||||||
|  | @ -91,7 +116,7 @@ void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kerne | ||||||
|                                   std::string(plgldr_context.user_load_parameters.path + 1); |                                   std::string(plgldr_context.user_load_parameters.path + 1); | ||||||
|         plgldr_context.is_default_path = false; |         plgldr_context.is_default_path = false; | ||||||
|         plgldr_context.plugin_path = plugin_file; |         plgldr_context.plugin_path = plugin_file; | ||||||
|         plugin_loader.Load(plgldr_context, process, kernel); |         plugin_loader.Load(plgldr_context, process, kernel, *this); | ||||||
|     } else { |     } else { | ||||||
|         const std::string plugin_root = |         const std::string plugin_root = | ||||||
|             FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "luma/plugins/"; |             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")) { |             if (!child.isDirectory && child.physicalName.ends_with(".3gx")) { | ||||||
|                 plgldr_context.is_default_path = false; |                 plgldr_context.is_default_path = false; | ||||||
|                 plgldr_context.plugin_path = child.physicalName; |                 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) { |                     Loader::ResultStatus::Success) { | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  | @ -114,7 +139,7 @@ void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kerne | ||||||
|         if (FileUtil::Exists(default_path)) { |         if (FileUtil::Exists(default_path)) { | ||||||
|             plgldr_context.is_default_path = true; |             plgldr_context.is_default_path = true; | ||||||
|             plgldr_context.plugin_path = default_path; |             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<Kernel::Handle> PLG_LDR::GetMemoryChangedHandle(Kernel::KernelSystem& | ||||||
|         return plgldr_context.memory_changed_handle; |         return plgldr_context.memory_changed_handle; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::shared_ptr<Kernel::Event> evt = kernel.CreateEvent( |     std::shared_ptr<Kernel::Event> evt = | ||||||
|         Kernel::ResetType::OneShot, |         kernel.CreateEvent(Kernel::ResetType::OneShot, | ||||||
|         fmt::format("event-{:08x}", Core::System::GetInstance().GetRunningCore().GetReg(14))); |                            fmt::format("event-{:08x}", system.GetRunningCore().GetReg(14))); | ||||||
|     R_TRY(kernel.GetCurrentProcess()->handle_table.Create( |     R_TRY(kernel.GetCurrentProcess()->handle_table.Create( | ||||||
|         std::addressof(plgldr_context.memory_changed_handle), std::move(evt))); |         std::addressof(plgldr_context.memory_changed_handle), std::move(evt))); | ||||||
|     return plgldr_context.memory_changed_handle; |     return plgldr_context.memory_changed_handle; | ||||||
|  | @ -274,7 +299,7 @@ std::shared_ptr<PLG_LDR> GetService(Core::System& system) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void InstallInterfaces(Core::System& system) { | void InstallInterfaces(Core::System& system) { | ||||||
|     std::make_shared<PLG_LDR>()->InstallAsNamedPort(system.Kernel()); |     std::make_shared<PLG_LDR>(system)->InstallAsNamedPort(system.Kernel()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace Service::PLGLDR
 | } // namespace Service::PLGLDR
 | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <boost/serialization/version.hpp> | #include <boost/serialization/export.hpp> | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
| 
 | 
 | ||||||
| namespace Core { | namespace Core { | ||||||
|  | @ -70,25 +70,11 @@ public: | ||||||
|         u32_le load_exe_args[4] = {0}; |         u32_le load_exe_args[4] = {0}; | ||||||
| 
 | 
 | ||||||
|         template <class Archive> |         template <class Archive> | ||||||
|         void serialize(Archive& ar, const unsigned int) { |         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; |  | ||||||
|         } |  | ||||||
|         friend class boost::serialization::access; |         friend class boost::serialization::access; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     PLG_LDR(); |     PLG_LDR(Core::System& system_); | ||||||
|     ~PLG_LDR() {} |     ~PLG_LDR() {} | ||||||
| 
 | 
 | ||||||
|     void OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kernel); |     void OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kernel); | ||||||
|  | @ -96,31 +82,31 @@ public: | ||||||
|     ResultVal<Kernel::Handle> GetMemoryChangedHandle(Kernel::KernelSystem& kernel); |     ResultVal<Kernel::Handle> GetMemoryChangedHandle(Kernel::KernelSystem& kernel); | ||||||
|     void OnMemoryChanged(Kernel::Process& process, 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; |         plgldr_context.is_enabled = enabled; | ||||||
|     } |     } | ||||||
|     static bool GetEnabled() { |     bool GetEnabled() { | ||||||
|         return plgldr_context.is_enabled; |         return plgldr_context.is_enabled; | ||||||
|     } |     } | ||||||
|     static void SetAllowGameChangeState(bool allow) { |     void SetAllowGameChangeState(bool allow) { | ||||||
|         allow_game_change = allow; |         allow_game_change = allow; | ||||||
|     } |     } | ||||||
|     static bool GetAllowGameChangeState() { |     bool GetAllowGameChangeState() { | ||||||
|         return allow_game_change; |         return allow_game_change; | ||||||
|     } |     } | ||||||
|     static void SetPluginFBAddr(PAddr addr) { |     void SetPluginFBAddr(PAddr addr) { | ||||||
|         plugin_fb_addr = addr; |         plugin_fb_addr = addr; | ||||||
|     } |     } | ||||||
|     static PAddr GetPluginFBAddr() { |     PAddr GetPluginFBAddr() { | ||||||
|         return plugin_fb_addr; |         return plugin_fb_addr; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     static const Kernel::CoreVersion plgldr_version; |     Core::System& system; | ||||||
| 
 | 
 | ||||||
|     static PluginLoaderContext plgldr_context; |     PluginLoaderContext plgldr_context; | ||||||
|     static PAddr plugin_fb_addr; |     PAddr plugin_fb_addr = 0; | ||||||
|     static bool allow_game_change; |     bool allow_game_change = true; | ||||||
| 
 | 
 | ||||||
|     void IsEnabled(Kernel::HLERequestContext& ctx); |     void IsEnabled(Kernel::HLERequestContext& ctx); | ||||||
|     void SetEnabled(Kernel::HLERequestContext& ctx); |     void SetEnabled(Kernel::HLERequestContext& ctx); | ||||||
|  | @ -131,12 +117,7 @@ private: | ||||||
|     void GetPluginPath(Kernel::HLERequestContext& ctx); |     void GetPluginPath(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|     void serialize(Archive& ar, const unsigned int) { |     void serialize(Archive& ar, const unsigned int); | ||||||
|         ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*this); |  | ||||||
|         ar& plgldr_context; |  | ||||||
|         ar& plugin_fb_addr; |  | ||||||
|         ar& allow_game_change; |  | ||||||
|     } |  | ||||||
|     friend class boost::serialization::access; |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -147,3 +128,4 @@ void InstallInterfaces(Core::System& system); | ||||||
| } // namespace Service::PLGLDR
 | } // namespace Service::PLGLDR
 | ||||||
| 
 | 
 | ||||||
| BOOST_CLASS_EXPORT_KEY(Service::PLGLDR::PLG_LDR) | BOOST_CLASS_EXPORT_KEY(Service::PLGLDR::PLG_LDR) | ||||||
|  | SERVICE_CONSTRUCT(Service::PLGLDR::PLG_LDR) | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ | ||||||
| #include "core/hle/service/ptm/ptm_u.h" | #include "core/hle/service/ptm/ptm_u.h" | ||||||
| 
 | 
 | ||||||
| SERIALIZE_EXPORT_IMPL(Service::PTM::Module) | SERIALIZE_EXPORT_IMPL(Service::PTM::Module) | ||||||
|  | SERVICE_CONSTRUCT_IMPL(Service::PTM::Module) | ||||||
| 
 | 
 | ||||||
| namespace Service::PTM { | namespace Service::PTM { | ||||||
| 
 | 
 | ||||||
|  | @ -136,7 +137,7 @@ void Module::Interface::CheckNew3DS(Kernel::HLERequestContext& ctx) { | ||||||
| void Module::Interface::GetSystemTime(Kernel::HLERequestContext& ctx) { | void Module::Interface::GetSystemTime(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(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(); |     const u64 console_time = share_page.GetSystemTimeSince2000(); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); | ||||||
|  | @ -207,7 +208,7 @@ static GameCoin ReadGameCoinData() { | ||||||
|     return gamecoin_data; |     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
 |     // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't
 | ||||||
|     // exist
 |     // exist
 | ||||||
|     const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); |     const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); | ||||||
|  | @ -221,6 +222,14 @@ Module::Module() { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template <class Archive> | ||||||
|  | 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() { | u16 Module::GetPlayCoins() { | ||||||
|     return ReadGameCoinData().total_coins; |     return ReadGameCoinData().total_coins; | ||||||
| } | } | ||||||
|  | @ -238,7 +247,7 @@ Module::Interface::Interface(std::shared_ptr<Module> ptm, const char* name, u32 | ||||||
| 
 | 
 | ||||||
| void InstallInterfaces(Core::System& system) { | void InstallInterfaces(Core::System& system) { | ||||||
|     auto& service_manager = system.ServiceManager(); |     auto& service_manager = system.ServiceManager(); | ||||||
|     auto ptm = std::make_shared<Module>(); |     auto ptm = std::make_shared<Module>(system); | ||||||
|     std::make_shared<PTM_Gets>(ptm)->InstallAsService(service_manager); |     std::make_shared<PTM_Gets>(ptm)->InstallAsService(service_manager); | ||||||
|     std::make_shared<PTM_Play>(ptm)->InstallAsService(service_manager); |     std::make_shared<PTM_Play>(ptm)->InstallAsService(service_manager); | ||||||
|     std::make_shared<PTM_Sets>(ptm)->InstallAsService(service_manager); |     std::make_shared<PTM_Sets>(ptm)->InstallAsService(service_manager); | ||||||
|  |  | ||||||
|  | @ -47,7 +47,9 @@ void CheckNew3DS(IPC::RequestBuilder& rb); | ||||||
| 
 | 
 | ||||||
| class Module final { | class Module final { | ||||||
| public: | public: | ||||||
|     Module(); |     explicit Module(Core::System& system_); | ||||||
|  |     ~Module() = default; | ||||||
|  | 
 | ||||||
|     static u16 GetPlayCoins(); |     static u16 GetPlayCoins(); | ||||||
|     static void SetPlayCoins(u16 play_coins); |     static void SetPlayCoins(u16 play_coins); | ||||||
| 
 | 
 | ||||||
|  | @ -150,16 +152,14 @@ public: | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     Core::System& system; | ||||||
|  | 
 | ||||||
|     bool shell_open = true; |     bool shell_open = true; | ||||||
|     bool battery_is_charging = true; |     bool battery_is_charging = true; | ||||||
|     bool pedometer_is_counting = false; |     bool pedometer_is_counting = false; | ||||||
| 
 | 
 | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|     void serialize(Archive& ar, const unsigned int) { |     void serialize(Archive& ar, const unsigned int); | ||||||
|         ar& shell_open; |  | ||||||
|         ar& battery_is_charging; |  | ||||||
|         ar& pedometer_is_counting; |  | ||||||
|     } |  | ||||||
|     friend class boost::serialization::access; |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -168,3 +168,4 @@ void InstallInterfaces(Core::System& system); | ||||||
| } // namespace Service::PTM
 | } // namespace Service::PTM
 | ||||||
| 
 | 
 | ||||||
| BOOST_CLASS_EXPORT_KEY(Service::PTM::Module) | BOOST_CLASS_EXPORT_KEY(Service::PTM::Module) | ||||||
|  | SERVICE_CONSTRUCT(Service::PTM::Module) | ||||||
|  |  | ||||||
|  | @ -249,7 +249,7 @@ void SRV::PublishToSubscriber(Kernel::HLERequestContext& ctx) { | ||||||
|     // console. Normally, this is handled by NS. If notification handling is properly implemented,
 |     // 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.
 |     // this piece of code should be removed, and handled by subscribing from NS instead.
 | ||||||
|     if (notification_id == 0x203) { |     if (notification_id == 0x203) { | ||||||
|         Core::System::GetInstance().RequestShutdown(); |         system.RequestShutdown(); | ||||||
|     } else { |     } else { | ||||||
|         LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x{:X}, flags={}", |         LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x{:X}, flags={}", | ||||||
|                     notification_id, flags); |                     notification_id, flags); | ||||||
|  |  | ||||||
|  | @ -94,7 +94,7 @@ static u32 TranslateAddr(u32 addr, const THREEloadinfo* loadinfo, u32* offsets) | ||||||
| 
 | 
 | ||||||
| using Kernel::CodeSet; | 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<CodeSet>* out_codeset) { |                                    std::shared_ptr<CodeSet>* out_codeset) { | ||||||
|     if (!file.IsOpen()) |     if (!file.IsOpen()) | ||||||
|         return ERROR_FILE; |         return ERROR_FILE; | ||||||
|  | @ -222,7 +222,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Create the CodeSet
 |     // Create the CodeSet
 | ||||||
|     std::shared_ptr<CodeSet> code_set = Core::System::GetInstance().Kernel().CreateCodeSet("", 0); |     std::shared_ptr<CodeSet> code_set = system.Kernel().CreateCodeSet("", 0); | ||||||
| 
 | 
 | ||||||
|     code_set->CodeSegment().offset = loadinfo.seg_ptrs[0] - program_image.data(); |     code_set->CodeSegment().offset = loadinfo.seg_ptrs[0] - program_image.data(); | ||||||
|     code_set->CodeSegment().addr = loadinfo.seg_addrs[0]; |     code_set->CodeSegment().addr = loadinfo.seg_addrs[0]; | ||||||
|  | @ -268,25 +268,24 @@ ResultStatus AppLoader_THREEDSX::Load(std::shared_ptr<Kernel::Process>& process) | ||||||
|         return ResultStatus::Error; |         return ResultStatus::Error; | ||||||
| 
 | 
 | ||||||
|     std::shared_ptr<CodeSet> codeset; |     std::shared_ptr<CodeSet> 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; |         return ResultStatus::Error; | ||||||
|     codeset->name = filename; |     codeset->name = filename; | ||||||
| 
 | 
 | ||||||
|     process = Core::System::GetInstance().Kernel().CreateProcess(std::move(codeset)); |     process = system.Kernel().CreateProcess(std::move(codeset)); | ||||||
|     process->Set3dsxKernelCaps(); |     process->Set3dsxKernelCaps(); | ||||||
| 
 | 
 | ||||||
|     // Attach the default resource limit (APPLICATION) to the process
 |     // Attach the default resource limit (APPLICATION) to the process
 | ||||||
|     process->resource_limit = Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory( |     process->resource_limit = | ||||||
|         Kernel::ResourceLimitCategory::Application); |         system.Kernel().ResourceLimit().GetForCategory(Kernel::ResourceLimitCategory::Application); | ||||||
| 
 | 
 | ||||||
|     // On real HW this is done with FS:Reg, but we can be lazy
 |     // On real HW this is done with FS:Reg, but we can be lazy
 | ||||||
|     auto fs_user = |     auto fs_user = system.ServiceManager().GetService<Service::FS::FS_USER>("fs:USER"); | ||||||
|         Core::System::GetInstance().ServiceManager().GetService<Service::FS::FS_USER>("fs:USER"); |  | ||||||
|     fs_user->RegisterProgramInfo(process->GetObjectId(), process->codeset->program_id, filepath); |     fs_user->RegisterProgramInfo(process->GetObjectId(), process->codeset->program_id, filepath); | ||||||
| 
 | 
 | ||||||
|     process->Run(48, Kernel::DEFAULT_STACK_SIZE); |     process->Run(48, Kernel::DEFAULT_STACK_SIZE); | ||||||
| 
 | 
 | ||||||
|     Core::System::GetInstance().ArchiveManager().RegisterSelfNCCH(*this); |     system.ArchiveManager().RegisterSelfNCCH(*this); | ||||||
| 
 | 
 | ||||||
|     is_loaded = true; |     is_loaded = true; | ||||||
|     return ResultStatus::Success; |     return ResultStatus::Success; | ||||||
|  |  | ||||||
|  | @ -14,9 +14,9 @@ namespace Loader { | ||||||
| /// Loads an 3DSX file
 | /// Loads an 3DSX file
 | ||||||
| class AppLoader_THREEDSX final : public AppLoader { | class AppLoader_THREEDSX final : public AppLoader { | ||||||
| public: | 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) |                        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 |      * Returns the type of the file | ||||||
|  |  | ||||||
|  | @ -199,7 +199,7 @@ public: | ||||||
|     u32 GetFlags() const { |     u32 GetFlags() const { | ||||||
|         return (u32)(header->e_flags); |         return (u32)(header->e_flags); | ||||||
|     } |     } | ||||||
|     std::shared_ptr<CodeSet> LoadInto(u32 vaddr); |     std::shared_ptr<CodeSet> LoadInto(Core::System& system, u32 vaddr); | ||||||
| 
 | 
 | ||||||
|     int GetNumSegments() const { |     int GetNumSegments() const { | ||||||
|         return (int)(header->e_phnum); |         return (int)(header->e_phnum); | ||||||
|  | @ -262,7 +262,7 @@ const char* ElfReader::GetSectionName(int section) const { | ||||||
|     return nullptr; |     return nullptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::shared_ptr<CodeSet> ElfReader::LoadInto(u32 vaddr) { | std::shared_ptr<CodeSet> ElfReader::LoadInto(Core::System& system, u32 vaddr) { | ||||||
|     LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx); |     LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx); | ||||||
| 
 | 
 | ||||||
|     // Should we relocate?
 |     // Should we relocate?
 | ||||||
|  | @ -290,7 +290,7 @@ std::shared_ptr<CodeSet> ElfReader::LoadInto(u32 vaddr) { | ||||||
|     std::vector<u8> program_image(total_image_size); |     std::vector<u8> program_image(total_image_size); | ||||||
|     std::size_t current_image_position = 0; |     std::size_t current_image_position = 0; | ||||||
| 
 | 
 | ||||||
|     std::shared_ptr<CodeSet> codeset = Core::System::GetInstance().Kernel().CreateCodeSet("", 0); |     std::shared_ptr<CodeSet> codeset = system.Kernel().CreateCodeSet("", 0); | ||||||
| 
 | 
 | ||||||
|     for (unsigned int i = 0; i < header->e_phnum; ++i) { |     for (unsigned int i = 0; i < header->e_phnum; ++i) { | ||||||
|         Elf32_Phdr* p = &segments[i]; |         Elf32_Phdr* p = &segments[i]; | ||||||
|  | @ -380,15 +380,15 @@ ResultStatus AppLoader_ELF::Load(std::shared_ptr<Kernel::Process>& process) { | ||||||
|         return ResultStatus::Error; |         return ResultStatus::Error; | ||||||
| 
 | 
 | ||||||
|     ElfReader elf_reader(&buffer[0]); |     ElfReader elf_reader(&buffer[0]); | ||||||
|     std::shared_ptr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR); |     std::shared_ptr<CodeSet> codeset = elf_reader.LoadInto(system, Memory::PROCESS_IMAGE_VADDR); | ||||||
|     codeset->name = filename; |     codeset->name = filename; | ||||||
| 
 | 
 | ||||||
|     process = Core::System::GetInstance().Kernel().CreateProcess(std::move(codeset)); |     process = system.Kernel().CreateProcess(std::move(codeset)); | ||||||
|     process->Set3dsxKernelCaps(); |     process->Set3dsxKernelCaps(); | ||||||
| 
 | 
 | ||||||
|     // Attach the default resource limit (APPLICATION) to the process
 |     // Attach the default resource limit (APPLICATION) to the process
 | ||||||
|     process->resource_limit = Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory( |     process->resource_limit = | ||||||
|         Kernel::ResourceLimitCategory::Application); |         system.Kernel().ResourceLimit().GetForCategory(Kernel::ResourceLimitCategory::Application); | ||||||
| 
 | 
 | ||||||
|     process->Run(48, Kernel::DEFAULT_STACK_SIZE); |     process->Run(48, Kernel::DEFAULT_STACK_SIZE); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,8 +14,8 @@ namespace Loader { | ||||||
| /// Loads an ELF/AXF file
 | /// Loads an ELF/AXF file
 | ||||||
| class AppLoader_ELF final : public AppLoader { | class AppLoader_ELF final : public AppLoader { | ||||||
| public: | public: | ||||||
|     AppLoader_ELF(FileUtil::IOFile&& file, std::string filename) |     AppLoader_ELF(Core::System& system_, FileUtil::IOFile&& file, std::string filename) | ||||||
|         : AppLoader(std::move(file)), filename(std::move(filename)) {} |         : AppLoader(system_, std::move(file)), filename(std::move(filename)) {} | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Returns the type of the file |      * Returns the type of the file | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| #include <string> | #include <string> | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
|  | #include "core/core.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
| #include "core/loader/3dsx.h" | #include "core/loader/3dsx.h" | ||||||
| #include "core/loader/elf.h" | #include "core/loader/elf.h" | ||||||
|  | @ -89,23 +90,23 @@ const char* GetFileTypeString(FileType type) { | ||||||
|  * @param filepath the file full path (with name) |  * @param filepath the file full path (with name) | ||||||
|  * @return std::unique_ptr<AppLoader> a pointer to a loader object;  nullptr for unsupported type |  * @return std::unique_ptr<AppLoader> a pointer to a loader object;  nullptr for unsupported type | ||||||
|  */ |  */ | ||||||
| static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileType type, | static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileUtil::IOFile&& file, | ||||||
|                                                 const std::string& filename, |                                                 FileType type, const std::string& filename, | ||||||
|                                                 const std::string& filepath) { |                                                 const std::string& filepath) { | ||||||
|     switch (type) { |     switch (type) { | ||||||
| 
 | 
 | ||||||
|     // 3DSX file format.
 |     // 3DSX file format.
 | ||||||
|     case FileType::THREEDSX: |     case FileType::THREEDSX: | ||||||
|         return std::make_unique<AppLoader_THREEDSX>(std::move(file), filename, filepath); |         return std::make_unique<AppLoader_THREEDSX>(system, std::move(file), filename, filepath); | ||||||
| 
 | 
 | ||||||
|     // Standard ELF file format.
 |     // Standard ELF file format.
 | ||||||
|     case FileType::ELF: |     case FileType::ELF: | ||||||
|         return std::make_unique<AppLoader_ELF>(std::move(file), filename); |         return std::make_unique<AppLoader_ELF>(system, std::move(file), filename); | ||||||
| 
 | 
 | ||||||
|     // NCCH/NCSD container formats.
 |     // NCCH/NCSD container formats.
 | ||||||
|     case FileType::CXI: |     case FileType::CXI: | ||||||
|     case FileType::CCI: |     case FileType::CCI: | ||||||
|         return std::make_unique<AppLoader_NCCH>(std::move(file), filepath); |         return std::make_unique<AppLoader_NCCH>(system, std::move(file), filepath); | ||||||
| 
 | 
 | ||||||
|     default: |     default: | ||||||
|         return nullptr; |         return nullptr; | ||||||
|  | @ -133,7 +134,8 @@ std::unique_ptr<AppLoader> GetLoader(const std::string& filename) { | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Loader, "Loading file {} as {}...", filename, GetFileTypeString(type)); |     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
 | } // namespace Loader
 | ||||||
|  |  | ||||||
|  | @ -82,7 +82,8 @@ constexpr u32 MakeMagic(char a, char b, char c, char d) { | ||||||
| /// Interface for loading an application
 | /// Interface for loading an application
 | ||||||
| class AppLoader : NonCopyable { | class AppLoader : NonCopyable { | ||||||
| public: | 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() {} |     virtual ~AppLoader() {} | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|  | @ -253,6 +254,7 @@ public: | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|  |     Core::System& system; | ||||||
|     FileUtil::IOFile file; |     FileUtil::IOFile file; | ||||||
|     bool is_loaded = false; |     bool is_loaded = false; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -113,8 +113,7 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process) | ||||||
|         std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( |         std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( | ||||||
|             (const char*)overlay_ncch->exheader_header.codeset_info.name, 8); |             (const char*)overlay_ncch->exheader_header.codeset_info.name, 8); | ||||||
| 
 | 
 | ||||||
|         std::shared_ptr<CodeSet> codeset = |         std::shared_ptr<CodeSet> codeset = system.Kernel().CreateCodeSet(process_name, program_id); | ||||||
|             Core::System::GetInstance().Kernel().CreateCodeSet(process_name, program_id); |  | ||||||
| 
 | 
 | ||||||
|         codeset->CodeSegment().offset = 0; |         codeset->CodeSegment().offset = 0; | ||||||
|         codeset->CodeSegment().addr = overlay_ncch->exheader_header.codeset_info.text.address; |         codeset->CodeSegment().addr = overlay_ncch->exheader_header.codeset_info.text.address; | ||||||
|  | @ -148,7 +147,6 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process) | ||||||
|         codeset->entrypoint = codeset->CodeSegment().addr; |         codeset->entrypoint = codeset->CodeSegment().addr; | ||||||
|         codeset->memory = std::move(code); |         codeset->memory = std::move(code); | ||||||
| 
 | 
 | ||||||
|         auto& system = Core::System::GetInstance(); |  | ||||||
|         process = system.Kernel().CreateProcess(std::move(codeset)); |         process = system.Kernel().CreateProcess(std::move(codeset)); | ||||||
| 
 | 
 | ||||||
|         // Attach a resource limit to the process based on the resource limit category
 |         // Attach a resource limit to the process based on the resource limit category
 | ||||||
|  | @ -276,7 +274,6 @@ ResultStatus AppLoader_NCCH::Load(std::shared_ptr<Kernel::Process>& process) { | ||||||
|         overlay_ncch = &update_ncch; |         overlay_ncch = &update_ncch; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto& system = Core::System::GetInstance(); |  | ||||||
|     system.TelemetrySession().AddField(Common::Telemetry::FieldType::Session, "ProgramId", |     system.TelemetrySession().AddField(Common::Telemetry::FieldType::Session, "ProgramId", | ||||||
|                                        program_id); |                                        program_id); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -15,8 +15,8 @@ namespace Loader { | ||||||
| /// Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI)
 | /// Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI)
 | ||||||
| class AppLoader_NCCH final : public AppLoader { | class AppLoader_NCCH final : public AppLoader { | ||||||
| public: | public: | ||||||
|     AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath) |     AppLoader_NCCH(Core::System& system_, FileUtil::IOFile&& file, const std::string& filepath) | ||||||
|         : AppLoader(std::move(file)), base_ncch(filepath), overlay_ncch(&base_ncch), |         : AppLoader(system_, std::move(file)), base_ncch(filepath), overlay_ncch(&base_ncch), | ||||||
|           filepath(filepath) {} |           filepath(filepath) {} | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|  |  | ||||||
|  | @ -264,14 +264,55 @@ public: | ||||||
|             return {vram_mem, addr - VRAM_VADDR}; |             return {vram_mem, addr - VRAM_VADDR}; | ||||||
|         } |         } | ||||||
|         if (addr >= PLUGIN_3GX_FB_VADDR && addr < PLUGIN_3GX_FB_VADDR_END) { |         if (addr >= PLUGIN_3GX_FB_VADDR && addr < PLUGIN_3GX_FB_VADDR_END) { | ||||||
|             return {fcram_mem, addr - PLUGIN_3GX_FB_VADDR + |             auto plg_ldr = Service::PLGLDR::GetService(system); | ||||||
|                                    Service::PLGLDR::PLG_LDR::GetPluginFBAddr() - FCRAM_PADDR}; |             if (plg_ldr) { | ||||||
|  |                 return {fcram_mem, | ||||||
|  |                         addr - PLUGIN_3GX_FB_VADDR + plg_ldr->GetPluginFBAddr() - FCRAM_PADDR}; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         UNREACHABLE(); |         UNREACHABLE(); | ||||||
|         return MemoryRef{}; |         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: | private: | ||||||
|     friend class boost::serialization::access; |     friend class boost::serialization::access; | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|  | @ -345,41 +386,8 @@ std::shared_ptr<PageTable> MemorySystem::GetCurrentPageTable() const { | ||||||
|     return impl->current_page_table; |     return impl->current_page_table; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) { | void MemorySystem::RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) { | ||||||
|     const VAddr end = start + size; |     impl->RasterizerFlushVirtualRegion(start, size, mode); | ||||||
| 
 |  | ||||||
|     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::MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, | void MemorySystem::MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, | ||||||
|  | @ -683,16 +691,19 @@ std::vector<VAddr> MemorySystem::PhysicalToVirtualAddressForRasterizer(PAddr add | ||||||
|     if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { |     if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { | ||||||
|         return {addr - VRAM_PADDR + VRAM_VADDR}; |         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) { |     if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { | ||||||
|         return {addr - FCRAM_PADDR + LINEAR_HEAP_VADDR, addr - FCRAM_PADDR + NEW_LINEAR_HEAP_VADDR}; |         return {addr - FCRAM_PADDR + LINEAR_HEAP_VADDR, addr - FCRAM_PADDR + NEW_LINEAR_HEAP_VADDR}; | ||||||
|     } |     } | ||||||
|     if (addr >= FCRAM_PADDR_END && addr < FCRAM_N3DS_PADDR_END) { |     if (addr >= FCRAM_PADDR_END && addr < FCRAM_N3DS_PADDR_END) { | ||||||
|         return {addr - FCRAM_PADDR + NEW_LINEAR_HEAP_VADDR}; |         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,
 |     // 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
 |     // 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
 |     // the end address of VRAM, causing the Virtual->Physical translation to fail when flushing
 | ||||||
|  |  | ||||||
|  | @ -235,8 +235,6 @@ enum class FlushMode { | ||||||
|     FlushAndInvalidate, |     FlushAndInvalidate, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); |  | ||||||
| 
 |  | ||||||
| class MemorySystem { | class MemorySystem { | ||||||
| public: | public: | ||||||
|     explicit MemorySystem(Core::System& system); |     explicit MemorySystem(Core::System& system); | ||||||
|  | @ -553,6 +551,8 @@ public: | ||||||
| 
 | 
 | ||||||
|     void SetDSP(AudioCore::DspInterface& dsp); |     void SetDSP(AudioCore::DspInterface& dsp); | ||||||
| 
 | 
 | ||||||
|  |     void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     template <typename T> |     template <typename T> | ||||||
|     T Read(const VAddr vaddr); |     T Read(const VAddr vaddr); | ||||||
|  |  | ||||||
|  | @ -22,28 +22,6 @@ namespace VideoCore { | ||||||
| constexpr VAddr VADDR_LCD = 0x1ED02000; | constexpr VAddr VADDR_LCD = 0x1ED02000; | ||||||
| constexpr VAddr VADDR_GPU = 0x1EF00000; | 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_DisplayTransfer, "GPU", "DisplayTransfer", MP_RGB(100, 100, 255)); | ||||||
| MICROPROFILE_DEFINE(GPU_CmdlistProcessing, "GPU", "Cmdlist Processing", MP_RGB(100, 255, 100)); | 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; | 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) { | void GPU::SetInterruptHandler(Service::GSP::InterruptHandler handler) { | ||||||
|     impl->signal_interrupt = handler; |     impl->signal_interrupt = handler; | ||||||
|     impl->pica.SetInterruptHandler(handler); |     impl->pica.SetInterruptHandler(handler); | ||||||
|  | @ -107,9 +110,9 @@ void GPU::Execute(const Service::GSP::Command& command) { | ||||||
| 
 | 
 | ||||||
|     switch (command.id) { |     switch (command.id) { | ||||||
|     case CommandId::RequestDma: { |     case CommandId::RequestDma: { | ||||||
|         Memory::RasterizerFlushVirtualRegion(command.dma_request.source_address, |         impl->system.Memory().RasterizerFlushVirtualRegion( | ||||||
|                                              command.dma_request.size, Memory::FlushMode::Flush); |             command.dma_request.source_address, command.dma_request.size, Memory::FlushMode::Flush); | ||||||
|         Memory::RasterizerFlushVirtualRegion(command.dma_request.dest_address, |         impl->system.Memory().RasterizerFlushVirtualRegion(command.dma_request.dest_address, | ||||||
|                                                            command.dma_request.size, |                                                            command.dma_request.size, | ||||||
|                                                            Memory::FlushMode::Invalidate); |                                                            Memory::FlushMode::Invalidate); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -108,6 +108,8 @@ private: | ||||||
| private: | private: | ||||||
|     struct Impl; |     struct Impl; | ||||||
|     std::unique_ptr<Impl> impl; |     std::unique_ptr<Impl> impl; | ||||||
|  | 
 | ||||||
|  |     PAddr VirtualToPhysicalAddress(VAddr addr); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace VideoCore
 | } // namespace VideoCore
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue