Add miiSelector configuration functions (#429)
This commit is contained in:
parent
c550a22259
commit
d3ea737071
@ -22,25 +22,25 @@
|
||||
/// 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,
|
||||
u8 enable_cancel_button; ///< Enables canceling of selection if nonzero.
|
||||
u8 enable_selecting_guests; ///< Makes Guets Miis selectable if nonzero.
|
||||
u8 show_on_top_screen; ///< Shows applet on top screen if nonzero,
|
||||
///< otherwise show it on the bottom screen.
|
||||
char _unk0x3[5]; ///< @private
|
||||
u8 _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
|
||||
u8 _unk0x88[4]; ///< @private
|
||||
u8 show_guest_page; ///< If nonzero, the applet shows a page with Guest
|
||||
///< Miis on launch.
|
||||
char _unk0x8D[3]; ///< @private
|
||||
u8 _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
|
||||
u8 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
|
||||
u8 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
|
||||
@ -48,9 +48,6 @@ typedef struct
|
||||
///< 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
|
||||
|
||||
@ -73,6 +70,21 @@ typedef struct
|
||||
///< string). Zeroed otherwise.
|
||||
} MiiSelectorReturn;
|
||||
|
||||
/// AppletEd options
|
||||
enum
|
||||
{
|
||||
MIISELECTOR_CANCEL = BIT(0), ///< Show the cancel button
|
||||
MIISELECTOR_GUESTS = BIT(1), ///< Make Guets Miis selectable
|
||||
MIISELECTOR_TOP = BIT(2), ///< Show AppletEd on top screen
|
||||
MIISELECTOR_GUESTSTART = BIT(3), ///< Start on guest page
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize Mii selector config
|
||||
* @param conf Pointer to Miiselector config.
|
||||
*/
|
||||
void miiSelectorInit(MiiSelectorConf *conf);
|
||||
|
||||
/**
|
||||
* @brief Launch the Mii selector library applet
|
||||
*
|
||||
@ -81,12 +93,97 @@ typedef struct
|
||||
*/
|
||||
Result miiSelectorLaunch(const MiiSelectorConf *conf, MiiSelectorReturn* returnbuf);
|
||||
|
||||
/**
|
||||
* @brief Sets title of the Mii selector library applet
|
||||
*
|
||||
* @param conf Pointer to miiSelector configuration
|
||||
* @param text Title text of Mii selector
|
||||
*/
|
||||
void miiSelectorSetTitle(MiiSelectorConf *conf, const char* text);
|
||||
|
||||
/**
|
||||
* @brief Specifies which special options are enabled in the Mii selector
|
||||
*
|
||||
* @param conf Pointer to miiSelector configuration
|
||||
* @param options Options bitmask
|
||||
*/
|
||||
void miiSelectorSetOptions(MiiSelectorConf *conf, u32 options);
|
||||
|
||||
/**
|
||||
* @brief Specifies which guest Miis will be selectable
|
||||
*
|
||||
* @param conf Pointer to miiSelector configuration
|
||||
* @param index Index of the guest Miis that will be whitelisted.
|
||||
* @ref MIISELECTOR_GUESTMII_SLOTS can be used to whitelist all the guest Miis.
|
||||
*/
|
||||
void miiSelectorWhitelistGuestMii(MiiSelectorConf *conf, u32 index);
|
||||
|
||||
/**
|
||||
* @brief Specifies which guest Miis will be unselectable
|
||||
*
|
||||
* @param conf Pointer to miiSelector configuration
|
||||
* @param index Index of the guest Miis that will be blacklisted.
|
||||
* @ref MIISELECTOR_GUESTMII_SLOTS can be used to blacklist all the guest Miis.
|
||||
*/
|
||||
void miiSelectorBlacklistGuestMii(MiiSelectorConf *conf, u32 index);
|
||||
|
||||
/**
|
||||
* @brief Specifies which user Miis will be selectable
|
||||
*
|
||||
* @param conf Pointer to miiSelector configuration
|
||||
* @param index Index of the user Miis that will be whitelisted.
|
||||
* @ref MIISELECTOR_USERMII_SLOTS can be used to whitlist all the user Miis
|
||||
*/
|
||||
void miiSelectorWhitelistUserMii(MiiSelectorConf *conf, u32 index);
|
||||
|
||||
/**
|
||||
* @brief Specifies which user Miis will be selectable
|
||||
*
|
||||
* @param conf Pointer to miiSelector configuration
|
||||
* @param index Index of the user Miis that will be blacklisted.
|
||||
* @ref MIISELECTOR_USERMII_SLOTS can be used to blacklist all the user Miis
|
||||
*/
|
||||
void miiSelectorBlacklistUserMii(MiiSelectorConf *conf, u32 index);
|
||||
|
||||
/**
|
||||
* @brief Specifies which Mii the cursor should start from
|
||||
*
|
||||
* @param conf Pointer to miiSelector configuration
|
||||
* @param index Indexed number of the Mii that the cursor will start on.
|
||||
* If there is no mii with that index, the the cursor will start at the Mii
|
||||
* with the index 0 (the personal Mii).
|
||||
*/
|
||||
static inline void miiSelectorSetInitialIndex(MiiSelectorConf *conf, u32 index)
|
||||
{
|
||||
conf->initial_index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Mii name
|
||||
*
|
||||
* @param returnbuf Pointer to miiSelector return
|
||||
* @param out String containing a Mii's name
|
||||
* @param max_size Size of string. Since UTF8 characters range in size from 1-3 bytes
|
||||
* (assuming that no non-BMP characters are used), this value should be 36 (or 30 if you are not
|
||||
* dealing with guest miis).
|
||||
*/
|
||||
void miiSelectorReturnGetName(const MiiSelectorReturn *returnbuf, char* out, size_t max_size);
|
||||
|
||||
/**
|
||||
* @brief Get Mii Author
|
||||
*
|
||||
* @param returnbuf Pointer to miiSelector return
|
||||
* @param out String containing a Mii's author
|
||||
* @param max_size Size of string. Since UTF8 characters range in size from 1-3 bytes
|
||||
* (assuming that no non-BMP characters are used), this value should be 30.
|
||||
*/
|
||||
void miiSelectorReturnGetAuthor(const MiiSelectorReturn *returnbuf, char* out, size_t max_size);
|
||||
|
||||
/**
|
||||
* @brief Verifies that the Mii data returned from the applet matches its
|
||||
* checksum
|
||||
*
|
||||
* @param returnbuffer Buffer filled by Mii selector applet
|
||||
*
|
||||
* @param returnbuf 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);
|
||||
|
@ -1,56 +1,84 @@
|
||||
/**
|
||||
* @file mii.h
|
||||
* @brief Shared Mii struct.
|
||||
*
|
||||
* @see https://www.3dbrew.org/wiki/Mii#Mii_format
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <3ds/types.h>
|
||||
|
||||
/// Shared Mii struct
|
||||
typedef struct
|
||||
{
|
||||
u8 magic;
|
||||
|
||||
u8 magic; ///< Always 3?
|
||||
|
||||
/// Mii options
|
||||
struct
|
||||
{
|
||||
bool allow_copying : 1;
|
||||
bool is_private_name : 1;
|
||||
u8 region_lock : 2;
|
||||
u8 char_set : 2;
|
||||
bool allow_copying : 1; ///< True if copying is allowed
|
||||
bool is_private_name : 1; ///< Private name?
|
||||
u8 region_lock : 2; ///< Region lock (0=no lock, 1=JPN, 2=USA, 3=EUR)
|
||||
u8 char_set : 2; ///< Character set (0=JPN+USA+EUR, 1=CHN, 2=KOR, 3=TWN)
|
||||
} mii_options;
|
||||
|
||||
|
||||
/// Mii position in Mii selector or Mii maker
|
||||
struct
|
||||
{
|
||||
u8 page_index : 4;
|
||||
u8 slot_index : 4;
|
||||
u8 page_index : 4; ///< Page index of Mii
|
||||
u8 slot_index : 4; ///< Slot offset of Mii on its Page
|
||||
} mii_pos;
|
||||
|
||||
u8 console_identity;
|
||||
u64 system_id;
|
||||
u32 mii_id;
|
||||
u8 mac[6];
|
||||
u8 pad[2];
|
||||
u16 mii_details;
|
||||
u16 mii_name[10];
|
||||
u8 height;
|
||||
u8 width;
|
||||
|
||||
|
||||
/// Console Identity
|
||||
struct
|
||||
{
|
||||
bool disable_sharing : 1;
|
||||
u8 shape : 4;
|
||||
u8 skinColor : 3;
|
||||
u8 unknown0 : 4; ///< Mabye padding (always seems to be 0)?
|
||||
u8 origin_console : 3; ///< Console that the Mii was created on (1=WII, 2=DSI, 3=3DS)
|
||||
} console_identity;
|
||||
|
||||
u64 system_id; ///< Identifies the system that the Mii was created on (Determines pants)
|
||||
u32 mii_id; ///< ID of Mii
|
||||
u8 mac[6]; ///< Creator's system's full MAC address
|
||||
u8 pad[2]; ///< Padding
|
||||
|
||||
/// Mii details
|
||||
struct {
|
||||
bool sex : 1; ///< Sex of Mii (False=Male, True=Female)
|
||||
u16 bday_month : 4; ///< Month of Mii's birthday
|
||||
u16 bday_day : 5; ///< Day of Mii's birthday
|
||||
u16 shirt_color : 4; ///< Color of Mii's shirt
|
||||
bool favorite : 1; ///< Whether the Mii is one of your 10 favorite Mii's
|
||||
} mii_details;
|
||||
|
||||
u16 mii_name[10]; ///< Name of Mii (Encoded using UTF16)
|
||||
u8 height; ///< How tall the Mii is
|
||||
u8 width; ///< How wide the Mii is
|
||||
|
||||
/// Face style
|
||||
struct
|
||||
{
|
||||
bool disable_sharing : 1; ///< Whether or not Sharing of the Mii is allowed
|
||||
u8 shape : 4; ///< Face shape
|
||||
u8 skinColor : 3; ///< Color of skin
|
||||
} face_style;
|
||||
|
||||
|
||||
/// Face details
|
||||
struct
|
||||
{
|
||||
u8 wrinkles : 4;
|
||||
u8 makeup : 4;
|
||||
} face_details;
|
||||
|
||||
|
||||
u8 hair_style;
|
||||
|
||||
|
||||
/// Hair details
|
||||
struct
|
||||
{
|
||||
u8 color : 3;
|
||||
bool flip : 1;
|
||||
} hair_details;
|
||||
|
||||
|
||||
/// Eye details
|
||||
struct
|
||||
{
|
||||
u32 style : 6;
|
||||
@ -61,18 +89,21 @@ typedef struct
|
||||
u32 xspacing : 4;
|
||||
u32 yposition : 5;
|
||||
} eye_details;
|
||||
|
||||
|
||||
/// Eyebrow details
|
||||
struct
|
||||
{
|
||||
u32 style : 6;
|
||||
u32 style : 5;
|
||||
u32 color : 3;
|
||||
u32 scale : 4;
|
||||
u32 yscale : 3;
|
||||
u32 pad : 1;
|
||||
u32 rotation : 5;
|
||||
u32 xspacing : 4;
|
||||
u32 yposition : 5;
|
||||
} eyebrow_details;
|
||||
|
||||
|
||||
/// Nose details
|
||||
struct
|
||||
{
|
||||
u16 style : 5;
|
||||
@ -80,21 +111,24 @@ typedef struct
|
||||
u16 yposition : 5;
|
||||
} nose_details;
|
||||
|
||||
/// Mouth details
|
||||
struct
|
||||
{
|
||||
u16 style : 6;
|
||||
u16 color : 3;
|
||||
u16 scale : 4;
|
||||
u16 yscale : 3;
|
||||
} mouse_details;
|
||||
} mouth_details;
|
||||
|
||||
/// Mustache details
|
||||
struct
|
||||
{
|
||||
u16 mouse_yposition : 5;
|
||||
u16 mouth_yposition : 5;
|
||||
u16 mustach_style : 3;
|
||||
u16 pad : 2;
|
||||
} mustache_details;
|
||||
|
||||
|
||||
/// Beard details
|
||||
struct
|
||||
{
|
||||
u16 style : 3;
|
||||
@ -103,6 +137,7 @@ typedef struct
|
||||
u16 ypos : 5;
|
||||
} beard_details;
|
||||
|
||||
/// Glasses details
|
||||
struct
|
||||
{
|
||||
u16 style : 4;
|
||||
@ -111,6 +146,7 @@ typedef struct
|
||||
u16 ypos : 5;
|
||||
} glasses_details;
|
||||
|
||||
/// Mole details
|
||||
struct
|
||||
{
|
||||
bool enable : 1;
|
||||
@ -119,5 +155,5 @@ typedef struct
|
||||
u16 ypos : 5;
|
||||
} mole_details;
|
||||
|
||||
u16 author_name[10];
|
||||
u16 author_name[10]; ///< Name of Mii's author (Encoded using UTF16)
|
||||
} PACKED MiiData;
|
||||
|
@ -1,11 +1,23 @@
|
||||
#include <3ds/types.h>
|
||||
#include <3ds/result.h>
|
||||
#include <3ds/services/apt.h>
|
||||
#include <3ds/util/utf.h>
|
||||
|
||||
#include <3ds/applets/miiselector.h>
|
||||
|
||||
#include <string.h> // for memcpy
|
||||
|
||||
void miiSelectorInit(MiiSelectorConf *conf)
|
||||
{
|
||||
memset(conf, 0, sizeof(*conf));
|
||||
|
||||
for (int i = 0; i < MIISELECTOR_GUESTMII_SLOTS; i ++)
|
||||
conf->mii_guest_whitelist[i] = 1;
|
||||
|
||||
for (int i = 0; i < MIISELECTOR_USERMII_SLOTS; i ++)
|
||||
conf->mii_whitelist[i] = 1;
|
||||
}
|
||||
|
||||
Result miiSelectorLaunch(const MiiSelectorConf *conf, MiiSelectorReturn *returnbuf)
|
||||
{
|
||||
union {
|
||||
@ -17,33 +29,139 @@ Result miiSelectorLaunch(const MiiSelectorConf *conf, MiiSelectorReturn *returnb
|
||||
ctx.config.magic = MIISELECTOR_MAGIC;
|
||||
|
||||
Result ret = aptLaunchLibraryApplet(APPID_APPLETED, &ctx.config, sizeof(MiiSelectorConf), 0);
|
||||
if(R_SUCCEEDED(ret) && returnbuf) {
|
||||
if(R_SUCCEEDED(ret) && returnbuf)
|
||||
memcpy(returnbuf, &ctx.ret, sizeof(MiiSelectorReturn));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void miiSelectorConvertToUTF8(char* out, const u16* in, int max)
|
||||
{
|
||||
if (!in || !*in)
|
||||
{
|
||||
out[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ssize_t units = utf16_to_utf8((uint8_t*)out, in, max);
|
||||
if (units < 0)
|
||||
{
|
||||
out[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
out[units] = 0;
|
||||
}
|
||||
|
||||
static void miiSelectorConvertToUTF16(u16* out, const char* in, int max)
|
||||
{
|
||||
if (!in || !*in)
|
||||
{
|
||||
out[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ssize_t units = utf8_to_utf16(out, (const uint8_t*)in, max);
|
||||
if (units < 0)
|
||||
{
|
||||
out[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
out[units] = 0;
|
||||
}
|
||||
|
||||
void miiSelectorSetTitle(MiiSelectorConf *conf, const char* text)
|
||||
{
|
||||
miiSelectorConvertToUTF16(conf->title, text, MIISELECTOR_TITLE_LEN);
|
||||
}
|
||||
|
||||
void miiSelectorSetOptions(MiiSelectorConf *conf, u32 options)
|
||||
{
|
||||
static const u8 miiSelectorOptions[] =
|
||||
{
|
||||
offsetof(MiiSelectorConf, enable_cancel_button),
|
||||
offsetof(MiiSelectorConf, enable_selecting_guests),
|
||||
offsetof(MiiSelectorConf, show_on_top_screen),
|
||||
offsetof(MiiSelectorConf, show_guest_page),
|
||||
};
|
||||
for (int i = 0; i < sizeof(miiSelectorOptions); i ++)
|
||||
*((u8*)conf + miiSelectorOptions[i]) = (options & BIT(i)) ? 1 : 0;
|
||||
}
|
||||
|
||||
void miiSelectorWhitelistGuestMii(MiiSelectorConf *conf, u32 index)
|
||||
{
|
||||
if (index < MIISELECTOR_GUESTMII_SLOTS)
|
||||
conf->mii_guest_whitelist[index] = 1;
|
||||
else if (index == MIISELECTOR_GUESTMII_SLOTS)
|
||||
for (int i = 0; i < MIISELECTOR_GUESTMII_SLOTS; i ++)
|
||||
conf->mii_guest_whitelist[i] = 1;
|
||||
}
|
||||
|
||||
void miiSelectorBlacklistGuestMii(MiiSelectorConf *conf, u32 index)
|
||||
{
|
||||
if (index < MIISELECTOR_GUESTMII_SLOTS)
|
||||
conf->mii_guest_whitelist[index] = 0;
|
||||
else if (index == MIISELECTOR_GUESTMII_SLOTS)
|
||||
for (int i = 0; i < MIISELECTOR_GUESTMII_SLOTS; i ++)
|
||||
conf->mii_guest_whitelist[i] = 0;
|
||||
}
|
||||
|
||||
void miiSelectorWhitelistUserMii(MiiSelectorConf *conf, u32 index)
|
||||
{
|
||||
if (index < MIISELECTOR_USERMII_SLOTS)
|
||||
conf->mii_whitelist[index] = 1;
|
||||
else if (index == MIISELECTOR_USERMII_SLOTS)
|
||||
for (int i = 0; i < MIISELECTOR_USERMII_SLOTS; i ++)
|
||||
conf->mii_whitelist[i] = 1;
|
||||
}
|
||||
|
||||
void miiSelectorBlacklistUserMii(MiiSelectorConf *conf, u32 index)
|
||||
{
|
||||
if (index < MIISELECTOR_USERMII_SLOTS)
|
||||
conf->mii_whitelist[index] = 0;
|
||||
else if (index == MIISELECTOR_USERMII_SLOTS)
|
||||
for (int i = 0; i < MIISELECTOR_USERMII_SLOTS; i ++)
|
||||
conf->mii_whitelist[i] = 0;
|
||||
}
|
||||
|
||||
void miiSelectorReturnGetName(const MiiSelectorReturn *returnbuf, char* out, size_t max_size)
|
||||
{
|
||||
if (!out)
|
||||
return;
|
||||
|
||||
if (returnbuf->guest_mii_was_selected)
|
||||
miiSelectorConvertToUTF8(out, returnbuf->guest_mii_name, max_size);
|
||||
else
|
||||
miiSelectorConvertToUTF8(out, returnbuf->mii.mii_name, max_size);
|
||||
}
|
||||
|
||||
void miiSelectorReturnGetAuthor(const MiiSelectorReturn *returnbuf, char* out, size_t max_size)
|
||||
{
|
||||
if (!out)
|
||||
return;
|
||||
|
||||
miiSelectorConvertToUTF8(out, returnbuf->mii.author_name, max_size);
|
||||
}
|
||||
|
||||
static u16 crc16_ccitt(void const *buf, size_t len, uint32_t starting_val)
|
||||
{
|
||||
if(buf == NULL) {
|
||||
if (!buf)
|
||||
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--) {
|
||||
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; _++) {
|
||||
for (int _ = 0; _ < 16; _++)
|
||||
crc = (crc << 1) ^ (crc & 0x8000 ? POLY : 0);
|
||||
}
|
||||
|
||||
return (u16)(crc & 0xffff);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user