diff --git a/nx/include/switch/services/applet.h b/nx/include/switch/services/applet.h index 3526a3c9..c6367a19 100644 --- a/nx/include/switch/services/applet.h +++ b/nx/include/switch/services/applet.h @@ -6,6 +6,7 @@ */ #pragma once #include "../types.h" +#include "../services/sm.h" typedef enum { AppletType_None = -2, @@ -60,6 +61,11 @@ struct AppletHookCookie void* param; ///< Callback parameter. }; +/// applet IStorage +typedef struct { + Service s; +} AppletStorage; + Result appletInitialize(void); void appletExit(void); Result appletGetAppletResourceUserId(u64 *out); @@ -110,6 +116,37 @@ Result appletSetScreenShotPermission(s32 val); Result appletSetScreenShotImageOrientation(s32 val); +/** + * @brief Creates a storage. + * @param s Storage object. + * @param size Size of storage. + */ +Result appletCreateStorage(AppletStorage *s, s64 size); + +/// Closes the storage object. +void appletStorageClose(AppletStorage *s); + +/// Gets the size of the storage. +Result appletStorageGetSize(AppletStorage *s, s64 *size); + +/** + * @brief Writes to a storage. offset(+size) must be within the actual storage size. + * @param s Storage object. + * @param offset Offset in storage. + * @param buffer Input data. + * @param size Data size. + */ +Result appletStorageWrite(AppletStorage *s, s64 offset, const void* buffer, size_t size); + +/** + * @brief Reads from a storage. offset(+size) must be within the actual storage size. + * @param s Storage object. + * @param offset Offset in storage. + * @param buffer Input data. + * @param size Data size. + */ +Result appletStorageRead(AppletStorage *s, s64 offset, void* buffer, size_t size); + /** * @brief Processes the current applet status. Generally used within a main loop. * @return Whether the application should continue running. diff --git a/nx/source/services/applet.c b/nx/source/services/applet.c index 492be55e..8681e1c1 100644 --- a/nx/source/services/applet.c +++ b/nx/source/services/applet.c @@ -548,7 +548,45 @@ static Result _appletGetSessionProxy(Service* srv_out, u64 cmd_id, Handle procha return rc; } -static Result _appletGetAppletResourceUserId(u64 *out) { +static Result _appletGetSessionIn64(Service* srv, Service* srv_out, u64 cmd_id, u64 inval) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 inval; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + raw->inval = inval; + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreateSubservice(srv_out, srv, &r, 0); + } + } + + return rc; +} + +static Result _appletCmdNoIO(Service* session, u64 cmd_id) { IpcCommand c; ipcInitialize(&c); @@ -557,12 +595,44 @@ static Result _appletGetAppletResourceUserId(u64 *out) { u64 cmd_id; } *raw; - raw = serviceIpcPrepareHeader(&g_appletIWindowController, &c, sizeof(*raw)); + raw = serviceIpcPrepareHeader(session, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; + raw->cmd_id = cmd_id; - Result rc = serviceIpcDispatch(&g_appletIWindowController); + Result rc = serviceIpcDispatch(session); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(session, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +static Result _appletCmdNoInOut64(Service* srv, u64 *out, u64 cmd_id) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + + Result rc = serviceIpcDispatch(srv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -572,12 +642,12 @@ static Result _appletGetAppletResourceUserId(u64 *out) { u64 out; } *resp; - serviceIpcParse(&g_appletIWindowController, &r, sizeof(*resp)); + serviceIpcParse(srv, &r, sizeof(*resp)); resp = r.Raw; rc = resp->result; - if (R_SUCCEEDED(rc)) { + if (R_SUCCEEDED(rc) && out) { *out = resp->out; } } @@ -585,36 +655,14 @@ static Result _appletGetAppletResourceUserId(u64 *out) { return rc; } +// IWindowController + +static Result _appletGetAppletResourceUserId(u64 *out) { + return _appletCmdNoInOut64(&g_appletIWindowController, out, 1); +} + static Result _appletAcquireForegroundRights(void) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIWindowController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 10; - - Result rc = serviceIpcDispatch(&g_appletIWindowController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIWindowController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _appletCmdNoIO(&g_appletIWindowController, 10); } Result appletGetAppletResourceUserId(u64 *out) { @@ -625,44 +673,13 @@ Result appletGetAppletResourceUserId(u64 *out) { return 0; } -Result appletGetDesiredLanguage(u64 *LanguageCode) { - IpcCommand c; - ipcInitialize(&c); +// IFunctions +Result appletGetDesiredLanguage(u64 *LanguageCode) { if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 21; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 LanguageCode; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && LanguageCode) { - *LanguageCode = resp->LanguageCode; - } - } - - return rc; + return _appletCmdNoInOut64(&g_appletIFunctions, LanguageCode, 21); } Result appletBeginBlockingHomeButton(s64 val) { @@ -703,38 +720,10 @@ Result appletBeginBlockingHomeButton(s64 val) { } Result appletEndBlockingHomeButton(void) { - IpcCommand c; - ipcInitialize(&c); - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 33; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _appletCmdNoIO(&g_appletIFunctions, 33); } void appletNotifyRunning(u8 *out) { @@ -930,6 +919,8 @@ Result appletInitializeGamePlayRecording(void) { return rc; } +// ICommonStateGetter + static Result _appletReceiveMessage(u32 *out) { IpcCommand c; ipcInitialize(&c); @@ -1077,37 +1068,7 @@ static Result _appletGetCurrentFocusState(u8 *out) { return rc; } -static Result _appletCmdNoIO(Service* session, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(session, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(session); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(session, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; -} +// ISelfController static Result _appletSelfExit(void) { return _appletCmdNoIO(&g_appletISelfController, 0); @@ -1367,46 +1328,107 @@ Result appletSetScreenShotImageOrientation(s32 val) { }*/ Result appletCreateManagedDisplayLayer(u64 *out) { + return _appletCmdNoInOut64(&g_appletISelfController, out, 40); +} + +// ILibraryAppletSelfAccessor + +static Result _appletExitProcessAndReturn(void) { + return _appletCmdNoIO(&g_appletILibraryAppletSelfAccessor, 10); +} + +// ILibraryAppletCreator + +Result appletCreateStorage(AppletStorage *s, s64 size) { + return _appletGetSessionIn64(&g_appletILibraryAppletCreator, &s->s, 10, size); +} + +void appletStorageClose(AppletStorage *s) { + serviceClose(&s->s); +} + +static Result _appletStorageAccessorRW(Service* srv, size_t ipcbufsize, s64 offset, void* buffer, size_t size, bool rw) { IpcCommand c; ipcInitialize(&c); + if(!rw)ipcAddRecvSmart(&c, ipcbufsize, buffer, size, 0); + if(rw)ipcAddSendSmart(&c, ipcbufsize, buffer, size, 0); + struct { u64 magic; u64 cmd_id; + s64 offset; } *raw; - raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw)); + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; - raw->cmd_id = 40; + raw->cmd_id = rw!=0 ? 10 : 11; + raw->offset = offset; - Result rc = serviceIpcDispatch(&g_appletISelfController); + Result rc = serviceIpcDispatch(srv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; struct { u64 magic; u64 result; - u64 out; } *resp; - serviceIpcParse(&g_appletISelfController, &r, sizeof(*resp)); + serviceIpcParse(srv, &r, sizeof(*resp)); resp = r.Raw; rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = resp->out; - } } return rc; } -static Result _appletExitProcessAndReturn(void) { - return _appletCmdNoIO(&g_appletILibraryAppletSelfAccessor, 10); +Result appletStorageGetSize(AppletStorage *s, s64 *size) { + Result rc=0; + Service tmp_srv;//IStorageAccessor + + if (!serviceIsActive(&s->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + rc = _appletGetSession(&s->s, &tmp_srv, 0);//Open + if (R_FAILED(rc)) return rc; + + rc = _appletCmdNoInOut64(&tmp_srv, (u64*)size, 0); + serviceClose(&tmp_srv); + + return rc; } +static Result _appletStorageRW(AppletStorage *s, s64 offset, void* buffer, size_t size, bool rw) { + Result rc=0; + size_t ipcbufsize=0; + Service tmp_srv;//IStorageAccessor + + if (!serviceIsActive(&s->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + rc = _appletGetSession(&s->s, &tmp_srv, 0);//Open + if (R_FAILED(rc)) return rc; + + rc = ipcQueryPointerBufferSize(tmp_srv.handle, &ipcbufsize); + + if (R_SUCCEEDED(rc)) rc = _appletStorageAccessorRW(&tmp_srv, ipcbufsize, offset, buffer, size, rw); + 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); +} + +// state / other + u8 appletGetOperationMode(void) { return g_appletOperationMode; }