mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40: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, NDM)                                                                              \ | ||||||
|     SUB(Service, NFC)                                                                              \ |     SUB(Service, NFC)                                                                              \ | ||||||
|     SUB(Service, NIM)                                                                              \ |     SUB(Service, NIM)                                                                              \ | ||||||
|  |     SUB(Service, NS)                                                                               \ | ||||||
|     SUB(Service, NWM)                                                                              \ |     SUB(Service, NWM)                                                                              \ | ||||||
|     SUB(Service, CAM)                                                                              \ |     SUB(Service, CAM)                                                                              \ | ||||||
|     SUB(Service, CECD)                                                                             \ |     SUB(Service, CECD)                                                                             \ | ||||||
|  |  | ||||||
|  | @ -64,6 +64,7 @@ enum class Class : ClassType { | ||||||
|     Service_NDM,       ///< The NDM (Network daemon manager) service
 |     Service_NDM,       ///< The NDM (Network daemon manager) service
 | ||||||
|     Service_NFC,       ///< The NFC service
 |     Service_NFC,       ///< The NFC service
 | ||||||
|     Service_NIM,       ///< The NIM (Network interface manager) 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_NWM,       ///< The NWM (Network wlan manager) service
 | ||||||
|     Service_CAM,       ///< The CAM (Camera) service
 |     Service_CAM,       ///< The CAM (Camera) service
 | ||||||
|     Service_CECD,      ///< The CECD (StreetPass) service
 |     Service_CECD,      ///< The CECD (StreetPass) service
 | ||||||
|  |  | ||||||
|  | @ -21,6 +21,7 @@ | ||||||
| #include "core/hle/service/apt/bcfnt/bcfnt.h" | #include "core/hle/service/apt/bcfnt/bcfnt.h" | ||||||
| #include "core/hle/service/cfg/cfg.h" | #include "core/hle/service/cfg/cfg.h" | ||||||
| #include "core/hle/service/fs/archive.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/ptm/ptm.h" | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
| #include "core/hw/aes/ccm.h" | #include "core/hw/aes/ccm.h" | ||||||
|  | @ -83,6 +84,41 @@ struct AppletSlotData { | ||||||
| // Holds data about the concurrently running applets in the system.
 | // Holds data about the concurrently running applets in the system.
 | ||||||
| static std::array<AppletSlotData, NumAppletSlot> applet_slots = {}; | 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.
 | // This overload returns nullptr if no applet with the specified id has been started.
 | ||||||
| static AppletSlotData* GetAppletSlotData(AppletId id) { | static AppletSlotData* GetAppletSlotData(AppletId id) { | ||||||
|     auto GetSlot = [](AppletSlot slot) -> AppletSlotData* { |     auto GetSlot = [](AppletSlot slot) -> AppletSlotData* { | ||||||
|  | @ -771,8 +807,29 @@ void PrepareToStartLibraryApplet(Service::Interface* self) { | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |     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); |     auto applet = HLE::Applets::Applet::Get(applet_id); | ||||||
|     if (applet) { |     if (applet) { | ||||||
|         LOG_WARNING(Service_APT, "applet has already been started id=%08X", |         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); |     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); |     auto applet = HLE::Applets::Applet::Get(applet_id); | ||||||
|     if (applet) { |     if (applet) { | ||||||
|         LOG_WARNING(Service_APT, "applet has already been started id=%08X", |         LOG_WARNING(Service_APT, "applet has already been started id=%08X", | ||||||
|  |  | ||||||
|  | @ -2,12 +2,35 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // 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.h" | ||||||
| #include "core/hle/service/ns/ns_s.h" | #include "core/hle/service/ns/ns_s.h" | ||||||
|  | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace NS { | 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) { | void InstallInterfaces(SM::ServiceManager& service_manager) { | ||||||
|     std::make_shared<NS_S>()->InstallAsService(service_manager); |     std::make_shared<NS_S>()->InstallAsService(service_manager); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,11 +4,15 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include "core/hle/kernel/process.h" | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace NS { | 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.
 | /// Registers all NS services with the specified service manager.
 | ||||||
| void InstallInterfaces(SM::ServiceManager& service_manager); | void InstallInterfaces(SM::ServiceManager& service_manager); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue