diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index 163460bc..603419e9 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -478,6 +478,32 @@ Result nsGetApplicationControlData(NsApplicationControlSource source, u64 applic */ Result nsRequestDownloadApplicationControlData(AsyncResult *a, u64 application_id); +/** + * @brief ListApplicationTitle + * @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 [8.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 nsListApplicationTitle(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. + * @note Only available on [8.0.0+]. + * @param[out] a \ref AsyncValue + * @param[in] source Source. + * @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: 0x4 + count*sizeof(u64) + count*sizeof(\ref NsApplicationControlData::icon) + count*sizeof(u64) + sizeof(\ref NsApplicationControlData). + */ +Result nsListApplicationIcon(AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, void* buffer, size_t size); + /** * @brief RequestCheckGameCardRegistration * @note \ref nifmInitialize must be used prior to this. Before using the cmd, this calls \ref nifmIsAnyInternetRequestAccepted with the output from \ref nifmGetClientId, an error is returned when that returns false. diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 177575c7..cddaa23a 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -470,6 +470,59 @@ Result nsRequestDownloadApplicationControlData(AsyncResult *a, u64 application_i return _nsCmdInU64OutAsyncResult(&g_nsAppManSrv, 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+] + const struct { + u8 source; + u8 pad[7]; + u64 size; + } in = { source, {0}, tmem->size }; + + memset(a, 0, sizeof(*a)); + Handle event = INVALID_HANDLE; + Result rc = serviceDispatchIn(&g_nsAppManSrv, 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); + 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); + + Result rc=0; + TransferMemory tmem={0}; + + rc = tmemCreateFromMemory(&tmem, buffer, size, Perm_R); + if (R_SUCCEEDED(rc)) rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 407); + 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}; + + rc = tmemCreateFromMemory(&tmem, buffer, size, Perm_R); + if (R_SUCCEEDED(rc)) rc = _nsListApplicationTitleIcon(a, source, application_ids, count, &tmem, 408); + tmemClose(&tmem); + + return rc; +} + Result nsRequestCheckGameCardRegistration(AsyncResult *a, u64 application_id) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);