diff --git a/libctru/include/3ds/services/am.h b/libctru/include/3ds/services/am.h index d02650b..580eb89 100644 --- a/libctru/include/3ds/services/am.h +++ b/libctru/include/3ds/services/am.h @@ -141,6 +141,37 @@ Result AM_GetPendingTitleInfo(u32 titleCount, FS_MediaType mediatype, u64 *title */ Result AM_GetDeviceId(u32 *deviceID); +/** + * @brief Exports DSiWare to the specified filepath. + * @param titleID TWL titleID. + * @param operation DSiWare operation type. + * @param workbuf Work buffer. + * @param workbuf_size Work buffer size, must be >=0x20000. + * @param filepath UTF-8 filepath(converted to UTF-16 internally). + */ +Result AM_ExportTwlBackup(u64 titleID, u8 operation, void* workbuf, u32 workbuf_size, const char *filepath); + +/** + * @brief Imports DSiWare from the specified file. + * @param filehandle FSUSER file handle. + * @param operation DSiWare operation type. + * @param buffer Work buffer. + * @param size Buffer size, must be >=0x20000. + */ +Result AM_ImportTwlBackup(Handle filehandle, u8 operation, void* buffer, u32 size); + +/** + * @brief Reads info from the specified DSiWare export file. This can only be used with DSiWare exported with certain operation value(s). + * @param filehandle FSUSER file handle. + * @param outinfo Output info buffer. + * @param outinfo_size Output info buffer size. + * @param workbuf Work buffer. + * @param workbuf_size Work buffer size. + * @param banner Output banner buffer. + * @param banner_size Output banner buffer size. + */ +Result AM_ReadTwlBackupInfo(Handle filehandle, void* outinfo, u32 outinfo_size, void* workbuf, u32 workbuf_size, void* banner, u32 banner_size); + /** * @brief Retrieves information about the NAND TWL partition. * @param[out] info Pointer to output the TWL partition info to. diff --git a/libctru/source/services/am.c b/libctru/source/services/am.c index 4d8e640..d73660d 100644 --- a/libctru/source/services/am.c +++ b/libctru/source/services/am.c @@ -1,5 +1,6 @@ #include #include +#include #include <3ds/types.h> #include <3ds/result.h> #include <3ds/svc.h> @@ -7,6 +8,7 @@ #include <3ds/synchronization.h> #include <3ds/services/am.h> #include <3ds/ipc.h> +#include <3ds/util/utf.h> static Handle amHandle; static int amRefCount; @@ -199,6 +201,77 @@ Result AM_GetDeviceId(u32 *deviceID) return (Result)cmdbuf[1]; } +Result AM_ExportTwlBackup(u64 titleID, u8 operation, void* workbuf, u32 workbuf_size, const char *filepath) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + size_t len=255; + ssize_t units=0; + uint16_t filepath16[256]; + + memset(filepath16, 0, sizeof(filepath16)); + units = utf8_to_utf16(filepath16, (uint8_t*)filepath, len); + if(units < 0 || units > len)return -2; + len = (units+1)*2; + + cmdbuf[0] = IPC_MakeHeader(0x1B,5,4); // 0x001B0144 + cmdbuf[1] = titleID & 0xffffffff; + cmdbuf[2] = (u32)(titleID >> 32); + cmdbuf[3] = len; + cmdbuf[4] = workbuf_size; + cmdbuf[5] = operation; + cmdbuf[6] = IPC_Desc_Buffer(len,IPC_BUFFER_R); + cmdbuf[7] = (u32)filepath16; + cmdbuf[8] = IPC_Desc_Buffer(workbuf_size,IPC_BUFFER_W); + cmdbuf[9] = (u32)workbuf; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_ImportTwlBackup(Handle filehandle, u8 operation, void* buffer, u32 size) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1C,2,4); // 0x001C0084 + cmdbuf[1] = size; + cmdbuf[2] = operation; + cmdbuf[3] = IPC_Desc_MoveHandles(1); + cmdbuf[4] = filehandle; + cmdbuf[5] = IPC_Desc_Buffer(size,IPC_BUFFER_W); + cmdbuf[6] = (u32)buffer; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_ReadTwlBackupInfo(Handle filehandle, void* outinfo, u32 outinfo_size, void* workbuf, u32 workbuf_size, void* banner, u32 banner_size) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1E,3,8); // 0x001E00C8 + cmdbuf[1] = outinfo_size; + cmdbuf[2] = workbuf_size; + cmdbuf[3] = banner_size; + cmdbuf[4] = IPC_Desc_MoveHandles(1); + cmdbuf[5] = filehandle; + cmdbuf[6] = IPC_Desc_Buffer(outinfo_size,IPC_BUFFER_W); + cmdbuf[7] = (u32)outinfo; + cmdbuf[8] = IPC_Desc_Buffer(workbuf_size,IPC_BUFFER_W); + cmdbuf[9] = (u32)workbuf; + cmdbuf[10] = IPC_Desc_Buffer(banner_size,IPC_BUFFER_W); + cmdbuf[11] = (u32)banner; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + Result AM_GetTWLPartitionInfo(AM_TWLPartitionInfo *info) { Result ret = 0;