Use an enum for appletSetScreenShotPermission with info from wiki. Improved applet docs. Use _appletIsApplication() instead of _appletIsRegularApplication() in appletQueryApplicationPlayStatistics/appletQueryApplicationPlayStatisticsByUid. Added appletGetGpuErrorDetectedSystemEvent. Added support for the [7.0.0+] CreateApplication*ToStartForQuest cmds.

This commit is contained in:
yellows8 2019-07-13 10:44:03 -04:00
parent 0e724040ad
commit 40d7e0de51
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
2 changed files with 139 additions and 14 deletions

View File

@ -106,6 +106,13 @@ typedef enum {
AppletThemeColorType_Unknown3 = 3, AppletThemeColorType_Unknown3 = 3,
} AppletThemeColorType; } AppletThemeColorType;
/// Permission values for \ref appletSetScreenShotPermission.
typedef enum {
AppletScreenShotPermission_Inherit = 0, ///< Inherit from parent applet.
AppletScreenShotPermission_Enable = 1, ///< Enable.
AppletScreenShotPermission_Disable = 2, ///< Disable.
} AppletScreenShotPermission;
/// applet hook function. /// applet hook function.
typedef void (*AppletHookFn)(AppletHookType hook, void* param); typedef void (*AppletHookFn)(AppletHookType hook, void* param);
@ -138,10 +145,19 @@ typedef struct {
/// Attributes for launching applications for Quest. /// Attributes for launching applications for Quest.
typedef struct { typedef struct {
u32 unk_x0; u32 unk_x0; ///< See AppletApplicationAttribute::unk_x0.
u32 unk_x4; u32 unk_x4; ///< See AppletApplicationAttribute::unk_x4.
float volume; ///< [7.0.0+] See AppletApplicationAttribute::volume.
} AppletApplicationAttributeForQuest; } AppletApplicationAttributeForQuest;
/// ApplicationAttribute
typedef struct {
u32 unk_x0; ///< Default is 0 for non-Quest. Only used when non-zero: unknown value in seconds.
u32 unk_x4; ///< Default is 0 for non-Quest. Only used when non-zero: unknown value in seconds.
float volume; ///< Audio volume. Must be in the range of 0.0f-1.0f. The default is 1.0f.
u8 unused[0x14]; ///< Unused. Default is 0.
} AppletApplicationAttribute;
/// Initialize applet, called automatically during app startup. /// Initialize applet, called automatically during app startup.
Result appletInitialize(void); Result appletInitialize(void);
@ -180,6 +196,7 @@ Result appletRequestLaunchApplication(u64 titleID, AppletStorage* s);
/** /**
* @brief Requests to launch the specified application, for kiosk systems. * @brief Requests to launch the specified application, for kiosk systems.
* @note Only available with AppletType_*Application on 3.0.0+. * @note Only available with AppletType_*Application on 3.0.0+.
* @note Identical to \ref appletRequestLaunchApplication, except this allows the user to specify the attribute fields instead of the defaults being used.
* @param[in] titleID Application titleID * @param[in] titleID Application titleID
* @param s Optional AppletStorage object, can be NULL. This is automatically closed. When NULL on pre-4.0.0, this will internally create a tmp storage with size 0 for use with the cmd. This is the storage available to the launched application via \ref appletPopLaunchParameter with ::AppletLaunchParameterKind_Application. * @param s Optional AppletStorage object, can be NULL. This is automatically closed. When NULL on pre-4.0.0, this will internally create a tmp storage with size 0 for use with the cmd. This is the storage available to the launched application via \ref appletPopLaunchParameter with ::AppletLaunchParameterKind_Application.
* @param[in] attr Kiosk application attributes. * @param[in] attr Kiosk application attributes.
@ -207,7 +224,7 @@ Result appletSetGamePlayRecordingState(bool state);
/// Initializes video recording. This allocates a 0x6000000-byte buffer for the TransferMemory, cleanup is handled automatically during app exit in \ref appletExit. /// Initializes video recording. This allocates a 0x6000000-byte buffer for the TransferMemory, cleanup is handled automatically during app exit in \ref appletExit.
/// Only available with AppletType_Application on 3.0.0+, hence errors from this can be ignored. /// Only available with AppletType_Application on 3.0.0+, hence errors from this can be ignored.
/// Video recording is only fully available system-side with 4.0.0+. /// Video recording is only fully available system-side with 4.0.0+.
/// Only usable when running under a title which supports video recording. /// Only usable when running under a title which supports video recording. Using this is only needed when the host title control.nacp has VideoCaptureMode set to Enabled, with Automatic appletInitializeGamePlayRecording is not needed.
Result appletInitializeGamePlayRecording(void); Result appletInitializeGamePlayRecording(void);
/** /**
@ -241,6 +258,15 @@ Result appletQueryApplicationPlayStatistics(PdmApplicationPlayStatistics *stats,
*/ */
Result appletQueryApplicationPlayStatisticsByUid(u128 userID, PdmApplicationPlayStatistics *stats, const u64 *titleIDs, s32 count, s32 *total_out); Result appletQueryApplicationPlayStatisticsByUid(u128 userID, PdmApplicationPlayStatistics *stats, const u64 *titleIDs, s32 count, s32 *total_out);
/**
* @brief Gets an Event which is signaled for GpuErrorDetected.
* @note Only available with AppletType_*Application on [8.0.0+].
* @note The Event must be closed by the user once finished with it.
* @note Official sw waits on this Event from a seperate thread, triggering an abort when it's signaled.
* @param[out] event_out Output Event with autoclear=false.
*/
Result appletGetGpuErrorDetectedSystemEvent(Event *out_event);
/** /**
* @brief Delay exiting until \ref appletUnlockExit is called, with a 15 second timeout once exit is requested. * @brief Delay exiting until \ref appletUnlockExit is called, with a 15 second timeout once exit is requested.
* @note When exit is requested \ref appletMainLoop will return false, hence any main-loop using appletMainLoop will exit. This allows the app to handle cleanup post-main-loop instead of being force-terminated. * @note When exit is requested \ref appletMainLoop will return false, hence any main-loop using appletMainLoop will exit. This allows the app to handle cleanup post-main-loop instead of being force-terminated.
@ -254,9 +280,9 @@ Result appletUnlockExit(void);
/** /**
* @brief Controls whether screenshot-capture is allowed. * @brief Controls whether screenshot-capture is allowed.
* @param val 0 = disable, 1 = enable. * @param permission \ref AppletScreenShotPermission
*/ */
Result appletSetScreenShotPermission(s32 val); Result appletSetScreenShotPermission(AppletScreenShotPermission permission);
Result appletSetScreenShotImageOrientation(s32 val); Result appletSetScreenShotImageOrientation(s32 val);

View File

@ -1084,11 +1084,11 @@ static Result _appletCreateApplicationAndPushAndRequestToStartForQuest(u64 title
return rc; return rc;
} }
static Result _appletCreateApplicationAndRequestToStart(u64 titleID) { //4.0.0+ static Result _appletCreateApplicationAndRequestToStart(u64 titleID) { // [4.0.0+]
return _appletCmdInU64(&g_appletIFunctions, titleID, 12); return _appletCmdInU64(&g_appletIFunctions, titleID, 12);
} }
static Result _appletCreateApplicationAndRequestToStartForQuest(u64 titleID, const AppletApplicationAttributeForQuest *attr) { //4.0.0+ static Result _appletCreateApplicationAndRequestToStartForQuest(u64 titleID, const AppletApplicationAttributeForQuest *attr) { // [4.0.0+]
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
@ -1125,6 +1125,80 @@ static Result _appletCreateApplicationAndRequestToStartForQuest(u64 titleID, con
return rc; return rc;
} }
static Result _appletCreateApplicationWithAttributeAndPushAndRequestToStartForQuest(u64 titleID, AppletStorage* s, const AppletApplicationAttribute *attr) { // [7.0.0+]
IpcCommand c;
ipcInitialize(&c);
serviceSendObject(&s->s, &c);
ipcAddSendBuffer(&c, attr, sizeof(*attr), BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
u64 titleID;
} *raw;
raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 14;
raw->titleID = titleID;
Result rc = serviceIpcDispatch(&g_appletIFunctions);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
static Result _appletCreateApplicationWithAttributeAndRequestToStartForQuest(u64 titleID, const AppletApplicationAttribute *attr) { // [7.0.0+]
IpcCommand c;
ipcInitialize(&c);
ipcAddSendBuffer(&c, attr, sizeof(*attr), BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
u64 titleID;
} *raw;
raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 15;
raw->titleID = titleID;
Result rc = serviceIpcDispatch(&g_appletIFunctions);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result appletRequestLaunchApplication(u64 titleID, AppletStorage* s) { Result appletRequestLaunchApplication(u64 titleID, AppletStorage* s) {
AppletStorage tmpstorage={0}; AppletStorage tmpstorage={0};
Result rc=0; Result rc=0;
@ -1160,6 +1234,7 @@ Result appletRequestLaunchApplication(u64 titleID, AppletStorage* s) {
Result appletRequestLaunchApplicationForQuest(u64 titleID, AppletStorage* s, const AppletApplicationAttributeForQuest *attr) { Result appletRequestLaunchApplicationForQuest(u64 titleID, AppletStorage* s, const AppletApplicationAttributeForQuest *attr) {
AppletStorage tmpstorage={0}; AppletStorage tmpstorage={0};
AppletApplicationAttribute appattr={0};
Result rc=0; Result rc=0;
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
@ -1173,12 +1248,26 @@ Result appletRequestLaunchApplicationForQuest(u64 titleID, AppletStorage* s, con
if (R_FAILED(rc)) return rc; if (R_FAILED(rc)) return rc;
} }
if (hosversionAtLeast(7,0,0)) {
appattr.unk_x0 = attr->unk_x0;
appattr.unk_x4 = attr->unk_x4;
appattr.volume = attr->volume;
}
if (hosversionAtLeast(4,0,0) && s==NULL) { if (hosversionAtLeast(4,0,0) && s==NULL) {
rc = _appletCreateApplicationAndRequestToStartForQuest(titleID, attr); if (hosversionAtLeast(7,0,0))
rc = _appletCreateApplicationWithAttributeAndRequestToStartForQuest(titleID, &appattr);
else
rc = _appletCreateApplicationAndRequestToStartForQuest(titleID, attr);
} }
else { else {
if (hosversionBefore(3,0,0)) rc = MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (hosversionBefore(3,0,0)) rc = MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
if (R_SUCCEEDED(rc)) rc = _appletCreateApplicationAndPushAndRequestToStartForQuest(titleID, s, attr); if (R_SUCCEEDED(rc)) {
if (hosversionAtLeast(7,0,0))
rc = _appletCreateApplicationWithAttributeAndPushAndRequestToStartForQuest(titleID, s, &appattr);
else
rc = _appletCreateApplicationAndPushAndRequestToStartForQuest(titleID, s, attr);
}
} }
if (s) appletStorageClose(s); if (s) appletStorageClose(s);
@ -1450,7 +1539,7 @@ Result appletQueryApplicationPlayStatistics(PdmApplicationPlayStatistics *stats,
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
if (!serviceIsActive(&g_appletSrv) || !_appletIsRegularApplication()) if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(5,0,0)) if (hosversionBefore(5,0,0))
@ -1494,7 +1583,7 @@ Result appletQueryApplicationPlayStatisticsByUid(u128 userID, PdmApplicationPlay
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
if (!serviceIsActive(&g_appletSrv) || !_appletIsRegularApplication()) if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0)) if (hosversionBefore(6,0,0))
@ -1536,6 +1625,16 @@ Result appletQueryApplicationPlayStatisticsByUid(u128 userID, PdmApplicationPlay
return rc; return rc;
} }
Result appletGetGpuErrorDetectedSystemEvent(Event *out_event) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletGetEvent(&g_appletIFunctions, out_event, 130, false);
}
// IOverlayFunctions // IOverlayFunctions
Result appletBeginToWatchShortHomeButtonMessage(void) { Result appletBeginToWatchShortHomeButtonMessage(void) {
@ -1775,21 +1874,21 @@ static Result _appletWaitLibraryAppletLaunchableEvent(void) {
return rc; return rc;
} }
Result appletSetScreenShotPermission(s32 val) { Result appletSetScreenShotPermission(AppletScreenShotPermission permission) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
struct { struct {
u64 magic; u64 magic;
u64 cmd_id; u64 cmd_id;
s32 val; s32 permission;
} *raw; } *raw;
raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw)); raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 10; raw->cmd_id = 10;
raw->val = val; raw->permission = permission;
Result rc = serviceIpcDispatch(&g_appletISelfController); Result rc = serviceIpcDispatch(&g_appletISelfController);