mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #3086 from Subv/swkbd_launch
HLE/APT: Allow launching native applets instead of HLE ones.
This commit is contained in:
		
						commit
						2664042325
					
				
					 5 changed files with 101 additions and 2 deletions
				
			
		|  | @ -47,6 +47,7 @@ namespace Log { | |||
|     SUB(Service, NDM)                                                                              \ | ||||
|     SUB(Service, NFC)                                                                              \ | ||||
|     SUB(Service, NIM)                                                                              \ | ||||
|     SUB(Service, NS)                                                                               \ | ||||
|     SUB(Service, NWM)                                                                              \ | ||||
|     SUB(Service, CAM)                                                                              \ | ||||
|     SUB(Service, CECD)                                                                             \ | ||||
|  |  | |||
|  | @ -64,6 +64,7 @@ enum class Class : ClassType { | |||
|     Service_NDM,       ///< The NDM (Network daemon manager) service
 | ||||
|     Service_NFC,       ///< The NFC service
 | ||||
|     Service_NIM,       ///< The NIM (Network interface manager) service
 | ||||
|     Service_NS,        ///< The NS (Nintendo User Interface Shell) service
 | ||||
|     Service_NWM,       ///< The NWM (Network wlan manager) service
 | ||||
|     Service_CAM,       ///< The CAM (Camera) service
 | ||||
|     Service_CECD,      ///< The CECD (StreetPass) service
 | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ | |||
| #include "core/hle/service/apt/bcfnt/bcfnt.h" | ||||
| #include "core/hle/service/cfg/cfg.h" | ||||
| #include "core/hle/service/fs/archive.h" | ||||
| #include "core/hle/service/ns/ns.h" | ||||
| #include "core/hle/service/ptm/ptm.h" | ||||
| #include "core/hle/service/service.h" | ||||
| #include "core/hw/aes/ccm.h" | ||||
|  | @ -83,6 +84,41 @@ struct AppletSlotData { | |||
| // Holds data about the concurrently running applets in the system.
 | ||||
| static std::array<AppletSlotData, NumAppletSlot> applet_slots = {}; | ||||
| 
 | ||||
| struct AppletTitleData { | ||||
|     // There are two possible applet ids for each applet.
 | ||||
|     std::array<AppletId, 2> applet_ids; | ||||
| 
 | ||||
|     // There's a specific TitleId per region for each applet.
 | ||||
|     static constexpr size_t NumRegions = 7; | ||||
|     std::array<u64, NumRegions> title_ids; | ||||
| }; | ||||
| 
 | ||||
| static constexpr size_t NumApplets = 29; | ||||
| static constexpr std::array<AppletTitleData, NumApplets> applet_titleids = {{ | ||||
|     {AppletId::HomeMenu, AppletId::None, 0x4003000008202, 0x4003000008F02, 0x4003000009802, | ||||
|      0x4003000008202, 0x400300000A102, 0x400300000A902, 0x400300000B102}, | ||||
|     {AppletId::SoftwareKeyboard1, AppletId::SoftwareKeyboard2, 0x400300000C002, 0x400300000C802, | ||||
|      0x400300000D002, 0x400300000C002, 0x400300000D802, 0x400300000DE02, 0x400300000E402}, | ||||
|     {AppletId::Error, AppletId::Error2, 0x400300000C502, 0x400300000C502, 0x400300000C502, | ||||
|      0x400300000C502, 0x400300000CF02, 0x400300000CF02, 0x400300000CF02}, | ||||
|     {AppletId::Ed1, AppletId::Ed2, 0x400300000C102, 0x400300000C902, 0x400300000D102, | ||||
|      0x400300000C102, 0x400300000D902, 0x400300000DF02, 0x400300000E502}, | ||||
|     // TODO(Subv): Fill in the rest of the titleids
 | ||||
| }}; | ||||
| 
 | ||||
| static u64 GetTitleIdForApplet(AppletId id) { | ||||
|     ASSERT_MSG(id != AppletId::None, "Invalid applet id"); | ||||
| 
 | ||||
|     auto itr = std::find_if(applet_titleids.begin(), applet_titleids.end(), | ||||
|                             [id](const AppletTitleData& data) { | ||||
|                                 return data.applet_ids[0] == id || data.applet_ids[1] == id; | ||||
|                             }); | ||||
| 
 | ||||
|     ASSERT_MSG(itr != applet_titleids.end(), "Unknown applet id"); | ||||
| 
 | ||||
|     return itr->title_ids[CFG::GetRegionValue()]; | ||||
| } | ||||
| 
 | ||||
| // This overload returns nullptr if no applet with the specified id has been started.
 | ||||
| static AppletSlotData* GetAppletSlotData(AppletId id) { | ||||
|     auto GetSlot = [](AppletSlot slot) -> AppletSlotData* { | ||||
|  | @ -771,8 +807,29 @@ void PrepareToStartLibraryApplet(Service::Interface* self) { | |||
| 
 | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||
| 
 | ||||
|     // TODO(Subv): Launch the requested applet application.
 | ||||
|     // The real APT service returns an error if there's a pending APT parameter when this function
 | ||||
|     // is called.
 | ||||
|     if (next_parameter) { | ||||
|         rb.Push(ResultCode(ErrCodes::ParameterPresent, ErrorModule::Applet, | ||||
|                            ErrorSummary::InvalidState, ErrorLevel::Status)); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const auto& slot = applet_slots[static_cast<size_t>(AppletSlot::LibraryApplet)]; | ||||
| 
 | ||||
|     if (slot.registered) { | ||||
|         rb.Push(ResultCode(ErrorDescription::AlreadyExists, ErrorModule::Applet, | ||||
|                            ErrorSummary::InvalidState, ErrorLevel::Status)); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     auto process = NS::LaunchTitle(FS::MediaType::NAND, GetTitleIdForApplet(applet_id)); | ||||
|     if (process) { | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // If we weren't able to load the native applet title, try to fallback to an HLE implementation.
 | ||||
|     auto applet = HLE::Applets::Applet::Get(applet_id); | ||||
|     if (applet) { | ||||
|         LOG_WARNING(Service_APT, "applet has already been started id=%08X", | ||||
|  | @ -805,8 +862,21 @@ void PreloadLibraryApplet(Service::Interface* self) { | |||
| 
 | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||
| 
 | ||||
|     // TODO(Subv): Launch the requested applet application.
 | ||||
|     const auto& slot = applet_slots[static_cast<size_t>(AppletSlot::LibraryApplet)]; | ||||
| 
 | ||||
|     if (slot.registered) { | ||||
|         rb.Push(ResultCode(ErrorDescription::AlreadyExists, ErrorModule::Applet, | ||||
|                            ErrorSummary::InvalidState, ErrorLevel::Status)); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     auto process = NS::LaunchTitle(FS::MediaType::NAND, GetTitleIdForApplet(applet_id)); | ||||
|     if (process) { | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // If we weren't able to load the native applet title, try to fallback to an HLE implementation.
 | ||||
|     auto applet = HLE::Applets::Applet::Get(applet_id); | ||||
|     if (applet) { | ||||
|         LOG_WARNING(Service_APT, "applet has already been started id=%08X", | ||||
|  |  | |||
|  | @ -2,12 +2,35 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <cinttypes> | ||||
| #include "core/hle/service/am/am.h" | ||||
| #include "core/hle/service/ns/ns.h" | ||||
| #include "core/hle/service/ns/ns_s.h" | ||||
| #include "core/loader/loader.h" | ||||
| 
 | ||||
| namespace Service { | ||||
| namespace NS { | ||||
| 
 | ||||
| Kernel::SharedPtr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id) { | ||||
|     std::string path = AM::GetTitleContentPath(media_type, title_id); | ||||
|     auto loader = Loader::GetLoader(path); | ||||
| 
 | ||||
|     if (!loader) { | ||||
|         LOG_WARNING(Service_NS, "Could not find .app for title 0x%016" PRIx64, title_id); | ||||
|         return nullptr; | ||||
|     } | ||||
| 
 | ||||
|     Kernel::SharedPtr<Kernel::Process> process; | ||||
|     Loader::ResultStatus result = loader->Load(process); | ||||
| 
 | ||||
|     if (result != Loader::ResultStatus::Success) { | ||||
|         LOG_WARNING(Service_NS, "Error loading .app for title 0x%016" PRIx64, title_id); | ||||
|         return nullptr; | ||||
|     } | ||||
| 
 | ||||
|     return process; | ||||
| } | ||||
| 
 | ||||
| void InstallInterfaces(SM::ServiceManager& service_manager) { | ||||
|     std::make_shared<NS_S>()->InstallAsService(service_manager); | ||||
| } | ||||
|  |  | |||
|  | @ -4,11 +4,15 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/service/service.h" | ||||
| 
 | ||||
| namespace Service { | ||||
| namespace NS { | ||||
| 
 | ||||
| /// Loads and launches the title identified by title_id in the specified media type.
 | ||||
| Kernel::SharedPtr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id); | ||||
| 
 | ||||
| /// Registers all NS services with the specified service manager.
 | ||||
| void InstallInterfaces(SM::ServiceManager& service_manager); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue