From 4a8d03835a0721a204541f65f801d452b0baa6a0 Mon Sep 17 00:00:00 2001 From: chaoskagami Date: Fri, 14 Oct 2016 07:38:15 -0400 Subject: [PATCH] Add PxiPM to ctru --- libctru/include/3ds.h | 1 + libctru/include/3ds/services/pxipm.h | 32 +++++++++++ libctru/source/services/pxipm.c | 81 ++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 libctru/include/3ds/services/pxipm.h create mode 100644 libctru/source/services/pxipm.c diff --git a/libctru/include/3ds.h b/libctru/include/3ds.h index e417c93..7d21548 100644 --- a/libctru/include/3ds.h +++ b/libctru/include/3ds.h @@ -50,6 +50,7 @@ extern "C" { #include <3ds/services/ir.h> #include <3ds/services/ns.h> #include <3ds/services/pm.h> +#include <3ds/services/pxipm.h> #include <3ds/services/ps.h> #include <3ds/services/ptmu.h> #include <3ds/services/ptmsysm.h> diff --git a/libctru/include/3ds/services/pxipm.h b/libctru/include/3ds/services/pxipm.h new file mode 100644 index 0000000..48b9bc5 --- /dev/null +++ b/libctru/include/3ds/services/pxipm.h @@ -0,0 +1,32 @@ +#pragma once + +#include <3ds/types.h> +#include <3ds/exheader.h> + + +/// Initialize PxiPM. Note that you must be able to access this, and few modules can. +Result pxipmInit(void); + +/// Deinitialize PxiPM. +void pxipmExit(void); + +/** + * @brief Register a program (or reregister) a program with PxiPM. + * @param prog_handle The program's handle + * @param title The program's current info + * @param update Information to update if re-registering + */ +Result PXIPM_RegisterProgram(u64 *prog_handle, FS_ProgramInfo *title, FS_ProgramInfo *update); + +/** + * @brief Get a program's information from PxiPM + * @param exheader Exheader to place infomation retrieved in + * @param prog_handle Handle to retrieve for + */ +Result PXIPM_GetProgramInfo(EXHEADER_header *exheader, u64 prog_handle); + +/** + * @brief Unregister a program from PxiPM. + * @param prog_handle Program handle to unregister for. + */ +Result PXIPM_UnregisterProgram(u64 prog_handle); diff --git a/libctru/source/services/pxipm.c b/libctru/source/services/pxipm.c new file mode 100644 index 0000000..e73e541 --- /dev/null +++ b/libctru/source/services/pxipm.c @@ -0,0 +1,81 @@ +#include <3ds.h> +#include + +static Handle pxipmHandle; +static int pxipmRefCount; + +Result pxipmInit(void) +{ + Result ret = 0; + + if (AtomicPostIncrement(&pxipmRefCount)) + return 0; + + ret = srvGetServiceHandle(&pxipmHandle, "PxiPM"); + + if (R_FAILED(ret)) + AtomicDecrement(&pxipmRefCount); + + return ret; +} + +void pxipmExit(void) +{ + if (AtomicDecrement(&pxipmRefCount)) + return; + + svcCloseHandle(pxipmHandle); +} + +Result PXIPM_RegisterProgram(u64 *prog_handle, FS_ProgramInfo *title, FS_ProgramInfo *update) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x2, 8, 0); // 0x20200 + memcpy(&cmdbuf[1], &title->programId, sizeof(u64)); + *(u8 *)&cmdbuf[3] = title->mediaType; + memcpy(((u8 *)&cmdbuf[3]) + 1, &title->padding, 7); + memcpy(&cmdbuf[5], &update->programId, sizeof(u64)); + *(u8 *)&cmdbuf[7] = update->mediaType; + memcpy(((u8 *)&cmdbuf[7]) + 1, &update->padding, 7); + + Result ret = 0; + if (R_FAILED(ret = svcSendSyncRequest(pxipmHandle))) + return ret; + + *prog_handle = *(u64 *)&cmdbuf[2]; + + return cmdbuf[1]; +} + +Result PXIPM_GetProgramInfo(EXHEADER_header *exheader, u64 prog_handle) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1, 2, 2); // 0x10082 + cmdbuf[1] = (u32)(prog_handle); + cmdbuf[2] = (u32)(prog_handle >> 32); + cmdbuf[3] = (0x400 << 8) | 0x4; + cmdbuf[4] = (u32)exheader; + + Result ret = 0; + if (R_FAILED(ret = svcSendSyncRequest(pxipmHandle))) + return ret; + + return cmdbuf[1]; +} + +Result PXIPM_UnregisterProgram(u64 prog_handle) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x3, 2, 0); // 0x30080 + cmdbuf[1] = (u32)(prog_handle); + cmdbuf[2] = (u32)(prog_handle >> 32); + + Result ret = 0; + if (R_FAILED(ret = svcSendSyncRequest(pxipmHandle))) + return ret; + + return cmdbuf[1]; +} -- 2.39.5