mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
177 lines
5.4 KiB
C
177 lines
5.4 KiB
C
#include <string.h>
|
|
#include "types.h"
|
|
#include "result.h"
|
|
#include "arm/counter.h"
|
|
#include "services/applet.h"
|
|
#include "applets/libapplet.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));
|
|
}
|
|
|