Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions nx/include/switch/services/ns.h
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,33 @@ 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 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.
Expand Down
93 changes: 85 additions & 8 deletions nx/source/services/ns.c
Original file line number Diff line number Diff line change
Expand Up @@ -980,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(Service* srv, AsyncValue *a, NsApplicationControlSource source, const u64 *application_ids, s32 count, TransferMemory *tmem, u32 cmd_id) {
const struct {
u8 source;
u8 pad[7];
Expand All @@ -992,7 +989,27 @@ 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,
Result 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);

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,
Expand All @@ -1006,7 +1023,6 @@ static Result _nsListApplicationTitleIcon(AsyncValue *a, NsApplicationControlSou
if (R_SUCCEEDED(rc))
eventLoadRemote(&a->event, event, false);

serviceClose(&srv);
return rc;
}

Expand All @@ -1016,23 +1032,84 @@ 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(&srv, a, source, application_ids, count, &tmem, 407);
serviceClose(&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(&srv, a, source, application_ids, count, &tmem, 10);
serviceClose(&srv);
}
}

tmemClose(&tmem);

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);

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(&srv, a, source, application_ids, count, &tmem, 408);
serviceClose(&srv);
}
}
tmemClose(&tmem);

return rc;
Expand Down