From e8c3a9139e37ddc0d4f2f624becd28db335a9c44 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 19 Dec 2016 19:49:51 -0500 Subject: [PATCH] Started implementing BOSS support. --- libctru/include/3ds.h | 1 + libctru/include/3ds/services/boss.h | 30 ++++++++ libctru/source/services/boss.c | 109 ++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 libctru/include/3ds/services/boss.h create mode 100644 libctru/source/services/boss.c diff --git a/libctru/include/3ds.h b/libctru/include/3ds.h index 7b8ed57..d4079d8 100644 --- a/libctru/include/3ds.h +++ b/libctru/include/3ds.h @@ -31,6 +31,7 @@ extern "C" { #include <3ds/services/am.h> #include <3ds/services/ampxi.h> #include <3ds/services/apt.h> +#include <3ds/services/boss.h> #include <3ds/services/cam.h> #include <3ds/services/cfgnor.h> #include <3ds/services/cfgu.h> diff --git a/libctru/include/3ds/services/boss.h b/libctru/include/3ds/services/boss.h new file mode 100644 index 0000000..479909c --- /dev/null +++ b/libctru/include/3ds/services/boss.h @@ -0,0 +1,30 @@ +/** + * @file boss.h + * @brief BOSS service, see also: https://www.3dbrew.org/wiki/BOSS_Services + */ +#pragma once + +/** + * @brief Initializes BOSS. + * @param programID programID to use, 0 for the current process. Not used internally unless BOSSP is available. + */ +Result bossInit(u64 programID); + +/// Exits BOSS. +void bossExit(void); + +/// Returns the BOSS session handle. +Handle bossGetSessionHandle(); + +/** + * @brief ? + * @param taskID BOSS taskID. + */ +Result bossStartTaskImmediate(char *taskID); + +/** + * @brief ? + * @param taskID BOSS taskID. + */ +Result bossStartBgImmediate(char *taskID); + diff --git a/libctru/source/services/boss.c b/libctru/source/services/boss.c new file mode 100644 index 0000000..987e0db --- /dev/null +++ b/libctru/source/services/boss.c @@ -0,0 +1,109 @@ +#include +#include +#include <3ds/types.h> +#include <3ds/result.h> +#include <3ds/svc.h> +#include <3ds/srv.h> +#include <3ds/synchronization.h> +#include <3ds/services/boss.h> +#include <3ds/ipc.h> +#include <3ds/env.h> + +static Handle bossHandle; +static int bossRefCount; +static u32 bossPriv = 0; + +static Result bossipc_InitializeSession(u64 programID); + +Result bossInit(u64 programID) +{ + Result res=0; + Handle envhandle=0; + Handle handle=0; + + if (AtomicPostIncrement(&bossRefCount)) return 0; + + res = srvGetServiceHandle(&handle, "boss:P"); + envhandle = envGetHandle("boss:P"); + bossPriv = 1; + if (R_FAILED(res)) + { + bossPriv = 0; + res = srvGetServiceHandle(&handle, "boss:U"); + envhandle = envGetHandle("boss:U"); + } + + if (R_FAILED(res)) AtomicDecrement(&bossRefCount); + + if (R_SUCCEEDED(res)) + { + bossHandle = handle; + + if(envhandle==0)res = bossipc_InitializeSession(programID); + + if (R_FAILED(res))bossExit(); + } + + return res; +} + +void bossExit(void) +{ + if (AtomicDecrement(&bossRefCount)) return; + svcCloseHandle(bossHandle); + bossHandle = 0; +} + +Handle bossGetSessionHandle() +{ + return bossHandle; +} + +static Result bossipc_InitializeSession(u64 programID) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + if(bossPriv==0)cmdbuf[0] = IPC_MakeHeader(0x1,2,2); // 0x10082 + if(bossPriv)cmdbuf[0] = IPC_MakeHeader(0x0401,2,2); // 0x04010082 + cmdbuf[1] = (u32) programID; + cmdbuf[2] = (u32) (programID >> 32); + cmdbuf[3] = IPC_Desc_CurProcessHandle(); + + if(R_FAILED(ret = svcSendSyncRequest(bossHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result bossStartTaskImmediate(char *taskID) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 size = strlen(taskID)+1; + + cmdbuf[0] = IPC_MakeHeader(0x1D,1,2); // 0x1D0042 + cmdbuf[1] = size; + cmdbuf[2] = IPC_Desc_Buffer(size, IPC_BUFFER_R); + cmdbuf[3] = (u32)taskID; + + if(R_FAILED(ret = svcSendSyncRequest(bossHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result bossStartBgImmediate(char *taskID) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 size = strlen(taskID)+1; + + cmdbuf[0] = IPC_MakeHeader(0x33,1,2); // 0x330042 + cmdbuf[1] = size; + cmdbuf[2] = IPC_Desc_Buffer(size, IPC_BUFFER_R); + cmdbuf[3] = (u32)taskID; + + if(R_FAILED(ret = svcSendSyncRequest(bossHandle)))return ret; + + return (Result)cmdbuf[1]; +} +