libnx/nx/source/services/applet.c

2952 lines
121 KiB
C

#include <string.h>
#include "service_guard.h"
#include "arm/counter.h"
#include "services/fatal.h"
#include "services/applet.h"
#include "runtime/env.h"
#include "runtime/hosversion.h"
__attribute__((weak)) u32 __nx_applet_type = AppletType_Default;
__attribute__((weak)) bool __nx_applet_auto_notifyrunning = true;
__attribute__((weak)) AppletAttribute __nx_applet_AppletAttribute;
/// When set, controls the PerformanceConfiguration passed to apmSetPerformanceConfiguration during app startup, where the array index is the PerformanceMode.
__attribute__((weak)) u32 __nx_applet_PerformanceConfiguration[2] = {/*0x92220008*//*0x20004*//*0x92220007*/0, 0};
//// Controls whether to use applet exit cmds during \ref appletExit. 0 (default): Only run exit cmds when running under a NSO. 1: Use exit cmds regardless. >1: Skip exit cmds.
__attribute__((weak)) u32 __nx_applet_exit_mode = 0;
static Service g_appletSrv;
static Service g_appletProxySession;
static bool g_appletLeftInitialized;
static bool g_appletExitProcessFlag;
static Result g_appletExitProcessResult;
// From Get*Functions.
static Service g_appletIAppletCommonFunctions;
static Service g_appletIFunctions;
static Service g_appletIGlobalStateController;
static Service g_appletIApplicationCreator;
static Service g_appletILibraryAppletSelfAccessor;
static Service g_appletIProcessWindingController;
static Service g_appletILibraryAppletCreator;
static Service g_appletICommonStateGetter;
static Service g_appletISelfController;
static Service g_appletIWindowController;
static Service g_appletIAudioController;
static Service g_appletIDisplayController;
static Service g_appletIDebugFunctions;
static Event g_appletMessageEvent;
static u64 g_appletResourceUserId = 0;
static u8 g_appletOperationMode;
static u32 g_appletPerformanceMode;
static u8 g_appletFocusState;
static bool g_appletNotifiedRunning = 0;
static AppletHookCookie g_appletFirstHook;
static TransferMemory g_appletRecordingTmem;
static u32 g_appletRecordingInitialized;
static TransferMemory g_appletCopyrightTmem;
static bool g_appletCopyrightInitialized;
static Event g_appletSuspendedTickEvent;
static u64 g_appletInitTickBase;
static u64 g_appletSuspendedTick;
static bool g_appletSuspendedTickInitialized;
static Event g_appletLibraryAppletLaunchableEvent;
static AppletThemeColorType g_appletThemeColorType = AppletThemeColorType_Default;
static ApmCpuBoostMode g_appletCpuBoostMode = ApmCpuBoostMode_Disabled;
static AppletInfo g_appletInfo;
static bool g_appletInfoInitialized;
static Result _appletCmdGetHandle(Service* srv, Handle* handle_out, u32 cmd_id);
static Result _appletCmdGetEvent(Service* srv, Event* out_event, bool autoclear, u32 cmd_id);
static Result _appletCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id);
static Result _appletOpenLibraryAppletProxy(Service* srv_out, Handle prochandle, const AppletAttribute *attr);
static Result _appletGetSessionProxy(Service* srv_out, Handle prochandle, u32 cmd_id);
static Result _appletGetAppletResourceUserId(u64 *out);
static Result _appletGetCurrentFocusState(u8 *out);
static Result _appletSetFocusHandlingMode(bool inval0, bool inval1, bool inval2);
static Result _appletSetOutOfFocusSuspendingEnabled(bool inval);
static Result _appletReceiveMessage(u32 *out);
static Result _appletAcquireForegroundRights(void);
static Result _appletGetOperationMode(u8 *out);
static Result _appletGetPerformanceMode(u32 *out);
static Result _appletSetOperationModeChangedNotification(bool flag);
static Result _appletSetPerformanceModeChangedNotification(bool flag);
static Result _appletSelfExit(void);
static Result _appletExitProcessAndReturn(void);
static Result _appletGetAccumulatedSuspendedTickValue(u64 *tick);
static Result _appletGetAccumulatedSuspendedTickChangedEvent(Event *out_event);
static Result _appletGetLaunchReason(AppletProcessLaunchReason *reason);
static Result _appletOpenCallingLibraryApplet(AppletHolder *h);
static Result _appletHolderCreateState(AppletHolder *h, LibAppletMode mode, bool creating_self);
static Result _appletOpenExistingLibraryApplet(AppletHolder *h, Service* srv, u32 cmd_id);
NX_GENERATE_SERVICE_GUARD(applet);
Result _appletInitialize(void) {
AppletAttribute *attr = NULL;
if (g_appletLeftInitialized) {
g_appletLeftInitialized = false;
return 0;
}
if (__nx_applet_type == AppletType_None)
return 0;
if (__nx_applet_type == AppletType_Default || __nx_applet_type == AppletType_Application) {
if (R_FAILED(apmInitialize()))
return MAKERESULT(Module_Libnx, LibnxError_ApmFailedToInitialize);
}
Result rc = 0;
g_appletResourceUserId = 0;
g_appletNotifiedRunning = 0;
g_appletExitProcessFlag = 0;
g_appletRecordingInitialized = 0;
g_appletInfoInitialized = 0;
memset(&g_appletInfo, 0, sizeof(g_appletInfo));
switch (__nx_applet_type) {
case AppletType_Default:
__nx_applet_type = AppletType_Application;
// Fallthrough.
case AppletType_Application:
rc = smGetService(&g_appletSrv, "appletOE");
break;
default:
rc = smGetService(&g_appletSrv, "appletAE");
break;
}
if (R_SUCCEEDED(rc)) {
rc = serviceConvertToDomain(&g_appletSrv);
}
if (R_SUCCEEDED(rc)) {
#define AM_BUSY_ERROR 0x19280
do {
u32 cmd_id;
switch(__nx_applet_type) {
case AppletType_Application: cmd_id = 0; break;
case AppletType_SystemApplet: cmd_id = 100; break;
case AppletType_LibraryApplet: cmd_id = 200; break;
case AppletType_OverlayApplet: cmd_id = 300; break;
case AppletType_SystemApplication: cmd_id = 350; break;
// TODO: Replace error code
default: fatalThrow(MAKERESULT(Module_Libnx, LibnxError_AppletCmdidNotFound));
}
if (__nx_applet_type == AppletType_LibraryApplet && hosversionAtLeast(3,0,0)) {
cmd_id = 201;
attr = &__nx_applet_AppletAttribute;
}
if (attr==NULL)
rc = _appletGetSessionProxy(&g_appletProxySession, CUR_PROCESS_HANDLE, cmd_id);
else
rc = _appletOpenLibraryAppletProxy(&g_appletProxySession, CUR_PROCESS_HANDLE, attr);
if (rc == AM_BUSY_ERROR) {
svcSleepThread(10000000);
}
} while (rc == AM_BUSY_ERROR);
}
// [7.0.0+] GetAppletCommonFunctions
if (R_SUCCEEDED(rc) && hosversionAtLeast(7,0,0)) {
if (__nx_applet_type == AppletType_SystemApplet || __nx_applet_type == AppletType_LibraryApplet || __nx_applet_type == AppletType_OverlayApplet) {
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletIAppletCommonFunctions, __nx_applet_type == AppletType_SystemApplet ? 23 : 21);
}
}
// Get*Functions
if (R_SUCCEEDED(rc) && __nx_applet_type != AppletType_LibraryApplet)
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletIFunctions, 20);
if (R_SUCCEEDED(rc) && __nx_applet_type == AppletType_SystemApplet) {
//GetGlobalStateController
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletIGlobalStateController, 21);
//GetApplicationCreator
if (R_SUCCEEDED(rc))
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletIApplicationCreator, 22);
}
if (R_SUCCEEDED(rc) && __nx_applet_type == AppletType_LibraryApplet) {
//GetLibraryAppletSelfAccessor
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletILibraryAppletSelfAccessor, 20);
//GetProcessWindingController
if (R_SUCCEEDED(rc))
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletIProcessWindingController, 10);
}
// GetLibraryAppletCreator
if (R_SUCCEEDED(rc))
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletILibraryAppletCreator, 11);
// GetCommonStateGetter
if (R_SUCCEEDED(rc))
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletICommonStateGetter, 0);
// GetSelfController
if (R_SUCCEEDED(rc))
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletISelfController, 1);
// GetWindowController
if (R_SUCCEEDED(rc))
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletIWindowController, 2);
// Get AppletResourceUserId.
if (R_SUCCEEDED(rc))
rc = _appletGetAppletResourceUserId(&g_appletResourceUserId);
// GetAudioController
if (R_SUCCEEDED(rc))
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletIAudioController, 3);
// GetDisplayController
if (R_SUCCEEDED(rc))
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletIDisplayController, 4);
// GetDebugFunctions
if (R_SUCCEEDED(rc))
rc = _appletCmdGetSession(&g_appletProxySession, &g_appletIDebugFunctions, 1000);
Result rc2 = _appletGetAccumulatedSuspendedTickChangedEvent(&g_appletSuspendedTickEvent);
if (R_SUCCEEDED(rc2)) {
g_appletInitTickBase = armGetSystemTick();
g_appletSuspendedTick = 0;
g_appletSuspendedTickInitialized = true;
}
// ICommonStateGetter::GetEventHandle
if (R_SUCCEEDED(rc))
rc = _appletCmdGetEvent(&g_appletICommonStateGetter, &g_appletMessageEvent, false, 0);
if (R_SUCCEEDED(rc) && (__nx_applet_type == AppletType_Application))
{
rc = _appletGetCurrentFocusState(&g_appletFocusState);
//Don't enter this msg-loop when g_appletFocusState is already 1, it will hang when applet was previously initialized in the context of the current process for AppletType_Application.
if (R_SUCCEEDED(rc) && g_appletFocusState != AppletFocusState_Focused) {
do {
eventWait(&g_appletMessageEvent, U64_MAX);
u32 msg;
rc = _appletReceiveMessage(&msg);
if (R_FAILED(rc))
{
if (R_VALUE(rc) == 0x680)
continue;
break;
}
if (msg != 0xF)
continue;
rc = _appletGetCurrentFocusState(&g_appletFocusState);
if (R_FAILED(rc))
break;
} while(g_appletFocusState != AppletFocusState_Focused);
}
if (R_SUCCEEDED(rc))
rc = _appletAcquireForegroundRights();
if (R_SUCCEEDED(rc))
rc = appletSetFocusHandlingMode(AppletFocusHandlingMode_SuspendHomeSleep);
}
if (R_SUCCEEDED(rc) && __nx_applet_auto_notifyrunning)
appletNotifyRunning(NULL);
if (R_SUCCEEDED(rc))
rc = _appletGetOperationMode(&g_appletOperationMode);
if (R_SUCCEEDED(rc))
rc = _appletGetPerformanceMode(&g_appletPerformanceMode);
if (R_SUCCEEDED(rc) && __nx_applet_type!=AppletType_Application)
rc = _appletGetCurrentFocusState(&g_appletFocusState);
if (R_SUCCEEDED(rc))
rc = _appletSetOperationModeChangedNotification(1);
if (R_SUCCEEDED(rc))
rc = _appletSetPerformanceModeChangedNotification(1);
// Official apps aren't known to use apmSetPerformanceConfiguration with mode=1.
if (R_SUCCEEDED(rc)) {
u32 i;
for (i=0; i<2; i++)
{
if (__nx_applet_PerformanceConfiguration[i])
rc = apmSetPerformanceConfiguration(i, __nx_applet_PerformanceConfiguration[i]);
if (R_FAILED(rc))
break;
}
}
if (R_SUCCEEDED(rc) && __nx_applet_type == AppletType_LibraryApplet) {
AppletProcessLaunchReason launchreason={0};
Result rc2 = appletGetLibraryAppletInfo(&g_appletInfo.info);
if (R_SUCCEEDED(rc2)) rc2 = _appletGetLaunchReason(&launchreason);
if (R_SUCCEEDED(rc2)) {
g_appletInfo.caller_flag = launchreason.flag!=0;
if (g_appletInfo.caller_flag) rc2 = _appletOpenCallingLibraryApplet(&g_appletInfo.caller);
}
if (R_SUCCEEDED(rc2)) g_appletInfoInitialized = true;
}
return rc;
}
static void _appletInfiniteSleepLoop(void) {
while(1) svcSleepThread(86400000000000ULL);
}
static void NORETURN _appletExitProcess(int result_code) {
appletInitialize();
appletExit();
if (R_SUCCEEDED(g_appletExitProcessResult)) _appletInfiniteSleepLoop();
svcExitProcess();
__builtin_unreachable();
}
static bool _appletIsApplication(void) {
return __nx_applet_type == AppletType_Application || __nx_applet_type == AppletType_SystemApplication;
}
static bool _appletIsRegularApplication(void) {
return __nx_applet_type == AppletType_Application;
}
void _appletCleanup(void) {
if (!g_appletExitProcessFlag) {
if (g_appletRecordingInitialized > 0) {
if (g_appletRecordingInitialized == 2) appletSetGamePlayRecordingState(0);
}
if (__nx_applet_type == AppletType_Application) appletSetFocusHandlingMode(AppletFocusHandlingMode_NoSuspend);
if (g_appletCpuBoostMode != ApmCpuBoostMode_Disabled) appletSetCpuBoostMode(ApmCpuBoostMode_Disabled);
}
if ((envIsNso() && __nx_applet_exit_mode==0) || __nx_applet_exit_mode==1) {
if (_appletIsApplication() ||
__nx_applet_type == AppletType_LibraryApplet) {
if (!g_appletExitProcessFlag) {
g_appletExitProcessFlag = 1;
g_appletLeftInitialized = true;
envSetExitFuncPtr(_appletExitProcess);
return;
}
else {
if (_appletIsApplication())
g_appletExitProcessResult = _appletSelfExit();
if (__nx_applet_type == AppletType_LibraryApplet)
g_appletExitProcessResult = _appletExitProcessAndReturn();
}
}
}
if (g_appletInfoInitialized) {
if (g_appletInfo.caller_flag) appletHolderClose(&g_appletInfo.caller);
g_appletInfoInitialized = 0;
memset(&g_appletInfo, 0, sizeof(g_appletInfo));
}
eventClose(&g_appletLibraryAppletLaunchableEvent);
eventClose(&g_appletMessageEvent);
if (g_appletSuspendedTickInitialized) {
eventClose(&g_appletSuspendedTickEvent);
g_appletSuspendedTickInitialized = false;
}
serviceClose(&g_appletIDebugFunctions);
serviceClose(&g_appletIDisplayController);
serviceClose(&g_appletIAudioController);
serviceClose(&g_appletIWindowController);
serviceClose(&g_appletISelfController);
serviceClose(&g_appletICommonStateGetter);
serviceClose(&g_appletILibraryAppletCreator);
if (__nx_applet_type == AppletType_SystemApplet) {
serviceClose(&g_appletIApplicationCreator);
serviceClose(&g_appletIGlobalStateController);
}
if (__nx_applet_type != AppletType_LibraryApplet)
serviceClose(&g_appletIFunctions);
if (__nx_applet_type == AppletType_LibraryApplet) {
serviceClose(&g_appletIProcessWindingController);
serviceClose(&g_appletILibraryAppletSelfAccessor);
}
serviceClose(&g_appletIAppletCommonFunctions);
serviceClose(&g_appletProxySession);
serviceClose(&g_appletSrv);
g_appletResourceUserId = 0;
if (g_appletRecordingInitialized > 0) {
tmemClose(&g_appletRecordingTmem);
g_appletRecordingInitialized = 0;
}
if (g_appletCopyrightInitialized) {
tmemClose(&g_appletCopyrightTmem);
g_appletCopyrightInitialized = 0;
}
if (_appletIsRegularApplication()) apmExit();
}
Service* appletGetServiceSession_Proxy(void) {
return &g_appletProxySession;
}
Service* appletGetServiceSession_AppletCommonFunctions(void) {
return &g_appletIAppletCommonFunctions;
}
Service* appletGetServiceSession_Functions(void) {
return &g_appletIFunctions;
}
Service* appletGetServiceSession_GlobalStateController(void) {
return &g_appletIGlobalStateController;
}
Service* appletGetServiceSession_ApplicationCreator(void) {
return &g_appletIApplicationCreator;
}
Service* appletGetServiceSession_LibraryAppletSelfAccessor(void) {
return &g_appletILibraryAppletSelfAccessor;
}
Service* appletGetServiceSession_ProcessWindingController(void) {
return &g_appletIProcessWindingController;
}
Service* appletGetServiceSession_LibraryAppletCreator(void) {
return &g_appletILibraryAppletCreator;
}
Service* appletGetServiceSession_CommonStateGetter(void) {
return &g_appletICommonStateGetter;
}
Service* appletGetServiceSession_SelfController(void) {
return &g_appletISelfController;
}
Service* appletGetServiceSession_WindowController(void) {
return &g_appletIWindowController;
}
Service* appletGetServiceSession_AudioController(void) {
return &g_appletIAudioController;
}
Service* appletGetServiceSession_DisplayController(void) {
return &g_appletIDisplayController;
}
Service* appletGetServiceSession_DebugFunctions(void) {
return &g_appletIDebugFunctions;
}
AppletType appletGetAppletType(void) {
return __nx_applet_type;
}
static void appletCallHook(AppletHookType hookType)
{
AppletHookCookie* c;
for (c = &g_appletFirstHook; c && c->callback; c = c->next)
c->callback(hookType, c->param);
}
void appletHook(AppletHookCookie* cookie, AppletHookFn callback, void* param)
{
if (callback == NULL)
return;
AppletHookCookie* hook = &g_appletFirstHook;
*cookie = *hook; // Structure copy.
hook->next = cookie;
hook->callback = callback;
hook->param = param;
}
void appletUnhook(AppletHookCookie* cookie)
{
AppletHookCookie* hook;
for (hook = &g_appletFirstHook; hook; hook = hook->next)
{
if (hook->next == cookie)
{
*hook = *cookie; // Structure copy.
break;
}
}
}
void appletSetThemeColorType(AppletThemeColorType theme) {
g_appletThemeColorType = theme;
}
AppletThemeColorType appletGetThemeColorType(void) {
return g_appletThemeColorType;
}
Result appletSetFocusHandlingMode(AppletFocusHandlingMode mode) {
Result rc;
bool invals[4];
if (mode >= AppletFocusHandlingMode_Max)
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
memset(invals, 0, sizeof(invals));
if ((mode == AppletFocusHandlingMode_SuspendHomeSleep) || (mode == AppletFocusHandlingMode_AlwaysSuspend)) {
invals[0] = 0;
invals[1] = 0;
invals[2] = 1;
}
if (mode != AppletFocusHandlingMode_AlwaysSuspend) {
invals[3] = 0;
if (mode == AppletFocusHandlingMode_NoSuspend) {
invals[0] = 1;
invals[1] = 1;
invals[2] = 0;
}
else if (mode == AppletFocusHandlingMode_SuspendHomeSleepNotify) {
invals[0] = 1;
invals[1] = 0;
invals[2] = 1;
}
}
else {
invals[3] = 1;
}
rc = _appletSetFocusHandlingMode(invals[0], invals[1], invals[2]);
if (R_SUCCEEDED(rc) && hosversionAtLeast(2,0,0))
rc = _appletSetOutOfFocusSuspendingEnabled(invals[3]);
return rc;
}
// Helper macros for use with the below ipc helper funcs.
#define IPC_MAKE_CMD_IMPL(proto,_s,_rid,func,...) \
proto { \
if (!serviceIsActive((_s))) \
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); \
return func((_s), ##__VA_ARGS__, (_rid)); \
}
#define IPC_MAKE_CMD_IMPL_HOSVER(proto,_s,_rid,func,_hosver,...) \
proto { \
if (!serviceIsActive((_s))) \
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); \
if (hosversionBefore _hosver) \
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); \
return func((_s), ##__VA_ARGS__, (_rid)); \
}
#define IPC_MAKE_CMD_IMPL_INITEXPR(proto,_s,_rid,func,initexpr,...) \
proto { \
if (!serviceIsActive((_s)) || initexpr) \
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); \
return func((_s), ##__VA_ARGS__, (_rid)); \
}
#define IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(proto,_s,_rid,func,initexpr,_hosver,...) \
proto { \
if (!serviceIsActive((_s)) || initexpr) \
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); \
if (hosversionBefore _hosver) \
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); \
return func((_s), ##__VA_ARGS__, (_rid)); \
}
static Result _appletCmdGetHandle(Service* srv, Handle* handle_out, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatch(srv, cmd_id,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = handle_out,
);
}
static Result _appletCmdGetEvent(Service* srv, Event* out_event, bool autoclear, u32 cmd_id) {
Handle tmp_handle = INVALID_HANDLE;
Result rc = 0;
rc = _appletCmdGetHandle(srv, &tmp_handle, cmd_id);
if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear);
return rc;
}
static Result _appletCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatch(srv, cmd_id,
.out_num_objects = 1,
.out_objects = srv_out,
);
}
static Result _appletOpenLibraryAppletProxy(Service* srv_out, Handle prochandle, const AppletAttribute *attr) {
u64 reserved=0;
serviceAssumeDomain(&g_appletSrv);
return serviceDispatchIn(&g_appletSrv, 201, reserved,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { attr, sizeof(*attr) } },
.in_send_pid = true,
.in_num_handles = 1,
.in_handles = { prochandle },
.out_num_objects = 1,
.out_objects = srv_out,
);
}
static Result _appletGetSessionProxy(Service* srv_out, Handle prochandle, u32 cmd_id) {
u64 reserved=0;
serviceAssumeDomain(&g_appletSrv);
return serviceDispatchIn(&g_appletSrv, cmd_id, reserved,
.in_send_pid = true,
.in_num_handles = 1,
.in_handles = { prochandle },
.out_num_objects = 1,
.out_objects = srv_out,
);
}
static Result _appletCmdGetSessionInU64(Service* srv, Service* srv_out, u64 inval, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchIn(srv, cmd_id, inval,
.out_num_objects = 1,
.out_objects = srv_out,
);
}
static Result _appletCmdGetSessionInU32(Service* srv, Service* srv_out, u32 inval, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchIn(srv, cmd_id, inval,
.out_num_objects = 1,
.out_objects = srv_out,
);
}
static Result _appletCmdNoIO(Service* srv, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatch(srv, cmd_id);
}
static Result _appletCmdNoInOutU64(Service* srv, u64 *out, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchOut(srv, cmd_id, *out);
}
static Result _appletCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchOut(srv, cmd_id, *out);
}
static Result _appletCmdNoInOutU8(Service* srv, u8 *out, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchOut(srv, cmd_id, *out);
}
static Result _appletCmdNoInOutBool(Service* srv, bool *out, u32 cmd_id) {
u8 tmp=0;
Result rc = _appletCmdNoInOutU8(srv, &tmp, cmd_id);
if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
return rc;
}
static Result _appletCmdInU8NoOut(Service* srv, u8 inval, u64 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchIn(srv, cmd_id, inval);
}
static Result _appletCmdInU32NoOut(Service* srv, u32 inval, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchIn(srv, cmd_id, inval);
}
static Result _appletCmdInU64NoOut(Service* srv, u64 inval, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchIn(srv, cmd_id, inval);
}
static Result _appletCmdInBoolNoOut(Service* srv, bool inval, u32 cmd_id) {
return _appletCmdInU8NoOut(srv, inval!=0, cmd_id);
}
static Result _appletCmdInHandleU64NoOut(Service* srv, Handle handle, u64 inval, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchIn(srv, cmd_id, inval,
.in_num_handles = 1,
.in_handles = { handle },
);
}
static Result _appletCmdInHandleU64OutSession(Service* srv, Service* srv_out, Handle handle, u64 inval, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchIn(srv, cmd_id, inval,
.in_num_handles = 1,
.in_handles = { handle },
.out_num_objects = 1,
.out_objects = srv_out,
);
}
static Result _appletCmdInTmemNoOut(Service* srv, TransferMemory *tmem, u32 cmd_id) {
serviceAssumeDomain(srv);
return _appletCmdInHandleU64NoOut(srv, tmem->handle, tmem->size, cmd_id);
}
static Result _appletCmdInTmemOutSession(Service* srv, Service* srv_out, TransferMemory *tmem, u32 cmd_id) {
serviceAssumeDomain(srv);
return _appletCmdInHandleU64OutSession(srv, srv_out, tmem->handle, tmem->size, cmd_id);
}
static Result _appletCmdInSession(Service* srv, Service* srv_in, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatch(srv, cmd_id,
.in_num_objects = 1,
.in_objects = { srv_in },
);
}
static Result _appletCmdInStorage(Service* srv, AppletStorage* s, u32 cmd_id) {
if (!serviceIsActive(&s->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
Result rc =_appletCmdInSession(srv, &s->s, cmd_id);
appletStorageClose(s);
return rc;
}
static Result _appletCmdInStorageU32(Service* srv, AppletStorage* s, u32 inval, u32 cmd_id) {
if (!serviceIsActive(&s->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
serviceAssumeDomain(srv);
Result rc = serviceDispatchIn(srv, cmd_id, inval,
.in_num_objects = 1,
.in_objects = { &s->s },
);
appletStorageClose(s);
return rc;
}
static Result _appletCmdInStorageU64(Service* srv, AppletStorage* s, u64 inval, u32 cmd_id) {
if (!serviceIsActive(&s->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
serviceAssumeDomain(srv);
Result rc = serviceDispatchIn(srv, cmd_id, inval,
.in_num_objects = 1,
.in_objects = { &s->s },
);
appletStorageClose(s);
return rc;
}
static Result _appletCmdInU32OutStorage(Service* srv, AppletStorage* s, u32 inval, u32 cmd_id) {
memset(s, 0, sizeof(AppletStorage));
serviceAssumeDomain(srv);
Result rc = serviceDispatchIn(srv, cmd_id, inval,
.out_num_objects = 1,
.out_objects = &s->s,
);
return rc;
}
static Result _appletCmdNoInOutStorage(Service* srv, AppletStorage* s, u32 cmd_id) {
memset(s, 0, sizeof(AppletStorage));
return _appletCmdGetSession(srv, &s->s, cmd_id);
}
static Result _appletCmdSendBufNoOut(Service* srv, const void* buffer, size_t size, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatch(srv, cmd_id,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { buffer, size } },
);
}
static Result _appletCmdNoInRecvBuf(Service* srv, void* buffer, size_t size, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatch(srv, cmd_id,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { buffer, size } },
);
}
static Result _appletGetLibraryAppletInfo(Service* srv, LibAppletInfo *info, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchOut(srv, cmd_id, *info);
}
static Result _appletGetIdentityInfo(Service* srv, AppletIdentityInfo *info, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchOut(srv, cmd_id, *info);
}
static Result _appletGetResolution(Service* srv, s32 *width, s32 *height, u32 cmd_id) {
struct {
s32 width;
s32 height;
} out;
serviceAssumeDomain(srv);
Result rc = serviceDispatchOut(srv, cmd_id, out);
if (R_SUCCEEDED(rc) && width) *width = out.width;
if (R_SUCCEEDED(rc) && height) *height = out.height;
return rc;
}
// ICommonStateGetter
IPC_MAKE_CMD_IMPL(static Result _appletReceiveMessage(u32 *out), &g_appletICommonStateGetter, 1, _appletCmdNoInOutU32, out)
IPC_MAKE_CMD_IMPL(static Result _appletGetOperationMode(u8 *out), &g_appletICommonStateGetter, 5, _appletCmdNoInOutU8, out)
IPC_MAKE_CMD_IMPL(static Result _appletGetPerformanceMode(u32 *out), &g_appletICommonStateGetter, 6, _appletCmdNoInOutU32, out)
IPC_MAKE_CMD_IMPL( Result appletGetCradleStatus(u8 *status), &g_appletICommonStateGetter, 7, _appletCmdNoInOutU8, status)
Result appletGetBootMode(PmBootMode *mode) {
u8 tmp=0;
Result rc = _appletCmdNoInOutU8(&g_appletICommonStateGetter, &tmp, 8);
if (R_SUCCEEDED(rc) && mode) *mode = tmp;
return rc;
}
IPC_MAKE_CMD_IMPL(static Result _appletGetCurrentFocusState(u8 *out), &g_appletICommonStateGetter, 9, _appletCmdNoInOutU8, out)
IPC_MAKE_CMD_IMPL(static Result _appletGetAcquiredSleepLockEvent(Event *out_event), &g_appletICommonStateGetter, 13, _appletCmdGetEvent, out_event, false)
static Result _appletWaitAcquiredSleepLockEvent(void) {
Result rc=0;
Event tmpevent={0};
rc = _appletGetAcquiredSleepLockEvent(&tmpevent);
if (R_SUCCEEDED(rc)) rc = eventWait(&tmpevent, U64_MAX);
eventClose(&tmpevent);
return rc;
}
Result appletRequestToAcquireSleepLock(void) {
Result rc = _appletCmdNoIO(&g_appletICommonStateGetter, 10);
if (R_SUCCEEDED(rc)) rc = _appletWaitAcquiredSleepLockEvent();
return rc;
}
IPC_MAKE_CMD_IMPL(Result appletReleaseSleepLock(void), &g_appletICommonStateGetter, 11, _appletCmdNoIO)
Result appletReleaseSleepLockTransiently(void) {
Result rc = _appletCmdNoIO(&g_appletICommonStateGetter, 12);
if (R_SUCCEEDED(rc)) rc = _appletWaitAcquiredSleepLockEvent();
return rc;
}
IPC_MAKE_CMD_IMPL(Result appletPushToGeneralChannel(AppletStorage *s), &g_appletICommonStateGetter, 20, _appletCmdInStorage, s)
static Result _appletGetHomeButtonRwLockAccessor(Service* srv, AppletLockAccessor *a, u32 cmd_id) {
Result rc = _appletCmdGetSession(srv, &a->s, cmd_id);
if (R_FAILED(rc))
return rc;
rc = _appletCmdGetEvent(&a->s, &a->event, false, 3);
if (R_FAILED(rc)) {
serviceAssumeDomain(&a->s);
serviceClose(&a->s);
}
return rc;
}
IPC_MAKE_CMD_IMPL(Result appletGetHomeButtonReaderLockAccessor(AppletLockAccessor *a), &g_appletICommonStateGetter, 30, _appletGetHomeButtonRwLockAccessor, a)
static Result _appletGetRwLockAccessor(Service* srv, AppletLockAccessor *a, s32 inval, u32 cmd_id) {
Result rc = _appletCmdGetSessionInU32(srv, &a->s, inval, cmd_id);
if (R_FAILED(rc))
return rc;
rc = _appletCmdGetEvent(&a->s, &a->event, false, 3);
if (R_FAILED(rc)) {
serviceAssumeDomain(&a->s);
serviceClose(&a->s);
}
return rc;
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetReaderLockAccessorEx(AppletLockAccessor *a, u32 inval), &g_appletICommonStateGetter, 31, _appletGetRwLockAccessor, (2,0,0), a, inval)
Result appletGetWriterLockAccessorEx(AppletLockAccessor *a, u32 inval) {
if (hosversionBefore(7,0,0)) {
if (__nx_applet_type == AppletType_SystemApplet && hosversionAtLeast(2,0,0))
return _appletGetRwLockAccessor(&g_appletIFunctions, a, inval, 31);
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
}
return _appletGetRwLockAccessor(&g_appletICommonStateGetter, a, inval, 32);
}
Result appletGetCradleFwVersion(u32 *out0, u32 *out1, u32 *out2, u32 *out3) {
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
struct {
u32 out0;
u32 out1;
u32 out2;
u32 out3;
} out;
serviceAssumeDomain(&g_appletICommonStateGetter);
Result rc = serviceDispatchOut(&g_appletICommonStateGetter, 40, out);
if (R_SUCCEEDED(rc)) {
if (out0) *out0 = out.out0;
if (out1) *out1 = out.out1;
if (out2) *out2 = out.out2;
if (out3) *out3 = out.out3;
}
return rc;
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletIsVrModeEnabled(bool *out), &g_appletICommonStateGetter, 50, _appletCmdNoInOutBool, (3,0,0), out)
Result appletSetVrModeEnabled(bool flag) {
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
if (hosversionBefore(7,0,0))
return _appletCmdInBoolNoOut(&g_appletICommonStateGetter, flag, 51);
return _appletCmdNoIO(&g_appletICommonStateGetter, flag ? 53 : 54);
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetLcdBacklightOffEnabled(bool flag), &g_appletICommonStateGetter, 52, _appletCmdInBoolNoOut, (4,0,0), flag)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletIsInControllerFirmwareUpdateSection(bool *out), &g_appletICommonStateGetter, 55, _appletCmdNoInOutBool, (3,0,0), out)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetDefaultDisplayResolution(s32 *width, s32 *height), &g_appletICommonStateGetter, 60, _appletGetResolution, (3,0,0), width, height)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetDefaultDisplayResolutionChangeEvent(Event *out_event), &g_appletICommonStateGetter, 61, _appletCmdGetEvent, (3,0,0), out_event, true)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetHdcpAuthenticationState(s32 *state), &g_appletICommonStateGetter, 62, _appletCmdNoInOutU32, (4,0,0), (u32*)state)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetHdcpAuthenticationStateChangeEvent(Event *out_event), &g_appletICommonStateGetter, 63, _appletCmdGetEvent, (4,0,0), out_event, true)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetTvPowerStateMatchingMode(AppletTvPowerStateMatchingMode mode), &g_appletICommonStateGetter, 64, _appletCmdInU32NoOut, (5,0,0), mode)
Result appletGetApplicationIdByContentActionName(u64 *application_id, const char *name) {
if (hosversionBefore(5,1,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
serviceAssumeDomain(&g_appletICommonStateGetter);
return serviceDispatchOut(&g_appletICommonStateGetter, 65, *application_id,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { name, strlen(name)+1 } },
);
}
Result appletSetCpuBoostMode(ApmCpuBoostMode mode) {
Result rc=0;
if (hosversionBefore(7,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdInU32NoOut(&g_appletICommonStateGetter, mode, 66);
if (R_SUCCEEDED(rc)) g_appletCpuBoostMode = mode;
return rc;
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletPerformSystemButtonPressingIfInFocus(AppletSystemButtonType type), &g_appletICommonStateGetter, 80, _appletCmdInU32NoOut, (6,0,0), type)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetPerformanceConfigurationChangedNotification(bool flag), &g_appletICommonStateGetter, 90, _appletCmdInBoolNoOut, (7,0,0), flag)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetCurrentPerformanceConfiguration(u32 *PerformanceConfiguration), &g_appletICommonStateGetter, 91, _appletCmdNoInOutU32, (7,0,0), PerformanceConfiguration)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetOperationModeSystemInfo(u32 *info), &g_appletICommonStateGetter, 200, _appletCmdNoInOutU32, (7,0,0), info)
Result appletGetSettingsPlatformRegion(SetSysPlatformRegion *out) {
if (hosversionBefore(9,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
u8 tmp=0;
Result rc = _appletCmdNoInOutU8(&g_appletICommonStateGetter, &tmp, 300);
if (R_SUCCEEDED(rc) && out) *out = tmp;
return rc;
}
// ISelfController
IPC_MAKE_CMD_IMPL(static Result _appletSelfExit(void), &g_appletISelfController, 0, _appletCmdNoIO)
IPC_MAKE_CMD_IMPL( Result appletLockExit(void), &g_appletISelfController, 1, _appletCmdNoIO)
IPC_MAKE_CMD_IMPL( Result appletUnlockExit(void), &g_appletISelfController, 2, _appletCmdNoIO)
IPC_MAKE_CMD_IMPL( Result appletEnterFatalSection(void), &g_appletISelfController, 3, _appletCmdNoIO)
IPC_MAKE_CMD_IMPL( Result appletLeaveFatalSection(void), &g_appletISelfController, 4, _appletCmdNoIO)
static Result _appletWaitLibraryAppletLaunchableEvent(void) {
Result rc=0;
if (!eventActive(&g_appletLibraryAppletLaunchableEvent))
rc = _appletCmdGetEvent(&g_appletISelfController, &g_appletLibraryAppletLaunchableEvent, false, 9);
if (R_SUCCEEDED(rc)) rc = eventWait(&g_appletLibraryAppletLaunchableEvent, U64_MAX);
return rc;
}
IPC_MAKE_CMD_IMPL( Result appletSetScreenShotPermission(AppletScreenShotPermission permission), &g_appletISelfController, 10, _appletCmdInU32NoOut, permission)
IPC_MAKE_CMD_IMPL(static Result _appletSetOperationModeChangedNotification(bool flag), &g_appletISelfController, 11, _appletCmdInBoolNoOut, flag)
IPC_MAKE_CMD_IMPL(static Result _appletSetPerformanceModeChangedNotification(bool flag), &g_appletISelfController, 12, _appletCmdInBoolNoOut, flag)
static Result _appletSetFocusHandlingMode(bool inval0, bool inval1, bool inval2) {
const struct {
u8 inval0;
u8 inval1;
u8 inval2;
} in = { inval0!=0, inval1!=0, inval2!=0 };
serviceAssumeDomain(&g_appletISelfController);
return serviceDispatchIn(&g_appletISelfController, 13, in);
}
IPC_MAKE_CMD_IMPL(Result appletSetRestartMessageEnabled(bool flag), &g_appletISelfController, 14, _appletCmdInBoolNoOut, flag)
Result appletSetScreenShotAppletIdentityInfo(AppletIdentityInfo *info) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
serviceAssumeDomain(&g_appletISelfController);
return serviceDispatchIn(&g_appletISelfController, 15, *info);
}
IPC_MAKE_CMD_IMPL(static Result _appletSetOutOfFocusSuspendingEnabled(bool flag), &g_appletISelfController, 16, _appletCmdInBoolNoOut, flag)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetControllerFirmwareUpdateSection(bool flag), &g_appletISelfController, 17, _appletCmdInBoolNoOut, (3,0,0), flag)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetRequiresCaptureButtonShortPressedMessage(bool flag), &g_appletISelfController, 18, _appletCmdInBoolNoOut, (3,0,0), flag)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetAlbumImageOrientation(AlbumImageOrientation orientation), &g_appletISelfController, 19, _appletCmdInU32NoOut, (3,0,0), orientation)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetDesirableKeyboardLayout(SetKeyboardLayout layout), &g_appletISelfController, 20, _appletCmdInU32NoOut, (4,0,0), layout)
IPC_MAKE_CMD_IMPL( Result appletCreateManagedDisplayLayer(u64 *out), &g_appletISelfController, 40, _appletCmdNoInOutU64, out)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletIsSystemBufferSharingEnabled(void), &g_appletISelfController, 41, _appletCmdNoIO, (4,0,0))
Result appletGetSystemSharedLayerHandle(u64 *SharedBufferHandle, u64 *SharedLayerHandle) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
struct {
u64 SharedBufferHandle;
u64 SharedLayerHandle;
} out;
serviceAssumeDomain(&g_appletISelfController);
Result rc = serviceDispatchOut(&g_appletISelfController, 42, out);
if (R_SUCCEEDED(rc) && SharedBufferHandle) *SharedBufferHandle = out.SharedBufferHandle;
if (R_SUCCEEDED(rc) && SharedLayerHandle) *SharedLayerHandle = out.SharedLayerHandle;
return rc;
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetSystemSharedBufferHandle(u64 *SharedBufferHandle) , &g_appletISelfController, 43, _appletCmdNoInOutU64, (5,0,0), SharedBufferHandle)
IPC_MAKE_CMD_IMPL( Result appletSetHandlesRequestToDisplay(bool flag), &g_appletISelfController, 50, _appletCmdInBoolNoOut, flag)
IPC_MAKE_CMD_IMPL( Result appletApproveToDisplay(void), &g_appletISelfController, 51, _appletCmdNoIO)
Result appletOverrideAutoSleepTimeAndDimmingTime(s32 inval0, s32 inval1, s32 inval2, s32 inval3) {
const struct {
s32 inval0;
s32 inval1;
s32 inval2;
s32 inval3;
} in = { inval0, inval1, inval2, inval3 };
serviceAssumeDomain(&g_appletISelfController);
return serviceDispatchIn(&g_appletISelfController, 60, in);
}
IPC_MAKE_CMD_IMPL( Result appletSetIdleTimeDetectionExtension(AppletIdleTimeDetectionExtension ext), &g_appletISelfController, 62, _appletCmdInU32NoOut, ext)
IPC_MAKE_CMD_IMPL( Result appletGetIdleTimeDetectionExtension(AppletIdleTimeDetectionExtension *ext), &g_appletISelfController, 63, _appletCmdNoInOutU32, ext)
IPC_MAKE_CMD_IMPL( Result appletSetInputDetectionSourceSet(u32 val), &g_appletISelfController, 64, _appletCmdInU32NoOut, val)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletReportUserIsActive(void), &g_appletISelfController, 65, _appletCmdNoIO, (2,0,0))
Result appletGetCurrentIlluminance(float *fLux) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
serviceAssumeDomain(&g_appletISelfController);
return serviceDispatchOut(&g_appletISelfController, 66, *fLux);
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletIsIlluminanceAvailable(bool *out), &g_appletISelfController, 67, _appletCmdNoInOutBool, (3,0,0), out)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetAutoSleepDisabled(bool flag), &g_appletISelfController, 68, _appletCmdInBoolNoOut, (5,0,0), flag)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletIsAutoSleepDisabled(bool *out), &g_appletISelfController, 69, _appletCmdNoInOutBool, (5,0,0), out)
Result appletGetCurrentIlluminanceEx(bool *bOverLimit, float *fLux) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
struct {
u8 bOverLimit;
float fLux;
} out;
serviceAssumeDomain(&g_appletISelfController);
Result rc = serviceDispatchOut(&g_appletISelfController, 71, out);
if (R_SUCCEEDED(rc) && bOverLimit) *bOverLimit = out.bOverLimit & 1;
if (R_SUCCEEDED(rc) && fLux) *fLux = out.fLux;
return rc;
}
IPC_MAKE_CMD_IMPL_HOSVER( Result appletSetInputDetectionPolicy(AppletInputDetectionPolicy policy), &g_appletISelfController, 72, _appletCmdInU32NoOut, (9,0,0), policy)
IPC_MAKE_CMD_IMPL_HOSVER( Result appletSetWirelessPriorityMode(AppletWirelessPriorityMode mode), &g_appletISelfController, 80, _appletCmdInU32NoOut, (4,0,0), mode)
IPC_MAKE_CMD_IMPL_HOSVER(static Result _appletGetAccumulatedSuspendedTickValue(u64 *tick), &g_appletISelfController, 90, _appletCmdNoInOutU64, (6,0,0), tick)
IPC_MAKE_CMD_IMPL_HOSVER(static Result _appletGetAccumulatedSuspendedTickChangedEvent(Event *out_event), &g_appletISelfController, 91, _appletCmdGetEvent, (6,0,0), out_event, true)
Result appletGetProgramTotalActiveTime(u64 *activeTime) {
if (!g_appletSuspendedTickInitialized)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
Result rc=0;
u64 suspendedTick = 0;
while (R_SUCCEEDED(eventWait(&g_appletSuspendedTickEvent, 0))) {
rc = _appletGetAccumulatedSuspendedTickValue(&suspendedTick);
if (R_FAILED(rc)) return rc;
if (suspendedTick > g_appletSuspendedTick) g_appletSuspendedTick = suspendedTick;
}
*activeTime = armTicksToNs(armGetSystemTick() - g_appletInitTickBase - g_appletSuspendedTick);
return rc;
}
IPC_MAKE_CMD_IMPL_HOSVER( Result appletSetAlbumImageTakenNotificationEnabled(bool flag), &g_appletISelfController, 100, _appletCmdInBoolNoOut, (7,0,0), flag)
Result appletSetApplicationAlbumUserData(const void* buffer, size_t size) {
if (hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
serviceAssumeDomain(&g_appletISelfController);
return serviceDispatch(&g_appletISelfController, 110,
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_In },
.buffers = { { buffer, size } },
);
}
// IWindowController
IPC_MAKE_CMD_IMPL(static Result _appletGetAppletResourceUserId(u64 *out), &g_appletIWindowController, 1, _appletCmdNoInOutU64, out)
Result appletGetAppletResourceUserId(u64 *out) {
if (!serviceIsActive(&g_appletSrv))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
*out = g_appletResourceUserId;
return 0;
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetAppletResourceUserIdOfCallerApplet(u64 *out), &g_appletIWindowController, 2, _appletCmdNoInOutU64, (6,0,0), out)
IPC_MAKE_CMD_IMPL(static Result _appletAcquireForegroundRights(void), &g_appletIWindowController, 10, _appletCmdNoIO)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetAppletWindowVisibility(bool flag), &g_appletIWindowController, 20, _appletCmdInBoolNoOut, (7,0,0), flag)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetAppletGpuTimeSlice(s64 val), &g_appletIWindowController, 21, _appletCmdInU64NoOut, (7,0,0), val)
// IAudioController
Result appletSetExpectedMasterVolume(float mainAppletVolume, float libraryAppletVolume) {
const struct {
float mainAppletVolume;
float libraryAppletVolume;
} in = { mainAppletVolume, libraryAppletVolume };
serviceAssumeDomain(&g_appletIAudioController);
return serviceDispatchIn(&g_appletIAudioController, 0, in);
}
Result appletGetExpectedMasterVolume(float *mainAppletVolume, float *libraryAppletVolume) {
Result rc=0;
if (mainAppletVolume) rc = _appletCmdNoInOutU32(&g_appletIAudioController, (u32*)mainAppletVolume, 1); // GetMainAppletExpectedMasterVolume
if (R_SUCCEEDED(rc) && libraryAppletVolume) rc = _appletCmdNoInOutU32(&g_appletIAudioController, (u32*)libraryAppletVolume, 2); // GetLibraryAppletExpectedMasterVolume
return rc;
}
Result appletChangeMainAppletMasterVolume(float volume, u64 unk) {
const struct {
float volume;
u64 unk;
} in = { volume, unk };
serviceAssumeDomain(&g_appletIAudioController);
return serviceDispatchIn(&g_appletIAudioController, 3, in);
}
Result appletSetTransparentVolumeRate(float val) {
serviceAssumeDomain(&g_appletIAudioController);
return serviceDispatchIn(&g_appletIAudioController, 4, val);
}
// IDisplayController
IPC_MAKE_CMD_IMPL(Result appletUpdateLastForegroundCaptureImage(void), &g_appletIDisplayController, 1, _appletCmdNoIO)
IPC_MAKE_CMD_IMPL(Result appletUpdateCallerAppletCaptureImage(void), &g_appletIDisplayController, 4, _appletCmdNoIO)
static Result _appletGetCaptureImageEx(void* buffer, size_t size, bool *flag, u32 cmd_id) {
u8 tmp=0;
serviceAssumeDomain(&g_appletIDisplayController);
Result rc = serviceDispatchOut(&g_appletIDisplayController, cmd_id, tmp,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { buffer, size } },
);
if (R_SUCCEEDED(rc) && flag) *flag = tmp & 1;
return rc;
}
Result appletGetLastForegroundCaptureImageEx(void* buffer, size_t size, bool *flag) {
return _appletGetCaptureImageEx(buffer, size, flag, 5);
}
Result appletGetLastApplicationCaptureImageEx(void* buffer, size_t size, bool *flag) {
return _appletGetCaptureImageEx(buffer, size, flag, 6);
}
Result appletGetCallerAppletCaptureImageEx(void* buffer, size_t size, bool *flag) {
return _appletGetCaptureImageEx(buffer, size, flag, 7);
}
Result appletTakeScreenShotOfOwnLayer(bool flag, AppletCaptureSharedBuffer captureBuf) {
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u8 flag;
s32 captureBuf;
} in = { flag!=0, captureBuf };
serviceAssumeDomain(&g_appletIDisplayController);
return serviceDispatchIn(&g_appletIDisplayController, 8, in);
}
Result appletCopyBetweenCaptureBuffers(AppletCaptureSharedBuffer dstCaptureBuf, AppletCaptureSharedBuffer srcCaptureBuf) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
s32 dstCaptureBuf;
s32 srcCaptureBuf;
} in = { dstCaptureBuf, srcCaptureBuf };
serviceAssumeDomain(&g_appletIDisplayController);
return serviceDispatchIn(&g_appletIDisplayController, 9, in);
}
Result appletClearCaptureBuffer(bool flag, AppletCaptureSharedBuffer captureBuf, u32 color) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u8 flag;
u8 pad[3];
s32 captureBuf;
u32 color;
} in = { flag!=0, {0}, captureBuf, color };
serviceAssumeDomain(&g_appletIDisplayController);
return serviceDispatchIn(&g_appletIDisplayController, 20, in);
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletClearAppletTransitionBuffer(u32 color), &g_appletIDisplayController, 21, _appletCmdInU32NoOut, (3,0,0), color)
static Result _appletAcquireCaptureSharedBuffer(bool *flag, s32 *id, u64 cmd_id) {
struct {
u8 flag;
s32 id;
} out;
serviceAssumeDomain(&g_appletIDisplayController);
Result rc = serviceDispatchOut(&g_appletIDisplayController, cmd_id, out);
if (R_SUCCEEDED(rc) && flag) *flag = out.flag & 1;
if (R_SUCCEEDED(rc) && id) *id = out.id;
return rc;
}
Result appletAcquireLastApplicationCaptureSharedBuffer(bool *flag, s32 *id) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletAcquireCaptureSharedBuffer(flag, id, 22);
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletReleaseLastApplicationCaptureSharedBuffer(void), &g_appletIDisplayController, 23, _appletCmdNoIO, (4,0,0))
Result appletAcquireLastForegroundCaptureSharedBuffer(bool *flag, s32 *id) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletAcquireCaptureSharedBuffer(flag, id, 24);
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletReleaseLastForegroundCaptureSharedBuffer(void), &g_appletIDisplayController, 25, _appletCmdNoIO, (4,0,0))
Result appletAcquireCallerAppletCaptureSharedBuffer(bool *flag, s32 *id) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletAcquireCaptureSharedBuffer(flag, id, 26);
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletReleaseCallerAppletCaptureSharedBuffer(void), &g_appletIDisplayController, 27, _appletCmdNoIO, (4,0,0))
Result appletTakeScreenShotOfOwnLayerEx(bool flag0, bool immediately, AppletCaptureSharedBuffer captureBuf) {
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u8 flag0;
u8 immediately;
s32 captureBuf;
} in = { flag0!=0, immediately!=0, captureBuf };
serviceAssumeDomain(&g_appletIDisplayController);
return serviceDispatchIn(&g_appletIDisplayController, 28, in);
}
// IProcessWindingController
static Result _appletGetLaunchReason(AppletProcessLaunchReason *reason) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
serviceAssumeDomain(&g_appletIProcessWindingController);
return serviceDispatchOut(&g_appletIProcessWindingController, 0, *reason);
}
static Result _appletOpenCallingLibraryApplet(AppletHolder *h) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletOpenExistingLibraryApplet(h, &g_appletIProcessWindingController, 11);
}
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPushContext(AppletStorage *s), &g_appletIProcessWindingController, 21, _appletCmdInStorage, __nx_applet_type != AppletType_LibraryApplet, s)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPopContext(AppletStorage *s), &g_appletIProcessWindingController, 22, _appletCmdNoInOutStorage, __nx_applet_type != AppletType_LibraryApplet, s)
IPC_MAKE_CMD_IMPL_INITEXPR( static Result _appletWindAndDoReserved(void), &g_appletIProcessWindingController, 30, _appletCmdNoIO, __nx_applet_type != AppletType_LibraryApplet)
IPC_MAKE_CMD_IMPL_INITEXPR( static Result _appletReserveToStartAndWaitAndUnwindThis(AppletHolder *h), &g_appletIProcessWindingController, 40, _appletCmdInSession, __nx_applet_type != AppletType_LibraryApplet, &h->s)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(static Result _appletReserveToStartAndWait(AppletHolder *h), &g_appletIProcessWindingController, 41, _appletCmdInSession, __nx_applet_type != AppletType_LibraryApplet, (4,0,0), &h->s)
// LockAccessor
void appletLockAccessorClose(AppletLockAccessor *a) {
eventClose(&a->event);
serviceAssumeDomain(&a->s);
serviceClose(&a->s);
}
static Result _appletLockAccessorTryLock(AppletLockAccessor *a, bool get_handle, Handle* handle_out, bool *outflag) {
Handle tmphandle = INVALID_HANDLE;
u8 tmp = get_handle!=0;
u8 tmpout=0;
serviceAssumeDomain(&a->s);
Result rc = serviceDispatchInOut(&a->s, 1, tmp, tmpout,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = &tmphandle,
);
if (R_SUCCEEDED(rc) && outflag) *outflag = tmpout & 1;
if (R_SUCCEEDED(rc) && handle_out) *handle_out = tmphandle;
return rc;
}
Result appletLockAccessorTryLock(AppletLockAccessor *a, bool *flag) {
Result rc=0;
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
rc = eventWait(&a->event, 0);
if (R_SUCCEEDED(rc)) rc = _appletLockAccessorTryLock(a, false, NULL, flag);
return rc;
}
Result appletLockAccessorLock(AppletLockAccessor *a) {
Result rc=0;
bool flag=0;
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
do {
rc = eventWait(&a->event, U64_MAX);
if (R_SUCCEEDED(rc)) rc = _appletLockAccessorTryLock(a, false, NULL, &flag);
if (R_FAILED(rc)) break;
} while(!flag);
return rc;
}
IPC_MAKE_CMD_IMPL(Result appletLockAccessorUnlock(AppletLockAccessor *a), &a->s, 2, _appletCmdNoIO)
// ILibraryAppletCreator
static Result _appletCreateLibraryApplet(Service* srv_out, AppletId id, LibAppletMode mode) {
const struct {
u32 id;
u32 mode;
} in = { id, mode };
serviceAssumeDomain(&g_appletILibraryAppletCreator);
return serviceDispatchIn(&g_appletILibraryAppletCreator, 0, in,
.out_num_objects = 1,
.out_objects = srv_out,
);
}
static Result _appletGetIndirectLayerConsumerHandle(Service* srv, u64 *out) {
Result rc;
u64 AppletResourceUserId;
rc = appletGetAppletResourceUserId(&AppletResourceUserId);
if (R_FAILED(rc)) return rc;
serviceAssumeDomain(srv);
return serviceDispatchInOut(srv, 160, AppletResourceUserId, *out,
.in_send_pid = true,
);
}
static Result _appletHolderCreateState(AppletHolder *h, LibAppletMode mode, bool creating_self) {
Result rc=0;
h->mode = mode;
h->creating_self = creating_self;
if (R_SUCCEEDED(rc)) rc = _appletCmdGetEvent(&h->s, &h->StateChangedEvent, false, 0);//GetAppletStateChangedEvent
if (R_SUCCEEDED(rc) && hosversionAtLeast(2,0,0) && h->mode == LibAppletMode_BackgroundIndirect) rc = _appletGetIndirectLayerConsumerHandle(&h->s, &h->layer_handle);
return rc;
}
static Result _appletHolderCreate(AppletHolder *h, AppletId id, LibAppletMode mode, bool creating_self) {
Result rc=0;
memset(h, 0, sizeof(AppletHolder));
if (!h->creating_self) rc = _appletWaitLibraryAppletLaunchableEvent();
if (R_SUCCEEDED(rc)) rc = _appletCreateLibraryApplet(&h->s, id, mode);
if (R_SUCCEEDED(rc)) rc = _appletHolderCreateState(h, mode, creating_self);
return rc;
}
static Result _appletOpenExistingLibraryApplet(AppletHolder *h, Service* srv, u32 cmd_id) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
Result rc=0;
LibAppletInfo info={0};
memset(h, 0, sizeof(AppletHolder));
rc = _appletCmdGetSession(srv, &h->s, cmd_id);
if (R_SUCCEEDED(rc)) rc = appletHolderGetLibraryAppletInfo(h, &info);
if (R_SUCCEEDED(rc)) rc = _appletHolderCreateState(h, info.mode, false);
if (R_FAILED(rc)) appletHolderClose(h);
return rc;
}
Result appletCreateLibraryApplet(AppletHolder *h, AppletId id, LibAppletMode mode) {
return _appletHolderCreate(h, id, mode, false);
}
Result appletCreateLibraryAppletSelf(AppletHolder *h, AppletId id, LibAppletMode mode) {
return _appletHolderCreate(h, id, mode, true);
}
IPC_MAKE_CMD_IMPL(Result appletTerminateAllLibraryApplets(void), &g_appletILibraryAppletCreator, 1, _appletCmdNoIO)
IPC_MAKE_CMD_IMPL(Result appletAreAnyLibraryAppletsLeft(bool *out), &g_appletILibraryAppletCreator, 2, _appletCmdNoInOutBool, out)
// ILibraryAppletAccessor
void appletHolderClose(AppletHolder *h) {
eventClose(&h->PopInteractiveOutDataEvent);
eventClose(&h->StateChangedEvent);
serviceAssumeDomain(&h->s);
serviceClose(&h->s);
memset(h, 0, sizeof(AppletHolder));
}
bool appletHolderActive(AppletHolder *h) {
return serviceIsActive(&h->s);
}
Result appletHolderGetIndirectLayerConsumerHandle(AppletHolder *h, u64 *out) {
if (!serviceIsActive(&h->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (h->mode!=LibAppletMode_BackgroundIndirect)
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
if (out) *out = h->layer_handle;
return 0;
}
Result appletHolderStart(AppletHolder *h) {
Result rc=0;
if (!serviceIsActive(&h->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (!h->creating_self) rc = _appletWaitLibraryAppletLaunchableEvent();
if (R_SUCCEEDED(rc)) rc = _appletCmdNoIO(&h->s, 10);//Start
return rc;
}
Result appletHolderJump(AppletHolder *h) {
Result rc=0;
if (!serviceIsActive(&h->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (!h->creating_self) rc = _appletWaitLibraryAppletLaunchableEvent();
if (hosversionBefore(4,0,0))
rc = _appletReserveToStartAndWaitAndUnwindThis(h);
else
rc = _appletReserveToStartAndWait(h);
if (R_SUCCEEDED(rc)) rc = _appletWindAndDoReserved();
if (R_SUCCEEDED(rc)) _appletInfiniteSleepLoop();
return rc;
}
Result appletHolderRequestExit(AppletHolder *h) {
Result rc=0;
if (!serviceIsActive(&h->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (!appletHolderCheckFinished(h)) rc = _appletCmdNoIO(&h->s, 20);//RequestExit
return rc;
}
IPC_MAKE_CMD_IMPL(Result appletHolderTerminate(AppletHolder *h), &h->s, 25, _appletCmdNoIO)
static Result _appletAccessorRequestExitOrTerminate(Service* srv, u64 timeout) {
Result rc=0;
Event StateChangedEvent={0};
if (!serviceIsActive(srv))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
rc = _appletCmdGetEvent(srv, &StateChangedEvent, false, 0);//GetAppletStateChangedEvent
if (R_SUCCEEDED(rc)) rc = _appletCmdNoIO(srv, 20);//RequestExit
if (R_SUCCEEDED(rc)) {
rc = eventWait(&StateChangedEvent, timeout);
if (R_FAILED(rc) && R_VALUE(rc) == KERNELRESULT(TimedOut))
rc = _appletCmdNoIO(srv, 25);//Terminate
}
eventClose(&StateChangedEvent);
return rc;
}
Result appletHolderRequestExitOrTerminate(AppletHolder *h, u64 timeout) {
return _appletAccessorRequestExitOrTerminate(&h->s, timeout);
}
void appletHolderJoin(AppletHolder *h) {
Result rc=0;
LibAppletExitReason res = LibAppletExitReason_Normal;
u32 desc=0;
eventWait(&h->StateChangedEvent, U64_MAX);
rc = _appletCmdNoIO(&h->s, 30);//GetResult
if (R_FAILED(rc)) {
res = LibAppletExitReason_Unexpected;
if (R_MODULE(rc) == 128) {
desc = R_DESCRIPTION(rc);
if (desc == 22) res = LibAppletExitReason_Canceled;
else {
if (desc >= 0x14 && desc < 0x32)res = LibAppletExitReason_Abnormal;
}
}
}
h->exitreason = res;
}
bool appletHolderCheckFinished(AppletHolder *h) {
return R_SUCCEEDED(eventWait(&h->StateChangedEvent, 0));
}
u32 appletHolderGetExitReason(AppletHolder *h) {
return h->exitreason;
}
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletHolderSetOutOfFocusApplicationSuspendingEnabled(AppletHolder *h, bool flag), &h->s, 50, _appletCmdInBoolNoOut, !_appletIsApplication(), flag)
static Result _appletHolderGetPopInteractiveOutDataEvent(AppletHolder *h) {
if (eventActive(&h->PopInteractiveOutDataEvent)) return 0;
return _appletCmdGetEvent(&h->s, &h->PopInteractiveOutDataEvent, false, 106);
}
bool appletHolderWaitInteractiveOut(AppletHolder *h) {
Result rc=0;
s32 idx = 0;
rc = _appletHolderGetPopInteractiveOutDataEvent(h);
if (R_FAILED(rc)) return false;
rc = waitMulti(&idx, U64_MAX, waiterForEvent(&h->PopInteractiveOutDataEvent), waiterForEvent(&h->StateChangedEvent));
if (R_FAILED(rc)) return false;
return idx==0;
}
IPC_MAKE_CMD_IMPL(Result appletHolderPushInData(AppletHolder *h, AppletStorage *s), &h->s, 100, _appletCmdInStorage, s)
IPC_MAKE_CMD_IMPL(Result appletHolderPopOutData(AppletHolder *h, AppletStorage *s), &h->s, 101, _appletCmdNoInOutStorage, s)
IPC_MAKE_CMD_IMPL(Result appletHolderPushExtraStorage(AppletHolder *h, AppletStorage *s), &h->s, 102, _appletCmdInStorage, s)
IPC_MAKE_CMD_IMPL(Result appletHolderPushInteractiveInData(AppletHolder *h, AppletStorage *s), &h->s, 103, _appletCmdInStorage, s)
IPC_MAKE_CMD_IMPL(Result appletHolderPopInteractiveOutData(AppletHolder *h, AppletStorage *s), &h->s, 104, _appletCmdNoInOutStorage, s)
IPC_MAKE_CMD_IMPL(Result appletHolderGetLibraryAppletInfo(AppletHolder *h, LibAppletInfo *info), &h->s, 120, _appletGetLibraryAppletInfo, info)
// (ILibraryAppletCreator ->) IStorage
Result appletCreateStorage(AppletStorage *s, s64 size) {
memset(s, 0, sizeof(AppletStorage));
return _appletCmdGetSessionInU64(&g_appletILibraryAppletCreator, &s->s, size, 10);
}
static Result _appletCreateTransferMemoryStorage(Service* srv_out, TransferMemory *tmem, bool writable) {
const struct {
u8 writable;
u64 size;
} in = { writable!=0, tmem->size };
serviceAssumeDomain(&g_appletILibraryAppletCreator);
return serviceDispatchIn(&g_appletILibraryAppletCreator, 11, in,
.in_num_handles = 1,
.in_handles = { tmem->handle },
.out_num_objects = 1,
.out_objects = srv_out,
);
}
Result appletCreateTransferMemoryStorage(AppletStorage *s, void* buffer, s64 size, bool writable) {
Result rc=0;
memset(s, 0, sizeof(AppletStorage));
if (buffer==NULL) rc = tmemCreate(&s->tmem, size, Perm_None);
else rc = tmemCreateFromMemory(&s->tmem, buffer, size, Perm_None);
if (R_FAILED(rc)) return rc;
rc = _appletCreateTransferMemoryStorage(&s->s, &s->tmem, writable);
if (R_FAILED(rc)) tmemClose(&s->tmem);
return rc;
}
Result appletCreateHandleStorage(AppletStorage *s, s64 inval, Handle handle) {
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletCmdInHandleU64OutSession(&g_appletILibraryAppletCreator, &s->s, handle, inval, 12);
}
Result appletCreateHandleStorageTmem(AppletStorage *s, void* buffer, s64 size) {
Result rc=0;
memset(s, 0, sizeof(AppletStorage));
if (buffer==NULL) rc = tmemCreate(&s->tmem, size, Perm_None);
else rc = tmemCreateFromMemory(&s->tmem, buffer, size, Perm_None);
if (R_FAILED(rc)) return rc;
rc = appletCreateHandleStorage(s, s->tmem.size, s->tmem.handle);
if (R_FAILED(rc)) tmemClose(&s->tmem);
return rc;
}
void appletStorageClose(AppletStorage *s) {
serviceAssumeDomain(&s->s);
serviceClose(&s->s);
}
void appletStorageCloseTmem(AppletStorage *s) {
tmemClose(&s->tmem);
}
static Result _appletStorageAccessorRW(Service* srv, size_t ipcbufsize, s64 offset, void* buffer, size_t size, bool rw) {
serviceAssumeDomain(srv);
return serviceDispatchIn(srv, rw ? 10 : 11, offset,
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | (rw ? SfBufferAttr_In : SfBufferAttr_Out) },
.buffers = { { buffer, size } },
);
}
Result appletStorageGetSize(AppletStorage *s, s64 *size) {
Result rc=0;
Service tmp_srv;//IStorageAccessor
if (!serviceIsActive(&s->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
rc = _appletCmdGetSession(&s->s, &tmp_srv, 0);//Open
if (R_FAILED(rc)) return rc;
rc = _appletCmdNoInOutU64(&tmp_srv, (u64*)size, 0);
serviceAssumeDomain(&tmp_srv);
serviceClose(&tmp_srv);
return rc;
}
static Result _appletStorageRW(AppletStorage *s, s64 offset, void* buffer, size_t size, bool rw) {
Result rc=0;
Service tmp_srv;//IStorageAccessor
if (!serviceIsActive(&s->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
rc = _appletCmdGetSession(&s->s, &tmp_srv, 0);//Open
if (R_FAILED(rc)) return rc;
if (R_SUCCEEDED(rc)) rc = _appletStorageAccessorRW(&tmp_srv, tmp_srv.pointer_buffer_size, offset, buffer, size, rw);
serviceAssumeDomain(&tmp_srv);
serviceClose(&tmp_srv);
return rc;
}
Result appletStorageWrite(AppletStorage *s, s64 offset, const void* buffer, size_t size) {
return _appletStorageRW(s, offset, (void*)buffer, size, true);
}
Result appletStorageRead(AppletStorage *s, s64 offset, void* buffer, size_t size) {
return _appletStorageRW(s, offset, buffer, size, false);
}
static Result _appletStorageGetHandle(Service* srv, s64 *out, Handle *handle) {
Handle tmphandle = INVALID_HANDLE;
serviceAssumeDomain(srv);
Result rc = serviceDispatchOut(srv, 1, *out,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = &tmphandle,
);
if (R_SUCCEEDED(rc) && handle) *handle = tmphandle;
return rc;
}
Result appletStorageGetHandle(AppletStorage *s, s64 *out, Handle *handle) {
Result rc=0;
Service tmp_srv;//ITransferStorageAccessor
if (!serviceIsActive(&s->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdGetSession(&s->s, &tmp_srv, 1);//OpenTransferStorage
if (R_FAILED(rc)) return rc;
rc = _appletStorageGetHandle(&tmp_srv, out, handle);
serviceAssumeDomain(&tmp_srv);
serviceClose(&tmp_srv);
return rc;
}
Result appletStorageMap(AppletStorage *s, void** addr, size_t *size) {
Result rc=0;
s64 tmpsize=0;
Handle tmphandle=0;
rc = appletStorageGetHandle(s, &tmpsize, &tmphandle);
if (R_FAILED(rc)) return rc;
tmemLoadRemote(&s->tmem, tmphandle, tmpsize, Perm_None);
rc = tmemMap(&s->tmem);
if (R_FAILED(rc)) tmemClose(&s->tmem);
if (R_SUCCEEDED(rc)) {
if (addr) *addr = s->tmem.map_addr;
if (size) *size = s->tmem.size;
}
return rc;
}
// IApplicationFunctions
Result appletPopLaunchParameter(AppletStorage *s, AppletLaunchParameterKind kind) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
u32 tmp=kind;
memset(s, 0, sizeof(AppletStorage));
serviceAssumeDomain(&g_appletIFunctions);
return serviceDispatchIn(&g_appletIFunctions, 1, tmp,
.out_num_objects = 1,
.out_objects = &s->s,
);
}
static Result _appletCreateApplicationAndPushAndRequestToStart(Service* srv, u64 application_id, AppletStorage* s, u32 cmd_id) {
serviceAssumeDomain(srv);
return serviceDispatchIn(srv, cmd_id, application_id,
.in_num_objects = 1,
.in_objects = { &s->s },
);
}
static Result _appletCreateApplicationAndPushAndRequestToStartForQuest(u64 application_id, AppletStorage* s, const AppletApplicationAttributeForQuest *attr) { // [2.0.0+]
const struct {
u32 val0, val1;
u64 application_id;
} in = { attr->unk_x0, attr->unk_x4, application_id };
serviceAssumeDomain(&g_appletIFunctions);
return serviceDispatchIn(&g_appletIFunctions, 11, in,
.in_num_objects = 1,
.in_objects = { &s->s },
);
}
static Result _appletCreateApplicationAndRequestToStart(u64 application_id) { // [4.0.0+]
return _appletCmdInU64NoOut(&g_appletIFunctions, application_id, 12);
}
static Result _appletCreateApplicationAndRequestToStartForQuest(u64 application_id, const AppletApplicationAttributeForQuest *attr) { // [4.0.0+]
const struct {
u32 val0, val1;
u64 application_id;
} in = { attr->unk_x0, attr->unk_x4, application_id };
serviceAssumeDomain(&g_appletIFunctions);
return serviceDispatchIn(&g_appletIFunctions, 13, in);
}
static Result _appletCreateApplicationWithAttributeAndPushAndRequestToStartForQuest(u64 application_id, AppletStorage* s, const AppletApplicationAttribute *attr) { // [7.0.0+]
serviceAssumeDomain(&g_appletIFunctions);
return serviceDispatchIn(&g_appletIFunctions, 14, application_id,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { attr, sizeof(*attr) } },
.in_num_objects = 1,
.in_objects = { &s->s },
);
}
static Result _appletCreateApplicationWithAttributeAndRequestToStartForQuest(u64 application_id, const AppletApplicationAttribute *attr) { // [7.0.0+]
serviceAssumeDomain(&g_appletIFunctions);
return serviceDispatchIn(&g_appletIFunctions, 15, application_id,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { attr, sizeof(*attr) } },
);
}
Result appletRequestLaunchApplication(u64 application_id, AppletStorage* s) {
AppletStorage tmpstorage={0};
Result rc=0;
bool is_libraryapplet = hosversionAtLeast(5,0,0) && __nx_applet_type == AppletType_LibraryApplet;
if (!serviceIsActive(&g_appletSrv) || (!_appletIsApplication() && !is_libraryapplet))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (s && !serviceIsActive(&s->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if ((hosversionBefore(4,0,0) || is_libraryapplet) && s==NULL) {
s = &tmpstorage;
rc = appletCreateStorage(&tmpstorage, 0);
if (R_FAILED(rc)) return rc;
}
if (is_libraryapplet) {
rc = _appletCreateApplicationAndPushAndRequestToStart(&g_appletILibraryAppletSelfAccessor, application_id, s, 90);
}
else {
if (hosversionAtLeast(4,0,0) && s==NULL) {
rc = _appletCreateApplicationAndRequestToStart(application_id);
}
else {
rc = _appletCreateApplicationAndPushAndRequestToStart(&g_appletIFunctions, application_id, s, 10);
}
}
if (s) appletStorageClose(s);
return rc;
}
Result appletRequestLaunchApplicationForQuest(u64 application_id, AppletStorage* s, const AppletApplicationAttributeForQuest *attr) {
AppletStorage tmpstorage={0};
AppletApplicationAttribute appattr={0};
Result rc=0;
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (s && !serviceIsActive(&s->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0) && s==NULL) {
s = &tmpstorage;
rc = appletCreateStorage(&tmpstorage, 0);
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(7,0,0))
rc = _appletCreateApplicationWithAttributeAndRequestToStartForQuest(application_id, &appattr);
else
rc = _appletCreateApplicationAndRequestToStartForQuest(application_id, attr);
}
else {
if (hosversionBefore(3,0,0)) rc = MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
if (R_SUCCEEDED(rc)) {
if (hosversionAtLeast(7,0,0))
rc = _appletCreateApplicationWithAttributeAndPushAndRequestToStartForQuest(application_id, s, &appattr);
else
rc = _appletCreateApplicationAndPushAndRequestToStartForQuest(application_id, s, attr);
}
}
if (s) appletStorageClose(s);
return rc;
}
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletGetDesiredLanguage(u64 *LanguageCode), &g_appletIFunctions, 21, _appletCmdNoInOutU64, !_appletIsApplication(), LanguageCode)
Result appletGetDisplayVersion(char *displayVersion) {
char out[0x10]={0};
if (displayVersion) memset(displayVersion, 0, 0x10);
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
serviceAssumeDomain(&g_appletIFunctions);
Result rc = serviceDispatchOut(&g_appletIFunctions, 23, out);
if (R_SUCCEEDED(rc) && displayVersion) {
strncpy(displayVersion, out, 0x10);
displayVersion[0xf] = 0;
}
return rc;
}
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletBeginBlockingHomeButtonShortAndLongPressed(s64 val), &g_appletIFunctions, 30, _appletCmdInU64NoOut, !_appletIsApplication(), val)
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletEndBlockingHomeButtonShortAndLongPressed(void), &g_appletIFunctions, 31, _appletCmdNoIO, !_appletIsApplication())
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletBeginBlockingHomeButton(s64 val), &g_appletIFunctions, 32, _appletCmdInU64NoOut, !_appletIsApplication(), val)
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletEndBlockingHomeButton(void), &g_appletIFunctions, 33, _appletCmdNoIO, !_appletIsApplication())
void appletNotifyRunning(bool *out) {
if (__nx_applet_type!=AppletType_Application || g_appletNotifiedRunning) return;
g_appletNotifiedRunning = 1;
Result rc = _appletCmdNoInOutBool(&g_appletIFunctions, out, 40);
if (R_FAILED(rc)) fatalThrow(MAKERESULT(Module_Libnx, LibnxError_BadAppletNotifyRunning));
}
Result appletGetPseudoDeviceId(Uuid *out) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
serviceAssumeDomain(&g_appletIFunctions);
return serviceDispatchOut(&g_appletIFunctions, 50, *out);
}
Result appletSetMediaPlaybackState(bool state) {
if (!serviceIsActive(&g_appletSrv))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (!_appletIsApplication())
return _appletCmdInBoolNoOut(&g_appletISelfController, state, 61);//SetMediaPlaybackState
return _appletCmdInBoolNoOut(&g_appletIFunctions, state, 60);//SetMediaPlaybackStateForApplication
}
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER( Result appletIsGamePlayRecordingSupported(bool *flag), &g_appletIFunctions, 65, _appletCmdNoInOutBool, !_appletIsRegularApplication(), (3,0,0), flag)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(static Result _appletInitializeGamePlayRecording(TransferMemory *tmem), &g_appletIFunctions, 66, _appletCmdInTmemNoOut, !_appletIsRegularApplication(), (3,0,0), tmem)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER( Result appletSetGamePlayRecordingState(bool state), &g_appletIFunctions, 67, _appletCmdInU32NoOut, !_appletIsRegularApplication() || g_appletRecordingInitialized==0, (3,0,0), state!=0)
Result appletInitializeGamePlayRecording(void) {
Result rc=0;
size_t size = 0x6000000;
g_appletRecordingInitialized = 0;
//These checks are done in the called applet funcs, but do it here too so that tmemCreate() doesn't run when it's not needed.
if (!serviceIsActive(&g_appletSrv) || !_appletIsRegularApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = tmemCreate(&g_appletRecordingTmem, size, Perm_None);
if (R_FAILED(rc)) return rc;
rc = _appletInitializeGamePlayRecording(&g_appletRecordingTmem);
if (R_FAILED(rc)) {
tmemClose(&g_appletRecordingTmem);
return rc;
}
g_appletRecordingInitialized = 1;
rc = appletSetGamePlayRecordingState(1);
if (R_SUCCEEDED(rc)) g_appletRecordingInitialized = 2;
return rc;
}
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletRequestFlushGamePlayingMovieForDebug(void), &g_appletIFunctions, 68, _appletCmdNoIO, !_appletIsApplication(), (4,0,0))
Result appletRequestToShutdown(void) {
Result rc=0;
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdNoIO(&g_appletIFunctions, 70);
if (R_SUCCEEDED(rc)) _appletInfiniteSleepLoop();
return rc;
}
Result appletRequestToReboot(void) {
Result rc=0;
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdNoIO(&g_appletIFunctions, 71);
if (R_SUCCEEDED(rc)) _appletInfiniteSleepLoop();
return rc;
}
Result appletExitAndRequestToShowThanksMessage(void) {
Result rc=0;
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdNoIO(&g_appletIFunctions, 80);
if (R_SUCCEEDED(rc)) _appletInfiniteSleepLoop();
return rc;
}
static Result _appletInitializeApplicationCopyrightFrameBuffer(TransferMemory *tmem, s32 width, s32 height) {
const struct {
s32 width;
s32 height;
u64 size;
} in = { width, height, tmem->size };
serviceAssumeDomain(&g_appletIFunctions);
return serviceDispatchIn(&g_appletIFunctions, 100, in,
.in_num_handles = 1,
.in_handles = { tmem->handle },
);
}
Result appletInitializeApplicationCopyrightFrameBuffer(void) {
Result rc=0;
s32 width = 1280;
s32 height = 720;
size_t size = 0x3C0000;
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
if (g_appletCopyrightInitialized)
return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
rc = tmemCreate(&g_appletCopyrightTmem, size, Perm_None);
if (R_FAILED(rc)) return rc;
rc = _appletInitializeApplicationCopyrightFrameBuffer(&g_appletCopyrightTmem, width, height);
if (R_FAILED(rc)) {
tmemClose(&g_appletCopyrightTmem);
return rc;
}
g_appletCopyrightInitialized = 1;
return rc;
}
Result appletSetApplicationCopyrightImage(const void* buffer, size_t size, s32 x, s32 y, s32 width, s32 height, s32 mode) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
s32 x;
s32 y;
s32 width;
s32 height;
s32 mode;
} in = { x, y, width, height, mode };
serviceAssumeDomain(&g_appletIFunctions);
return serviceDispatchIn(&g_appletIFunctions, 101, in,
.buffer_attrs = { SfBufferAttr_HipcMapTransferAllowsNonSecure | SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { buffer, size } },
);
}
Result appletSetApplicationCopyrightVisibility(bool visible) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletCmdInBoolNoOut(&g_appletIFunctions, visible, 102);
}
//Official sw has these under 'pdm'.
Result appletQueryApplicationPlayStatistics(PdmApplicationPlayStatistics *stats, const u64 *application_ids, s32 count, s32 *total_out) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
serviceAssumeDomain(&g_appletIFunctions);
return serviceDispatchOut(&g_appletIFunctions, 110, *total_out,
.buffer_attrs = {
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
},
.buffers = {
{ stats, count*sizeof(PdmApplicationPlayStatistics) },
{ application_ids, count*sizeof(u64) },
},
);
}
Result appletQueryApplicationPlayStatisticsByUid(AccountUid uid, PdmApplicationPlayStatistics *stats, const u64 *application_ids, s32 count, s32 *total_out) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
serviceAssumeDomain(&g_appletIFunctions);
return serviceDispatchInOut(&g_appletIFunctions, 111, uid, *total_out,
.buffer_attrs = {
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
},
.buffers = {
{ stats, count*sizeof(PdmApplicationPlayStatistics) },
{ application_ids, count*sizeof(u64) },
},
);
}
static Result _appletExecuteProgramCmd(AppletProgramSpecifyKind kind, u64 inval) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u32 kind;
u64 inval;
} in = { kind, inval };
serviceAssumeDomain(&g_appletIFunctions);
return serviceDispatchIn(&g_appletIFunctions, 120, in);
}
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(static Result _appletClearUserChannel(void), &g_appletIFunctions, 121, _appletCmdNoIO, !_appletIsApplication(), (5,0,0))
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(static Result _appletUnpopToUserChannel(AppletStorage *s), &g_appletIFunctions, 122, _appletCmdInStorage, !_appletIsApplication(), (5,0,0), s)
static Result _appletExecuteProgram(AppletProgramSpecifyKind kind, u64 inval, const void* buffer, size_t size) {
Result rc=0;
AppletStorage storage={0};
if (size > 0x1000)
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (buffer!=NULL && size!=0) {
rc = appletCreateStorage(&storage, size);
if (R_SUCCEEDED(rc)) rc = appletStorageWrite(&storage, 0, buffer, size);
}
if (R_SUCCEEDED(rc)) rc = _appletClearUserChannel();
if (R_SUCCEEDED(rc) && buffer!=0 && size!=0) rc = _appletUnpopToUserChannel(&storage);
if (R_SUCCEEDED(rc)) rc = _appletExecuteProgramCmd(kind, inval);
appletStorageClose(&storage);
return rc;
}
Result appletExecuteProgram(s32 programIndex, const void* buffer, size_t size) {
Result rc=0;
if (programIndex<0 || programIndex>0xff) rc = MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (R_SUCCEEDED(rc)) rc = _appletExecuteProgram(AppletProgramSpecifyKind_ExecuteProgram, (u64)programIndex, buffer, size);
if (R_SUCCEEDED(rc)) _appletInfiniteSleepLoop();
return rc;
}
Result appletJumpToSubApplicationProgramForDevelopment(u64 application_id, const void* buffer, size_t size) {
return _appletExecuteProgram(AppletProgramSpecifyKind_JumpToSubApplicationProgramForDevelopment, application_id, buffer, size);
}
Result appletRestartProgram(const void* buffer, size_t size) {
return _appletExecuteProgram(AppletProgramSpecifyKind_RestartProgram, 0, buffer, size);
}
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetPreviousProgramIndex(s32 *programIndex), &g_appletIFunctions, 123, _appletCmdNoInOutU32, !_appletIsApplication(), (5,0,0), (u32*)programIndex)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetFriendInvitationStorageChannelEvent(Event *out_event), &g_appletIFunctions, 140, _appletCmdGetEvent, !_appletIsApplication(), (9,0,0), out_event, false)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletTryPopFromFriendInvitationStorageChannel(AppletStorage *s), &g_appletIFunctions, 141, _appletCmdNoInOutStorage, !_appletIsApplication(), (9,0,0), s)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetNotificationStorageChannelEvent(Event *out_event), &g_appletIFunctions, 150, _appletCmdGetEvent, !_appletIsApplication(), (9,0,0), out_event, false)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletTryPopFromNotificationStorageChannel(AppletStorage *s), &g_appletIFunctions, 151, _appletCmdNoInOutStorage, !_appletIsApplication(), (9,0,0), s)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetHealthWarningDisappearedSystemEvent(Event *out_event), &g_appletIFunctions, 160, _appletCmdGetEvent, !_appletIsApplication(), (9,0,0), out_event, false)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletSetHdcpAuthenticationActivated(bool flag), &g_appletIFunctions, 170, _appletCmdInBoolNoOut, !_appletIsApplication(), (9,0,0), flag)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletCreateMovieMaker(Service* srv_out, TransferMemory *tmem), &g_appletIFunctions, 1000, _appletCmdInTmemOutSession, !_appletIsApplication(), (5,0,0), srv_out, tmem)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletPrepareForJit(void), &g_appletIFunctions, 1001, _appletCmdNoIO, !_appletIsApplication(), (5,0,0))
// IHomeMenuFunctions
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletRequestToGetForeground(void), &g_appletIFunctions, 10, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet)
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletLockForeground(void), &g_appletIFunctions, 11, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet)
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletUnlockForeground(void), &g_appletIFunctions, 12, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet)
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletPopFromGeneralChannel(AppletStorage *s), &g_appletIFunctions, 20, _appletCmdNoInOutStorage, __nx_applet_type != AppletType_SystemApplet, s)
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletGetPopFromGeneralChannelEvent(Event *out_event), &g_appletIFunctions, 21, _appletCmdGetEvent, __nx_applet_type != AppletType_SystemApplet, out_event, false)
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletGetHomeButtonWriterLockAccessor(AppletLockAccessor *a), &g_appletIFunctions, 30, _appletGetHomeButtonRwLockAccessor, __nx_applet_type != AppletType_SystemApplet, a)
Result appletPopRequestLaunchApplicationForDebug(AccountUid *uids, s32 count, u64 *application_id, s32 *total_out) {
if (__nx_applet_type != AppletType_SystemApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
struct {
u64 application_id;
s32 total_out;
} out;
serviceAssumeDomain(&g_appletIFunctions);
Result rc = serviceDispatchOut(&g_appletIFunctions, 100, out,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { uids, count*sizeof(AccountUid) } },
);
if (R_SUCCEEDED(rc) && application_id) *application_id = out.application_id;
if (R_SUCCEEDED(rc) && total_out) *total_out = out.total_out;
return rc;
}
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletIsForceTerminateApplicationDisabledForDebug(bool *out), &g_appletIFunctions, 110, _appletCmdNoInOutBool, __nx_applet_type != AppletType_SystemApplet, (9,0,0), out)
Result appletLaunchDevMenu(void) {
Result rc=0;
if (__nx_applet_type != AppletType_SystemApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdNoIO(&g_appletIFunctions, 200);
if (R_SUCCEEDED(rc)) _appletInfiniteSleepLoop();
return rc;
}
// IGlobalStateController
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletStartSleepSequence(bool flag), &g_appletIGlobalStateController, 2, _appletCmdInBoolNoOut, __nx_applet_type != AppletType_SystemApplet, flag)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletStartShutdownSequence(void), &g_appletIGlobalStateController, 3, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletStartRebootSequence(void), &g_appletIGlobalStateController, 4, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletIsAutoPowerDownRequested(bool *out), &g_appletIGlobalStateController, 9, _appletCmdNoInOutBool, __nx_applet_type != AppletType_SystemApplet, (7,0,0), out)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletLoadAndApplyIdlePolicySettings(void), &g_appletIGlobalStateController, 10, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletNotifyCecSettingsChanged(void), &g_appletIGlobalStateController, 11, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet, (2,0,0))
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletSetDefaultHomeButtonLongPressTime(s64 val), &g_appletIGlobalStateController, 12, _appletCmdInU64NoOut, __nx_applet_type != AppletType_SystemApplet, (3,0,0), val)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletUpdateDefaultDisplayResolution(void), &g_appletIGlobalStateController, 13, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet, (3,0,0))
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletShouldSleepOnBoot(bool *out), &g_appletIGlobalStateController, 14, _appletCmdNoInOutBool, __nx_applet_type != AppletType_SystemApplet, (3,0,0), out)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetHdcpAuthenticationFailedEvent(Event *out_event), &g_appletIGlobalStateController, 15, _appletCmdGetEvent, __nx_applet_type != AppletType_SystemApplet, (4,0,0), out_event, false)
// IApplicationCreator
static Result _appletApplicationCreateState(AppletApplication *a) {
return _appletCmdGetEvent(&a->s, &a->StateChangedEvent, false, 0);//GetAppletStateChangedEvent
}
static Result _appletApplicationCreate(Service* srv, AppletApplication *a, u32 cmd_id) {
Result rc=0;
memset(a, 0, sizeof(AppletApplication));
rc = _appletCmdGetSession(srv, &a->s, cmd_id);
if (R_SUCCEEDED(rc)) rc = _appletApplicationCreateState(a);
return rc;
}
static Result _appletApplicationCreateIn64(Service* srv, AppletApplication *a, u64 val, u32 cmd_id) {
Result rc=0;
memset(a, 0, sizeof(AppletApplication));
rc = _appletCmdGetSessionInU64(srv, &a->s, val, cmd_id);
if (R_SUCCEEDED(rc)) rc = _appletApplicationCreateState(a);
return rc;
}
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletCreateApplication(AppletApplication *a, u64 application_id), &g_appletIApplicationCreator, 0, _appletApplicationCreateIn64, __nx_applet_type != AppletType_SystemApplet, a, application_id)
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletPopLaunchRequestedApplication(AppletApplication *a), &g_appletIApplicationCreator, 1, _appletApplicationCreate, __nx_applet_type != AppletType_SystemApplet, a)
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletCreateSystemApplication(AppletApplication *a, u64 system_application_id), &g_appletIApplicationCreator, 10, _appletApplicationCreateIn64, __nx_applet_type != AppletType_SystemApplet, a, system_application_id)
IPC_MAKE_CMD_IMPL_INITEXPR(Result appletPopFloatingApplicationForDevelopment(AppletApplication *a), &g_appletIApplicationCreator, 100, _appletApplicationCreate, __nx_applet_type != AppletType_SystemApplet, a)
// IApplicationAccessor
void appletApplicationClose(AppletApplication *a) {
eventClose(&a->StateChangedEvent);
serviceAssumeDomain(&a->s);
serviceClose(&a->s);
memset(a, 0, sizeof(AppletApplication));
}
bool appletApplicationActive(AppletApplication *a) {
return serviceIsActive(&a->s);
}
IPC_MAKE_CMD_IMPL(Result appletApplicationStart(AppletApplication *a), &a->s, 10, _appletCmdNoIO)
IPC_MAKE_CMD_IMPL(Result appletApplicationRequestExit(AppletApplication *a), &a->s, 20, _appletCmdNoIO)
IPC_MAKE_CMD_IMPL(Result appletApplicationTerminate(AppletApplication *a), &a->s, 25, _appletCmdNoIO)
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;
}
IPC_MAKE_CMD_IMPL(Result appletApplicationRequestForApplicationToGetForeground(AppletApplication *a), &a->s, 101, _appletCmdNoIO)
IPC_MAKE_CMD_IMPL(Result appletApplicationTerminateAllLibraryApplets(AppletApplication *a), &a->s, 110, _appletCmdNoIO)
IPC_MAKE_CMD_IMPL(Result appletApplicationAreAnyLibraryAppletsLeft(AppletApplication *a, bool *out), &a->s, 111, _appletCmdNoInOutBool, out)
Result appletApplicationRequestExitLibraryAppletOrTerminate(AppletApplication *a, u64 timeout) {
Result rc=0;
Service srv={0};
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
rc = _appletCmdGetSession(&a->s, &srv, 112);//GetCurrentLibraryApplet
if (R_SUCCEEDED(rc)) rc = _appletAccessorRequestExitOrTerminate(&srv, timeout);
serviceAssumeDomain(&srv);
serviceClose(&srv);
return rc;
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationGetApplicationId(AppletApplication *a, u64 *application_id), &a->s, 120, _appletCmdNoInOutU64, (6,0,0), application_id)
Result appletApplicationPushLaunchParameter(AppletApplication *a, AppletLaunchParameterKind kind, AppletStorage* s) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletCmdInStorageU32(&a->s, s, kind, 121);
}
IPC_MAKE_CMD_IMPL( Result appletApplicationGetApplicationControlProperty(AppletApplication *a, NacpStruct *nacp), &a->s, 122, _appletCmdNoInRecvBuf, nacp, sizeof(*nacp))
IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationGetApplicationLaunchProperty(AppletApplication *a, AppletApplicationLaunchProperty *out), &a->s, 123, _appletCmdNoInRecvBuf, (2,0,0), out, sizeof(*out))
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);
serviceAssumeDomain(&a->s);
return serviceDispatchOut(&a->s, 124, *out);
}
Result appletApplicationSetUsers(AppletApplication *a, const AccountUid *uids, 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);
u8 tmp = flag!=0;
serviceAssumeDomain(&a->s);
return serviceDispatchIn(&a->s, 130, tmp,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { uids, count*sizeof(AccountUid) } },
);
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationCheckRightsEnvironmentAvailable(AppletApplication *a, bool *out), &a->s, 131, _appletCmdNoInOutBool, (6,0,0), out)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationGetNsRightsEnvironmentHandle(AppletApplication *a, u64 *handle), &a->s, 132, _appletCmdNoInOutU64, (6,0,0), handle)
Result appletApplicationGetDesirableUids(AppletApplication *a, AccountUid *uids, 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);
serviceAssumeDomain(&a->s);
return serviceDispatchOut(&a->s, 140, *total_out,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { uids, count*sizeof(AccountUid) } },
);
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationReportApplicationExitTimeout(AppletApplication *a), &a->s, 150, _appletCmdNoIO, (6,0,0))
IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationSetApplicationAttribute(AppletApplication *a, const AppletApplicationAttribute *attr), &a->s, 160, _appletCmdSendBufNoOut, (8,0,0), attr, sizeof(*attr))
Result appletApplicationHasSaveDataAccessPermission(AppletApplication *a, u64 application_id, bool *out) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
u8 tmpout=0;
serviceAssumeDomain(&a->s);
Result rc = serviceDispatchInOut(&a->s, 170, application_id, tmpout);
if (R_SUCCEEDED(rc) && out) *out = tmpout & 1;
return rc;
}
static Result _appletPushToFriendInvitationStorageChannel(Service* srv, AccountUid uid, const void* buffer, u64 size, u32 cmd_id) {
if (hosversionBefore(9,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
Result rc=0;
AppletStorage storage;
rc = appletCreateStorage(&storage, size+sizeof(uid));
if (R_SUCCEEDED(rc)) rc = appletStorageWrite(&storage, 0, &uid, sizeof(uid));
if (R_SUCCEEDED(rc)) rc = appletStorageWrite(&storage, sizeof(uid), buffer, size);
if (R_SUCCEEDED(rc)) rc = _appletCmdInStorage(srv, &storage, cmd_id);
appletStorageClose(&storage);
return rc;
}
static Result _appletPushToNotificationStorageChannel(Service* srv, const void* buffer, u64 size, u32 cmd_id) {
if (hosversionBefore(9,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
Result rc=0;
AppletStorage storage;
rc = appletCreateStorage(&storage, size);
if (R_SUCCEEDED(rc)) rc = appletStorageWrite(&storage, 0, buffer, size);
if (R_SUCCEEDED(rc)) rc = _appletCmdInStorage(srv, &storage, cmd_id);
appletStorageClose(&storage);
return rc;
}
Result appletApplicationPushToFriendInvitationStorageChannel(AppletApplication *a, AccountUid uid, const void* buffer, u64 size) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletPushToFriendInvitationStorageChannel(&a->s, uid, buffer, size, 180);
}
Result appletApplicationPushToNotificationStorageChannel(AppletApplication *a, const void* buffer, u64 size) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletPushToNotificationStorageChannel(&a->s, buffer, size, 190);
}
// ILibraryAppletSelfAccessor
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPopInData(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 0, _appletCmdNoInOutStorage, __nx_applet_type != AppletType_LibraryApplet, s)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPushOutData(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 1, _appletCmdInStorage, __nx_applet_type != AppletType_LibraryApplet, s)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPopInteractiveInData(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 2, _appletCmdNoInOutStorage, __nx_applet_type != AppletType_LibraryApplet, s)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPushInteractiveOutData(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 3, _appletCmdInStorage, __nx_applet_type != AppletType_LibraryApplet, s)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetPopInDataEvent(Event *out_event), &g_appletILibraryAppletSelfAccessor, 5, _appletCmdGetEvent, __nx_applet_type != AppletType_LibraryApplet, out_event, false)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetPopInteractiveInDataEvent(Event *out_event), &g_appletILibraryAppletSelfAccessor, 6, _appletCmdGetEvent, __nx_applet_type != AppletType_LibraryApplet, out_event, false)
IPC_MAKE_CMD_IMPL_INITEXPR(static Result _appletExitProcessAndReturn(void), &g_appletILibraryAppletSelfAccessor, 10, _appletCmdNoIO, __nx_applet_type != AppletType_LibraryApplet)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetLibraryAppletInfo(LibAppletInfo *info), &g_appletILibraryAppletSelfAccessor, 11, _appletGetLibraryAppletInfo, __nx_applet_type != AppletType_LibraryApplet, info)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetMainAppletIdentityInfo(AppletIdentityInfo *info), &g_appletILibraryAppletSelfAccessor, 12, _appletGetIdentityInfo, __nx_applet_type != AppletType_LibraryApplet, info)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletCanUseApplicationCore(bool *out), &g_appletILibraryAppletSelfAccessor, 13, _appletCmdNoInOutBool, __nx_applet_type != AppletType_LibraryApplet, out)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetCallerAppletIdentityInfo(AppletIdentityInfo *info), &g_appletILibraryAppletSelfAccessor, 14, _appletGetIdentityInfo, __nx_applet_type != AppletType_LibraryApplet, info)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetMainAppletApplicationControlProperty(NacpStruct *nacp), &g_appletILibraryAppletSelfAccessor, 15, _appletCmdNoInRecvBuf, __nx_applet_type != AppletType_LibraryApplet, (2,0,0), nacp, sizeof(*nacp))
Result appletGetMainAppletStorageId(NcmStorageId *storageId) {
u8 tmp=0;
Result rc=0;
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdNoInOutU8(&g_appletILibraryAppletSelfAccessor, &tmp, 16);
if (R_SUCCEEDED(rc) && storageId) *storageId = tmp;
return rc;
}
Result appletGetCallerAppletIdentityInfoStack(AppletIdentityInfo *stack, s32 count, s32 *total_out) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
serviceAssumeDomain(&g_appletILibraryAppletSelfAccessor);
return serviceDispatchOut(&g_appletILibraryAppletSelfAccessor, 17, *total_out,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { stack, count*sizeof(AppletIdentityInfo) } },
);
}
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetNextReturnDestinationAppletIdentityInfo(AppletIdentityInfo *info), &g_appletILibraryAppletSelfAccessor, 18, _appletGetIdentityInfo, __nx_applet_type != AppletType_LibraryApplet, (4,0,0), info)
Result appletGetDesirableKeyboardLayout(SetKeyboardLayout *layout) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
u32 tmp=0;
Result rc = _appletCmdNoInOutU32(&g_appletILibraryAppletSelfAccessor, &tmp, 19);
if (R_SUCCEEDED(rc) && layout) *layout = tmp;
return rc;
}
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPopExtraStorage(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 20, _appletCmdNoInOutStorage, __nx_applet_type != AppletType_LibraryApplet, s)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetPopExtraStorageEvent(Event *out_event), &g_appletILibraryAppletSelfAccessor, 25, _appletCmdGetEvent, __nx_applet_type != AppletType_LibraryApplet, out_event, false)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletUnpopInData(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 30, _appletCmdInStorage, __nx_applet_type != AppletType_LibraryApplet, s)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletUnpopExtraStorage(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 31, _appletCmdInStorage, __nx_applet_type != AppletType_LibraryApplet, s)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetIndirectLayerProducerHandle(u64 *out), &g_appletILibraryAppletSelfAccessor, 40, _appletCmdNoInOutU64, __nx_applet_type != AppletType_LibraryApplet, (2,0,0), out)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetMainAppletApplicationDesiredLanguage(u64 *LanguageCode), &g_appletILibraryAppletSelfAccessor, 60, _appletCmdNoInOutU64, __nx_applet_type != AppletType_LibraryApplet, (4,0,0), LanguageCode)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetCurrentApplicationId(u64 *application_id), &g_appletILibraryAppletSelfAccessor, 70, _appletCmdNoInOutU64, __nx_applet_type != AppletType_LibraryApplet, (8,0,0), application_id)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletRequestExitToSelf(void), &g_appletILibraryAppletSelfAccessor, 80, _appletCmdNoIO, __nx_applet_type != AppletType_LibraryApplet, (6,0,0))
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletCreateGameMovieTrimmer(Service* srv_out, TransferMemory *tmem), &g_appletILibraryAppletSelfAccessor, 100, _appletCmdInTmemOutSession, __nx_applet_type != AppletType_LibraryApplet, (4,0,0), srv_out, tmem)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletReserveResourceForMovieOperation(void), &g_appletILibraryAppletSelfAccessor, 101, _appletCmdNoIO, __nx_applet_type != AppletType_LibraryApplet, (5,0,0))
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletUnreserveResourceForMovieOperation(void), &g_appletILibraryAppletSelfAccessor, 102, _appletCmdNoIO, __nx_applet_type != AppletType_LibraryApplet, (5,0,0))
Result appletGetMainAppletAvailableUsers(AccountUid *uids, s32 count, bool *flag, s32 *total_out) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
struct {
u8 flag;
s32 total_out;
} out;
serviceAssumeDomain(&g_appletILibraryAppletSelfAccessor);
Result rc = serviceDispatchOut(&g_appletILibraryAppletSelfAccessor, 110, out,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { uids, count*sizeof(AccountUid) } },
);
if (R_SUCCEEDED(rc) && flag) *flag = out.flag & 1;
if (R_SUCCEEDED(rc) && total_out) *total_out = out.total_out;
return rc;
}
// IOverlayFunctions
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletBeginToWatchShortHomeButtonMessage(void), &g_appletIFunctions, 0, _appletCmdNoIO, __nx_applet_type != AppletType_OverlayApplet)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletEndToWatchShortHomeButtonMessage(void), &g_appletIFunctions, 1, _appletCmdNoIO, __nx_applet_type != AppletType_OverlayApplet)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetApplicationIdForLogo(u64 *application_id), &g_appletIFunctions, 2, _appletCmdNoInOutU64, __nx_applet_type != AppletType_OverlayApplet, application_id)
IPC_MAKE_CMD_IMPL_INITEXPR( Result appletSetGpuTimeSliceBoost(u64 val), &g_appletIFunctions, 3, _appletCmdInU64NoOut, __nx_applet_type != AppletType_OverlayApplet, val)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletSetAutoSleepTimeAndDimmingTimeEnabled(bool flag), &g_appletIFunctions, 4, _appletCmdInBoolNoOut, __nx_applet_type != AppletType_OverlayApplet, (2,0,0), flag)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletTerminateApplicationAndSetReason(Result reason), &g_appletIFunctions, 5, _appletCmdInU32NoOut, __nx_applet_type != AppletType_OverlayApplet, (2,0,0), reason)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletSetScreenShotPermissionGlobally(bool flag), &g_appletIFunctions, 6, _appletCmdInBoolNoOut, __nx_applet_type != AppletType_OverlayApplet, (3,0,0), flag)
Result appletStartShutdownSequenceForOverlay(void) {
Result rc=0;
if (__nx_applet_type != AppletType_OverlayApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdNoIO(&g_appletIFunctions, 10);
if (R_SUCCEEDED(rc)) _appletInfiniteSleepLoop();
return rc;
}
Result appletStartRebootSequenceForOverlay(void) {
Result rc=0;
if (__nx_applet_type != AppletType_OverlayApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
rc = _appletCmdNoIO(&g_appletIFunctions, 11);
if (R_SUCCEEDED(rc)) _appletInfiniteSleepLoop();
return rc;
}
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletSetHealthWarningShowingState(bool flag), &g_appletIFunctions, 30, _appletCmdInBoolNoOut, __nx_applet_type != AppletType_OverlayApplet, (9,0,0), flag)
IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletBeginToObserveHidInputForDevelop(void), &g_appletIFunctions, 101, _appletCmdNoIO, __nx_applet_type != AppletType_OverlayApplet, (5,0,0))
// IAppletCommonFunctions
Result appletReadThemeStorage(void* buffer, size_t size, u64 offset, u64 *transfer_size) {
if (!serviceIsActive(&g_appletIAppletCommonFunctions))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
serviceAssumeDomain(&g_appletIAppletCommonFunctions);
return serviceDispatchInOut(&g_appletIAppletCommonFunctions, 10, offset, *transfer_size,
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
.buffers = { { buffer, size } },
);
}
Result appletWriteThemeStorage(const void* buffer, size_t size, u64 offset) {
if (!serviceIsActive(&g_appletIAppletCommonFunctions))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
serviceAssumeDomain(&g_appletIAppletCommonFunctions);
return serviceDispatchIn(&g_appletIAppletCommonFunctions, 11, offset,
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_In },
.buffers = { { buffer, size } },
);
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletPushToAppletBoundChannel(AppletStorage *s), &g_appletIAppletCommonFunctions, 20, _appletCmdInStorage, (9,0,0), s)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletTryPopFromAppletBoundChannel(AppletStorage *s), &g_appletIAppletCommonFunctions, 21, _appletCmdNoInOutStorage, (9,0,0), s)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetDisplayLogicalResolution(s32 *width, s32 *height), &g_appletIAppletCommonFunctions, 40, _appletGetResolution, (8,0,0), width, height)
Result appletSetDisplayMagnification(float x, float y, float width, float height) {
if (!serviceIsActive(&g_appletIAppletCommonFunctions))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
float x;
float y;
float width;
float height;
} in = { x, y, width, height };
serviceAssumeDomain(&g_appletIAppletCommonFunctions);
return serviceDispatchIn(&g_appletIAppletCommonFunctions, 42, in);
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetHomeButtonDoubleClickEnabled(bool flag), &g_appletIAppletCommonFunctions, 50, _appletCmdInBoolNoOut, (8,0,0), flag)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetHomeButtonDoubleClickEnabled(bool *out), &g_appletIAppletCommonFunctions, 51, _appletCmdNoInOutBool, (8,0,0), out)
// IDebugFunctions
IPC_MAKE_CMD_IMPL(Result appletOpenMainApplication(AppletApplication *a), &g_appletIDebugFunctions, 1, _appletApplicationCreate, a)
IPC_MAKE_CMD_IMPL(Result appletPerformSystemButtonPressing(AppletSystemButtonType type), &g_appletIDebugFunctions, 10, _appletCmdInU32NoOut, type)
IPC_MAKE_CMD_IMPL(Result appletInvalidateTransitionLayer(void), &g_appletIDebugFunctions, 20, _appletCmdNoIO)
Result appletRequestLaunchApplicationWithUserAndArgumentForDebug(u64 application_id, const AccountUid *uids, s32 total_uids, bool flag, const void* buffer, size_t size) {
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u8 flag;
u64 application_id;
} in = { flag!=0, application_id };
serviceAssumeDomain(&g_appletIDebugFunctions);
return serviceDispatchIn(&g_appletIDebugFunctions, 30, in,
.buffer_attrs = {
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
},
.buffers = {
{ uids, total_uids*sizeof(AccountUid) },
{ buffer, size },
},
);
}
Result appletGetAppletResourceUsageInfo(AppletResourceUsageInfo *info) {
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
serviceAssumeDomain(&g_appletIDebugFunctions);
return serviceDispatchOut(&g_appletIDebugFunctions, 40, *info);
}
IPC_MAKE_CMD_IMPL_HOSVER(Result appletPushToAppletBoundChannelForDebug(AppletStorage *s, s32 channel), &g_appletIDebugFunctions, 110, _appletCmdInStorageU32, (9,0,0), s, channel)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletTryPopFromAppletBoundChannelForDebug(AppletStorage *s, s32 channel), &g_appletIDebugFunctions, 111, _appletCmdInU32OutStorage, (9,0,0), s, channel)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletAlarmSettingNotificationEnableAppEventReserve(AppletStorage *s, u64 application_id), &g_appletIDebugFunctions, 120, _appletCmdInStorageU64, (9,0,0), s, application_id)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletAlarmSettingNotificationDisableAppEventReserve(void), &g_appletIDebugFunctions, 121, _appletCmdNoIO, (9,0,0))
IPC_MAKE_CMD_IMPL_HOSVER(Result appletAlarmSettingNotificationPushAppEventNotify(const void* buffer, u64 size), &g_appletIDebugFunctions, 122, _appletPushToNotificationStorageChannel, (9,0,0), buffer, size)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletFriendInvitationSetApplicationParameter(AppletStorage *s, u64 application_id), &g_appletIDebugFunctions, 130, _appletCmdInStorageU64, (9,0,0), s, application_id)
IPC_MAKE_CMD_IMPL_HOSVER(Result appletFriendInvitationClearApplicationParameter(void), &g_appletIDebugFunctions, 131, _appletCmdNoIO, (9,0,0))
IPC_MAKE_CMD_IMPL_HOSVER(Result appletFriendInvitationPushApplicationParameter(AccountUid uid, const void* buffer, u64 size), &g_appletIDebugFunctions, 132, _appletPushToFriendInvitationStorageChannel, (9,0,0), uid, buffer, size)
// Common cmds
Result appletSetTerminateResult(Result res) {
if (!serviceIsActive(&g_appletSrv) || (!_appletIsApplication() && !serviceIsActive(&g_appletIAppletCommonFunctions)))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (serviceIsActive(&g_appletIAppletCommonFunctions) && hosversionBefore(9,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
Service *srv = &g_appletIFunctions;
u32 cmd_id = 22;
if (serviceIsActive(&g_appletIAppletCommonFunctions)) {
srv = &g_appletIAppletCommonFunctions;
cmd_id = 0;
}
return _appletCmdInU32NoOut(srv, res, cmd_id);
}
Result appletGetLaunchStorageInfoForDebug(NcmStorageId *app_storageId, NcmStorageId *update_storageId) {
if (!serviceIsActive(&g_appletSrv) || (!_appletIsApplication() && __nx_applet_type != AppletType_LibraryApplet))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (_appletIsApplication() && hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
if (__nx_applet_type == AppletType_LibraryApplet && hosversionBefore(9,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
Service *srv = &g_appletIFunctions;
u32 cmd_id = 24;
if (__nx_applet_type == AppletType_LibraryApplet) {
srv = &g_appletILibraryAppletSelfAccessor;
cmd_id = 120;
}
struct {
u8 app_storageId;
u8 update_storageId;
} out;
serviceAssumeDomain(srv);
Result rc = serviceDispatchOut(srv, cmd_id, out);
if (R_SUCCEEDED(rc) && app_storageId) *app_storageId = out.app_storageId;
if (R_SUCCEEDED(rc) && update_storageId) *update_storageId = out.update_storageId;
return rc;
}
Result appletGetGpuErrorDetectedSystemEvent(Event *out_event) {
if (!serviceIsActive(&g_appletSrv) || (!_appletIsApplication() && __nx_applet_type != AppletType_LibraryApplet))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (_appletIsApplication() && hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
if (__nx_applet_type == AppletType_LibraryApplet && hosversionBefore(9,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
Service *srv = &g_appletIFunctions;
if (__nx_applet_type == AppletType_LibraryApplet)
srv = &g_appletILibraryAppletSelfAccessor;
return _appletCmdGetEvent(srv, out_event, false, 130);
}
Result appletSetHandlingHomeButtonShortPressedEnabled(bool flag) {
if (__nx_applet_type == AppletType_OverlayApplet && hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
if (__nx_applet_type != AppletType_OverlayApplet && hosversionBefore(9,1,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
Service *srv = &g_appletIFunctions;
u32 cmd_id = 20;
if (__nx_applet_type != AppletType_OverlayApplet && hosversionAtLeast(9,1,0)) {
srv = &g_appletICommonStateGetter;
cmd_id = 100;
}
return _appletCmdInBoolNoOut(srv, flag, cmd_id);
}
// State / other
AppletOperationMode appletGetOperationMode(void) {
return g_appletOperationMode;
}
ApmPerformanceMode appletGetPerformanceMode(void) {
return g_appletPerformanceMode;
}
AppletFocusState appletGetFocusState(void) {
return (AppletFocusState)g_appletFocusState;
}
AppletInfo *appletGetAppletInfo(void) {
if (!g_appletInfoInitialized) return NULL;
return &g_appletInfo;
}
Result appletGetMessage(u32 *msg) {
Result rc=0;
if (msg==NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput);
rc = eventWait(&g_appletMessageEvent, 0);
if (R_FAILED(rc))
return rc;
rc = _appletReceiveMessage(msg);
if (R_FAILED(rc)) {
if (R_VALUE(rc) == MAKERESULT(128, 3))
return rc;
fatalThrow(MAKERESULT(Module_Libnx, LibnxError_BadAppletReceiveMessage));
}
return 0;
}
bool appletProcessMessage(u32 msg) {
Result rc=0;
switch(msg) {
case AppletMessage_ExitRequested:
appletCallHook(AppletHookType_OnExitRequest);
return false;
break;
case AppletMessage_FocusStateChanged:
rc = _appletGetCurrentFocusState(&g_appletFocusState);
if (R_FAILED(rc))
fatalThrow(MAKERESULT(Module_Libnx, LibnxError_BadAppletGetCurrentFocusState));
appletCallHook(AppletHookType_OnFocusState);
break;
case AppletMessage_Restart:
appletCallHook(AppletHookType_OnRestart);
break;
case AppletMessage_OperationModeChanged:
rc = _appletGetOperationMode(&g_appletOperationMode);
if (R_FAILED(rc))
fatalThrow(MAKERESULT(Module_Libnx, LibnxError_BadAppletGetOperationMode));
appletCallHook(AppletHookType_OnOperationMode);
break;
case AppletMessage_PerformanceModeChanged:
rc = _appletGetPerformanceMode(&g_appletPerformanceMode);
if (R_FAILED(rc))
fatalThrow(MAKERESULT(Module_Libnx, LibnxError_BadAppletGetPerformanceMode));
appletCallHook(AppletHookType_OnPerformanceMode);
break;
case AppletMessage_RequestToDisplay:
appletCallHook(AppletHookType_RequestToDisplay);
break;
case AppletMessage_CaptureButtonShortPressed:
appletCallHook(AppletHookType_OnCaptureButtonShortPressed);
break;
case AppletMessage_AlbumImageTaken:
appletCallHook(AppletHookType_OnAlbumImageTaken);
break;
}
return true;
}
bool appletMainLoop(void) {
u32 msg = 0;
if (R_FAILED(appletGetMessage(&msg))) return true;
return appletProcessMessage(msg);
}