Merge branch 'master' into master
This commit is contained in:
commit
f95d206eb4
@ -63,6 +63,7 @@ extern "C" {
|
|||||||
#include <3ds/services/news.h>
|
#include <3ds/services/news.h>
|
||||||
#include <3ds/services/qtm.h>
|
#include <3ds/services/qtm.h>
|
||||||
#include <3ds/services/srvpm.h>
|
#include <3ds/services/srvpm.h>
|
||||||
|
#include <3ds/services/loader.h>
|
||||||
#include <3ds/services/y2r.h>
|
#include <3ds/services/y2r.h>
|
||||||
#include <3ds/services/mcuhwc.h>
|
#include <3ds/services/mcuhwc.h>
|
||||||
#include <3ds/services/hb.h>
|
#include <3ds/services/hb.h>
|
||||||
@ -78,6 +79,8 @@ extern "C" {
|
|||||||
#include <3ds/applets/swkbd.h>
|
#include <3ds/applets/swkbd.h>
|
||||||
#include <3ds/applets/error.h>
|
#include <3ds/applets/error.h>
|
||||||
|
|
||||||
|
#include <3ds/applets/miiselector.h>
|
||||||
|
|
||||||
#include <3ds/sdmc.h>
|
#include <3ds/sdmc.h>
|
||||||
#include <3ds/romfs.h>
|
#include <3ds/romfs.h>
|
||||||
#include <3ds/font.h>
|
#include <3ds/font.h>
|
||||||
|
90
libctru/include/3ds/applets/miiselector.h
Normal file
90
libctru/include/3ds/applets/miiselector.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
* @file miiselector.h
|
||||||
|
* @brief Mii Selector Applet (appletEd).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/// Magic value needed to launch the applet.
|
||||||
|
#define MIISELECTOR_MAGIC 0x13DE28CF
|
||||||
|
|
||||||
|
/// Maximum length of title to be displayed at the top of the Mii selector applet
|
||||||
|
#define MIISELECTOR_TITLE_LEN 64
|
||||||
|
|
||||||
|
/// Number of Guest Miis available for selection
|
||||||
|
#define MIISELECTOR_GUESTMII_SLOTS 6
|
||||||
|
|
||||||
|
/// Maximum number of user Miis available for selection
|
||||||
|
#define MIISELECTOR_USERMII_SLOTS 100
|
||||||
|
|
||||||
|
/// Parameter structure passed to AppletEd
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char enable_cancel_button; ///< Enables canceling of selection if nonzero.
|
||||||
|
char enable_selecting_guests; ///< Makes Guets Miis selectable if nonzero.
|
||||||
|
char show_on_top_screen; ///< Shows applet on top screen if nonzero,
|
||||||
|
///< otherwise show it on the bottom screen.
|
||||||
|
char _unk0x3[5]; ///< @private
|
||||||
|
u16 title[MIISELECTOR_TITLE_LEN]; ///< UTF16-LE string displayed at the top of the applet. If
|
||||||
|
///< set to the empty string, a default title is displayed.
|
||||||
|
char _unk0x88[4]; ///< @private
|
||||||
|
char show_guest_page; ///< If nonzero, the applet shows a page with Guest
|
||||||
|
///< Miis on launch.
|
||||||
|
char _unk0x8D[3]; ///< @private
|
||||||
|
u32 initial_index; ///< Index of the initially selected Mii. If
|
||||||
|
///< @ref MiiSelectorConf.show_guest_page is
|
||||||
|
///< set, this is the index of a Guest Mii,
|
||||||
|
///< otherwise that of a user Mii.
|
||||||
|
char mii_guest_whitelist[MIISELECTOR_GUESTMII_SLOTS]; ///< Each byte set to a nonzero value
|
||||||
|
///< enables its corresponding Guest
|
||||||
|
///< Mii to be enabled for selection.
|
||||||
|
char mii_whitelist[MIISELECTOR_USERMII_SLOTS]; ///< Each byte set to a nonzero value enables
|
||||||
|
///< its corresponding user Mii to be enabled
|
||||||
|
///< for selection.
|
||||||
|
u16 _unk0xFE; ///< @private
|
||||||
|
u32 magic; ///< Will be set to @ref MIISELECTOR_MAGIC before launching the
|
||||||
|
///< applet.
|
||||||
|
} MiiSelectorConf;
|
||||||
|
|
||||||
|
/// Size of the data describing a single Mii
|
||||||
|
#define MIISELECTOR_MIIDATA_SIZE 0x5c
|
||||||
|
|
||||||
|
/// Maximum length of the localized name of a Guest Mii
|
||||||
|
#define MIISELECTOR_GUESTMII_NAME_LEN 12
|
||||||
|
|
||||||
|
/// Structure written by AppletEd
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 no_mii_selected; ///< 0 if a Mii was selected, 1 if the selection was
|
||||||
|
///< canceled.
|
||||||
|
u32 guest_mii_was_selected; ///< 1 if a Guest Mii was selected, 0 otherwise.
|
||||||
|
u32 guest_mii_index; ///< Index of the selected Guest Mii,
|
||||||
|
///< 0xFFFFFFFF if no guest was selected.
|
||||||
|
char mii[MIISELECTOR_MIIDATA_SIZE]; ///< Data of selected Mii.
|
||||||
|
u16 _pad0x68; ///< @private
|
||||||
|
u16 checksum; ///< Checksum of the returned Mii data.
|
||||||
|
///< Stored as a big-endian value; use
|
||||||
|
///< @ref miiSelectorChecksumIsValid to
|
||||||
|
///< verify.
|
||||||
|
u16 guest_mii_name[MIISELECTOR_GUESTMII_NAME_LEN]; ///< Localized name of a Guest Mii,
|
||||||
|
///< if one was selected (UTF16-LE
|
||||||
|
///< string). Zeroed otherwise.
|
||||||
|
} MiiSelectorReturn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Launch the Mii selector library applet
|
||||||
|
*
|
||||||
|
* @param conf Configuration determining how the applet should behave
|
||||||
|
* @param returnbuf Data returned by the applet
|
||||||
|
*/
|
||||||
|
Result miiSelectorLaunch(const MiiSelectorConf *conf, MiiSelectorReturn* returnbuf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Verifies that the Mii data returned from the applet matches its
|
||||||
|
* checksum
|
||||||
|
*
|
||||||
|
* @param returnbuffer Buffer filled by Mii selector applet
|
||||||
|
*
|
||||||
|
* @return `true` if `returnbuf->checksum` is the same as the one computed from `returnbuf`
|
||||||
|
*/
|
||||||
|
bool miiSelectorChecksumIsValid(const MiiSelectorReturn *returnbuf);
|
@ -385,7 +385,7 @@ typedef enum
|
|||||||
/// Light distance attenuation disable bits in GPUREG_LIGHT_CONFIG1.
|
/// Light distance attenuation disable bits in GPUREG_LIGHT_CONFIG1.
|
||||||
#define GPU_LC1_ATTNBIT(n) BIT((n)+24)
|
#define GPU_LC1_ATTNBIT(n) BIT((n)+24)
|
||||||
/// Creates a light permutation parameter.
|
/// Creates a light permutation parameter.
|
||||||
#define GPU_LIGHTPERM(i,n) ((n) << (i))
|
#define GPU_LIGHTPERM(i,n) ((n) << ((i)*4))
|
||||||
/// Creates a light LUT input parameter.
|
/// Creates a light LUT input parameter.
|
||||||
#define GPU_LIGHTLUTINPUT(i,n) ((n) << ((i)*4))
|
#define GPU_LIGHTLUTINPUT(i,n) ((n) << ((i)*4))
|
||||||
/// Creates a light LUT index parameter.
|
/// Creates a light LUT index parameter.
|
||||||
|
@ -56,12 +56,6 @@ static inline void GPUCMD_GetBuffer(u32** addr, u32* size, u32* offset)
|
|||||||
*/
|
*/
|
||||||
void GPUCMD_AddRawCommands(const u32* cmd, u32 size);
|
void GPUCMD_AddRawCommands(const u32* cmd, u32 size);
|
||||||
|
|
||||||
/// Executes the GPU command buffer.
|
|
||||||
DEPRECATED void GPUCMD_Run(void);
|
|
||||||
|
|
||||||
/// Flushes linear memory and executes the GPU command buffer.
|
|
||||||
DEPRECATED void GPUCMD_FlushAndRun(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds a GPU command to the current command buffer.
|
* @brief Adds a GPU command to the current command buffer.
|
||||||
* @param header Header of the command.
|
* @param header Header of the command.
|
||||||
@ -77,9 +71,6 @@ void GPUCMD_Add(u32 header, const u32* param, u32 paramlength);
|
|||||||
*/
|
*/
|
||||||
void GPUCMD_Split(u32** addr, u32* size);
|
void GPUCMD_Split(u32** addr, u32* size);
|
||||||
|
|
||||||
/// Finalizes the GPU command buffer.
|
|
||||||
DEPRECATED void GPUCMD_Finalize(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Converts a 32-bit float to a 16-bit float.
|
* @brief Converts a 32-bit float to a 16-bit float.
|
||||||
* @param f Float to convert.
|
* @param f Float to convert.
|
||||||
|
@ -218,3 +218,8 @@ Result GSPGPU_UnregisterInterruptRelayQueue(void);
|
|||||||
/// Triggers a handling of commands written to shared memory.
|
/// Triggers a handling of commands written to shared memory.
|
||||||
Result GSPGPU_TriggerCmdReqQueue(void);
|
Result GSPGPU_TriggerCmdReqQueue(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets 3D_LEDSTATE to the input state value.
|
||||||
|
* @param disable False = 3D LED enable, true = 3D LED disable.
|
||||||
|
*/
|
||||||
|
Result GSPGPU_SetLedForceOff(bool disable);
|
@ -19,6 +19,12 @@ Result gspLcdInit(void);
|
|||||||
/// Exits GSPLCD.
|
/// Exits GSPLCD.
|
||||||
void gspLcdExit(void);
|
void gspLcdExit(void);
|
||||||
|
|
||||||
|
/// Powers on both backlights.
|
||||||
|
Result GSPLCD_PowerOnAllBacklights(void);
|
||||||
|
|
||||||
|
/// Powers off both backlights.
|
||||||
|
Result GSPLCD_PowerOffAllBacklights(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Powers on the backlight.
|
* @brief Powers on the backlight.
|
||||||
* @param screen Screen to power on.
|
* @param screen Screen to power on.
|
||||||
@ -31,6 +37,12 @@ Result GSPLCD_PowerOnBacklight(u32 screen);
|
|||||||
*/
|
*/
|
||||||
Result GSPLCD_PowerOffBacklight(u32 screen);
|
Result GSPLCD_PowerOffBacklight(u32 screen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets 3D_LEDSTATE to the input state value.
|
||||||
|
* @param disable False = 3D LED enable, true = 3D LED disable.
|
||||||
|
*/
|
||||||
|
Result GSPLCD_SetLedForceOff(bool disable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the LCD screens' vendors. Stubbed on old 3ds.
|
* @brief Gets the LCD screens' vendors. Stubbed on old 3ds.
|
||||||
* @param vendor Pointer to output the screen vendors to.
|
* @param vendor Pointer to output the screen vendors to.
|
||||||
|
@ -87,7 +87,7 @@ Result IRU_GetBitRate(u8 *out);
|
|||||||
Result IRU_SetIRLEDState(u32 value);
|
Result IRU_SetIRLEDState(u32 value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the IR KED state.
|
* @brief Gets the IR LED state.
|
||||||
* @param out Pointer to write the IR LED state to.
|
* @param out Pointer to write the IR LED state to.
|
||||||
*/
|
*/
|
||||||
Result IRU_GetIRLEDRecvState(u32 *out);
|
Result IRU_GetIRLEDRecvState(u32 *out);
|
||||||
|
45
libctru/include/3ds/services/loader.h
Normal file
45
libctru/include/3ds/services/loader.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* @file loader.h
|
||||||
|
* @brief LOADER Service
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <3ds/exheader.h>
|
||||||
|
#include <3ds/services/fs.h>
|
||||||
|
|
||||||
|
/// Initializes LOADER.
|
||||||
|
Result loaderInit(void);
|
||||||
|
|
||||||
|
/// Exits LOADER.
|
||||||
|
void loaderExit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Loads a program and returns a process handle to the newly created process.
|
||||||
|
* @param[out] process Pointer to output the process handle to.
|
||||||
|
* @param programHandle The handle of the program to load.
|
||||||
|
*/
|
||||||
|
Result LOADER_LoadProcess(Handle* process, u64 programHandle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers a program (along with its update).
|
||||||
|
* @param[out] programHandle Pointer to output the program handle to.
|
||||||
|
* @param titleId The program's title ID.
|
||||||
|
* @param mediaType The program's media type.
|
||||||
|
* @param updateTitleId The program update's title ID.
|
||||||
|
* @param updateMediaType The program update's media type.
|
||||||
|
*/
|
||||||
|
Result LOADER_RegisterProgram(u64* programHandle, u64 titleId, FS_MediaType mediaType, u64 updateTitleId, FS_MediaType updateMediaType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers a program (along with its update).
|
||||||
|
* @param programHandle The handle of the program to unregister.
|
||||||
|
*/
|
||||||
|
Result LOADER_UnregisterProgram(u64 programHandle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrives a program's main NCCH extended header info (SCI + ACI, see @ref ExHeader_Info).
|
||||||
|
* @param[out] exheaderInfo Pointer to output the main NCCH extended header info.
|
||||||
|
* @param programHandle The handle of the program to unregister
|
||||||
|
*/
|
||||||
|
Result LOADER_GetProgramInfo(ExHeader_Info* exheaderInfo, u64 programHandle);
|
57
libctru/source/applets/miiselector.c
Normal file
57
libctru/source/applets/miiselector.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include <3ds/types.h>
|
||||||
|
#include <3ds/result.h>
|
||||||
|
#include <3ds/services/apt.h>
|
||||||
|
|
||||||
|
#include <3ds/applets/miiselector.h>
|
||||||
|
|
||||||
|
#include <string.h> // for memcpy
|
||||||
|
|
||||||
|
Result miiSelectorLaunch(const MiiSelectorConf *conf, MiiSelectorReturn *returnbuf)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
MiiSelectorConf config;
|
||||||
|
MiiSelectorReturn ret;
|
||||||
|
} ctx;
|
||||||
|
|
||||||
|
memcpy(&ctx.config, conf, sizeof(MiiSelectorConf));
|
||||||
|
ctx.config.magic = MIISELECTOR_MAGIC;
|
||||||
|
|
||||||
|
Result ret = aptLaunchLibraryApplet(APPID_APPLETED, &ctx.config, sizeof(MiiSelectorConf), 0);
|
||||||
|
if(R_SUCCEEDED(ret) && returnbuf) {
|
||||||
|
memcpy(returnbuf, &ctx.ret, sizeof(MiiSelectorReturn));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u16 crc16_ccitt(void const *buf, size_t len, uint32_t starting_val)
|
||||||
|
{
|
||||||
|
if(buf == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 const *cbuf = buf;
|
||||||
|
u32 crc = starting_val;
|
||||||
|
|
||||||
|
static const u16 POLY = 0x1021;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < len; i++) {
|
||||||
|
for(int bit = 7; bit >= 0; bit--) {
|
||||||
|
crc = ((crc << 1) | ((cbuf[i] >> bit) & 0x1)) ^ (crc & 0x8000 ? POLY : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int _ = 0; _ < 16; _++) {
|
||||||
|
crc = (crc << 1) ^ (crc & 0x8000 ? POLY : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (u16)(crc & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool miiSelectorChecksumIsValid(const MiiSelectorReturn *returnbuf)
|
||||||
|
{
|
||||||
|
u16 computed =
|
||||||
|
crc16_ccitt(&returnbuf->mii, sizeof(returnbuf->mii) + sizeof(returnbuf->_pad0x68), 0x0000);
|
||||||
|
u16 chk_little_endian = __builtin_bswap16(returnbuf->checksum);
|
||||||
|
return computed == chk_little_endian;
|
||||||
|
}
|
@ -22,21 +22,6 @@ void GPUCMD_AddRawCommands(const u32* cmd, u32 size)
|
|||||||
gpuCmdBufOffset+=size;
|
gpuCmdBufOffset+=size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPUCMD_Run(void)
|
|
||||||
{
|
|
||||||
GX_ProcessCommandList(gpuCmdBuf, gpuCmdBufOffset*4, GX_CMDLIST_FLUSH);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern u32 __ctru_linear_heap;
|
|
||||||
extern u32 __ctru_linear_heap_size;
|
|
||||||
|
|
||||||
void GPUCMD_FlushAndRun(void)
|
|
||||||
{
|
|
||||||
//take advantage of GX_FlushCacheRegions to flush gsp heap
|
|
||||||
GX_FlushCacheRegions(gpuCmdBuf, gpuCmdBufOffset*4, (u32 *) __ctru_linear_heap, __ctru_linear_heap_size, NULL, 0);
|
|
||||||
GX_ProcessCommandList(gpuCmdBuf, gpuCmdBufOffset*4, 0x0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPUCMD_Add(u32 header, const u32* param, u32 paramlength)
|
void GPUCMD_Add(u32 header, const u32* param, u32 paramlength)
|
||||||
{
|
{
|
||||||
if(!paramlength)paramlength=1;
|
if(!paramlength)paramlength=1;
|
||||||
@ -74,15 +59,6 @@ void GPUCMD_Split(u32** addr, u32* size)
|
|||||||
gpuCmdBufOffset = 0;
|
gpuCmdBufOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPUCMD_Finalize(void)
|
|
||||||
{
|
|
||||||
GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x8, 0x00000000);
|
|
||||||
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_FLUSH, 0x00000001);
|
|
||||||
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_INVALIDATE, 0x00000001);
|
|
||||||
GPUCMD_AddWrite(GPUREG_FINALIZE, 0x12345678);
|
|
||||||
GPUCMD_AddWrite(GPUREG_FINALIZE, 0x12345678); //not the cleanest way of guaranteeing 0x10-byte size but whatever good enough for now
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline u32 floatrawbits(float f)
|
static inline u32 floatrawbits(float f)
|
||||||
{
|
{
|
||||||
union { float f; u32 i; } s;
|
union { float f; u32 i; } s;
|
||||||
|
@ -430,3 +430,15 @@ Result GSPGPU_RestoreVramSysArea(void)
|
|||||||
return cmdbuf[1];
|
return cmdbuf[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result GSPGPU_SetLedForceOff(bool disable)
|
||||||
|
{
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x1C,1,0); // 0x1C0040
|
||||||
|
cmdbuf[1] = disable & 0xFF;
|
||||||
|
|
||||||
|
Result ret=0;
|
||||||
|
if (R_FAILED(ret = svcSendSyncRequest(gspGpuHandle))) return ret;
|
||||||
|
|
||||||
|
return cmdbuf[1];
|
||||||
|
}
|
@ -26,6 +26,30 @@ void gspLcdExit(void)
|
|||||||
svcCloseHandle(gspLcdHandle);
|
svcCloseHandle(gspLcdHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result GSPLCD_PowerOnAllBacklights(void)
|
||||||
|
{
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x0F,0,0); // 0x0F0000
|
||||||
|
|
||||||
|
Result ret=0;
|
||||||
|
if (R_FAILED(ret = svcSendSyncRequest(gspLcdHandle))) return ret;
|
||||||
|
|
||||||
|
return cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GSPLCD_PowerOffAllBacklights(void)
|
||||||
|
{
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x10,0,0); // 0x100000
|
||||||
|
|
||||||
|
Result ret=0;
|
||||||
|
if (R_FAILED(ret = svcSendSyncRequest(gspLcdHandle))) return ret;
|
||||||
|
|
||||||
|
return cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
Result GSPLCD_PowerOnBacklight(u32 screen)
|
Result GSPLCD_PowerOnBacklight(u32 screen)
|
||||||
{
|
{
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
@ -52,6 +76,19 @@ Result GSPLCD_PowerOffBacklight(u32 screen)
|
|||||||
return cmdbuf[1];
|
return cmdbuf[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result GSPLCD_SetLedForceOff(bool disable)
|
||||||
|
{
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x13,1,0); // 0x130040
|
||||||
|
cmdbuf[1] = disable & 0xFF;
|
||||||
|
|
||||||
|
Result ret=0;
|
||||||
|
if (R_FAILED(ret = svcSendSyncRequest(gspLcdHandle))) return ret;
|
||||||
|
|
||||||
|
return cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
Result GSPLCD_GetVendors(u8 *vendors)
|
Result GSPLCD_GetVendors(u8 *vendors)
|
||||||
{
|
{
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
93
libctru/source/services/loader.c
Normal file
93
libctru/source/services/loader.c
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#include <3ds/services/loader.h>
|
||||||
|
#include <3ds/result.h>
|
||||||
|
#include <3ds/svc.h>
|
||||||
|
#include <3ds/srv.h>
|
||||||
|
#include <3ds/synchronization.h>
|
||||||
|
#include <3ds/ipc.h>
|
||||||
|
|
||||||
|
static Handle loaderHandle;
|
||||||
|
static int loaderRefCount;
|
||||||
|
|
||||||
|
Result loaderInit(void)
|
||||||
|
{
|
||||||
|
Result res;
|
||||||
|
if (AtomicPostIncrement(&loaderRefCount)) return 0;
|
||||||
|
res = srvGetServiceHandle(&loaderHandle, "Loader");
|
||||||
|
if (R_FAILED(res)) AtomicDecrement(&loaderRefCount);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loaderExit(void)
|
||||||
|
{
|
||||||
|
if (AtomicDecrement(&loaderRefCount)) return;
|
||||||
|
svcCloseHandle(loaderHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result LOADER_LoadProcess(Handle* process, u64 programHandle)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(1, 2, 0); // 0x10080
|
||||||
|
cmdbuf[1] = (u32)programHandle;
|
||||||
|
cmdbuf[2] = (u32)(programHandle >> 32);
|
||||||
|
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(loaderHandle))) return ret;
|
||||||
|
|
||||||
|
*process = cmdbuf[3];
|
||||||
|
|
||||||
|
return (Result)cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Result LOADER_RegisterProgram(u64* programHandle, u64 titleId, FS_MediaType mediaType, u64 updateTitleId, FS_MediaType updateMediaType)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(2, 8, 0); // 0x20200
|
||||||
|
cmdbuf[1] = (u32)titleId;
|
||||||
|
cmdbuf[2] = (u32)(titleId >> 32);
|
||||||
|
cmdbuf[3] = mediaType;
|
||||||
|
|
||||||
|
cmdbuf[5] = (u32)updateTitleId;
|
||||||
|
cmdbuf[6] = (u32)(updateTitleId >> 32);
|
||||||
|
cmdbuf[7] = updateMediaType;
|
||||||
|
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(loaderHandle))) return ret;
|
||||||
|
|
||||||
|
*programHandle = ((u64)cmdbuf[2] << 32) | cmdbuf[3];
|
||||||
|
|
||||||
|
return (Result)cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Result LOADER_UnregisterProgram(u64 programHandle)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(3, 2, 0); // 0x30080
|
||||||
|
cmdbuf[1] = (u32)programHandle;
|
||||||
|
cmdbuf[2] = (u32)(programHandle >> 32);
|
||||||
|
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(loaderHandle))) return ret;
|
||||||
|
|
||||||
|
return (Result)cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Result LOADER_GetProgramInfo(ExHeader_Info* exheaderInfo, u64 programHandle)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
u32 *staticbufs = getThreadStaticBuffers();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(4, 2, 0); // 0x40080
|
||||||
|
cmdbuf[1] = (u32)programHandle;
|
||||||
|
cmdbuf[2] = (u32)(programHandle >> 32);
|
||||||
|
|
||||||
|
staticbufs[0] = IPC_Desc_StaticBuffer(0x400, 0);
|
||||||
|
staticbufs[1] = (u32)exheaderInfo;
|
||||||
|
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(loaderHandle))) return ret;
|
||||||
|
|
||||||
|
return (Result)cmdbuf[1];
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user