181 lines
4.1 KiB
C
181 lines
4.1 KiB
C
#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;
|
|
u32 storage[8] = {0};
|
|
|
|
storage[6] = 0x680; // SDMC access and NAND access flag
|
|
info.programId = 0x0004013000001302LL; // loader PID
|
|
info.mediaType = MEDIATYPE_NAND;
|
|
res = svcGetProcessId(&pid, 0xFFFF8001);
|
|
if (R_SUCCEEDED(res))
|
|
{
|
|
res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, (u8 *)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];
|
|
}
|
|
|
|
Result FSDIRLDR_Close(Handle handle)
|
|
{
|
|
u32 *cmdbuf = getThreadCommandBuffer();
|
|
|
|
cmdbuf[0] = IPC_MakeHeader(0x802,0,0); // 0x8020000
|
|
|
|
Result ret = 0;
|
|
if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
|
|
|
|
ret = cmdbuf[1];
|
|
if(R_SUCCEEDED(ret)) ret = svcCloseHandle(handle);
|
|
|
|
return ret;
|
|
} |