diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 776ad350c..3940638f8 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -422,8 +422,17 @@ void IGeneralService::GetCurrentNetworkProfile(HLERequestContext& ctx) { void IGeneralService::EnumerateNetworkInterfaces(HLERequestContext& ctx) { LOG_ERROR(Service_NIFM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); + rb.Push(0); +} + +void IGeneralService::EnumerateNetworkProfiles(HLERequestContext& ctx) { + LOG_ERROR(Service_NIFM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); } @@ -584,6 +593,14 @@ void IGeneralService::IsAnyForegroundRequestAccepted(HLERequestContext& ctx) { rb.Push(is_accepted); } +void IGeneralService::ConfirmSystemAvailability(HLERequestContext& ctx) { + LOG_ERROR(Service_NIFM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(true); +} + void IGeneralService::GetCurrentAccessPoint(HLERequestContext& ctx) { LOG_ERROR(Service_NIFM, "(STUBBED) called"); @@ -600,7 +617,7 @@ IGeneralService::IGeneralService(Core::System& system_) {4, &IGeneralService::CreateRequest, "CreateRequest"}, {5, &IGeneralService::GetCurrentNetworkProfile, "GetCurrentNetworkProfile"}, {6, &IGeneralService::EnumerateNetworkInterfaces, "EnumerateNetworkInterfaces"}, - {7, nullptr, "EnumerateNetworkProfiles"}, + {7, &IGeneralService::EnumerateNetworkProfiles, "EnumerateNetworkProfiles"}, {8, nullptr, "GetNetworkProfile"}, {9, nullptr, "SetNetworkProfile"}, {10, &IGeneralService::RemoveNetworkProfile, "RemoveNetworkProfile"}, @@ -626,7 +643,7 @@ IGeneralService::IGeneralService(Core::System& system_) {30, nullptr, "SetEthernetCommunicationEnabledForTest"}, {31, nullptr, "GetTelemetorySystemEventReadableHandle"}, {32, nullptr, "GetTelemetryInfo"}, - {33, nullptr, "ConfirmSystemAvailability"}, + {33, &IGeneralService::ConfirmSystemAvailability, "ConfirmSystemAvailability"}, {34, nullptr, "SetBackgroundRequestEnabled"}, {35, nullptr, "GetScanData"}, {36, &IGeneralService::GetCurrentAccessPoint, "GetCurrentAccessPoint"}, diff --git a/src/core/hle/service/nifm/nifm.h b/src/core/hle/service/nifm/nifm.h index 6bdc4558f..a617da0df 100644 --- a/src/core/hle/service/nifm/nifm.h +++ b/src/core/hle/service/nifm/nifm.h @@ -28,6 +28,7 @@ private: void CreateRequest(HLERequestContext& ctx); void GetCurrentNetworkProfile(HLERequestContext& ctx); void EnumerateNetworkInterfaces(HLERequestContext& ctx); + void EnumerateNetworkProfiles(HLERequestContext& ctx); void RemoveNetworkProfile(HLERequestContext& ctx); void GetCurrentIpAddress(HLERequestContext& ctx); void CreateTemporaryNetworkProfile(HLERequestContext& ctx); @@ -38,6 +39,7 @@ private: void IsEthernetCommunicationEnabled(HLERequestContext& ctx); void IsAnyInternetRequestAccepted(HLERequestContext& ctx); void IsAnyForegroundRequestAccepted(HLERequestContext& ctx); + void ConfirmSystemAvailability(HLERequestContext& ctx); void GetCurrentAccessPoint(HLERequestContext& ctx); Network::RoomNetwork& network; diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 97e080565..9413d334d 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -5,8 +5,13 @@ #include "common/settings.h" #include "core/arm/debug.h" #include "core/core.h" +#include "core/file_sys/content_archive.h" #include "core/file_sys/control_metadata.h" +#include "core/file_sys/fs_filesystem.h" +#include "core/file_sys/nca_metadata.h" #include "core/file_sys/patch_manager.h" +#include "core/file_sys/registered_cache.h" +#include "core/file_sys/submission_package.h" #include "core/file_sys/vfs/vfs.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/glue/glue_manager.h" @@ -198,7 +203,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ {1003, nullptr, "RequestVerifyApplication"}, {1004, nullptr, "CorruptContentForDebug"}, {1200, nullptr, "NeedsUpdateVulnerability"}, - {1300, nullptr, "IsAnyApplicationEntityInstalled"}, + {1300, &IApplicationManagerInterface::IsAnyApplicationEntityInstalled, "IsAnyApplicationEntityInstalled"}, {1301, nullptr, "DeleteApplicationContentEntities"}, {1302, nullptr, "CleanupUnrecordedApplicationEntity"}, {1303, nullptr, "CleanupAddOnContentsWithNoRights"}, @@ -340,7 +345,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ service_context.CreateEvent("IApplicationManagerInterface::GamecardMountFailureEvent"); } -IApplicationManagerInterface::~IApplicationManagerInterface(){ +IApplicationManagerInterface::~IApplicationManagerInterface() { service_context.CloseEvent(record_update_system_event); service_context.CloseEvent(gamecard_update_detection_event); service_context.CloseEvent(gamecard_mount_status_event); @@ -353,54 +358,39 @@ void IApplicationManagerInterface::ListApplicationRecord(HLERequestContext& ctx) const auto limit = ctx.GetWriteBufferNumElements(); LOG_ERROR(Service_NS, "(STUBBED) called"); + const auto& cache = system.GetContentProviderUnion(); + const auto installed_games = cache.ListEntriesFilterOrigin( + std::nullopt, FileSys::TitleType::Application, FileSys::ContentRecordType::Program); std::vector application_records; - std::vector application_records2; - - application_records.push_back(ApplicationRecord{ - .application_id = 0x010074F013262000, - .type = 3, - .unknown = 2, - .unknown2 = 0, - }); - application_records.push_back(ApplicationRecord{ - .application_id = 0x01000F0002BB6000, - .type = 2, - .unknown = 2, - .unknown2 = 1, - }); - application_records.push_back(ApplicationRecord{ - .application_id = 0x0100A7F002830000, - .type = 1, - .unknown = 2, - .unknown2 = 2, - }); - application_records.push_back(ApplicationRecord{ - .application_id = 0x01008DF012A7A000, - .type = 3, - .unknown = 2, - .unknown2 = 3, - }); - - for (const auto& data : application_records) { - if (application_records2.size() >= limit) { + u8 ii{24}; + for (const auto& [slot, game] : installed_games) { + if (application_records.size() >= limit) { break; } + if (game.title_id == 0 || game.title_id < 0x0100000000001FFFull) { + continue; + } if (offset > 0) { offset--; continue; } - application_records2.push_back(data); + application_records.push_back(ApplicationRecord{ + .application_id = game.title_id, + .type = ApplicationRecordType::Installed, + .unknown = 0, // 2 = needs update + .unknown2 = ii++, + }); } - if (!application_records2.empty()) { - ctx.WriteBuffer(application_records2); + if (!application_records.empty()) { + ctx.WriteBuffer(application_records); } IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(application_records2.size()); + rb.Push(application_records.size()); } void IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent(HLERequestContext& ctx) { LOG_ERROR(Service_NS, "(STUBBED) called"); @@ -478,6 +468,14 @@ void IApplicationManagerInterface::GetGameCardMountFailureEvent(HLERequestContex rb.PushCopyObjects(gamecard_mount_failure_event->GetReadableEvent()); } +void IApplicationManagerInterface::IsAnyApplicationEntityInstalled(HLERequestContext& ctx) { + LOG_ERROR(Service_NS, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(true); +} + void IApplicationManagerInterface::GetApplicationView(HLERequestContext& ctx) { std::vector application_id(ctx.GetReadBufferNumElements()); const auto app_buffer = ctx.ReadBuffer(); @@ -485,10 +483,12 @@ void IApplicationManagerInterface::GetApplicationView(HLERequestContext& ctx) { std::vector app_view; - LOG_DEBUG(Service_NS, "(STUBBED) called, size={}", application_id.size()); + LOG_ERROR(Service_NS, "(STUBBED) called, size={}", application_id.size()); for (const u64& data : application_id) { app_view.push_back(ApplicationView{ .application_id = data, + .unk = 0x70000, + .flags = 0x401f17, }); } @@ -505,12 +505,14 @@ void IApplicationManagerInterface::GetApplicationViewWithPromotionInfo(HLEReques std::vector app_view; - LOG_DEBUG(Service_NS, "(STUBBED) called, size={}", application_id.size()); + LOG_ERROR(Service_NS, "(STUBBED) called, size={}", application_id.size()); for (const u64& data : application_id) { app_view.push_back(ApplicationViewWithPromotionInfo{ .view{ .application_id = data, + .unk = 0x70000, + .flags = 0x401f17, }, .promotion = {}, }); @@ -672,7 +674,7 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_) : ServiceFramework{system_, "IContentManagementInterface"} { // clang-format off static const FunctionInfo functions[] = { - {11, nullptr, "CalculateApplicationOccupiedSize"}, + {11, &IContentManagementInterface::CalculateApplicationOccupiedSize, "CalculateApplicationOccupiedSize"}, {43, &IContentManagementInterface::CheckSdCardMountStatus, "CheckSdCardMountStatus"}, {47, &IContentManagementInterface::GetTotalSpaceSize, "GetTotalSpaceSize"}, {48, &IContentManagementInterface::GetFreeSpaceSize, "GetFreeSpaceSize"}, @@ -688,6 +690,37 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_) IContentManagementInterface::~IContentManagementInterface() = default; +void IContentManagementInterface::CalculateApplicationOccupiedSize(HLERequestContext& ctx) { + struct ApplicationOccupiedSizeEntity { + u8 storage; + INSERT_PADDING_BYTES(0x7); + u64 app_size; + u64 patch_size; + u64 aoc_size; + }; + + struct ApplicationOccupiedSize { + ApplicationOccupiedSizeEntity a; + ApplicationOccupiedSizeEntity b; + ApplicationOccupiedSizeEntity c; + ApplicationOccupiedSizeEntity d; + }; + + ApplicationOccupiedSizeEntity dat{ + .storage = 5, + .app_size = 8ULL * 1024ULL * 1024ULL * 1024ULL, + .patch_size = 2ULL * 1024ULL * 1024ULL * 1024ULL, + .aoc_size = 12ULL * 1024ULL * 1024ULL, + }; + ApplicationOccupiedSize oout{dat, dat, dat, dat}; + + LOG_ERROR(Service_NS, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 34}; + rb.Push(ResultSuccess); + rb.PushRaw(oout); +} + void IContentManagementInterface::CheckSdCardMountStatus(HLERequestContext& ctx) { LOG_ERROR(Service_NS, "(STUBBED) called"); @@ -696,27 +729,63 @@ void IContentManagementInterface::CheckSdCardMountStatus(HLERequestContext& ctx) } void IContentManagementInterface::GetTotalSpaceSize(HLERequestContext& ctx) { - IPC::RequestParser rp{ ctx }; - const auto storage{ rp.PopEnum() }; + IPC::RequestParser rp{ctx}; + const auto storage{rp.PopEnum()}; LOG_INFO(Service_Capture, "called, storage={}", storage); - IPC::ResponseBuilder rb{ ctx, 4 }; + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.Push(system.GetFileSystemController().GetTotalSpaceSize(storage)); } void IContentManagementInterface::GetFreeSpaceSize(HLERequestContext& ctx) { - IPC::RequestParser rp{ ctx }; - const auto storage{ rp.PopEnum() }; + IPC::RequestParser rp{ctx}; + const auto storage{rp.PopEnum()}; LOG_INFO(Service_Capture, "called, storage={}", storage); - IPC::ResponseBuilder rb{ ctx, 4 }; + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.Push(system.GetFileSystemController().GetFreeSpaceSize(storage)); } +DynamicRightsInterface::DynamicRightsInterface(Core::System& system_) + : ServiceFramework{system_, "DynamicRightsInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "RequestApplicationRightsOnServer"}, + {1, nullptr, "RequestAssignRights"}, + {4, nullptr, "DeprecatedRequestAssignRightsToResume"}, + {5, nullptr, "VerifyActivatedRightsOwners"}, + {6, nullptr, "DeprecatedGetApplicationRightsStatus"}, + {7, nullptr, "RequestPrefetchForDynamicRights"}, + {8, nullptr, "GetDynamicRightsState"}, + {9, nullptr, "RequestApplicationRightsOnServerToResume"}, + {10, nullptr, "RequestAssignRightsToResume"}, + {11, nullptr, "GetActivatedRightsUsers"}, + {12, nullptr, "GetApplicationRightsStatus"}, + {13, nullptr, "GetRunningApplicationStatus"}, + {14, nullptr, "SelectApplicationLicense"}, + {15, nullptr, "RequestContentsAuthorizationToken"}, + {16, nullptr, "QualifyUser"}, + {17, nullptr, "QualifyUserWithProcessId"}, + {18, nullptr, "NotifyApplicationRightsCheckStart"}, + {19, nullptr, "UpdateUserList"}, + {20, nullptr, "IsRightsLostUser"}, + {21, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"}, + {22, nullptr, "GetLimitedApplicationLicense"}, + {23, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"}, + {24, nullptr, "NotifyLimitedApplicationLicenseUpgradableEventForDebug"}, + {25, nullptr, "RequestProceedDynamicRightsState"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +DynamicRightsInterface::~DynamicRightsInterface() = default; + IDocumentInterface::IDocumentInterface(Core::System& system_) : ServiceFramework{system_, "IDocumentInterface"} { // clang-format off @@ -769,7 +838,7 @@ IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_) {705, nullptr, "RequestDownloadTaskListData"}, {706, nullptr, "TryCommitCurrentApplicationDownloadTask"}, {707, &IDownloadTaskInterface::EnableAutoCommit, "EnableAutoCommit"}, - {708, nullptr, "DisableAutoCommit"}, + {708, &IDownloadTaskInterface::DisableAutoCommit, "DisableAutoCommit"}, {709, nullptr, "TriggerDynamicCommitEvent"}, }; // clang-format on @@ -784,6 +853,11 @@ void IDownloadTaskInterface::EnableAutoCommit(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } +void IDownloadTaskInterface::DisableAutoCommit(HLERequestContext& ctx) { + LOG_ERROR(Service_SET, "called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} IECommerceInterface::IECommerceInterface(Core::System& system_) : ServiceFramework{system_, "IECommerceInterface"} { @@ -863,7 +937,7 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa // clang-format off static const FunctionInfo functions[] = { {0, &IReadOnlyApplicationControlDataInterface::GetApplicationControlData, "GetApplicationControlData"}, - {1, nullptr, "GetApplicationDesiredLanguage"}, + {1, &IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage, "GetApplicationDesiredLanguage"}, {2, nullptr, "ConvertApplicationLanguageToLanguageCode"}, {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, {4, nullptr, "SelectApplicationDesiredLanguage"}, @@ -876,36 +950,121 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default; void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequestContext& ctx) { - enum class ApplicationControlSource : u8 { - CacheOnly, - Storage, - StorageOnly, - }; - - struct RequestParameters { - ApplicationControlSource source; - u64 application_id; - }; - static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size."); - IPC::RequestParser rp{ctx}; - std::vector nacp_data{}; - const auto parameters{rp.PopRaw()}; - const auto result = - system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id); + const auto flag = rp.PopRaw(); + const auto title_id = rp.PopRaw(); + const auto size = ctx.GetWriteBufferSize(); - if (result == ResultSuccess) { - ctx.WriteBuffer(nacp_data.data(), nacp_data.size()); + LOG_ERROR(Service_NS, "called with flag={:016X}, title_id={:016X}", flag, title_id); + + const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), + system.GetContentProvider()}; + const auto control = pm.GetControlMetadata(); + + std::vector out; + + if (control.first != nullptr) { + if (size < 0x4000) { + LOG_ERROR(Service_NS, + "output buffer is too small! (actual={:016X}, expected_min=0x4000)", size); + IPC::ResponseBuilder rb{ctx, 2}; + // TODO(DarkLordZach): Find a better error code for this. + rb.Push(ResultUnknown); + return; + } + + out.resize(0x4000); + const auto bytes = control.first->GetRawBytes(); + std::memcpy(out.data(), bytes.data(), bytes.size()); + } else { + LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.", + title_id); + out.resize(std::min(0x4000, size)); } - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + if (control.second != nullptr) { + if (size < 0x4000 + control.second->GetSize()) { + LOG_ERROR(Service_NS, + "output buffer is too small! (actual={:016X}, expected_min={:016X})", size, + 0x4000 + control.second->GetSize()); + IPC::ResponseBuilder rb{ctx, 2}; + // TODO(DarkLordZach): Find a better error code for this. + rb.Push(ResultUnknown); + return; + } + + out.resize(0x4000 + control.second->GetSize()); + control.second->Read(out.data() + 0x4000, control.second->GetSize()); + } else { + LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.", + title_id); + } + + ctx.WriteBuffer(out); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast(out.size())); +} + +void IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage( + HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto supported_languages = rp.Pop(); + + u8 desired_language{}; + const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages); + if (res == ResultSuccess) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(desired_language); + } else { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res); + } +} + +Result IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage( + u8* out_desired_language, const u32 supported_languages) { + LOG_ERROR(Service_NS, "called with supported_languages={:08X}", supported_languages); + + // Get language code from settings + const auto language_code = + Set::GetLanguageCodeFromIndex(static_cast(Settings::values.language_index.GetValue())); + + // Convert to application language, get priority list + const auto application_language = ConvertToApplicationLanguage(language_code); + if (application_language == std::nullopt) { + LOG_ERROR(Service_NS, "Could not convert application language! language_code={}", + language_code); + return Service::NS::ResultApplicationLanguageNotFound; + } + const auto priority_list = GetApplicationLanguagePriorityList(*application_language); + if (!priority_list) { + LOG_ERROR(Service_NS, + "Could not find application language priorities! application_language={}", + *application_language); + return Service::NS::ResultApplicationLanguageNotFound; + } + + // Try to find a valid language. + for (const auto lang : *priority_list) { + const auto supported_flag = GetSupportedLanguageFlag(lang); + if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { + *out_desired_language = static_cast(lang); + return ResultSuccess; + } + } + + LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}", + supported_languages); + return Service::NS::ResultApplicationLanguageNotFound; } NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { - {7988, nullptr, "GetDynamicRightsInterface"}, + {7988, &NS::PushInterface, "GetDynamicRightsInterface"}, {7989, &NS::PushInterface, "GetReadOnlyApplicationControlDataInterface"}, {7991, &NS::PushInterface, "GetReadOnlyApplicationRecordInterface"}, {7992, &NS::PushInterface, "GetECommerceInterface"}, diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index 0e5e97bd2..8be31968f 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h @@ -34,19 +34,28 @@ public: u8 application_language); private: + enum class ApplicationRecordType : u8 { + Installing = 2, + Installed = 3, + GameCardNotInserted = 5, + Archived = 0xB, + GameCard = 0x10, + }; + struct ApplicationRecord { u64 application_id; - u8 type; + ApplicationRecordType type; u8 unknown; INSERT_PADDING_BYTES(0x6); u8 unknown2; INSERT_PADDING_BYTES(0x7); }; + static_assert(sizeof(ApplicationRecord) == 0x18, "ApplicationRecord is an invalid size"); /// ApplicationView struct ApplicationView { u64 application_id; ///< ApplicationId. - u8 unk_x8[0x4]; ///< Unknown. + u32 unk; ///< Unknown. u32 flags; ///< Flags. u8 unk_x10[0x10]; ///< Unknown. u32 unk_x20; ///< Unknown. @@ -81,6 +90,7 @@ private: void GetApplicationRecordUpdateSystemEvent(HLERequestContext& ctx); void GetApplicationControlData(HLERequestContext& ctx); void GetGameCardMountFailureEvent(HLERequestContext& ctx); + void IsAnyApplicationEntityInstalled(HLERequestContext& ctx); void GetApplicationView(HLERequestContext& ctx); void GetApplicationViewWithPromotionInfo(HLERequestContext& ctx); void CheckSdCardMountStatus(HLERequestContext& ctx); @@ -110,6 +120,7 @@ public: ~IContentManagementInterface() override; private: + void CalculateApplicationOccupiedSize(HLERequestContext& ctx); void CheckSdCardMountStatus(HLERequestContext& ctx); void GetTotalSpaceSize(HLERequestContext& ctx); void GetFreeSpaceSize(HLERequestContext& ctx); @@ -125,6 +136,12 @@ private: void GetRunningApplicationProgramId(HLERequestContext& ctx); }; +class DynamicRightsInterface final : public ServiceFramework { +public: + explicit DynamicRightsInterface(Core::System& system_); + ~DynamicRightsInterface() override; +}; + class IDownloadTaskInterface final : public ServiceFramework { public: explicit IDownloadTaskInterface(Core::System& system_); @@ -132,6 +149,7 @@ public: private: void EnableAutoCommit(HLERequestContext& ctx); + void DisableAutoCommit(HLERequestContext& ctx); }; class IECommerceInterface final : public ServiceFramework { @@ -165,6 +183,8 @@ public: private: void GetApplicationControlData(HLERequestContext& ctx); + void GetApplicationDesiredLanguage(HLERequestContext& ctx); + Result GetApplicationDesiredLanguage(u8* out_desired_language, u32 supported_languages); }; class NS final : public ServiceFramework {