From 63181714e1b2a82bd1e9b872f1ce84a654bfdde0 Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 06:09:10 +0100 Subject: [PATCH 01/14] Update ns.h --- nx/include/switch/services/ns.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index 969610a20c..b7d8c77c8e 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -334,6 +334,20 @@ Result nsGetApplicationControlData2(NsApplicationControlSource source, u64 appli */ Result nsGetApplicationDesiredLanguage(NacpStruct *nacp, NacpLanguageEntry **langentry); +/** + * @brief GetApplicationTitle. Returns \ref NacpLanguageEntry matching currently set system language for specified application_ids. + * @note The data available with \ref asyncValueGet is a s32 for the offset within the buffer where the output data is located, \ref asyncValueGetSize returns the total byte-size of the data located here. The data located here is the \ref NacpLanguageEntry for each specified ApplicationId. + * @note Only available on [20.0.0+]. + * @note NacpLanguageEntry is decompressed when necessary only on [21.0.0+]. + * @param[out] a \ref AsyncValue + * @param[in] source Source, qlaunch uses ::NsApplicationControlSource_Storage. + * @param[in] application_ids Input array of ApplicationIds. + * @param[in] count Size of the application_ids array in entries. + * @param buffer 0x1000-byte aligned buffer for TransferMemory. This buffer must not be accessed until the async operation finishes. + * @param[in] size 0x1000-byte aligned buffer size for TransferMemory. This must be at least: count*sizeof(\ref NacpLanguageEntry) + count*sizeof(u64) + count*sizeof(\ref NsApplicationControlData). + */ +Result nsGetApplicationTitle(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size); + ///@} ///@name IECommerceInterface From a417c3c0b9dccfe94f30257b96c8b593d0df50bf Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 06:14:35 +0100 Subject: [PATCH 02/14] Update ns.c --- nx/source/services/ns.c | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index a1ec650e83..69c131c0e0 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -563,6 +563,52 @@ Result nsGetApplicationDesiredLanguage(NacpStruct *nacp, NacpLanguageEntry **lan return rc; } +Result nsGetApplicationTitle(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size) { + if (hosversionBefore(20,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc=0; + TransferMemory tmem={0}; + Service srv={0}; + u32 cmd_id = 10; + + rc = tmemCreateFromMemory(&tmem, buffer, size, Perm_R); + if (R_FAILED(rc)) + return rc; + + rc = nsGetReadOnlyApplicationControlDataInterface(&srv); + + if (R_SUCCEEDED(rc)) { + const struct { + u8 source; + u8 pad[7]; + u64 size; + } in = { source, {0}, tmem.size }; + + memset(a, 0, sizeof(*a)); + Handle event = INVALID_HANDLE; + rc = serviceDispatchIn(&srv, cmd_id, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { application_ids, count*sizeof(u64) } }, + .in_num_handles = 1, + .in_handles = { tmem.handle }, + .out_num_objects = 1, + .out_objects = &a->s, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); + + if (R_SUCCEEDED(rc)) + eventLoadRemote(&a->event, event, false); + + serviceClose(&srv); + } + + tmemClose(&tmem); + + return rc; +} + // IECommerceInterface Result nsRequestLinkDevice(AsyncResult *a, AccountUid uid) { From eef62577fe67cea0dfcaf675dd69a4fad7738aa7 Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 06:18:19 +0100 Subject: [PATCH 03/14] Update ns.h --- nx/include/switch/services/ns.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index b7d8c77c8e..5e611882b8 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -340,7 +340,7 @@ Result nsGetApplicationDesiredLanguage(NacpStruct *nacp, NacpLanguageEntry **lan * @note Only available on [20.0.0+]. * @note NacpLanguageEntry is decompressed when necessary only on [21.0.0+]. * @param[out] a \ref AsyncValue - * @param[in] source Source, qlaunch uses ::NsApplicationControlSource_Storage. + * @param[in] source Source, official sw uses ::NsApplicationControlSource_Storage. * @param[in] application_ids Input array of ApplicationIds. * @param[in] count Size of the application_ids array in entries. * @param buffer 0x1000-byte aligned buffer for TransferMemory. This buffer must not be accessed until the async operation finishes. From 2b87491567395f34290045f3e7d8af35a0c28ad2 Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 06:23:08 +0100 Subject: [PATCH 04/14] Update ns.h --- nx/include/switch/services/ns.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index 5e611882b8..fdff4a8316 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -335,7 +335,7 @@ Result nsGetApplicationControlData2(NsApplicationControlSource source, u64 appli Result nsGetApplicationDesiredLanguage(NacpStruct *nacp, NacpLanguageEntry **langentry); /** - * @brief GetApplicationTitle. Returns \ref NacpLanguageEntry matching currently set system language for specified application_ids. + * @brief GetApplicationTitle. Returns \ref NacpLanguageEntry matching currently set system language for each specified ApplicationId. * @note The data available with \ref asyncValueGet is a s32 for the offset within the buffer where the output data is located, \ref asyncValueGetSize returns the total byte-size of the data located here. The data located here is the \ref NacpLanguageEntry for each specified ApplicationId. * @note Only available on [20.0.0+]. * @note NacpLanguageEntry is decompressed when necessary only on [21.0.0+]. From 5574752996c077068ec2a6416ba04833367bb9ad Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 06:36:25 +0100 Subject: [PATCH 05/14] Update ns.c --- nx/source/services/ns.c | 86 ++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 53 deletions(-) diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 69c131c0e0..2755e638d4 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -563,52 +563,6 @@ Result nsGetApplicationDesiredLanguage(NacpStruct *nacp, NacpLanguageEntry **lan return rc; } -Result nsGetApplicationTitle(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size) { - if (hosversionBefore(20,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - Result rc=0; - TransferMemory tmem={0}; - Service srv={0}; - u32 cmd_id = 10; - - rc = tmemCreateFromMemory(&tmem, buffer, size, Perm_R); - if (R_FAILED(rc)) - return rc; - - rc = nsGetReadOnlyApplicationControlDataInterface(&srv); - - if (R_SUCCEEDED(rc)) { - const struct { - u8 source; - u8 pad[7]; - u64 size; - } in = { source, {0}, tmem.size }; - - memset(a, 0, sizeof(*a)); - Handle event = INVALID_HANDLE; - rc = serviceDispatchIn(&srv, cmd_id, in, - .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, - .buffers = { { application_ids, count*sizeof(u64) } }, - .in_num_handles = 1, - .in_handles = { tmem.handle }, - .out_num_objects = 1, - .out_objects = &a->s, - .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, - .out_handles = &event, - ); - - if (R_SUCCEEDED(rc)) - eventLoadRemote(&a->event, event, false); - - serviceClose(&srv); - } - - tmemClose(&tmem); - - return rc; -} - // IECommerceInterface Result nsRequestLinkDevice(AsyncResult *a, AccountUid uid) { @@ -1026,10 +980,7 @@ Result nsRequestDownloadApplicationControlData(AsyncResult *a, u64 application_i return _nsManCmdInU64OutAsyncResult(a, application_id, 402); } -static Result _nsListApplicationTitleIcon(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, TransferMemory *tmem, u32 cmd_id) { // [8.0.0+] - Service srv={0}; - Result rc = nsGetApplicationManagerInterface(&srv); - +static Result _nsListApplicationTitleIcon(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, TransferMemory *tmem, u32 cmd_id, Service* srv) { // [8.0.0+] const struct { u8 source; u8 pad[7]; @@ -1038,7 +989,7 @@ static Result _nsListApplicationTitleIcon(AsyncValue *a, NsApplicationControlSou memset(a, 0, sizeof(*a)); Handle event = INVALID_HANDLE; - if (R_SUCCEEDED(rc)) rc = serviceDispatchIn(&srv, cmd_id, in, + rc = serviceDispatchIn(&srv, cmd_id, in, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffers = { { application_ids, count*sizeof(u64) } }, .in_num_handles = 1, @@ -1062,23 +1013,52 @@ Result nsListApplicationTitle(AsyncValue *a, NsApplicationControlSource source, Result rc=0; TransferMemory tmem={0}; + Service srv={0}; rc = tmemCreateFromMemory(&tmem, buffer, size, Perm_R); - if (R_SUCCEEDED(rc)) rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 407); + + if (R_SUCCEEDED(rc)) { + rc = nsGetApplicationManagerInterface(&srv); + if (R_SUCCEEDED(rc)) rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 407, &srv); + } tmemClose(&tmem); return rc; } +Result nsListApplicationTitle2(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size) { + if (hosversionBefore(20,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc=0; + TransferMemory tmem={0}; + Service srv={0}; + + rc = tmemCreateFromMemory(&tmem, buffer, size, Perm_R); + + if (R_SUCCEEDED(rc)) { + rc = nsGetReadOnlyApplicationControlDataInterface(&srv); + if (R_SUCCEEDED(rc)) rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 10, &srv); + } + + tmemClose(&tmem); + + return rc; +} + Result nsListApplicationIcon(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size) { if (hosversionBefore(8,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); Result rc=0; TransferMemory tmem={0}; + Service srv={0}; rc = tmemCreateFromMemory(&tmem, buffer, size, Perm_R); - if (R_SUCCEEDED(rc)) rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 408); + if (R_SUCCEEDED(rc)) { + rc = nsGetApplicationManagerInterface(&srv); + if (R_SUCCEEDED(rc)) rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 408, &srv); + } tmemClose(&tmem); return rc; From bb39c67d560d98f4871cb47d8a126f9f2b3248af Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 06:38:14 +0100 Subject: [PATCH 06/14] Update ns.h --- nx/include/switch/services/ns.h | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index fdff4a8316..3c0662c7f7 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -334,20 +334,6 @@ Result nsGetApplicationControlData2(NsApplicationControlSource source, u64 appli */ Result nsGetApplicationDesiredLanguage(NacpStruct *nacp, NacpLanguageEntry **langentry); -/** - * @brief GetApplicationTitle. Returns \ref NacpLanguageEntry matching currently set system language for each specified ApplicationId. - * @note The data available with \ref asyncValueGet is a s32 for the offset within the buffer where the output data is located, \ref asyncValueGetSize returns the total byte-size of the data located here. The data located here is the \ref NacpLanguageEntry for each specified ApplicationId. - * @note Only available on [20.0.0+]. - * @note NacpLanguageEntry is decompressed when necessary only on [21.0.0+]. - * @param[out] a \ref AsyncValue - * @param[in] source Source, official sw uses ::NsApplicationControlSource_Storage. - * @param[in] application_ids Input array of ApplicationIds. - * @param[in] count Size of the application_ids array in entries. - * @param buffer 0x1000-byte aligned buffer for TransferMemory. This buffer must not be accessed until the async operation finishes. - * @param[in] size 0x1000-byte aligned buffer size for TransferMemory. This must be at least: count*sizeof(\ref NacpLanguageEntry) + count*sizeof(u64) + count*sizeof(\ref NsApplicationControlData). - */ -Result nsGetApplicationTitle(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size); - ///@} ///@name IECommerceInterface @@ -670,6 +656,21 @@ Result nsRequestDownloadApplicationControlData(AsyncResult *a, u64 application_i */ Result nsListApplicationTitle(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size); + +/** + * @brief ListApplicationTitle2. Returns \ref NacpLanguageEntry matching currently set system language for each specified ApplicationId. + * @note The data available with \ref asyncValueGet is a s32 for the offset within the buffer where the output data is located, \ref asyncValueGetSize returns the total byte-size of the data located here. The data located here is the \ref NacpLanguageEntry for each specified ApplicationId. + * @note Only available on [20.0.0+]. + * @note NacpLanguageEntry is decompressed when necessary only on [21.0.0+]. + * @param[out] a \ref AsyncValue + * @param[in] source Source, official sw uses ::NsApplicationControlSource_Storage. + * @param[in] application_ids Input array of ApplicationIds. + * @param[in] count Size of the application_ids array in entries. + * @param buffer 0x1000-byte aligned buffer for TransferMemory. This buffer must not be accessed until the async operation finishes. + * @param[in] size 0x1000-byte aligned buffer size for TransferMemory. This must be at least: count*sizeof(\ref NacpLanguageEntry) + count*sizeof(u64) + count*sizeof(\ref NsApplicationControlData). + */ +Result nsListApplicationTitle2(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size); + /** * @brief ListApplicationIcon * @note The data available with \ref asyncValueGet is a s32 for the offset within the buffer where the output data is located, \ref asyncValueGetSize returns the total byte-size of the data located here. This data is: an u64 for total entries, an array of u64s for each icon size, then the icon JPEGs for the specified ApplicationIds. From 3aabc1c2916928bb9fe951093e7734c31064ff2e Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 06:41:21 +0100 Subject: [PATCH 07/14] Update ns.c --- nx/source/services/ns.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 2755e638d4..985bb649e9 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -1003,7 +1003,6 @@ static Result _nsListApplicationTitleIcon(AsyncValue *a, NsApplicationControlSou if (R_SUCCEEDED(rc)) eventLoadRemote(&a->event, event, false); - serviceClose(&srv); return rc; } @@ -1019,7 +1018,10 @@ Result nsListApplicationTitle(AsyncValue *a, NsApplicationControlSource source, if (R_SUCCEEDED(rc)) { rc = nsGetApplicationManagerInterface(&srv); - if (R_SUCCEEDED(rc)) rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 407, &srv); + if (R_SUCCEEDED(rc)) { + rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 407, &srv); + serviceClose(&srv); + } } tmemClose(&tmem); @@ -1038,7 +1040,10 @@ Result nsListApplicationTitle2(AsyncValue *a, NsApplicationControlSource source, if (R_SUCCEEDED(rc)) { rc = nsGetReadOnlyApplicationControlDataInterface(&srv); - if (R_SUCCEEDED(rc)) rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 10, &srv); + if (R_SUCCEEDED(rc)) { + rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 10, &srv); + serviceClose(&srv); + } } tmemClose(&tmem); @@ -1057,7 +1062,10 @@ Result nsListApplicationIcon(AsyncValue *a, NsApplicationControlSource source, c rc = tmemCreateFromMemory(&tmem, buffer, size, Perm_R); if (R_SUCCEEDED(rc)) { rc = nsGetApplicationManagerInterface(&srv); - if (R_SUCCEEDED(rc)) rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 408, &srv); + if (R_SUCCEEDED(rc)) { + rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 408, &srv); + serviceClose(&srv); + } } tmemClose(&tmem); From ec64b51f511af0e2e4673e41ebd8a7d27b972e5e Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 06:42:32 +0100 Subject: [PATCH 08/14] Update ns.c --- nx/source/services/ns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 985bb649e9..15ca24a1b5 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -989,7 +989,7 @@ static Result _nsListApplicationTitleIcon(AsyncValue *a, NsApplicationControlSou memset(a, 0, sizeof(*a)); Handle event = INVALID_HANDLE; - rc = serviceDispatchIn(&srv, cmd_id, in, + rc = serviceDispatchIn(srv, cmd_id, in, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffers = { { application_ids, count*sizeof(u64) } }, .in_num_handles = 1, From 3d38ae0e50e3ac61d75d459ce016c9dcbf41c865 Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 06:44:33 +0100 Subject: [PATCH 09/14] Update ns.c --- nx/source/services/ns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 15ca24a1b5..7444b1610d 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -989,7 +989,7 @@ static Result _nsListApplicationTitleIcon(AsyncValue *a, NsApplicationControlSou memset(a, 0, sizeof(*a)); Handle event = INVALID_HANDLE; - rc = serviceDispatchIn(srv, cmd_id, in, + Result rc = serviceDispatchIn(srv, cmd_id, in, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffers = { { application_ids, count*sizeof(u64) } }, .in_num_handles = 1, From 9842112d1df85afb4077f86d70cc62dd5f052a86 Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 06:45:15 +0100 Subject: [PATCH 10/14] Update ns.c --- nx/source/services/ns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 7444b1610d..93945bb01b 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -980,7 +980,7 @@ Result nsRequestDownloadApplicationControlData(AsyncResult *a, u64 application_i return _nsManCmdInU64OutAsyncResult(a, application_id, 402); } -static Result _nsListApplicationTitleIcon(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, TransferMemory *tmem, u32 cmd_id, Service* srv) { // [8.0.0+] +static Result _nsListApplicationTitleIcon(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, TransferMemory *tmem, u32 cmd_id, Service* srv) { const struct { u8 source; u8 pad[7]; From 8b0e61fd172439b537262b3025ef20da2cdc295c Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 06:47:40 +0100 Subject: [PATCH 11/14] Update ns.h --- nx/include/switch/services/ns.h | 1 - 1 file changed, 1 deletion(-) diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index 3c0662c7f7..1c1d3477e8 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -656,7 +656,6 @@ Result nsRequestDownloadApplicationControlData(AsyncResult *a, u64 application_i */ Result nsListApplicationTitle(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size); - /** * @brief ListApplicationTitle2. Returns \ref NacpLanguageEntry matching currently set system language for each specified ApplicationId. * @note The data available with \ref asyncValueGet is a s32 for the offset within the buffer where the output data is located, \ref asyncValueGetSize returns the total byte-size of the data located here. The data located here is the \ref NacpLanguageEntry for each specified ApplicationId. From dc2f2dac239ac16d9af009d9f8082d99d07001fb Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Sun, 22 Feb 2026 07:47:11 +0100 Subject: [PATCH 12/14] Update ns.c --- nx/source/services/ns.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 93945bb01b..ce38fbf9a6 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -980,7 +980,7 @@ Result nsRequestDownloadApplicationControlData(AsyncResult *a, u64 application_i return _nsManCmdInU64OutAsyncResult(a, application_id, 402); } -static Result _nsListApplicationTitleIcon(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, TransferMemory *tmem, u32 cmd_id, Service* srv) { +static Result _nsListApplicationTitleIcon(Service* srv, AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, TransferMemory *tmem, u32 cmd_id) { const struct { u8 source; u8 pad[7]; @@ -1019,7 +1019,7 @@ Result nsListApplicationTitle(AsyncValue *a, NsApplicationControlSource source, if (R_SUCCEEDED(rc)) { rc = nsGetApplicationManagerInterface(&srv); if (R_SUCCEEDED(rc)) { - rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 407, &srv); + rc = _nsListApplicationTitleIcon(&srv, a, source, application_ids, count, &tmem, 407); serviceClose(&srv); } } @@ -1041,7 +1041,7 @@ Result nsListApplicationTitle2(AsyncValue *a, NsApplicationControlSource source, if (R_SUCCEEDED(rc)) { rc = nsGetReadOnlyApplicationControlDataInterface(&srv); if (R_SUCCEEDED(rc)) { - rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 10, &srv); + rc = _nsListApplicationTitleIcon(&srv, a, source, application_ids, count, &tmem, 10); serviceClose(&srv); } } @@ -1063,7 +1063,7 @@ Result nsListApplicationIcon(AsyncValue *a, NsApplicationControlSource source, c if (R_SUCCEEDED(rc)) { rc = nsGetApplicationManagerInterface(&srv); if (R_SUCCEEDED(rc)) { - rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 408, &srv); + rc = _nsListApplicationTitleIcon(&srv, a, source, application_ids, count, &tmem, 408); serviceClose(&srv); } } From 283eb4c95e1cd15044d5676b7f19badc2ffd69b1 Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Thu, 26 Feb 2026 12:43:10 +0100 Subject: [PATCH 13/14] Update ns.h --- nx/include/switch/services/ns.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index 1c1d3477e8..a15dd6362b 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -670,6 +670,19 @@ Result nsListApplicationTitle(AsyncValue *a, NsApplicationControlSource source, */ Result nsListApplicationTitle2(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size); +/** + * @brief ListApplicationTitle3. Returns \ref NacpLanguageEntry matching currently set system language for each specified ApplicationId. + * @note The data available with \ref asyncValueGet is a s32 for the offset within the buffer where the output data is located, \ref asyncValueGetSize returns the total byte-size of the data located here. The data located here is the \ref NacpLanguageEntry for each specified ApplicationId. + * @note Only available on [20.0.0+]. + * @note NacpLanguageEntry is decompressed when necessary only on [21.0.0+]. + * @param[out] a \ref AsyncValue + * @param[in] application_ids Input array of ApplicationIds. + * @param[in] count Size of the application_ids array in entries. + * @param buffer 0x1000-byte aligned buffer for TransferMemory. This buffer must not be accessed until the async operation finishes. + * @param[in] size 0x1000-byte aligned buffer size for TransferMemory. This must be at least: count*sizeof(\ref NacpLanguageEntry) + count*sizeof(u64) + sizeof(\ref NsApplicationControlData). + */ +Result nsListApplicationTitle3(AsyncValue *a, const u64 *application_ids, s32 count, void* buffer, size_t size); + /** * @brief ListApplicationIcon * @note The data available with \ref asyncValueGet is a s32 for the offset within the buffer where the output data is located, \ref asyncValueGetSize returns the total byte-size of the data located here. This data is: an u64 for total entries, an array of u64s for each icon size, then the icon JPEGs for the specified ApplicationIds. From 37f9a25618d446c7fc3c1f0995707fe2663264ec Mon Sep 17 00:00:00 2001 From: MasaGratoR Date: Thu, 26 Feb 2026 12:45:33 +0100 Subject: [PATCH 14/14] Update ns.c --- nx/source/services/ns.c | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index ce38fbf9a6..8a39079ad1 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -1006,6 +1006,26 @@ static Result _nsListApplicationTitleIcon(Service* srv, AsyncValue *a, NsApplica return rc; } +static Result _nsListApplicationTitleIcon2(Service* srv, AsyncValue *a, const u64 *application_ids, s32 count, TransferMemory *tmem, u32 cmd_id) { + memset(a, 0, sizeof(*a)); + Handle event = INVALID_HANDLE; + Result rc = serviceDispatchIn(srv, cmd_id, tmem->size, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { application_ids, count*sizeof(u64) } }, + .in_num_handles = 1, + .in_handles = { tmem->handle }, + .out_num_objects = 1, + .out_objects = &a->s, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); + + if (R_SUCCEEDED(rc)) + eventLoadRemote(&a->event, event, false); + + return rc; +} + Result nsListApplicationTitle(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size) { if (hosversionBefore(8,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -1051,6 +1071,29 @@ Result nsListApplicationTitle2(AsyncValue *a, NsApplicationControlSource source, return rc; } +Result nsListApplicationTitle3(AsyncValue *a, const u64 *application_ids, s32 count, void* buffer, size_t size) { + if (hosversionBefore(20,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc=0; + TransferMemory tmem={0}; + Service srv={0}; + + rc = tmemCreateFromMemory(&tmem, buffer, size, Perm_R); + + if (R_SUCCEEDED(rc)) { + rc = nsGetReadOnlyApplicationControlDataInterface(&srv); + if (R_SUCCEEDED(rc)) { + rc = _nsListApplicationTitleIcon2(&srv, a, application_ids, count, &tmem, 13); + serviceClose(&srv); + } + } + + tmemClose(&tmem); + + return rc; +} + Result nsListApplicationIcon(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size) { if (hosversionBefore(8,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);