ctrulib changes

This commit is contained in:
TuxSH
2019-03-11 00:17:01 +01:00
parent 74bbfb95d3
commit e57abad52f
20 changed files with 141 additions and 1063 deletions

View File

@@ -1,166 +0,0 @@
#include <3ds.h>
#include "fsldr.h"
#include "fsreg.h"
#include "srvsys.h"
#define SDK_VERSION 0x70200C8
static Handle fsldrHandle;
static int fsldrRefCount;
// MAKE SURE fsreg has been init before calling this
static Result fsldrPatchPermissions(void)
{
u32 pid;
Result res;
FS_ProgramInfo info;
ExHeader_Arm11StorageInfo storage = {0};
// SDMC access and NAND access flags
storage.fs_access_info = FSACCESS_NANDRW | FSACCESS_NANDRO_RO | FSACCESS_SDMC_RW;
info.programId = 0x0004013000001302LL; // loader PID
info.mediaType = MEDIATYPE_NAND;
if(R_SUCCEEDED(res = svcGetProcessId(&pid, CUR_PROCESS_HANDLE)))
res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, &storage);
return res;
}
Result fsldrInit(void)
{
Result ret = 0;
if (AtomicPostIncrement(&fsldrRefCount)) return 0;
ret = srvSysGetServiceHandle(&fsldrHandle, "fs:LDR");
if (R_SUCCEEDED(ret))
{
fsldrPatchPermissions();
ret = FSLDR_InitializeWithSdkVersion(fsldrHandle, SDK_VERSION);
ret = FSLDR_SetPriority(0);
if (R_FAILED(ret)) svcBreak(USERBREAK_ASSERT);
}
else
{
AtomicDecrement(&fsldrRefCount);
}
return ret;
}
void fsldrExit(void)
{
if (AtomicDecrement(&fsldrRefCount)) return;
svcCloseHandle(fsldrHandle);
}
Result FSLDR_InitializeWithSdkVersion(Handle session, u32 version)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x861,1,2); // 0x8610042
cmdbuf[1] = version;
cmdbuf[2] = 32;
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(session))) return ret;
return cmdbuf[1];
}
Result FSLDR_SetPriority(u32 priority)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x862,1,0); // 0x8620040
cmdbuf[1] = priority;
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
return cmdbuf[1];
}
Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x803,8,4); // 0x8030204
cmdbuf[1] = 0;
cmdbuf[2] = archiveId;
cmdbuf[3] = archivePath.type;
cmdbuf[4] = archivePath.size;
cmdbuf[5] = filePath.type;
cmdbuf[6] = filePath.size;
cmdbuf[7] = openFlags;
cmdbuf[8] = attributes;
cmdbuf[9] = IPC_Desc_StaticBuffer(archivePath.size, 2);
cmdbuf[10] = (u32)archivePath.data;
cmdbuf[11] = IPC_Desc_StaticBuffer(filePath.size, 0);
cmdbuf[12] = (u32)filePath.data;
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
if(out) *out = cmdbuf[3];
return cmdbuf[1];
}
Result FSLDR_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path)
{
if(!archive) return -2;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x80C,3,2); // 0x80C00C2
cmdbuf[1] = id;
cmdbuf[2] = path.type;
cmdbuf[3] = path.size;
cmdbuf[4] = IPC_Desc_StaticBuffer(path.size, 0);
cmdbuf[5] = (u32) path.data;
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
if(archive) *archive = cmdbuf[2] | ((u64) cmdbuf[3] << 32);
return cmdbuf[1];
}
Result FSLDR_CloseArchive(FS_Archive archive)
{
if(!archive) return -2;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x80E,2,0); // 0x80E0080
cmdbuf[1] = (u32) archive;
cmdbuf[2] = (u32) (archive >> 32);
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
return cmdbuf[1];
}
Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x80B,4,2); // 0x80B0102
cmdbuf[1] = (u32) archive;
cmdbuf[2] = (u32) (archive >> 32);
cmdbuf[3] = path.type;
cmdbuf[4] = path.size;
cmdbuf[5] = IPC_Desc_StaticBuffer(path.size, 0);
cmdbuf[6] = (u32) path.data;
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
if(out) *out = cmdbuf[3];
return cmdbuf[1];
}

View File

@@ -1,12 +0,0 @@
#pragma once
#include <3ds/types.h>
Result fsldrInit(void);
void fsldrExit(void);
Result FSLDR_InitializeWithSdkVersion(Handle session, u32 version);
Result FSLDR_SetPriority(u32 priority);
Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes);
Result FSLDR_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path);
Result FSLDR_CloseArchive(FS_Archive archive);
Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path);

View File

@@ -1,116 +0,0 @@
#include <3ds.h>
#include <string.h>
#include "fsreg.h"
#include "srvsys.h"
static Handle fsregHandle;
static int fsregRefCount;
Result fsregInit(void)
{
Result ret = 0;
if (AtomicPostIncrement(&fsregRefCount)) return 0;
ret = srvSysGetServiceHandle(&fsregHandle, "fs:REG");
if (R_FAILED(ret)) AtomicDecrement(&fsregRefCount);
return ret;
}
void fsregExit(void)
{
if (AtomicDecrement(&fsregRefCount)) return;
svcCloseHandle(fsregHandle);
}
Result FSREG_CheckHostLoadId(u64 prog_handle)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x406,2,0); // 0x4060080
cmdbuf[1] = (u32) (prog_handle);
cmdbuf[2] = (u32) (prog_handle >> 32);
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
return cmdbuf[1];
}
Result FSREG_LoadProgram(u64 *prog_handle, FS_ProgramInfo *title)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x404,4,0); // 0x4040100
memcpy(&cmdbuf[1], &title->programId, sizeof(u64));
*(u8 *)&cmdbuf[3] = title->mediaType;
memcpy(((u8 *)&cmdbuf[3])+1, &title->padding, 7);
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
*prog_handle = *(u64 *)&cmdbuf[2];
return cmdbuf[1];
}
Result FSREG_GetProgramInfo(ExHeader *exheader, u32 entry_count, u64 prog_handle)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x403,3,0); // 0x40300C0
cmdbuf[1] = entry_count;
*(u64 *)&cmdbuf[2] = prog_handle;
cmdbuf[64] = ((entry_count << 10) << 14) | 2;
cmdbuf[65] = (u32) exheader;
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
return cmdbuf[1];
}
Result FSREG_UnloadProgram(u64 prog_handle)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x405,2,0); // 0x4050080
cmdbuf[1] = (u32) (prog_handle);
cmdbuf[2] = (u32) (prog_handle >> 32);
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
return cmdbuf[1];
}
Result FSREG_Unregister(u32 pid)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x402,1,0); // 0x4020040
cmdbuf[1] = pid;
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
return cmdbuf[1];
}
Result FSREG_Register(u32 pid, u64 prog_handle, FS_ProgramInfo *info, void *storageinfo)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x401,0xf,0); // 0x40103C0
cmdbuf[1] = pid;
*(u64 *)&cmdbuf[2] = prog_handle;
memcpy(&cmdbuf[4], &info->programId, sizeof(u64));
*(u8 *)&cmdbuf[6] = info->mediaType;
memcpy(((u8 *)&cmdbuf[6])+1, &info->padding, 7);
memcpy((u8 *)&cmdbuf[8], storageinfo, 32);
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
return cmdbuf[1];
}

View File

@@ -1,13 +0,0 @@
#pragma once
#include <3ds/types.h>
#include <3ds/exheader.h>
Result fsregInit(void);
void fsregExit(void);
Result FSREG_CheckHostLoadId(u64 prog_handle);
Result FSREG_LoadProgram(u64 *prog_handle, FS_ProgramInfo *title);
Result FSREG_GetProgramInfo(ExHeader *exheader, u32 entry_count, u64 prog_handle);
Result FSREG_UnloadProgram(u64 prog_handle);
Result FSREG_Unregister(u32 pid);
Result FSREG_Register(u32 pid, u64 prog_handle, FS_ProgramInfo *info, void *storageinfo);

View File

@@ -1,12 +1,11 @@
#include <3ds.h>
#include "ifile.h"
#include "fsldr.h"
Result IFile_Open(IFile *file, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 flags)
{
Result res;
res = FSLDR_OpenFileDirectly(&file->handle, archiveId, archivePath, filePath, flags, 0);
res = FSUSER_OpenFileDirectly(&file->handle, archiveId, archivePath, filePath, flags, 0);
file->pos = 0;
file->size = 0;
return res;

View File

@@ -2,10 +2,6 @@
#include "memory.h"
#include "patcher.h"
#include "ifile.h"
#include "fsldr.h"
#include "fsreg.h"
#include "pxipm.h"
#include "srvsys.h"
#define MAX_SESSIONS 1
#define HBLDR_3DSX_TID (*(vu64 *)0x1FF81100)
@@ -29,9 +25,29 @@ typedef struct
static Handle g_handles[MAX_SESSIONS+2];
static int g_active_handles;
static u64 g_cached_prog_handle;
static ExHeader g_exheader;
static ExHeader_Info g_exheader;
static char g_ret_buf[1024];
// MAKE SURE fsreg has been init before calling this
static Result fsldrPatchPermissions(void)
{
u32 pid;
Result res;
FS_ProgramInfo info;
ExHeader_Arm11StorageInfo storageInfo = {
.fs_access_info = FSACCESS_NANDRW | FSACCESS_NANDRO_RO | FSACCESS_SDMC_RW,
};
info.programId = 0x0004013000001302LL; // loader PID
info.mediaType = MEDIATYPE_NAND;
res = svcGetProcessId(&pid, CUR_PROCESS_HANDLE);
if (R_SUCCEEDED(res))
{
res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, &storageInfo);
}
return res;
}
static inline void loadCFWInfo(void)
{
s64 out;
@@ -183,12 +199,9 @@ static Result load_code(u64 progid, prog_addrs_t *shared, u64 prog_handle, int i
}
}
ExHeader_CodeSetInfo *csi = &g_exheader.info.sci.codeset_info;
u16 progver = csi->flags.remaster_version;
ExHeader_CodeSetInfo *csi = &g_exheader.sci.codeset_info;
// patch
patchCode(progid, progver, (u8 *)shared->text_addr, shared->total_size << 12,
csi->text.size, csi->rodata.size, csi->data.size, csi->rodata.address, csi->data.address);
patchCode(progid, csi->flags.remaster_version, (u8 *)shared->text_addr, shared->total_size << 12, csi->text.size, csi->rodata.size, csi->data.size, csi->rodata.address, csi->data.address);
return 0;
}
@@ -208,7 +221,7 @@ static Result HBLDR_Init(Handle *session)
return res;
}
static Result loader_GetProgramInfo(ExHeader *exheader, u64 prog_handle)
static Result loader_GetProgramInfo(ExHeader_Info *exheader, u64 prog_handle)
{
Result res;
@@ -237,13 +250,12 @@ static Result loader_GetProgramInfo(ExHeader *exheader, u64 prog_handle)
svcGetSystemInfo(&nbSection0Modules, 26, 0);
// Force always having sdmc:/ and nand:/rw permission
exheader->info.aci.local_caps.storage_info.fs_access_info |= FSACCESS_SDMC_RW | FSACCESS_NANDRW;
exheader->access_descriptor.acli.local_caps.storage_info.fs_access_info |= FSACCESS_SDMC_RW | FSACCESS_NANDRW;;
exheader->aci.local_caps.storage_info.fs_access_info |= FSACCESS_NANDRW | FSACCESS_SDMC_RW;
// Tweak 3dsx placeholder title exheader
if (nbSection0Modules == 6)
{
if(exheader->info.aci.local_caps.title_id == HBLDR_3DSX_TID)
if(exheader->aci.local_caps.title_id == HBLDR_3DSX_TID)
{
Handle hbldr = 0;
res = HBLDR_Init(&hbldr);
@@ -261,11 +273,10 @@ static Result loader_GetProgramInfo(ExHeader *exheader, u64 prog_handle)
}
}
u64 originalProgId = exheader->info.aci.local_caps.title_id;
if(CONFIG(PATCHGAMES) && loadTitleExheader(exheader->info.aci.local_caps.title_id, exheader))
u64 originalProgId = exheader->aci.local_caps.title_id;
if(CONFIG(PATCHGAMES) && loadTitleExheader(exheader->aci.local_caps.title_id, exheader))
{
exheader->info.aci.local_caps.title_id = originalProgId;
exheader->access_descriptor.acli.local_caps.title_id = originalProgId;
exheader->aci.local_caps.title_id = originalProgId;
}
}
}
@@ -288,7 +299,7 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
u64 progid;
// make sure the cached info corrosponds to the current prog_handle
if (g_cached_prog_handle != prog_handle || g_exheader.info.aci.local_caps.title_id == HBLDR_3DSX_TID)
if (g_cached_prog_handle != prog_handle || g_exheader.aci.local_caps.title_id == HBLDR_3DSX_TID)
{
res = loader_GetProgramInfo(&g_exheader, prog_handle);
g_cached_prog_handle = prog_handle;
@@ -303,7 +314,7 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
flags = 0;
for (count = 0; count < 28; count++)
{
desc = g_exheader.info.aci.kernel_caps.descriptors[count];
desc = g_exheader.aci.kernel_caps.descriptors[count];
if (0x1FE == desc >> 23)
{
flags = desc & 0xF00;
@@ -315,7 +326,9 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
}
// check for 3dsx process
progid = g_exheader.info.aci.local_caps.title_id;
progid = g_exheader.aci.local_caps.title_id;
ExHeader_CodeSetInfo *csi = &g_exheader.sci.codeset_info;
if (progid == HBLDR_3DSX_TID)
{
Handle hbldr = 0;
@@ -327,11 +340,11 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
}
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(1,6,0);
cmdbuf[1] = g_exheader.info.sci.codeset_info.text.address;
cmdbuf[1] = csi->text.address;
cmdbuf[2] = flags & 0xF00;
cmdbuf[3] = progid;
cmdbuf[4] = progid>>32;
memcpy(&cmdbuf[5], g_exheader.info.sci.codeset_info.name, 8);
memcpy(&cmdbuf[5], csi->name, 8);
res = svcSendSyncRequest(hbldr);
svcCloseHandle(hbldr);
if (R_SUCCEEDED(res))
@@ -344,13 +357,12 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
return res;
}
codeset = (Handle)cmdbuf[3];
res = svcCreateProcess(process, codeset, g_exheader.info.aci.kernel_caps.descriptors, count);
res = svcCreateProcess(process, codeset, g_exheader.aci.kernel_caps.descriptors, count);
svcCloseHandle(codeset);
return res;
}
// allocate process memory
ExHeader_CodeSetInfo *csi = &g_exheader.info.sci.codeset_info;
vaddr.text_addr = csi->text.address;
vaddr.text_size = (csi->text.size + 4095) >> 12;
vaddr.ro_addr = csi->rodata.address;
@@ -381,7 +393,7 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
res = svcCreateCodeSet(&codeset, &codesetinfo, (void *)shared_addr.text_addr, (void *)shared_addr.ro_addr, (void *)shared_addr.data_addr);
if (res >= 0)
{
res = svcCreateProcess(process, codeset, g_exheader.info.aci.kernel_caps.descriptors, count);
res = svcCreateProcess(process, codeset, g_exheader.aci.kernel_caps.descriptors, count);
svcCloseHandle(codeset);
if (res >= 0)
{
@@ -517,7 +529,7 @@ static void handle_commands(void)
case 4: // GetProgramInfo
{
prog_handle = *(u64 *)&cmdbuf[1];
if (prog_handle != g_cached_prog_handle || g_exheader.info.aci.local_caps.title_id == HBLDR_3DSX_TID)
if (prog_handle != g_cached_prog_handle || g_exheader.aci.local_caps.title_id == HBLDR_3DSX_TID)
{
res = loader_GetProgramInfo(&g_exheader, prog_handle);
if (res >= 0)
@@ -550,7 +562,7 @@ static Result should_terminate(int *term_request)
u32 notid;
Result ret;
ret = srvSysReceiveNotification(&notid);
ret = srvReceiveNotification(&notid);
if (R_FAILED(ret))
{
return ret;
@@ -565,19 +577,36 @@ static Result should_terminate(int *term_request)
// this is called before main
void __appInit()
{
srvSysInit();
fsregInit();
fsldrInit();
pxipmInit();
Result res;
for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
{
res = srvInit();
if(R_FAILED(res) && res != (Result)0xD88007FA)
svcBreak(USERBREAK_PANIC);
}
fsRegInit();
fsldrPatchPermissions();
//fsldrInit();
res = srvGetServiceHandle(fsGetSessionHandle(), "fs:LDR");
if (R_FAILED(res)) svcBreak(USERBREAK_PANIC);
res = FSUSER_InitializeWithSdkVersion(*fsGetSessionHandle(), 0x70200C8);
if (R_FAILED(res)) svcBreak(USERBREAK_PANIC);
res = FSUSER_SetPriority(0);
if (R_FAILED(res)) svcBreak(USERBREAK_PANIC);
pxiPmInit();
}
// this is called after main exits
void __appExit()
{
pxipmExit();
fsldrExit();
fsregExit();
srvSysExit();
pxiPmExit();
//fsldrExit();
svcCloseHandle(*fsGetSessionHandle());
fsRegExit();
srvExit();
}
// stubs for non-needed pre-main functions
@@ -623,12 +652,12 @@ int main()
srv_handle = &g_handles[1];
notification_handle = &g_handles[0];
if (R_FAILED(srvSysRegisterService(srv_handle, "Loader", MAX_SESSIONS)))
if (R_FAILED(srvRegisterService(srv_handle, "Loader", MAX_SESSIONS)))
{
svcBreak(USERBREAK_ASSERT);
}
if (R_FAILED(srvSysEnableNotification(notification_handle)))
if (R_FAILED(srvEnableNotification(notification_handle)))
{
svcBreak(USERBREAK_ASSERT);
}
@@ -717,7 +746,7 @@ int main()
}
} while (!term_request || g_active_handles != 2);
srvSysUnregisterService("Loader");
srvUnregisterService("Loader");
svcCloseHandle(*srv_handle);
svcCloseHandle(*notification_handle);

View File

@@ -2,7 +2,6 @@
#include "patcher.h"
#include "memory.h"
#include "strings.h"
#include "fsldr.h"
#include "romfsredir.h"
static u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, s32 offset, const void *replace, u32 repSize, u32 count)
@@ -44,12 +43,12 @@ static bool dirCheck(FS_ArchiveID archiveId, const char *path)
FS_Path dirPath = {PATH_ASCII, strnlen(path, 255) + 1, path},
archivePath = {PATH_EMPTY, 1, (u8 *)""};
if(R_FAILED(FSLDR_OpenArchive(&archive, archiveId, archivePath))) ret = false;
if(R_FAILED(FSUSER_OpenArchive(&archive, archiveId, archivePath))) ret = false;
else
{
ret = R_SUCCEEDED(FSLDR_OpenDirectory(&handle, archive, dirPath));
ret = R_SUCCEEDED(FSUSER_OpenDirectory(&handle, archive, dirPath));
if(ret) FSDIR_Close(handle);
FSLDR_CloseArchive(archive);
FSUSER_CloseArchive(archive);
}
return ret;
@@ -356,7 +355,7 @@ error:
while(true);
}
bool loadTitleExheader(u64 progId, ExHeader *exheader)
bool loadTitleExheader(u64 progId, ExHeader_Info *exheader)
{
/* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/exheader.bin"
If it exists it should be a decrypted exheader */
@@ -370,12 +369,12 @@ bool loadTitleExheader(u64 progId, ExHeader *exheader)
u64 fileSize;
if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize != sizeof(ExHeader)) goto error;
if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize != sizeof(ExHeader_Info) || fileSize != sizeof(ExHeader)) goto error;
else
{
u64 total;
if(R_FAILED(IFile_Read(&file, &total, exheader, fileSize)) || total != fileSize) goto error;
if(R_FAILED(IFile_Read(&file, &total, exheader, sizeof(ExHeader_Info))) || total != sizeof(ExHeader_Info)) goto error;
}
IFile_Close(&file);

View File

@@ -44,4 +44,4 @@ extern bool isN3DS, needToInitSd, isSdMode;
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress);
Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags);
bool loadTitleCodeSection(u64 progId, u8 *code, u32 size);
bool loadTitleExheader(u64 progId, ExHeader *exheader);
bool loadTitleExheader(u64 progId, ExHeader_Info *exheader);

View File

@@ -1,74 +0,0 @@
#include <3ds.h>
#include <string.h>
#include "pxipm.h"
#include "srvsys.h"
static Handle pxipmHandle;
static int pxipmRefCount;
Result pxipmInit(void)
{
Result ret = 0;
if (AtomicPostIncrement(&pxipmRefCount)) return 0;
ret = srvSysGetServiceHandle(&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 *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];
}

View File

@@ -1,10 +0,0 @@
#pragma once
#include <3ds/types.h>
#include <3ds/exheader.h>
Result pxipmInit(void);
void pxipmExit(void);
Result PXIPM_RegisterProgram(u64 *prog_handle, FS_ProgramInfo *title, FS_ProgramInfo *update);
Result PXIPM_GetProgramInfo(ExHeader *exheader, u64 prog_handle);
Result PXIPM_UnregisterProgram(u64 prog_handle);

View File

@@ -1,154 +0,0 @@
#include <3ds.h>
#include <string.h>
#include "srvsys.h"
static Handle srvHandle;
static int srvRefCount;
static RecursiveLock initLock;
static int initLockinit = 0;
Result srvSysInit()
{
Result rc = 0;
if (!initLockinit)
{
RecursiveLock_Init(&initLock);
}
RecursiveLock_Lock(&initLock);
if (srvRefCount > 0)
{
RecursiveLock_Unlock(&initLock);
return MAKERESULT(RL_INFO, RS_NOP, 25, RD_ALREADY_INITIALIZED);
}
while (1)
{
rc = svcConnectToPort(&srvHandle, "srv:");
if (R_LEVEL(rc) != RL_PERMANENT ||
R_SUMMARY(rc) != RS_NOTFOUND ||
R_DESCRIPTION(rc) != RD_NOT_FOUND
) break;
svcSleepThread(500000);
}
if (R_SUCCEEDED(rc))
{
rc = srvSysRegisterClient();
srvRefCount++;
}
RecursiveLock_Unlock(&initLock);
return rc;
}
Result srvSysRegisterClient(void)
{
Result rc = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x1,0,2); // 0x10002
cmdbuf[1] = IPC_Desc_CurProcessHandle();
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
return cmdbuf[1];
}
Result srvSysExit()
{
Result rc;
RecursiveLock_Lock(&initLock);
if (srvRefCount > 1)
{
srvRefCount--;
RecursiveLock_Unlock(&initLock);
return MAKERESULT(RL_INFO, RS_NOP, 25, RD_BUSY);
}
if (srvHandle != 0) svcCloseHandle(srvHandle);
else svcBreak(USERBREAK_ASSERT);
rc = (Result)srvHandle; // yeah, I think this is a benign bug
srvHandle = 0;
srvRefCount--;
RecursiveLock_Unlock(&initLock);
return rc;
}
Result srvSysGetServiceHandle(Handle* out, const char* name)
{
Result rc = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x5,4,0); // 0x50100
strncpy((char*) &cmdbuf[1], name,8);
cmdbuf[3] = strlen(name);
cmdbuf[4] = 0x0;
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
if(out) *out = cmdbuf[3];
return cmdbuf[1];
}
Result srvSysEnableNotification(Handle* semaphoreOut)
{
Result rc = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x2,0,0);
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
if(semaphoreOut) *semaphoreOut = cmdbuf[3];
return cmdbuf[1];
}
Result srvSysReceiveNotification(u32* notificationIdOut)
{
Result rc = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0xB,0,0); // 0xB0000
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
if(notificationIdOut) *notificationIdOut = cmdbuf[2];
return cmdbuf[1];
}
Result srvSysRegisterService(Handle* out, const char* name, int maxSessions)
{
Result rc = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x3,4,0); // 0x30100
strncpy((char*) &cmdbuf[1], name,8);
cmdbuf[3] = strlen(name);
cmdbuf[4] = maxSessions;
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
if(out) *out = cmdbuf[3];
return cmdbuf[1];
}
Result srvSysUnregisterService(const char* name)
{
Result rc = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x4,3,0); // 0x400C0
strncpy((char*) &cmdbuf[1], name,8);
cmdbuf[3] = strlen(name);
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
return cmdbuf[1];
}

View File

@@ -1,47 +0,0 @@
/**
* @file srv.h
* @brief Service API.
*/
#pragma once
/// Initializes the service API.
Result srvSysInit(void);
/// Exits the service API.
Result srvSysExit(void);
/**
* @brief Retrieves a service handle, retrieving from the environment handle list if possible.
* @param out Pointer to write the handle to.
* @param name Name of the service.
*/
Result srvSysGetServiceHandle(Handle* out, const char* name);
/// Registers the current process as a client to the service API.
Result srvSysRegisterClient(void);
/**
* @brief Enables service notificatios, returning a notification semaphore.
* @param semaphoreOut Pointer to output the notification semaphore to.
*/
Result srvSysEnableNotification(Handle* semaphoreOut);
/**
* @brief Receives a notification.
* @param notificationIdOut Pointer to output the ID of the received notification to.
*/
Result srvSysReceiveNotification(u32* notificationIdOut);
/**
* @brief Registers the current process as a service.
* @param out Pointer to write the service handle to.
* @param name Name of the service.
* @param maxSessions Maximum number of sessions the service can handle.
*/
Result srvSysRegisterService(Handle* out, const char* name, int maxSessions);
/**
* @brief Unregisters the current process as a service.
* @param name Name of the service.
*/
Result srvSysUnregisterService(const char* name);