Browse Source

Apply some suggestions

pull/78/head
TechiePi 2 years ago
parent
commit
7ca152a02a
  1. 114
      ctru-rs/src/applets/mii_selector.rs
  2. 174
      ctru-rs/src/mii.rs

114
ctru-rs/src/applets/mii_selector.rs

@ -28,13 +28,16 @@ pub struct MiiSelector { @@ -28,13 +28,16 @@ pub struct MiiSelector {
}
pub struct MiiSelectorReturn {
raw_return: Box<ctru_sys::MiiSelectorReturn>,
pub mii_data: MiiData,
pub is_mii_selected: bool,
pub mii_type: MiiType,
pub checksum: u16,
}
pub enum MiiLaunchError {
InvalidChecksum,
}
impl MiiSelector {
pub fn init() -> Self {
let mut config = Box::<ctru_sys::MiiSelectorConf>::default();
@ -47,7 +50,7 @@ impl MiiSelector { @@ -47,7 +50,7 @@ impl MiiSelector {
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");
let c_text = CString::new(text).expect("Failed to convert the title text into a CString");
unsafe {
ctru_sys::miiSelectorSetTitle(self.config.as_mut(), c_text.as_ptr());
}
@ -58,59 +61,39 @@ impl MiiSelector { @@ -58,59 +61,39 @@ impl MiiSelector {
}
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,
)
},
}
let index = match mii_index {
MiiConfigIndex::Index(i) => i,
MiiConfigIndex::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS,
};
unsafe { ctru_sys::miiSelectorWhitelistGuestMii(self.config.as_mut(), index) }
}
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,
)
},
}
let index = match mii_index {
MiiConfigIndex::Index(i) => i,
MiiConfigIndex::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS,
};
unsafe { ctru_sys::miiSelectorBlacklistGuestMii(self.config.as_mut(), index) }
}
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,
)
},
}
let index = match mii_index {
MiiConfigIndex::Index(i) => i,
MiiConfigIndex::All => ctru_sys::MIISELECTOR_USERMII_SLOTS,
};
unsafe { ctru_sys::miiSelectorWhitelistUserMii(self.config.as_mut(), index) }
}
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,
)
},
}
let index = match mii_index {
MiiConfigIndex::Index(i) => i,
MiiConfigIndex::All => ctru_sys::MIISELECTOR_USERMII_SLOTS,
};
unsafe { ctru_sys::miiSelectorBlacklistUserMii(self.config.as_mut(), index) }
}
// This function is static inline in libctru
@ -119,54 +102,27 @@ impl MiiSelector { @@ -119,54 +102,27 @@ impl MiiSelector {
self.config.initial_index = index
}
pub fn launch(&mut self) -> MiiSelectorReturn {
pub fn launch(&mut self) -> Result<MiiSelectorReturn, MiiLaunchError> {
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::miiSelectorReturnGetAuthor(self.raw_return.as_ref(), tmp.as_mut_ptr(), 30)
}
let len = unsafe { libc::strlen(tmp.as_ptr()) };
let utf8 = unsafe { std::str::from_utf8_unchecked(&tmp[..len]) };
utf8.to_owned()
if unsafe { ctru_sys::miiSelectorChecksumIsValid(return_val.as_mut()) } {
Ok(return_val.into())
} else {
Err(MiiLaunchError::InvalidChecksum)
}
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 raw_mii_data = ret.mii._bindgen_opaque_blob;
let raw_mii_data = ret.mii;
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,
mii_data: raw_mii_data.into(),
is_mii_selected: no_mii_selected == 0,
mii_type: if guest_mii_index_clone != 0xFFFFFFFF {

174
ctru-rs/src/mii.rs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum RegionLock {
None,
Japan,
@ -6,7 +6,7 @@ pub enum RegionLock { @@ -6,7 +6,7 @@ pub enum RegionLock {
Europe,
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Charset {
JapanUSAEurope,
China,
@ -14,7 +14,7 @@ pub enum Charset { @@ -14,7 +14,7 @@ pub enum Charset {
Taiwan,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct MiiDataOptions {
pub is_copying_allowed: bool,
pub is_profanity_flag_enabled: bool,
@ -22,13 +22,13 @@ pub struct MiiDataOptions { @@ -22,13 +22,13 @@ pub struct MiiDataOptions {
pub charset: Charset,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct SelectorPosition {
pub page_index: u8,
pub slot_index: u8,
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum OriginConsole {
ConsoleWii,
ConsoleDSi,
@ -36,18 +36,18 @@ pub enum OriginConsole { @@ -36,18 +36,18 @@ pub enum OriginConsole {
ConsoleWiiUSwitch,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct ConsoleIdentity {
pub origin_console: OriginConsole,
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum MiiSex {
Male,
Female,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct Details {
pub sex: MiiSex,
pub birthday_month: u8,
@ -56,26 +56,26 @@ pub struct Details { @@ -56,26 +56,26 @@ pub struct Details {
pub is_favorite: bool,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct FaceStyle {
pub is_sharing_enabled: bool,
pub shape: u8,
pub skin_color: u8,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct FaceDetails {
pub wrinkles: u8,
pub makeup: u8,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct HairDetails {
pub color: u8,
pub is_flipped: bool,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct EyeDetails {
pub style: u8,
pub color: u8,
@ -86,7 +86,7 @@ pub struct EyeDetails { @@ -86,7 +86,7 @@ pub struct EyeDetails {
pub y_position: u8,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct EyebrowDetails {
pub style: u8,
pub color: u8,
@ -97,14 +97,14 @@ pub struct EyebrowDetails { @@ -97,14 +97,14 @@ pub struct EyebrowDetails {
pub y_position: u8,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct NoseDetails {
pub style: u8,
pub scale: u8,
pub y_position: u8,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct MouthDetails {
pub style: u8,
pub color: u8,
@ -112,13 +112,13 @@ pub struct MouthDetails { @@ -112,13 +112,13 @@ pub struct MouthDetails {
pub y_scale: u8,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct MustacheDetails {
pub mouth_y_position: u8,
pub mustache_style: u8,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct BeardDetails {
pub style: u8,
pub color: u8,
@ -126,7 +126,7 @@ pub struct BeardDetails { @@ -126,7 +126,7 @@ pub struct BeardDetails {
pub y_position: u8,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct GlassDetails {
pub style: u8,
pub color: u8,
@ -134,7 +134,7 @@ pub struct GlassDetails { @@ -134,7 +134,7 @@ pub struct GlassDetails {
pub y_position: u8,
}
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct MoleDetails {
pub is_enabled: bool,
pub scale: u8,
@ -144,15 +144,15 @@ pub struct MoleDetails { @@ -144,15 +144,15 @@ pub struct MoleDetails {
#[derive(Clone, Debug)]
pub struct MiiData {
pub mii_options: MiiDataOptions,
pub mii_selector_position: SelectorPosition,
pub mii_console_identity: ConsoleIdentity,
pub options: MiiDataOptions,
pub selector_position: SelectorPosition,
pub console_identity: ConsoleIdentity,
pub system_id: [u8; 8],
pub mac_address: [u8; 6],
pub mii_details: Details,
pub mii_name: String,
pub details: Details,
pub name: String,
pub height: u8,
pub width: u8,
@ -175,8 +175,9 @@ pub struct MiiData { @@ -175,8 +175,9 @@ pub struct MiiData {
pub author_name: String,
}
impl From<[u8; 92]> for MiiData {
fn from(raw_mii_data: [u8; 92]) -> Self {
impl From<ctru_sys::MiiData> for MiiData {
fn from(mii_data: ctru_sys::MiiData) -> Self {
let raw_mii_data = mii_data._bindgen_opaque_blob;
// Source for the representation and what each thing means: https://www.3dbrew.org/wiki/Mii
let raw_options = vec_bit(raw_mii_data[0x1]);
let raw_position = vec_bit(raw_mii_data[0x2]);
@ -200,10 +201,10 @@ impl From<[u8; 92]> for MiiData { @@ -200,10 +201,10 @@ impl From<[u8; 92]> for MiiData {
raw_mii_data[0x15],
];
let raw_details: [bool; 16] =
get_and_concat_vec_bit(raw_mii_data.as_slice(), &[0x18, 0x19])
get_and_concat_vec_bit(&raw_mii_data, &[0x18, 0x19])
.try_into()
.unwrap();
let raw_utf16_name = &raw_mii_data.as_slice()[0x1A..0x2D];
let raw_utf16_name = &raw_mii_data[0x1A..0x2D];
let height = raw_mii_data[0x2E];
let width = raw_mii_data[0x2F];
let raw_face_style = vec_bit(raw_mii_data[0x30]);
@ -211,75 +212,59 @@ impl From<[u8; 92]> for MiiData { @@ -211,75 +212,59 @@ impl From<[u8; 92]> for MiiData {
let hair_style = raw_mii_data[0x32];
let raw_hair_details = vec_bit(raw_mii_data[0x33]);
let raw_eye_details: [bool; 32] =
get_and_concat_vec_bit(raw_mii_data.as_slice(), &[0x34, 0x35, 0x36, 0x37])
get_and_concat_vec_bit(&raw_mii_data, &[0x34, 0x35, 0x36, 0x37])
.try_into()
.unwrap();
let raw_eyebrow_details: [bool; 32] =
get_and_concat_vec_bit(raw_mii_data.as_slice(), &[0x38, 0x39, 0x3A, 0x3B])
get_and_concat_vec_bit(&raw_mii_data, &[0x38, 0x39, 0x3A, 0x3B])
.try_into()
.unwrap();
let raw_nose_details: [bool; 16] =
get_and_concat_vec_bit(raw_mii_data.as_slice(), &[0x3C, 0x3D])
get_and_concat_vec_bit(&raw_mii_data, &[0x3C, 0x3D])
.try_into()
.unwrap();
let raw_mouth_details: [bool; 16] =
get_and_concat_vec_bit(raw_mii_data.as_slice(), &[0x3E, 0x3F])
get_and_concat_vec_bit(&raw_mii_data, &[0x3E, 0x3F])
.try_into()
.unwrap();
let raw_mustache_details: [bool; 16] =
get_and_concat_vec_bit(raw_mii_data.as_slice(), &[0x40, 0x41])
get_and_concat_vec_bit(&raw_mii_data, &[0x40, 0x41])
.try_into()
.unwrap();
let raw_beard_details: [bool; 16] =
get_and_concat_vec_bit(raw_mii_data.as_slice(), &[0x42, 0x42])
get_and_concat_vec_bit(&raw_mii_data, &[0x42, 0x42])
.try_into()
.unwrap();
let raw_glass_details: [bool; 16] =
get_and_concat_vec_bit(raw_mii_data.as_slice(), &[0x44, 0x45])
get_and_concat_vec_bit(&raw_mii_data, &[0x44, 0x45])
.try_into()
.unwrap();
let raw_mole_details: [bool; 16] =
get_and_concat_vec_bit(raw_mii_data.as_slice(), &[0x46, 0x47])
get_and_concat_vec_bit(&raw_mii_data, &[0x46, 0x47])
.try_into()
.unwrap();
let raw_utf16_author = &raw_mii_data.as_slice()[0x48..0x5C];
let raw_utf16_author = &raw_mii_data[0x48..0x5C];
let mii_name = utf16_byte_pairs_to_string(raw_utf16_name);
let author_name = utf16_byte_pairs_to_string(raw_utf16_author);
let options = MiiDataOptions {
is_copying_allowed: *raw_options.first().unwrap(),
is_profanity_flag_enabled: *raw_options.get(1).unwrap(),
is_copying_allowed: raw_options[0],
is_profanity_flag_enabled: raw_options[1],
region_lock: {
let first_bit = raw_options[3];
let second_bit = raw_options[2];
if !first_bit && !second_bit {
// 0b00
RegionLock::None
} else if !first_bit && second_bit {
// 0b01
RegionLock::Japan
} else if first_bit && !second_bit {
// 0b10
RegionLock::USA
} else {
RegionLock::Europe
match (raw_options[3], raw_options[2]) {
(false, false) => RegionLock::None,
(false, true) => RegionLock::Japan,
(true, false) => RegionLock::USA,
(true, true) => RegionLock::Europe,
}
},
charset: {
let first_bit = raw_options[5];
let second_bit = raw_options[4];
if !first_bit && !second_bit {
// 0b00
Charset::JapanUSAEurope
} else if !first_bit && second_bit {
// 0b01
Charset::China
} else if first_bit && !second_bit {
// 0b10
Charset::Korea
} else {
Charset::Taiwan
match (raw_options[5], raw_options[4]) {
(false, false) => Charset::JapanUSAEurope,
(false, true) => Charset::China,
(true, false) => Charset::Korea,
(true, true) => Charset::Taiwan,
}
},
};
@ -291,29 +276,20 @@ impl From<[u8; 92]> for MiiData { @@ -291,29 +276,20 @@ impl From<[u8; 92]> for MiiData {
let device = ConsoleIdentity {
origin_console: {
let first_bit = raw_device[6];
let second_bit = raw_device[5];
let third_bit = raw_device[4];
if !first_bit && !second_bit && third_bit {
OriginConsole::ConsoleWii
} else if !first_bit && second_bit && !third_bit {
OriginConsole::ConsoleDSi
} else if !first_bit && second_bit && third_bit {
OriginConsole::Console3DS
} else {
OriginConsole::ConsoleWiiUSwitch
match (raw_device[6], raw_device[5], raw_device[4]) {
(false, false, true) => OriginConsole::ConsoleWii,
(false, true, false) => OriginConsole::ConsoleDSi,
(false, true, true) => OriginConsole::Console3DS,
_ => OriginConsole::ConsoleWiiUSwitch,
}
},
};
let details = Details {
sex: {
let first_bit = raw_details[0];
if first_bit {
MiiSex::Female
} else {
MiiSex::Male
match raw_details[0] {
true => MiiSex::Female,
false => MiiSex::Male,
}
},
birthday_month: partial_vec_to_u8_with_reverse(&raw_details[1..4]),
@ -398,13 +374,13 @@ impl From<[u8; 92]> for MiiData { @@ -398,13 +374,13 @@ impl From<[u8; 92]> for MiiData {
};
MiiData {
mii_options: options,
mii_selector_position: position,
mii_console_identity: device,
options: options,
selector_position: position,
console_identity: device,
system_id,
mac_address: creator_mac,
mii_details: details,
mii_name,
details: details,
name: mii_name,
height,
width,
face_style,
@ -438,12 +414,9 @@ fn vec_bit(data: u8) -> [bool; 8] { @@ -438,12 +414,9 @@ fn vec_bit(data: u8) -> [bool; 8] {
/// Transforms a [bool; 8] into an u8
fn vec_bit_to_u8(data: [bool; 8]) -> u8 {
let mut result: u8 = 0;
data.map(u8::from).iter().for_each(|&bit| {
result <<= 1;
result ^= bit;
});
result
data.into_iter().fold(0, |result, bit| {
(result << 1) ^ u8::from(bit)
})
}
/// The reverse allows to write things on a more _humane_ way, but return a LE u8
@ -458,22 +431,17 @@ fn partial_vec_to_u8_with_reverse(data: &[bool]) -> u8 { @@ -458,22 +431,17 @@ fn partial_vec_to_u8_with_reverse(data: &[bool]) -> u8 {
/// UTF-16 Strings are give in pairs of bytes (u8), this converts them into an _actual_ string
fn utf16_byte_pairs_to_string(data: &[u8]) -> String {
let raw_utf16_composed = data
.chunks(2)
.collect::<Vec<&[u8]>>()
.iter()
.map(|v| u16::from_le_bytes([*v.first().unwrap_or(&0), *v.get(1).unwrap_or(&0)]))
.chunks_exact(2)
.map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]]))
.collect::<Vec<u16>>();
String::from_utf16(raw_utf16_composed.as_slice())
.unwrap()
.replace('\0', "")
String::from_utf16_lossy(raw_utf16_composed.as_slice())
}
/// Gets the values from the slice and concatenates them
fn get_and_concat_vec_bit(data: &[u8], get_values: &[usize]) -> Vec<bool> {
get_values
.iter()
.map(|v| vec_bit(data[*v]))
.collect::<Vec<[bool; 8]>>()
.concat()
.flat_map(|v| vec_bit(data[*v]))
.collect()
}

Loading…
Cancel
Save