TechiePi
2 years ago
2 changed files with 167 additions and 0 deletions
@ -0,0 +1,166 @@ |
|||||||
|
use std::ffi::{CString}; |
||||||
|
use bitflags::bitflags; |
||||||
|
|
||||||
|
#[derive(Debug, Clone)] |
||||||
|
pub enum MiiConfigIndex { |
||||||
|
Index(u32), |
||||||
|
All, |
||||||
|
} |
||||||
|
|
||||||
|
#[derive(Debug, Clone)] |
||||||
|
pub enum MiiType { |
||||||
|
Guest { |
||||||
|
index: u32, |
||||||
|
name: String, |
||||||
|
}, |
||||||
|
User, |
||||||
|
} |
||||||
|
|
||||||
|
bitflags! { |
||||||
|
pub struct Options: u32 { |
||||||
|
const MII_SELECTOR_CANCEL = ctru_sys::MIISELECTOR_CANCEL; |
||||||
|
const MII_SELECTOR_GUESTS = ctru_sys::MIISELECTOR_GUESTS; |
||||||
|
const MII_SELECTOR_TOP = ctru_sys::MIISELECTOR_TOP; |
||||||
|
const MII_SELECTOR_GUEST_START = ctru_sys::MIISELECTOR_GUESTSTART; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub struct MiiSelector { |
||||||
|
config: Box<ctru_sys::MiiSelectorConf>, |
||||||
|
} |
||||||
|
|
||||||
|
pub struct MiiSelectorReturn { |
||||||
|
raw_return: Box<ctru_sys::MiiSelectorReturn>, |
||||||
|
pub is_mii_selected: bool, |
||||||
|
pub mii_type: MiiType, |
||||||
|
pub checksum: u16, |
||||||
|
} |
||||||
|
|
||||||
|
impl MiiSelector { |
||||||
|
pub fn init() -> Self { |
||||||
|
let mut config = Box::<ctru_sys::MiiSelectorConf>::default(); |
||||||
|
unsafe { ctru_sys::miiSelectorInit(config.as_mut()); } |
||||||
|
Self { config } |
||||||
|
} |
||||||
|
|
||||||
|
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
|
||||||
|
let c_text = CString::new(text).expect("Cstring::new failed"); |
||||||
|
unsafe { ctru_sys::miiSelectorSetTitle(self.config.as_mut(), c_text.as_ptr()); } |
||||||
|
} |
||||||
|
|
||||||
|
pub fn set_options(&mut self, options: Options) { |
||||||
|
unsafe { ctru_sys::miiSelectorSetOptions(self.config.as_mut(), options.bits) } |
||||||
|
} |
||||||
|
|
||||||
|
pub fn whitelist_guest_mii(&mut self, mii_index: MiiConfigIndex) { |
||||||
|
match mii_index { |
||||||
|
MiiConfigIndex::Index(i) => { |
||||||
|
unsafe { ctru_sys::miiSelectorWhitelistGuestMii(self.config.as_mut(), i) } |
||||||
|
} |
||||||
|
MiiConfigIndex::All => { |
||||||
|
unsafe { ctru_sys::miiSelectorWhitelistGuestMii(self.config.as_mut(), ctru_sys::MIISELECTOR_GUESTMII_SLOTS) } |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn blacklist_guest_mii(&mut self, mii_index: MiiConfigIndex) { |
||||||
|
match mii_index { |
||||||
|
MiiConfigIndex::Index(i) => { |
||||||
|
unsafe { ctru_sys::miiSelectorBlacklistGuestMii(self.config.as_mut(), i) } |
||||||
|
} |
||||||
|
MiiConfigIndex::All => { |
||||||
|
unsafe { ctru_sys::miiSelectorBlacklistGuestMii(self.config.as_mut(), ctru_sys::MIISELECTOR_GUESTMII_SLOTS) } |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn whitelist_user_mii(&mut self, mii_index: MiiConfigIndex) { |
||||||
|
match mii_index { |
||||||
|
MiiConfigIndex::Index(i) => { |
||||||
|
unsafe { ctru_sys::miiSelectorWhitelistUserMii(self.config.as_mut(), i) } |
||||||
|
} |
||||||
|
MiiConfigIndex::All => { |
||||||
|
unsafe { ctru_sys::miiSelectorWhitelistUserMii(self.config.as_mut(), ctru_sys::MIISELECTOR_USERMII_SLOTS) } |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn blacklist_user_mii(&mut self, mii_index: MiiConfigIndex) { |
||||||
|
match mii_index { |
||||||
|
MiiConfigIndex::Index(i) => { |
||||||
|
unsafe { ctru_sys::miiSelectorBlacklistUserMii(self.config.as_mut(), i) } |
||||||
|
} |
||||||
|
MiiConfigIndex::All => { |
||||||
|
unsafe { ctru_sys::miiSelectorBlacklistUserMii(self.config.as_mut(), ctru_sys::MIISELECTOR_USERMII_SLOTS) } |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// This function is static inline in libctru
|
||||||
|
// https://github.com/devkitPro/libctru/blob/af5321c78ee5c72a55b526fd2ed0d95ca1c05af9/libctru/include/3ds/applets/miiselector.h#L155
|
||||||
|
pub fn set_initial_index(&mut self, index: u32) { |
||||||
|
self.config.initial_index = index |
||||||
|
} |
||||||
|
|
||||||
|
pub fn launch(&mut self) -> MiiSelectorReturn { |
||||||
|
let mut return_val = Box::<ctru_sys::MiiSelectorReturn>::default(); |
||||||
|
unsafe { |
||||||
|
ctru_sys::miiSelectorLaunch(self.config.as_mut(), return_val.as_mut()) |
||||||
|
} |
||||||
|
|
||||||
|
return_val.into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl MiiSelectorReturn { |
||||||
|
pub fn name(&self) -> String { |
||||||
|
let mut tmp = [0u8; 36]; |
||||||
|
unsafe { ctru_sys::miiSelectorReturnGetName(self.raw_return.as_ref(), tmp.as_mut_ptr(), 36) } |
||||||
|
|
||||||
|
let len = unsafe { libc::strlen(tmp.as_ptr()) }; |
||||||
|
let utf8 = unsafe { std::str::from_utf8_unchecked(&tmp[..len]) }; |
||||||
|
|
||||||
|
utf8.to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
pub fn author(&self) -> String { |
||||||
|
let mut tmp = [0u8; 30]; |
||||||
|
unsafe { ctru_sys::miiSelectorReturnGetName(self.raw_return.as_ref(), tmp.as_mut_ptr(), 30) } |
||||||
|
let utf8 = unsafe { std::str::from_utf8_unchecked(&tmp) }; |
||||||
|
|
||||||
|
utf8.to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
pub fn valid_checksum(&self) -> bool { |
||||||
|
unsafe { ctru_sys::miiSelectorChecksumIsValid(self.raw_return.as_ref()) } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Box<ctru_sys::MiiSelectorReturn>> for MiiSelectorReturn { |
||||||
|
fn from(ret: Box<ctru_sys::MiiSelectorReturn>) -> Self { |
||||||
|
let checksum = ret.checksum; |
||||||
|
let no_mii_selected = ret.no_mii_selected; |
||||||
|
let guest_mii_index_clone = ret.guest_mii_index; |
||||||
|
let mut guest_mii_name = ret.guest_mii_name; |
||||||
|
|
||||||
|
MiiSelectorReturn { |
||||||
|
raw_return: ret, |
||||||
|
is_mii_selected: no_mii_selected == 0, |
||||||
|
mii_type: if guest_mii_index_clone != 0xFFFFFFFF { |
||||||
|
MiiType::Guest { |
||||||
|
index: guest_mii_index_clone, |
||||||
|
name: { |
||||||
|
let utf16_be = &mut guest_mii_name; |
||||||
|
utf16_be.reverse(); |
||||||
|
String::from_utf16(utf16_be.as_slice()).unwrap() |
||||||
|
}, |
||||||
|
} |
||||||
|
} else { |
||||||
|
MiiType::User |
||||||
|
}, |
||||||
|
checksum, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue