Added support for AppletApplication. Added AppletApplicationExitReason. Added AppletApplicationLaunchProperty and AppletApplicationLaunchRequestInfo. Added appletCreateApplication, appletPopLaunchRequestedApplication, appletCreateSystemApplication, appletPopFloatingApplicationForDevelopment, and appletOpenMainApplication. Minor internal changes + updated docs.

This commit is contained in:
yellows8 2019-08-18 17:29:26 -04:00
parent 758db03ca4
commit f1dfb2c23b
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
2 changed files with 735 additions and 32 deletions

View File

@ -126,6 +126,17 @@ typedef enum {
LibAppletExitReason_Unexpected = 10,
} LibAppletExitReason;
/// AppletApplicationExitReason
typedef enum {
AppletApplicationExitReason_Normal = 0,
AppletApplicationExitReason_Unknown1 = 1,
AppletApplicationExitReason_Unknown2 = 2,
AppletApplicationExitReason_Unknown3 = 3,
AppletApplicationExitReason_Unknown4 = 4,
AppletApplicationExitReason_Unknown5 = 5,
AppletApplicationExitReason_Unexpected = 100,
} AppletApplicationExitReason;
/// ThemeColorType
typedef enum {
AppletThemeColorType_Default = 0,
@ -214,6 +225,13 @@ typedef struct {
LibAppletExitReason exitreason; ///< Set by \ref appletHolderJoin using the output from cmd GetResult, see \ref LibAppletExitReason.
} AppletHolder;
/// IApplicationAccessor container.
typedef struct {
Service s; ///< IApplicationAccessor
Event StateChangedEvent; ///< Output from GetAppletStateChangedEvent, autoclear=false.
AppletApplicationExitReason exitreason; ///< Set by \ref appletApplicationJoin using the output from cmd GetResult, see \ref AppletApplicationExitReason.
} AppletApplication;
/// Used by \ref appletInitialize with __nx_applet_AppletAttribute for cmd OpenLibraryAppletProxy (AppletType_LibraryApplet), on [3.0.0+]. The default for this struct is all-zero.
typedef struct {
u8 flag; ///< Flag. When non-zero, two state fields are set to 1.
@ -261,6 +279,23 @@ typedef struct {
u8 unused[0x14]; ///< Unused. Default is 0.
} AppletApplicationAttribute;
/// ApplicationLaunchProperty
typedef struct {
u64 titleID; ///< Application titleID.
u32 version; ///< Application title-version.
u8 app_storageId; ///< FsStorageId for the Application base title.
u8 update_storageId; ///< FsStorageId for the Application update title.
u8 unk_xa; ///< Unknown.
u8 pad; ///< Padding.
} AppletApplicationLaunchProperty;
/// ApplicationLaunchRequestInfo
typedef struct {
u32 unk_x0; ///< Unknown.
u32 unk_x4; ///< Unknown.
u8 unk_x8[0x8]; ///< Unknown.
} AppletApplicationLaunchRequestInfo;
/// AppletResourceUsageInfo, from \ref appletGetAppletResourceUsageInfo.
typedef struct {
u32 counter0; ///< Unknown counter.
@ -1397,6 +1432,191 @@ Result appletShouldSleepOnBoot(bool *out);
*/
Result appletGetHdcpAuthenticationFailedEvent(Event *out_event);
// IApplicationCreator
/**
* @brief Creates an Application.
* @note Only available with AppletType_SystemApplet.
* @param[out] a \ref AppletApplication
* @param[in] titleID Application titleID.
*/
Result appletCreateApplication(AppletApplication *a, u64 titleID);
/**
* @brief Pops a \ref AppletApplication for a requested Application launch.
* @note Only available with AppletType_SystemApplet.
* @param[out] a \ref AppletApplication
*/
Result appletPopLaunchRequestedApplication(AppletApplication *a);
/**
* @brief Creates a SystemApplication.
* @note Only available with AppletType_SystemApplet.
* @param[out] a \ref AppletApplication
* @param[in] titleID SystemApplication titleID.
*/
Result appletCreateSystemApplication(AppletApplication *a, u64 titleID);
/**
* @brief PopFloatingApplicationForDevelopment.
* @note Only available with AppletType_SystemApplet. Should not be used if no FloatingApplication is available.
* @param[out] a \ref AppletApplication
*/
Result appletPopFloatingApplicationForDevelopment(AppletApplication *a);
/**
* @brief Close an \ref AppletApplication.
* @param a \ref AppletApplication
*/
void appletApplicationClose(AppletApplication *a);
/**
* @brief Returns whether the AppletApplication object was initialized.
* @param a \ref AppletApplication
*/
bool appletApplicationActive(AppletApplication *a);
/**
* @brief Starts the Application.
* @param a \ref AppletApplication
*/
Result appletApplicationStart(AppletApplication *a);
/**
* @brief Requests the Application to exit.
* @param a \ref AppletApplication
*/
Result appletApplicationRequestExit(AppletApplication *a);
/**
* @brief Terminate the Application.
* @param a \ref AppletApplication
*/
Result appletApplicationTerminate(AppletApplication *a);
/**
* @brief Waits for the Application to exit.
* @param a \ref AppletApplication
*/
void appletApplicationJoin(AppletApplication *a);
/**
* @brief Waits on the Application StateChangedEvent with timeout=0, and returns whether it was successful.
* @param a \ref AppletApplication
*/
bool appletApplicationCheckFinished(AppletApplication *a);
/**
* @brief Gets the \ref AppletApplicationExitReason set by \ref appletApplicationJoin.
* @param a \ref AppletApplication
*/
AppletApplicationExitReason appletApplicationGetExitReason(AppletApplication *a);
/**
* @brief RequestForApplicationToGetForeground.
* @param a \ref AppletApplication
*/
Result appletApplicationRequestForApplicationToGetForeground(AppletApplication *a);
/**
* @brief Gets the titleID for the Application.
* @param a \ref AppletApplication
* @param[out] titleID Output Application titleID.
*/
Result appletApplicationGetApplicationId(AppletApplication *a, u64 *titleID);
/**
* @brief Pushes a LaunchParameter AppletStorage to the Application.
* @note This uses \ref appletStorageClose automatically.
* @param[in] s Input storage.
* @param kind \ref AppletLaunchParameterKind
*/
Result appletApplicationPushLaunchParameter(AppletApplication *a, AppletLaunchParameterKind kind, AppletStorage* s);
/**
* @brief Gets the \ref NacpStruct for the Application.
* @param a \ref AppletApplication
* @param[out] nacp \ref NacpStruct
*/
Result appletApplicationGetApplicationControlProperty(AppletApplication *a, NacpStruct *nacp);
/**
* @brief Gets the \ref AppletApplicationLaunchProperty for the Application.
* @note Only available on [2.0.0+]. Not usable when the AppletId is ::AppletId_starter.
* @param a \ref AppletApplication
* @param[out] out \ref AppletApplicationLaunchProperty
*/
Result appletApplicationGetApplicationLaunchProperty(AppletApplication *a, AppletApplicationLaunchProperty *out);
/**
* @brief Gets the \ref AppletApplicationLaunchRequestInfo for the Application.
* @note Only available on [6.0.0+].
* @param a \ref AppletApplication
* @param[out] out \ref AppletApplicationLaunchRequestInfo
*/
Result appletApplicationGetApplicationLaunchRequestInfo(AppletApplication *a, AppletApplicationLaunchRequestInfo *out);
/**
* @brief SetUsers for the Application.
* @note Only available on [6.0.0+].
* @param a \ref AppletApplication
* @param[in] userIDs Input array of userIDs.
* @param[in] count Size of the userID array in entries, must be <=ACC_USER_LIST_SIZE.
* @param[in] flag When this flag is true, this just clears the users_available state flag to 0 and returns.
*/
Result appletApplicationSetUsers(AppletApplication *a, const u128 *userIDs, s32 count, bool flag);
/**
* @brief CheckRightsEnvironmentAvailable.
* @note Only available on [6.0.0+].
* @param a \ref AppletApplication
* @param[out] out Output flag.
*/
Result appletApplicationCheckRightsEnvironmentAvailable(AppletApplication *a, bool *out);
/**
* @brief GetNsRightsEnvironmentHandle.
* @note Only available on [6.0.0+].
* @param a \ref AppletApplication
* @param[out] handle Output NsRightsEnvironmentHandle.
*/
Result appletApplicationGetNsRightsEnvironmentHandle(AppletApplication *a, u64 *handle);
/**
* @brief Gets an array of userIDs for the Application DesirableUids.
* @note Only available on [6.0.0+].
* @note qlaunch only uses 1 userID with this.
* @param a \ref AppletApplication
* @param[out] userIDs Output array of userIDs.
* @param[in] count Size of the userID array in entries, must be at least the size stored in state.
* @param[out] total_out Total output entries.
*/
Result appletApplicationGetDesirableUids(AppletApplication *a, u128 *userIDs, s32 count, s32 *total_out);
/**
* @brief ReportApplicationExitTimeout.
* @note Only available on [6.0.0+].
* @param a \ref AppletApplication
*/
Result appletApplicationReportApplicationExitTimeout(AppletApplication *a);
/**
* @brief Sets the \ref AppletApplicationAttribute for the Application.
* @note Only available on [8.0.0+].
* @param a \ref AppletApplication
* @param[in] attr \ref AppletApplicationAttribute
*/
Result appletApplicationSetApplicationAttribute(AppletApplication *a, const AppletApplicationAttribute *attr);
/**
* @brief Gets whether the savedata specified by the input titleID is accessible.
* @note Only available on [8.0.0+].
* @param a \ref AppletApplication
* @param[in] titleID titleID for the savedata.
* @param[out] out Output flag.
*/
Result appletApplicationHasSaveDataAccessPermission(AppletApplication *a, u64 titleID, bool *out);
// ILibraryAppletSelfAccessor
/**
@ -1572,7 +1792,7 @@ Result appletRequestExitToSelf(void);
* @brief Gets an array of userIDs for the MainApplet AvailableUsers.
* @note Only available with AppletType_LibraryApplet on [6.0.0+].
* @param[out] userIDs Output array of userIDs.
* @param[in] count Size of the userID array, must be at least ACC_USER_LIST_SIZE.
* @param[in] count Size of the userID array in entries, must be at least ACC_USER_LIST_SIZE.
* @param[out] flag When true, this indicates that no users are available.
* @param[out] total_out Total output entries. This is -1 when flag is true.
*/
@ -1706,6 +1926,13 @@ Result appletGetHomeButtonDoubleClickEnabled(bool *out);
// IDebugFunctions
/**
* @brief Open an \ref AppletApplication for the currently running Application.
* @note Should not be used when no Application is running.
* @param[out] a \ref AppletApplication
*/
Result appletOpenMainApplication(AppletApplication *a);
/**
* @brief Perform SystemButtonPressing with the specified \ref AppletSystemButtonType.
* @param[in] type \ref AppletSystemButtonType

View File

@ -1083,6 +1083,74 @@ static Result _appletCmdNoInOutStorage(Service* srv, AppletStorage* s, u64 cmd_i
return _appletGetSession(srv, &s->s, cmd_id);
}
static Result _appletCmdSendBufNoOut(Service* srv, const void* buffer, size_t size, u64 cmd_id) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendBuffer(&c, buffer, size, BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = cmd_id;
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
static Result _appletCmdNoInRecvBuf(Service* srv, void* buffer, size_t size, u64 cmd_id) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, buffer, size, BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = cmd_id;
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
static Result _appletGetLibraryAppletInfo(Service* srv, LibAppletInfo *info, u64 cmd_id) {
IpcCommand c;
ipcInitialize(&c);
@ -4245,6 +4313,440 @@ Result appletGetHdcpAuthenticationFailedEvent(Event *out_event) {
return _appletGetEvent(&g_appletIGlobalStateController, out_event, 15, false);
}
// IApplicationCreator
static Result _appletApplicationCreateState(AppletApplication *a) {
Result rc=0;
rc = _appletGetEvent(&a->s, &a->StateChangedEvent, 0, false);//GetAppletStateChangedEvent
return rc;
}
static Result _appletApplicationCreate(AppletApplication *a, Service* srv, u64 cmd_id) {
Result rc=0;
memset(a, 0, sizeof(AppletApplication));
rc = _appletGetSession(srv, &a->s, cmd_id);
if (R_SUCCEEDED(rc)) rc = _appletApplicationCreateState(a);
return rc;
}
static Result _appletApplicationCreateIn64(AppletApplication *a, Service* srv, u64 cmd_id, u64 val) {
Result rc=0;
memset(a, 0, sizeof(AppletApplication));
rc = _appletGetSessionIn64(srv, &a->s, cmd_id, val);
if (R_SUCCEEDED(rc)) rc = _appletApplicationCreateState(a);
return rc;
}
Result appletCreateApplication(AppletApplication *a, u64 titleID) {
if (__nx_applet_type != AppletType_SystemApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletApplicationCreateIn64(a, &g_appletIApplicationCreator, 0, titleID);
}
Result appletPopLaunchRequestedApplication(AppletApplication *a) {
if (__nx_applet_type != AppletType_SystemApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletApplicationCreate(a, &g_appletIApplicationCreator, 1);
}
Result appletCreateSystemApplication(AppletApplication *a, u64 titleID) {
if (__nx_applet_type != AppletType_SystemApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletApplicationCreateIn64(a, &g_appletIApplicationCreator, 10, titleID);
}
Result appletPopFloatingApplicationForDevelopment(AppletApplication *a) {
if (__nx_applet_type != AppletType_SystemApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletApplicationCreate(a, &g_appletIApplicationCreator, 100);
}
void appletApplicationClose(AppletApplication *a) {
eventClose(&a->StateChangedEvent);
serviceClose(&a->s);
memset(a, 0, sizeof(AppletApplication));
}
bool appletApplicationActive(AppletApplication *a) {
return serviceIsActive(&a->s);
}
Result appletApplicationStart(AppletApplication *a) {
Result rc=0;
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
rc = _appletCmdNoIO(&a->s, 10);//Start
return rc;
}
Result appletApplicationRequestExit(AppletApplication *a) {
Result rc=0;
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
rc = _appletCmdNoIO(&a->s, 20);//RequestExit
return rc;
}
Result appletApplicationTerminate(AppletApplication *a) {
Result rc=0;
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
rc = _appletCmdNoIO(&a->s, 25);//Terminate
return rc;
}
void appletApplicationJoin(AppletApplication *a) {
Result rc=0;
AppletApplicationExitReason res = AppletApplicationExitReason_Normal;
u32 desc=0;
eventWait(&a->StateChangedEvent, U64_MAX);
rc = _appletCmdNoIO(&a->s, 30);//GetResult
if (R_FAILED(rc)) {
res = AppletApplicationExitReason_Unexpected;
if (R_MODULE(rc) == 128) {
desc = R_DESCRIPTION(rc);
if (desc >= 35 && desc < 40) res = AppletApplicationExitReason_Unknown5;
else if (desc >= 31 && desc < 40) res = AppletApplicationExitReason_Unknown1;
else if (desc == 23) res = AppletApplicationExitReason_Unknown2;
else if (desc >= 40 && desc < 45) res = AppletApplicationExitReason_Unknown3;
else if (desc == 51) res = AppletApplicationExitReason_Unknown4;
}
}
a->exitreason = res;
}
bool appletApplicationCheckFinished(AppletApplication *a) {
return R_SUCCEEDED(eventWait(&a->StateChangedEvent, 0));
}
AppletApplicationExitReason appletApplicationGetExitReason(AppletApplication *a) {
return a->exitreason;
}
Result appletApplicationRequestForApplicationToGetForeground(AppletApplication *a) {
Result rc=0;
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
rc = _appletCmdNoIO(&a->s, 101);//RequestForApplicationToGetForeground
return rc;
}
Result appletApplicationGetApplicationId(AppletApplication *a, u64 *titleID) {
Result rc=0;
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdNoInOut64(&a->s, titleID, 120);//GetApplicationId
return rc;
}
Result appletApplicationPushLaunchParameter(AppletApplication *a, AppletLaunchParameterKind kind, AppletStorage* s) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (!serviceIsActive(&s->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
IpcCommand c;
ipcInitialize(&c);
serviceSendObject(&s->s, &c);
struct {
u64 magic;
u64 cmd_id;
u32 kind;
} *raw;
raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 121;
raw->kind = kind;
Result rc = serviceIpcDispatch(&a->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&a->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
appletStorageClose(s);
return rc;
}
Result appletApplicationGetApplicationControlProperty(AppletApplication *a, NacpStruct *nacp) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletCmdNoInRecvBuf(&a->s, nacp, sizeof(*nacp), 122);//GetApplicationControlProperty
}
Result appletApplicationGetApplicationLaunchProperty(AppletApplication *a, AppletApplicationLaunchProperty *out) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletCmdNoInRecvBuf(&a->s, out, sizeof(*out), 123);//GetApplicationLaunchProperty
}
Result appletApplicationGetApplicationLaunchRequestInfo(AppletApplication *a, AppletApplicationLaunchRequestInfo *out) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 124;
Result rc = serviceIpcDispatch(&a->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
AppletApplicationLaunchRequestInfo out;
} *resp;
serviceIpcParse(&a->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->out;
}
return rc;
}
Result appletApplicationSetUsers(AppletApplication *a, const u128 *userIDs, s32 count, bool flag) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
IpcCommand c;
ipcInitialize(&c);
ipcAddSendBuffer(&c, userIDs, count*sizeof(u128), BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
u8 flag;
} *raw;
raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 130;
raw->flag = flag!=0;
Result rc = serviceIpcDispatch(&a->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&a->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result appletApplicationCheckRightsEnvironmentAvailable(AppletApplication *a, bool *out) {
Result rc=0;
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdNoInOutBool(&a->s, out, 131);//CheckRightsEnvironmentAvailable
return rc;
}
Result appletApplicationGetNsRightsEnvironmentHandle(AppletApplication *a, u64 *handle) {
Result rc=0;
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdNoInOut64(&a->s, handle, 132);//GetNsRightsEnvironmentHandle
return rc;
}
Result appletApplicationGetDesirableUids(AppletApplication *a, u128 *userIDs, s32 count, s32 *total_out) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, userIDs, count*sizeof(u128), BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 140;
Result rc = serviceIpcDispatch(&a->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
s32 total_out;
} *resp;
serviceIpcParse(&a->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out;
}
return rc;
}
Result appletApplicationReportApplicationExitTimeout(AppletApplication *a) {
Result rc=0;
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdNoIO(&a->s, 150);//ReportApplicationExitTimeout
return rc;
}
Result appletApplicationSetApplicationAttribute(AppletApplication *a, const AppletApplicationAttribute *attr) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletCmdSendBufNoOut(&a->s, attr, sizeof(*attr), 160);//SetApplicationAttribute
}
Result appletApplicationHasSaveDataAccessPermission(AppletApplication *a, u64 titleID, bool *out) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 titleID;
} *raw;
raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 170;
raw->titleID = titleID;
Result rc = serviceIpcDispatch(&a->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u8 out;
} *resp;
serviceIpcParse(&a->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->out!=0;
}
return rc;
}
// ILibraryAppletSelfAccessor
Result appletPopInData(AppletStorage *s) {
@ -4330,37 +4832,7 @@ Result appletGetMainAppletApplicationControlProperty(NacpStruct *nacp) {
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, nacp, sizeof(*nacp), BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&g_appletILibraryAppletSelfAccessor, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 15;
Result rc = serviceIpcDispatch(&g_appletILibraryAppletSelfAccessor);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&g_appletILibraryAppletSelfAccessor, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
return _appletCmdNoInRecvBuf(&g_appletILibraryAppletSelfAccessor, nacp, sizeof(*nacp), 15);
}
Result appletGetMainAppletStorageId(FsStorageId *storageId) {
@ -4787,6 +5259,10 @@ Result appletGetHomeButtonDoubleClickEnabled(bool *out) {
// IDebugFunctions
Result appletOpenMainApplication(AppletApplication *a) {
return _appletApplicationCreate(a, &g_appletIDebugFunctions, 1);
}
Result appletPerformSystemButtonPressing(AppletSystemButtonType type) {
return _appletCmdInU32(&g_appletIDebugFunctions, type, 10);
}