diff --git a/ctru-rs/src/applets/mii_selector.rs b/ctru-rs/src/applets/mii_selector.rs index d4fe6d1..342b797 100644 --- a/ctru-rs/src/applets/mii_selector.rs +++ b/ctru-rs/src/applets/mii_selector.rs @@ -1,13 +1,20 @@ +//! Mii Selector applet +//! +//! This module contains the methods to launch the Mii Selector. + use crate::mii::MiiData; use bitflags::bitflags; use std::ffi::CString; +/// Index of a Mii used to configure some parameters of the Mii Selector +/// Can be either a single index, or _all_ Miis #[derive(Debug, Clone)] pub enum MiiConfigIndex { Index(u32), All, } +/// The type of a Mii with their respective data #[derive(Debug, Clone)] pub enum MiiType { Guest { index: u32, name: String }, @@ -15,19 +22,36 @@ pub enum MiiType { } bitflags! { + /// Options for the Mii Selector pub struct Options: u32 { + /// Show the cancel button const MII_SELECTOR_CANCEL = ctru_sys::MIISELECTOR_CANCEL; + /// Make guest Miis selectable const MII_SELECTOR_GUESTS = ctru_sys::MIISELECTOR_GUESTS; + /// Show on the top screen const MII_SELECTOR_TOP = ctru_sys::MIISELECTOR_TOP; + /// Start on the guest's page const MII_SELECTOR_GUEST_START = ctru_sys::MIISELECTOR_GUESTSTART; } } +/// An instance of the Mii Selector +/// +/// # Example +/// ``` +/// use ctru::applets::mii_selector::MiiSelector; +/// +/// let mut mii_selector = MiiSelector::init(); +/// mii_selector.set_title("Example Mii selector"); +/// +/// let result = mii_selector.launch().unwrap(); +/// ``` #[derive(Clone, Debug)] pub struct MiiSelector { config: Box, } +/// Return value from a MiiSelector's launch #[derive(Clone, Debug)] pub struct MiiSelectorReturn { pub mii_data: MiiData, @@ -36,12 +60,14 @@ pub struct MiiSelectorReturn { pub checksum: u16, } +/// Error type for the Mii selector #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum MiiLaunchError { InvalidChecksum, } impl MiiSelector { + /// Initializes a Mii Selector pub fn init() -> Self { let mut config = Box::::default(); unsafe { @@ -50,6 +76,7 @@ impl MiiSelector { Self { config } } + /// Set the title of the Mii Selector pub fn set_title(&mut self, text: &str) { // This can only fail if the text contains NUL bytes in the string... which seems // unlikely and is documented @@ -59,10 +86,12 @@ impl MiiSelector { } } + /// Set the options of the Mii Selector pub fn set_options(&mut self, options: Options) { unsafe { ctru_sys::miiSelectorSetOptions(self.config.as_mut(), options.bits) } } + /// Whitelist a guest Mii pub fn whitelist_guest_mii(&mut self, mii_index: MiiConfigIndex) { let index = match mii_index { MiiConfigIndex::Index(i) => i, @@ -72,6 +101,7 @@ impl MiiSelector { unsafe { ctru_sys::miiSelectorWhitelistGuestMii(self.config.as_mut(), index) } } + /// Blacklist a guest Mii pub fn blacklist_guest_mii(&mut self, mii_index: MiiConfigIndex) { let index = match mii_index { MiiConfigIndex::Index(i) => i, @@ -81,6 +111,7 @@ impl MiiSelector { unsafe { ctru_sys::miiSelectorBlacklistGuestMii(self.config.as_mut(), index) } } + /// Whitelist a user Mii pub fn whitelist_user_mii(&mut self, mii_index: MiiConfigIndex) { let index = match mii_index { MiiConfigIndex::Index(i) => i, @@ -90,6 +121,7 @@ impl MiiSelector { unsafe { ctru_sys::miiSelectorWhitelistUserMii(self.config.as_mut(), index) } } + /// Blacklist a user Mii pub fn blacklist_user_mii(&mut self, mii_index: MiiConfigIndex) { let index = match mii_index { MiiConfigIndex::Index(i) => i, @@ -99,12 +131,17 @@ impl MiiSelector { unsafe { ctru_sys::miiSelectorBlacklistUserMii(self.config.as_mut(), index) } } - // This function is static inline in libctru - // https://github.com/devkitPro/libctru/blob/af5321c78ee5c72a55b526fd2ed0d95ca1c05af9/libctru/include/3ds/applets/miiselector.h#L155 + + /// Set where the cursor will be. + /// If there's no Mii at that index, the cursor will start at the Mii with the index 0 pub fn set_initial_index(&mut self, index: u32) { + // This function is static inline in libctru + // https://github.com/devkitPro/libctru/blob/af5321c78ee5c72a55b526fd2ed0d95ca1c05af9/libctru/include/3ds/applets/miiselector.h#L155 self.config.initial_index = index } + /// Launch the Mii Selector. + /// Returns an error when the checksum of the Mii is invalid. pub fn launch(&mut self) -> Result { let mut return_val = Box::::default(); unsafe { ctru_sys::miiSelectorLaunch(self.config.as_mut(), return_val.as_mut()) } diff --git a/ctru-rs/src/mii.rs b/ctru-rs/src/mii.rs index b969c78..b40c836 100644 --- a/ctru-rs/src/mii.rs +++ b/ctru-rs/src/mii.rs @@ -1,3 +1,9 @@ +//! Mii Data +//! +//! This module contains the structs that represent all the data of a Mii. +//! This data is given by the [``MiiSelector``] + +/// Represents the region lock of the console #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum RegionLock { None, @@ -6,6 +12,7 @@ pub enum RegionLock { Europe, } +/// Represent the charset of the console #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Charset { JapanUSAEurope, @@ -14,6 +21,7 @@ pub enum Charset { Taiwan, } +/// Represents the options of the Mii #[derive(Copy, Clone, Debug)] pub struct MiiDataOptions { pub is_copying_allowed: bool, @@ -22,12 +30,14 @@ pub struct MiiDataOptions { pub charset: Charset, } +/// Represents the position that the Mii has on the selector #[derive(Copy, Clone, Debug)] pub struct SelectorPosition { pub page_index: u8, pub slot_index: u8, } +/// Represents the kind of origin console #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum OriginConsole { ConsoleWii, @@ -36,17 +46,20 @@ pub enum OriginConsole { ConsoleWiiUSwitch, } +/// Represents the identity of the origin console #[derive(Copy, Clone, Debug)] pub struct ConsoleIdentity { pub origin_console: OriginConsole, } +/// Represents the sex of the Mii #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum MiiSex { Male, Female, } +/// Represents the details of the Mii #[derive(Copy, Clone, Debug)] pub struct Details { pub sex: MiiSex, @@ -56,6 +69,7 @@ pub struct Details { pub is_favorite: bool, } +/// Represents the face style of the Mii #[derive(Copy, Clone, Debug)] pub struct FaceStyle { pub is_sharing_enabled: bool, @@ -63,18 +77,21 @@ pub struct FaceStyle { pub skin_color: u8, } +/// Represents the face details of the Mii #[derive(Copy, Clone, Debug)] pub struct FaceDetails { pub wrinkles: u8, pub makeup: u8, } +/// Represents the hair details of the Mii #[derive(Copy, Clone, Debug)] pub struct HairDetails { pub color: u8, pub is_flipped: bool, } +/// Represents the eye details of the Mii #[derive(Copy, Clone, Debug)] pub struct EyeDetails { pub style: u8, @@ -82,10 +99,12 @@ pub struct EyeDetails { pub scale: u8, pub y_scale: u8, pub rotation: u8, + /// Spacing between the eyes pub x_spacing: u8, pub y_position: u8, } +/// Represents the eyebrow details of the Mii #[derive(Copy, Clone, Debug)] pub struct EyebrowDetails { pub style: u8, @@ -93,10 +112,12 @@ pub struct EyebrowDetails { pub scale: u8, pub y_scale: u8, pub rotation: u8, + /// Spacing between the eyebrows pub x_spacing: u8, pub y_position: u8, } +/// Represents the details of the nose #[derive(Copy, Clone, Debug)] pub struct NoseDetails { pub style: u8, @@ -104,6 +125,7 @@ pub struct NoseDetails { pub y_position: u8, } +/// Represents the details of the mouth #[derive(Copy, Clone, Debug)] pub struct MouthDetails { pub style: u8, @@ -112,12 +134,14 @@ pub struct MouthDetails { pub y_scale: u8, } +/// Represents the details of the mustache #[derive(Copy, Clone, Debug)] pub struct MustacheDetails { pub mouth_y_position: u8, pub mustache_style: u8, } +/// Represents the details of the beard #[derive(Copy, Clone, Debug)] pub struct BeardDetails { pub style: u8, @@ -126,6 +150,7 @@ pub struct BeardDetails { pub y_position: u8, } +/// Represents the details of the glass #[derive(Copy, Clone, Debug)] pub struct GlassDetails { pub style: u8, @@ -134,6 +159,7 @@ pub struct GlassDetails { pub y_position: u8, } +/// Represents the details of the mole #[derive(Copy, Clone, Debug)] pub struct MoleDetails { pub is_enabled: bool, @@ -142,12 +168,14 @@ pub struct MoleDetails { pub y_position: u8, } +/// Represents all the data of a Mii #[derive(Clone, Debug)] pub struct MiiData { pub options: MiiDataOptions, pub selector_position: SelectorPosition, pub console_identity: ConsoleIdentity, + /// Unique system ID, not dependant on the MAC address pub system_id: [u8; 8], pub mac_address: [u8; 6], @@ -411,11 +439,12 @@ fn vec_bit_to_u8(data: [bool; 8]) -> u8 { .fold(0, |result, bit| (result << 1) ^ u8::from(bit)) } +/// Given a series of LE bits, they are filled until a full LE u8 is reached fn partial_u8_bits_to_u8(data: &[bool]) -> u8 { let leading_zeroes_to_add = 8 - data.len(); let leading_zeroes = vec![false; leading_zeroes_to_add]; - let mut val = [data, leading_zeroes.as_slice()].concat(); - vec_bit_to_u8(val.try_into().unwrap()) + + vec_bit_to_u8([data, &leading_zeroes].concat().try_into().unwrap()) } /// UTF-16 Strings are give in pairs of bytes (u8), this converts them into an _actual_ string