From 07759f38d9ef21c218ad43bbf31fb181a660902b Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 23 Apr 2018 21:15:32 -0400 Subject: [PATCH] Added pl. --- nx/include/switch.h | 1 + nx/include/switch/services/pl.h | 34 +++++++ nx/source/services/pl.c | 166 ++++++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 nx/include/switch/services/pl.h create mode 100644 nx/source/services/pl.c diff --git a/nx/include/switch.h b/nx/include/switch.h index 75577dea..085bdb9d 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -45,6 +45,7 @@ extern "C" { #include "switch/services/usb.h" #include "switch/services/hid.h" #include "switch/services/irs.h" +#include "switch/services/pl.h" #include "switch/services/vi.h" #include "switch/services/nv.h" #include "switch/services/ns.h" diff --git a/nx/include/switch/services/pl.h b/nx/include/switch/services/pl.h new file mode 100644 index 00000000..da500921 --- /dev/null +++ b/nx/include/switch/services/pl.h @@ -0,0 +1,34 @@ +/** + * @file plu.h + * @brief pl:u service IPC wrapper. + * @author yellows8 + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" + +typedef enum +{ + PlSharedFontType_Standard = 0, ///< Japan, US and Europe + PlSharedFontType_ChineseSimplified = 1, ///< Chinese Simplified + PlSharedFontType_ExtChineseSimplified = 2, ///< Extended Chinese Simplified + PlSharedFontType_ChineseTraditional = 3, ///< Chinese Traditional + PlSharedFontType_KO = 4, ///< Korean (Hangul) + PlSharedFontType_NintendoExt = 5, ///< Nintendo Extended + PlSharedFontType_Total, ///< Total fonts supported by this enum. +} PlSharedFontType; + +typedef struct { + u32 type; + u32 offset; + u32 size; + void* address; +} plFontData; + +Result plInitialize(void); +void plExit(void); +void* plGetSharedmemAddr(void); + +///< Gets shared font(s). +Result plGetSharedFont(u64 LanguageCode, plFontData* fonts, size_t max_fonts, size_t* total_fonts); + diff --git a/nx/source/services/pl.c b/nx/source/services/pl.c new file mode 100644 index 00000000..560cec82 --- /dev/null +++ b/nx/source/services/pl.c @@ -0,0 +1,166 @@ +#include + +#include "types.h" +#include "result.h" +#include "arm/atomics.h" +#include "kernel/ipc.h" +#include "kernel/shmem.h" +#include "services/sm.h" +#include "services/pl.h" + +#define SHAREDMEMFONT_SIZE 0x1100000 + +static Service g_plSrv; +static u64 g_plRefCnt; +static SharedMemory g_plSharedmem; + +static Result _plGetSharedMemoryNativeHandle(Handle* handle_out); + +Result plInitialize(void) +{ + Result rc=0; + Handle sharedmem_handle=0; + + atomicIncrement64(&g_plRefCnt); + + if (serviceIsActive(&g_plSrv)) + return 0; + + rc = smGetService(&g_plSrv, "pl:u"); + + if (R_SUCCEEDED(rc)) + { + rc = _plGetSharedMemoryNativeHandle(&sharedmem_handle); + + if (R_SUCCEEDED(rc)) + { + shmemLoadRemote(&g_plSharedmem, sharedmem_handle, 0x1100000, Perm_R); + + rc = shmemMap(&g_plSharedmem); + } + } + + if (R_FAILED(rc)) plExit(); + + return rc; +} + +void plExit(void) +{ + if (atomicDecrement64(&g_plRefCnt) == 0) { + serviceClose(&g_plSrv); + shmemClose(&g_plSharedmem); + } +} + +void* plGetSharedmemAddr(void) { + return shmemGetAddr(&g_plSharedmem); +} + +static Result _plGetSharedMemoryNativeHandle(Handle* handle_out) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 4; + + Result rc = serviceIpcDispatch(&g_plSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *handle_out = r.Handles[0]; + } + } + + return rc; +} + +Result plGetSharedFont(u64 LanguageCode, plFontData* fonts, size_t max_fonts, size_t* total_fonts) { + u32 types[PlSharedFontType_Total]; + u32 offsets[PlSharedFontType_Total]; + u32 sizes[PlSharedFontType_Total]; + size_t size = sizeof(u32) * PlSharedFontType_Total; + u32 font_count=0, i; + u8* sharedmem_addr = (u8*)plGetSharedmemAddr(); + + IpcCommand c; + ipcInitialize(&c); + ipcAddRecvBuffer(&c, types, size, 0); + ipcAddRecvBuffer(&c, offsets, size, 0); + ipcAddRecvBuffer(&c, sizes, size, 0); + + memset(types, 0, sizeof(types)); + memset(offsets, 0, sizeof(offsets)); + memset(sizes, 0, sizeof(sizes)); + memset(fonts, 0, sizeof(plFontData) * max_fonts); + + if (total_fonts) *total_fonts = 0; + + struct { + u64 magic; + u64 cmd_id; + u64 LanguageCode; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 5; + raw->LanguageCode = LanguageCode; + + Result rc = serviceIpcDispatch(&g_plSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + u8 fonts_loaded; + u32 total_fonts; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + if (resp->fonts_loaded==0) return rc; + + font_count = resp->total_fonts; + if (font_count > PlSharedFontType_Total) font_count = PlSharedFontType_Total; + if (font_count > max_fonts) font_count = max_fonts; + if (total_fonts) *total_fonts = font_count; + if (font_count==0) return rc; + + for (i=0; i= SHAREDMEMFONT_SIZE || sizes[i] > SHAREDMEMFONT_SIZE || ((u64)offsets[i] + (u64)sizes[i]) > SHAREDMEMFONT_SIZE) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + + fonts[i].type = types[i]; + fonts[i].offset = offsets[i]; + fonts[i].size = sizes[i]; + + fonts[i].address = &sharedmem_addr[offsets[i]]; + } + } + } + + return rc; +}