mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Implement plugin loader Mode3 mem strategy (#7)
This commit is contained in:
		
							parent
							
								
									f5316532e6
								
							
						
					
					
						commit
						c710c0009f
					
				
					 8 changed files with 61 additions and 12 deletions
				
			
		|  | @ -263,6 +263,18 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st | |||
|         return ResultStatus::ErrorGetLoader; | ||||
|     } | ||||
| 
 | ||||
|     if (restore_plugin_context.has_value() && restore_plugin_context->is_enabled && | ||||
|         restore_plugin_context->use_user_load_parameters) { | ||||
|         u64_le program_id = 0; | ||||
|         app_loader->ReadProgramId(program_id); | ||||
|         if (restore_plugin_context->user_load_parameters.low_title_Id == | ||||
|                 static_cast<u32_le>(program_id) && | ||||
|             restore_plugin_context->user_load_parameters.plugin_memory_strategy == | ||||
|                 Service::PLGLDR::PLG_LDR::PluginMemoryStrategy::PLG_STRATEGY_MODE3) { | ||||
|             app_loader->SetKernelMemoryModeOverride(Kernel::MemoryMode::Dev2); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     auto memory_mode = app_loader->LoadKernelMemoryMode(); | ||||
|     if (memory_mode.second != Loader::ResultStatus::Success) { | ||||
|         LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!", | ||||
|  |  | |||
|  | @ -574,7 +574,7 @@ Result AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) { | |||
| 
 | ||||
|     if (Settings::values.lle_applets) { | ||||
|         auto cfg = Service::CFG::GetModule(system); | ||||
|         auto process = NS::LaunchTitle(FS::MediaType::NAND, | ||||
|         auto process = NS::LaunchTitle(system, FS::MediaType::NAND, | ||||
|                                        GetTitleIdForApplet(applet_id, cfg->GetRegionValue())); | ||||
|         if (process) { | ||||
|             return ResultSuccess; | ||||
|  | @ -603,7 +603,7 @@ Result AppletManager::PreloadLibraryApplet(AppletId applet_id) { | |||
| 
 | ||||
|     if (Settings::values.lle_applets) { | ||||
|         auto cfg = Service::CFG::GetModule(system); | ||||
|         auto process = NS::LaunchTitle(FS::MediaType::NAND, | ||||
|         auto process = NS::LaunchTitle(system, FS::MediaType::NAND, | ||||
|                                        GetTitleIdForApplet(applet_id, cfg->GetRegionValue())); | ||||
|         if (process) { | ||||
|             return ResultSuccess; | ||||
|  | @ -815,7 +815,7 @@ Result AppletManager::StartSystemApplet(AppletId applet_id, std::shared_ptr<Kern | |||
|         applet_id == AppletId::HomeMenu ? AppletSlot::HomeMenu : AppletSlot::SystemApplet; | ||||
|     if (!GetAppletSlot(slot_id)->registered) { | ||||
|         auto cfg = Service::CFG::GetModule(system); | ||||
|         auto process = NS::LaunchTitle(FS::MediaType::NAND, | ||||
|         auto process = NS::LaunchTitle(system, FS::MediaType::NAND, | ||||
|                                        GetTitleIdForApplet(applet_id, cfg->GetRegionValue())); | ||||
|         if (!process) { | ||||
|             // TODO: Find the right error code.
 | ||||
|  | @ -1346,8 +1346,8 @@ Result AppletManager::StartApplication(const std::vector<u8>& parameter, | |||
|     active_slot = AppletSlot::Application; | ||||
| 
 | ||||
|     // Launch the title directly.
 | ||||
|     auto process = | ||||
|         NS::LaunchTitle(app_start_parameters->next_media_type, app_start_parameters->next_title_id); | ||||
|     auto process = NS::LaunchTitle(system, app_start_parameters->next_media_type, | ||||
|                                    app_start_parameters->next_title_id); | ||||
|     if (!process) { | ||||
|         LOG_CRITICAL(Service_APT, "Failed to launch title during application start, exiting."); | ||||
|         system.RequestShutdown(); | ||||
|  | @ -1423,7 +1423,7 @@ void AppletManager::EnsureHomeMenuLoaded() { | |||
| 
 | ||||
|     auto cfg = Service::CFG::GetModule(system); | ||||
|     auto menu_title_id = GetTitleIdForApplet(AppletId::HomeMenu, cfg->GetRegionValue()); | ||||
|     auto process = NS::LaunchTitle(FS::MediaType::NAND, menu_title_id); | ||||
|     auto process = NS::LaunchTitle(system, FS::MediaType::NAND, menu_title_id); | ||||
|     if (!process) { | ||||
|         LOG_WARNING(Service_APT, | ||||
|                     "The Home Menu failed to launch, application jumping will not work."); | ||||
|  |  | |||
|  | @ -9,7 +9,8 @@ | |||
| 
 | ||||
| namespace Service::NS { | ||||
| 
 | ||||
| std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id) { | ||||
| std::shared_ptr<Kernel::Process> LaunchTitle(Core::System& system, FS::MediaType media_type, | ||||
|                                              u64 title_id) { | ||||
|     std::string path = AM::GetTitleContentPath(media_type, title_id); | ||||
|     auto loader = Loader::GetLoader(path); | ||||
| 
 | ||||
|  | @ -18,6 +19,17 @@ std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title | |||
|         return nullptr; | ||||
|     } | ||||
| 
 | ||||
|     auto plg_ldr = Service::PLGLDR::GetService(system); | ||||
|     if (plg_ldr) { | ||||
|         const auto& plg_context = plg_ldr->GetPluginLoaderContext(); | ||||
|         if (plg_context.is_enabled && plg_context.use_user_load_parameters && | ||||
|             plg_context.user_load_parameters.low_title_Id == static_cast<u32>(title_id) && | ||||
|             plg_context.user_load_parameters.plugin_memory_strategy == | ||||
|                 PLGLDR::PLG_LDR::PluginMemoryStrategy::PLG_STRATEGY_MODE3) { | ||||
|             loader->SetKernelMemoryModeOverride(Kernel::MemoryMode::Dev2); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::shared_ptr<Kernel::Process> process; | ||||
|     Loader::ResultStatus result = loader->Load(process); | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,7 +16,8 @@ class System; | |||
| namespace Service::NS { | ||||
| 
 | ||||
| /// Loads and launches the title identified by title_id in the specified media type.
 | ||||
| std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id); | ||||
| std::shared_ptr<Kernel::Process> LaunchTitle(Core::System& system, FS::MediaType media_type, | ||||
|                                              u64 title_id); | ||||
| 
 | ||||
| /// Reboots the system to the specified title.
 | ||||
| void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id); | ||||
|  |  | |||
|  | @ -204,7 +204,10 @@ void PLG_LDR::SetLoadSettings(Kernel::HLERequestContext& ctx) { | |||
|     IPC::RequestParser rp(ctx); | ||||
| 
 | ||||
|     plgldr_context.use_user_load_parameters = true; | ||||
|     plgldr_context.user_load_parameters.no_flash = rp.Pop<u32>() == 1; | ||||
|     u32_le flags = rp.Pop<u32>(); | ||||
|     plgldr_context.user_load_parameters.no_flash = (flags & 1) == 1; | ||||
|     plgldr_context.user_load_parameters.plugin_memory_strategy = | ||||
|         static_cast<PluginMemoryStrategy>((flags >> 8) & 0xF); | ||||
|     plgldr_context.user_load_parameters.low_title_Id = rp.Pop<u32>(); | ||||
| 
 | ||||
|     auto path = rp.PopMappedBuffer(); | ||||
|  |  | |||
|  | @ -33,10 +33,16 @@ namespace Service::PLGLDR { | |||
| 
 | ||||
| class PLG_LDR final : public ServiceFramework<PLG_LDR> { | ||||
| public: | ||||
|     enum class PluginMemoryStrategy : u8 { | ||||
|         PLG_STRATEGY_NONE = 2, | ||||
|         PLG_STRATEGY_SWAP = 0, | ||||
|         PLG_STRATEGY_MODE3 = 1, | ||||
|     }; | ||||
| 
 | ||||
|     struct PluginLoaderContext { | ||||
|         struct PluginLoadParameters { | ||||
|             u8 no_flash = 0; | ||||
|             u8 no_IR_Patch = 0; | ||||
|             PluginMemoryStrategy plugin_memory_strategy = PluginMemoryStrategy::PLG_STRATEGY_SWAP; | ||||
|             u32_le low_title_Id = 0; | ||||
|             char path[256] = {0}; | ||||
|             u32_le config[32] = {0}; | ||||
|  | @ -44,7 +50,7 @@ public: | |||
|             template <class Archive> | ||||
|             void serialize(Archive& ar, const unsigned int) { | ||||
|                 ar& no_flash; | ||||
|                 ar& no_IR_Patch; | ||||
|                 ar& plugin_memory_strategy; | ||||
|                 ar& low_title_Id; | ||||
|                 ar& path; | ||||
|                 ar& config; | ||||
|  |  | |||
|  | @ -117,6 +117,14 @@ public: | |||
|         return std::make_pair(0x2, ResultStatus::Success); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Forces the application memory mode to the specified value, | ||||
|      * overriding the memory mode specified in the metadata. | ||||
|      */ | ||||
|     void SetKernelMemoryModeOverride(Kernel::MemoryMode mem_override) { | ||||
|         memory_mode_override = mem_override; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Loads the memory mode that this application needs. | ||||
|      * This function defaults to Dev1 (96MB allocated to the application) if it can't read the | ||||
|  | @ -124,6 +132,9 @@ public: | |||
|      * @returns A pair with the optional memory mode, and the status. | ||||
|      */ | ||||
|     virtual std::pair<std::optional<Kernel::MemoryMode>, ResultStatus> LoadKernelMemoryMode() { | ||||
|         if (memory_mode_override.has_value()) { | ||||
|             return std::make_pair(*memory_mode_override, ResultStatus::Success); | ||||
|         } | ||||
|         // 96MB allocated to the application.
 | ||||
|         return std::make_pair(Kernel::MemoryMode::Dev1, ResultStatus::Success); | ||||
|     } | ||||
|  | @ -257,6 +268,7 @@ protected: | |||
|     Core::System& system; | ||||
|     FileUtil::IOFile file; | ||||
|     bool is_loaded = false; | ||||
|     std::optional<Kernel::MemoryMode> memory_mode_override = std::nullopt; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -69,6 +69,9 @@ std::pair<std::optional<Kernel::MemoryMode>, ResultStatus> AppLoader_NCCH::LoadK | |||
|             return std::make_pair(std::nullopt, res); | ||||
|         } | ||||
|     } | ||||
|     if (memory_mode_override.has_value()) { | ||||
|         return std::make_pair(memory_mode_override, ResultStatus::Success); | ||||
|     } | ||||
| 
 | ||||
|     // Provide the memory mode from the exheader.
 | ||||
|     auto& ncch_caps = overlay_ncch->exheader_header.arm11_system_local_caps; | ||||
|  | @ -159,7 +162,7 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process) | |||
|         // APPLICATION. See:
 | ||||
|         // https://github.com/LumaTeam/Luma3DS/blob/e2778a45/sysmodules/pm/source/launch.c#L237
 | ||||
|         auto& ncch_caps = overlay_ncch->exheader_header.arm11_system_local_caps; | ||||
|         const auto o3ds_mode = static_cast<Kernel::MemoryMode>(ncch_caps.system_mode.Value()); | ||||
|         const auto o3ds_mode = *LoadKernelMemoryMode().first; | ||||
|         const auto n3ds_mode = static_cast<Kernel::New3dsMemoryMode>(ncch_caps.n3ds_mode); | ||||
|         const bool is_new_3ds = Settings::values.is_new_3ds.GetValue(); | ||||
|         if (is_new_3ds && n3ds_mode == Kernel::New3dsMemoryMode::Legacy && | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue