#include #include "libapplet_internal.h" #include "arm/counter.h" #include "runtime/hosversion.h" static bool g_libappletJumpFlag; void libappletArgsCreate(LibAppletArgs* a, u32 version) { memset(a, 0, sizeof(LibAppletArgs)); a->CommonArgs_version = 1; a->CommonArgs_size = sizeof(LibAppletArgs); a->LaVersion = version; a->ExpectedThemeColor = appletGetThemeColorType(); } void libappletArgsSetPlayStartupSound(LibAppletArgs* a, bool flag) { a->PlayStartupSound = flag!=0; } Result libappletCreateWriteStorage(AppletStorage* s, const void* buffer, size_t size) { Result rc=0; rc = appletCreateStorage(s, size); if (R_FAILED(rc)) return rc; rc = appletStorageWrite(s, 0, buffer, size); if (R_FAILED(rc)) { appletStorageClose(s); return rc; } return rc; } Result libappletReadStorage(AppletStorage* s, void* buffer, size_t size, size_t *transfer_size) { Result rc=0; s64 tmpsize=0; rc = appletStorageGetSize(s, &tmpsize); if (R_SUCCEEDED(rc)) { if (tmpsize < size) size = tmpsize; rc = appletStorageRead(s, 0, buffer, size); } if (R_SUCCEEDED(rc) && transfer_size) *transfer_size = size; return rc; } static Result _libappletPushInData(AppletHolder *h, const void* buffer, size_t size) { Result rc=0; AppletStorage storage; rc = libappletCreateWriteStorage(&storage, buffer, size); if (R_FAILED(rc)) return rc; return appletHolderPushInData(h, &storage); } Result libappletArgsPush(LibAppletArgs* a, AppletHolder *h) { //Official sw stores the header in LibAppletArgs seperately (first 8-bytes), but here we're including it with the LibAppletCommonArguments struct. //Official sw uses appletStorageWrite twice, for writing the header then the rest of the struct. a->tick = armGetSystemTick(); return _libappletPushInData(h, a, sizeof(LibAppletArgs)); } Result libappletArgsPop(LibAppletArgs* a) { //Official sw stores the header in LibAppletArgs seperately (first 8-bytes), but here we're including it with the LibAppletCommonArguments struct. //Official sw uses appletStorageRead twice, for reading the header then the rest of the struct. AppletStorage storage; s64 tmpsize=0; size_t tmpsize2=0; Result rc=0; memset(a, 0, sizeof(LibAppletArgs)); rc = appletPopInData(&storage); if (R_SUCCEEDED(rc)) rc = appletStorageGetSize(&storage, &tmpsize); if (R_SUCCEEDED(rc) && tmpsize != sizeof(LibAppletArgs)) rc = MAKERESULT(Module_Libnx, LibnxError_BadInput); if (R_SUCCEEDED(rc)) rc = libappletReadStorage(&storage, a, sizeof(LibAppletArgs), &tmpsize2); if (R_SUCCEEDED(rc) && tmpsize2 != sizeof(LibAppletArgs)) rc = MAKERESULT(Module_Libnx, LibnxError_BadInput); if (R_SUCCEEDED(rc)) { if (a->CommonArgs_version != 1 || a->CommonArgs_size != sizeof(LibAppletArgs)) rc = MAKERESULT(Module_Libnx, LibnxError_BadInput); } return rc; } static Result _libappletQlaunchRequest(u8* buf, size_t size) { Result rc=0; AppletStorage storage; rc = libappletCreateWriteStorage(&storage, buf, size); if (R_FAILED(rc)) return rc; return appletPushToGeneralChannel(&storage); } Result libappletPushInData(AppletHolder *h, const void* buffer, size_t size) { return _libappletPushInData(h, buffer, size); } Result libappletPopOutData(AppletHolder *h, void* buffer, size_t size, size_t *transfer_size) { Result rc=0; AppletStorage storage; rc = appletHolderPopOutData(h, &storage); if (R_FAILED(rc)) return rc; rc = libappletReadStorage(&storage, buffer, size, transfer_size); appletStorageClose(&storage); return rc; } void libappletSetJumpFlag(bool flag) { g_libappletJumpFlag = flag; } Result libappletStart(AppletHolder *h) { Result rc=0; if (g_libappletJumpFlag) return appletHolderJump(h); rc = appletHolderStart(h); if (R_SUCCEEDED(rc)) { appletHolderJoin(h); LibAppletExitReason reason = appletHolderGetExitReason(h); if (reason == LibAppletExitReason_Canceled || reason == LibAppletExitReason_Abnormal || reason == LibAppletExitReason_Unexpected) { rc = MAKERESULT(Module_Libnx, LibnxError_LibAppletBadExit); } } return rc; } Result libappletLaunch(AppletId id, LibAppletArgs *commonargs, const void* arg, size_t arg_size, void* reply, size_t reply_size, size_t *out_reply_size) { Result rc=0; AppletHolder holder; rc = appletCreateLibraryApplet(&holder, id, LibAppletMode_AllForeground); if (R_FAILED(rc)) return rc; rc = libappletArgsPush(commonargs, &holder); if (R_SUCCEEDED(rc) && arg && arg_size) rc = libappletPushInData(&holder, arg, arg_size); if (R_SUCCEEDED(rc)) rc = libappletStart(&holder); if (R_SUCCEEDED(rc) && reply && reply_size) rc = libappletPopOutData(&holder, reply, reply_size, out_reply_size); appletHolderClose(&holder); return rc; } Result libappletRequestHomeMenu(void) { u8 storagedata[0x10] = {0x53, 0x41, 0x4d, 0x53, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};//RequestHomeMenu return _libappletQlaunchRequest(storagedata, sizeof(storagedata)); } Result libappletRequestJumpToSystemUpdate(void) { u8 storagedata[0x10] = {0x53, 0x41, 0x4d, 0x53, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};//RequestJumpToSystemUpdate return _libappletQlaunchRequest(storagedata, sizeof(storagedata)); } Result libappletRequestToLaunchApplication(u64 application_id, AccountUid uid, const void* buffer, size_t size, u32 sender) { if (hosversionBefore(11,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); Result rc=0; u32 tmp=size; AppletStorage s={0}; u8 storagedata[0x10] = {0x53, 0x41, 0x4d, 0x53, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; rc = appletCreateStorage(&s, 0x800); if (R_FAILED(rc)) return rc; rc = appletStorageWrite(&s, 0, &storagedata, sizeof(storagedata)); if (R_SUCCEEDED(rc)) rc = appletStorageWrite(&s, sizeof(storagedata), &sender, sizeof(sender)); if (R_SUCCEEDED(rc)) rc = appletStorageWrite(&s, sizeof(storagedata)+sizeof(u32), &application_id, sizeof(application_id)); if (R_SUCCEEDED(rc)) rc = appletStorageWrite(&s, sizeof(storagedata)+sizeof(u32)+sizeof(u64), &uid, sizeof(AccountUid)); if (R_SUCCEEDED(rc)) rc = appletStorageWrite(&s, sizeof(storagedata)+sizeof(u32)+sizeof(u64)+sizeof(AccountUid), &tmp, sizeof(tmp)); if (R_SUCCEEDED(rc)) rc = appletStorageWrite(&s, sizeof(storagedata)+sizeof(u32)+sizeof(u64)+sizeof(AccountUid)+sizeof(tmp), buffer, tmp); if (R_FAILED(rc)) { appletStorageClose(&s); return rc; } return appletPushToGeneralChannel(&s); } Result libappletRequestJumpToStory(AccountUid uid, u64 application_id) { if (hosversionBefore(11,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); u8 storagedata[0x28] = {0x53, 0x41, 0x4d, 0x53, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; memcpy(&storagedata[0x10], &uid, sizeof(uid)); memcpy(&storagedata[0x20], &application_id, sizeof(application_id)); return _libappletQlaunchRequest(storagedata, sizeof(storagedata)); }