Merge branch 'master' into master

This commit is contained in:
fincs 2017-09-23 16:03:23 +02:00 committed by GitHub
commit f95d206eb4
13 changed files with 356 additions and 35 deletions

View File

@ -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>

View 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);

View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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);

View 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);

View 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;
}

View File

@ -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;

View File

@ -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];
}

View File

@ -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();

View 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];
}