1use chrono::{DateTime, Duration, NaiveDateTime};
2
3use crate::{
4 byte_handler::{ByteHandler, ByteHandlerError, FromByteHandler},
5 header::mii::{
6 birthday::{Birthday, BirthdayError},
7 build::{Build, BuildError},
8 eyebrows::{Eyebrows, EyebrowsError},
9 eyes::{Eyes, EyesError},
10 facial_hair::{FacialHair, FacialHairError},
11 favorite_color::{FavoriteColor, FavoriteColorError},
12 glasses::{Glasses, GlassesError},
13 hair::{Hair, HairError},
14 head::{Head, HeadError},
15 lips::{Lips, LipsError},
16 mii_type::{MiiType, MiiTypeError},
17 mole::{Mole, MoleError},
18 nose::{Nose, NoseError},
19 },
20 write_bits,
21};
22
23use std::io::{Read, Write};
24
25pub mod birthday;
26pub mod build;
27pub mod eyebrows;
28pub mod eyes;
29pub mod facial_hair;
30pub mod favorite_color;
31pub mod glasses;
32pub mod hair;
33pub mod head;
34pub mod lips;
35pub mod mii_type;
36pub mod mole;
37pub mod nose;
38
39#[derive(thiserror::Error, Debug)]
41pub enum MiiError {
42 #[error("FromUtf16Error: {0}")]
44 FromUtf16Error(#[from] std::string::FromUtf16Error),
45 #[error("Invalid data length")]
47 InvalidLength,
48 #[error("Birthday Error: {0}")]
50 BirthdayError(#[from] BirthdayError),
51 #[error("FavColor Error: {0}")]
53 FavColorError(#[from] FavoriteColorError),
54 #[error("Build Error: {0}")]
56 BuildError(#[from] BuildError),
57 #[error("Head Error: {0}")]
59 HeadError(#[from] HeadError),
60 #[error("Hair Error: {0}")]
62 HairError(#[from] HairError),
63 #[error("Eyebrows Error: {0}")]
65 EyebrowsError(#[from] EyebrowsError),
66 #[error("Eyes Error: {0}")]
68 EyesError(#[from] EyesError),
69 #[error("Nose Error: {0}")]
71 NoseError(#[from] NoseError),
72 #[error("Lips Error: {0}")]
74 LipsError(#[from] LipsError),
75 #[error("Glasses Error: {0}")]
77 GlassesError(#[from] GlassesError),
78 #[error("Facial Hair Error: {0}")]
80 FacialHairError(#[from] FacialHairError),
81 #[error("Mole Error: {0}")]
83 MoleError(#[from] MoleError),
84 #[error("Mii Type Error: {0}")]
86 MiiTypeError(#[from] MiiTypeError),
87 #[error("ByteHandler Error: {0}")]
89 ByteHandlerError(#[from] ByteHandlerError),
90 #[error("IO Error: {0}")]
92 IOError(#[from] std::io::Error),
93}
94
95pub struct Mii {
104 raw_data: [u8; 0x4A],
106 is_modified: bool,
108 is_girl: bool,
110 birthday: Birthday,
112 favorite_color: FavoriteColor,
114 is_favorite: bool,
116 name: String,
118 build: Build,
120 mii_type: MiiType,
122 creation_date: NaiveDateTime,
124 mii_id: u32,
126 system_id: u32,
128 head: Head,
130 mingle_off: bool,
132 downloaded: bool,
134 hair: Hair,
136 eyebrows: Eyebrows,
138 eyes: Eyes,
140 nose: Nose,
142 lips: Lips,
144 glasses: Glasses,
146 facial_hair: FacialHair,
148 mole: Mole,
150 creator_name: String,
152}
153
154impl Mii {
155 pub fn new(mii_data: impl TryInto<[u8; 0x4A]>) -> Result<Self, MiiError> {
166 let raw_data = mii_data.try_into().map_err(|_| MiiError::InvalidLength)?;
167
168 let bytes = ByteHandler::try_from(&raw_data[0..=1])?;
169 let is_girl = bytes.read_bool(6);
170 let birthday = Birthday::from_byte_handler(bytes)?;
171
172 let favorite_color = FavoriteColor::from_byte_handler(raw_data[1])?;
173 let is_favorite = raw_data[1].is_multiple_of(2);
174
175 let name = utf16be_to_string(&raw_data[0x02..=0x15])?;
176
177 let build = Build::from_byte_handler(&raw_data[0x16..=0x17])?;
178
179 let mii_type = MiiType::try_from(&raw_data[0x18] >> 5)?;
180
181 let mut mii_id = raw_data[0x18..0x1C].to_owned();
182 mii_id[0] &= 0x1F;
183 let creation_date =
184 creation_date_from_timestamp(u32::from_be_bytes(mii_id.try_into().unwrap()));
185
186 let mii_id = ByteHandler::try_from(&raw_data[0x18..=0x1B])?.copy_dword();
187 let system_id = ByteHandler::try_from(&raw_data[0x1C..=0x1F])?.copy_dword();
188
189 let bytes = ByteHandler::try_from(&raw_data[0x20..=0x21])?;
190 let mingle_off = bytes.read_bool(10);
191 let downloaded = bytes.read_bool(8);
192 let head = Head::from_byte_handler(bytes)?;
193 let hair = Hair::from_byte_handler(&raw_data[0x22..=0x23])?;
194 let eyebrows = Eyebrows::from_byte_handler(&raw_data[0x24..=0x27])?;
195 let eyes = Eyes::from_byte_handler(&raw_data[0x28..=0x2B])?;
196 let nose = Nose::from_byte_handler(&raw_data[0x2C..=0x2D])?;
197 let lips = Lips::from_byte_handler(&raw_data[0x2E..=0x2F])?;
198 let glasses = Glasses::from_byte_handler(&raw_data[0x30..=0x31])?;
199 let facial_hair = FacialHair::from_byte_handler(&raw_data[0x32..=0x33])?;
200 let mole = Mole::from_byte_handler(&raw_data[0x34..=0x35])?;
201
202 let creator_name = utf16be_to_string(&raw_data[0x36..=0x49])?;
203
204 let is_modified = false;
205
206 Ok(Self {
207 raw_data,
208 is_modified,
209 is_girl,
210 birthday,
211 favorite_color,
212 is_favorite,
213 name,
214 build,
215 mii_type,
216 creation_date,
217 mii_id,
218 system_id,
219 head,
220 mingle_off,
221 downloaded,
222 hair,
223 eyebrows,
224 eyes,
225 nose,
226 lips,
227 glasses,
228 facial_hair,
229 mole,
230 creator_name,
231 })
232 }
233
234 pub fn new_from_file<T: AsRef<std::path::Path>>(path: T) -> Result<Self, MiiError> {
246 let mut data = Vec::with_capacity(0x4A);
247 std::fs::File::open(&path)?.read_exact(&mut data)?;
248
249 if data[..4] == *b"RKGD" {
250 data = Vec::from(&data[0x3C..]);
252 }
253
254 if data.len() < 0x4A {
255 return Err(MiiError::InvalidLength);
256 }
257
258 Self::new(&data[..0x4A])
259 }
260
261 pub fn save_to_file<T: AsRef<std::path::Path>>(&self, path: T) -> Result<(), MiiError> {
267 let mut file = std::fs::File::create(path)?;
268 file.write_all(self.raw_data())?;
269
270 Ok(())
271 }
272
273 pub fn raw_data(&self) -> &[u8] {
275 &self.raw_data
276 }
277
278 pub fn raw_data_mut(&mut self) -> &mut [u8] {
280 &mut self.raw_data
281 }
282
283 pub fn is_modified(&self) -> bool {
285 self.is_modified
286 }
287
288 pub fn is_girl(&self) -> bool {
290 self.is_girl
291 }
292
293 pub fn set_is_girl(&mut self, is_girl: bool) {
295 self.is_girl = is_girl;
296 write_bits(self.raw_data_mut(), 0x00, 1, 1, is_girl as u64);
297 self.is_modified = true;
298 }
299
300 pub fn birthday(&self) -> Birthday {
302 self.birthday
303 }
304
305 pub fn set_birthday(&mut self, birthday: Birthday) {
307 self.birthday = birthday;
310
311 let month = birthday.month().unwrap_or(0) as u64;
312 let day = birthday.day().unwrap_or(0) as u64;
313
314 write_bits(self.raw_data_mut(), 0x00, 2, 4, month);
315 write_bits(self.raw_data_mut(), 0x00, 6, 5, day);
316
317 self.is_modified = true;
318 }
319
320 pub fn favorite_color(&self) -> FavoriteColor {
322 self.favorite_color
323 }
324
325 pub fn set_favorite_color(&mut self, favorite_color: FavoriteColor) {
327 self.favorite_color = favorite_color;
328 write_bits(
329 self.raw_data_mut(),
330 0x01,
331 3,
332 4,
333 u8::from(favorite_color) as u64,
334 );
335 self.is_modified = true;
336 }
337
338 pub fn is_favorite(&self) -> bool {
340 self.is_favorite
341 }
342
343 pub fn set_is_favorite(&mut self, is_favorite: bool) {
345 self.is_favorite = is_favorite;
346 write_bits(self.raw_data_mut(), 0x01, 7, 1, is_favorite as u64);
347 self.is_modified = true;
348 }
349
350 pub fn name(&self) -> &str {
352 &self.name
353 }
354
355 pub fn set_name(&mut self, name: &str) {
359 if name.len() > 10 {
360 return;
361 }
362 self.name = name.to_string();
363 let name_bytes = string_to_utf16be(name);
364 let mut padded = [0u8; 0x14];
365 padded[..name_bytes.len()].copy_from_slice(&name_bytes);
366 self.raw_data_mut()[0x02..0x16].copy_from_slice(&padded);
367 self.is_modified = true;
368 }
369
370 pub fn build(&self) -> Build {
372 self.build
373 }
374
375 pub fn set_build(&mut self, build: Build) {
377 self.build = build;
378
379 write_bits(self.raw_data_mut(), 0x16, 1, 7, build.height() as u64);
380 write_bits(self.raw_data_mut(), 0x17, 1, 7, build.weight() as u64);
381
382 self.is_modified = true;
383 }
384
385 pub fn mii_type(&self) -> MiiType {
387 self.mii_type
388 }
389
390 pub fn set_mii_type(&mut self, mii_type: MiiType) {
394 if self.mii_type() == mii_type {
395 return;
396 }
397 let raw_data = self.raw_data_mut();
398 write_bits(raw_data, 0x18, 0, 3, u8::from(mii_type) as u64);
399 self.mii_id = u32::from_be_bytes(raw_data[0x18..0x1C].try_into().unwrap());
400 self.mii_type = mii_type;
401 }
402
403 pub fn creation_date(&self) -> NaiveDateTime {
405 self.creation_date
406 }
407
408 pub fn set_creation_date(&mut self, creation_date: NaiveDateTime) {
412 let raw_data = self.raw_data_mut();
414 write_bits(
415 raw_data,
416 0x18,
417 3,
418 29,
419 timestamp_from_creation_date(creation_date) as u64,
420 );
421 self.mii_id = u32::from_be_bytes(raw_data[0x18..0x1C].try_into().unwrap());
422 self.creation_date = creation_date;
423 }
424
425 pub fn mii_id(&self) -> u32 {
427 self.mii_id
428 }
429
430 pub fn system_id(&self) -> u32 {
432 self.system_id
433 }
434
435 pub fn set_system_id(&mut self, system_id: u32) {
437 self.system_id = system_id;
438 self.raw_data_mut()[0x1C..0x20].copy_from_slice(&system_id.to_be_bytes());
439 self.is_modified = true;
440 }
441
442 pub fn head(&self) -> Head {
444 self.head
445 }
446
447 pub fn set_head(&mut self, head: Head) {
449 self.head = head;
450
451 write_bits(
452 self.raw_data_mut(),
453 0x20,
454 0,
455 3,
456 u8::from(head.shape()) as u64,
457 );
458 write_bits(
459 self.raw_data_mut(),
460 0x20,
461 3,
462 3,
463 u8::from(head.skin_tone()) as u64,
464 );
465 write_bits(
466 self.raw_data_mut(),
467 0x20,
468 6,
469 4,
470 u8::from(head.face_features()) as u64,
471 );
472
473 self.is_modified = true;
474 }
475
476 pub fn is_mingle_enabled(&self) -> bool {
478 !self.mingle_off
479 }
480
481 pub fn set_mingle_enabled(&mut self, enabled: bool) {
483 self.mingle_off = !enabled;
484 write_bits(self.raw_data_mut(), 0x21, 5, 1, !enabled as u64);
485 self.is_modified = true;
486 }
487
488 pub fn downloaded(&self) -> bool {
490 self.downloaded
491 }
492
493 pub fn set_downloaded(&mut self, downloaded: bool) {
495 self.downloaded = downloaded;
496 write_bits(self.raw_data_mut(), 0x21, 7, 1, downloaded as u64);
497 self.is_modified = true;
498 }
499
500 pub fn hair(&self) -> Hair {
502 self.hair
503 }
504
505 pub fn set_hair(&mut self, hair: Hair) {
507 self.hair = hair;
508
509 write_bits(
510 self.raw_data_mut(),
511 0x22,
512 0,
513 7,
514 u8::from(hair.hair_type()) as u64,
515 );
516 write_bits(
517 self.raw_data_mut(),
518 0x22,
519 7,
520 3,
521 u8::from(hair.hair_color()) as u64,
522 );
523 write_bits(self.raw_data_mut(), 0x23, 2, 1, hair.is_flipped() as u64);
524
525 self.is_modified = true;
526 }
527
528 pub fn eyebrows(&self) -> Eyebrows {
530 self.eyebrows
531 }
532
533 pub fn set_eyebrows(&mut self, eyebrows: Eyebrows) {
535 self.eyebrows = eyebrows;
536
537 write_bits(
538 self.raw_data_mut(),
539 0x24,
540 0,
541 5,
542 u8::from(eyebrows.eyebrow_type()) as u64,
543 );
544 write_bits(self.raw_data_mut(), 0x24, 5, 5, eyebrows.rotation() as u64);
545 write_bits(
546 self.raw_data_mut(),
547 0x26,
548 0,
549 3,
550 u8::from(eyebrows.eyebrow_color()) as u64,
551 );
552 write_bits(self.raw_data_mut(), 0x26, 3, 4, eyebrows.size() as u64);
553 write_bits(self.raw_data_mut(), 0x26, 7, 5, eyebrows.y() as u64);
554 write_bits(self.raw_data_mut(), 0x27, 4, 4, eyebrows.x() as u64);
555
556 self.is_modified = true;
557 }
558
559 pub fn eyes(&self) -> Eyes {
561 self.eyes
562 }
563
564 pub fn set_eyes(&mut self, eyes: Eyes) {
566 self.eyes = eyes;
567
568 write_bits(
569 self.raw_data_mut(),
570 0x28,
571 0,
572 6,
573 u8::from(eyes.eye_type()) as u64,
574 );
575 write_bits(self.raw_data_mut(), 0x28, 6, 5, eyes.rotation() as u64);
576 write_bits(self.raw_data_mut(), 0x29, 3, 5, eyes.y() as u64);
577 write_bits(
578 self.raw_data_mut(),
579 0x2A,
580 0,
581 3,
582 u8::from(eyes.eye_color()) as u64,
583 );
584 write_bits(self.raw_data_mut(), 0x2A, 3, 4, eyes.size() as u64);
585 write_bits(self.raw_data_mut(), 0x2A, 7, 4, eyes.x() as u64);
586
587 self.is_modified = true;
588 }
589
590 pub fn nose(&self) -> Nose {
592 self.nose
593 }
594
595 pub fn set_nose(&mut self, nose: Nose) {
597 self.nose = nose;
598
599 write_bits(
600 self.raw_data_mut(),
601 0x2C,
602 0,
603 4,
604 u8::from(nose.nose_type()) as u64,
605 );
606 write_bits(self.raw_data_mut(), 0x2C, 4, 4, nose.size() as u64);
607 write_bits(self.raw_data_mut(), 0x2D, 0, 5, nose.y() as u64);
608
609 self.is_modified = true;
610 }
611
612 pub fn lips(&self) -> Lips {
614 self.lips
615 }
616
617 pub fn set_lips(&mut self, lips: Lips) {
619 self.lips = lips;
620
621 write_bits(
622 self.raw_data_mut(),
623 0x2E,
624 0,
625 5,
626 u8::from(lips.lips_type()) as u64,
627 );
628 write_bits(
629 self.raw_data_mut(),
630 0x2E,
631 5,
632 2,
633 u8::from(lips.lips_color()) as u64,
634 );
635 write_bits(self.raw_data_mut(), 0x2E, 7, 4, lips.size() as u64);
636 write_bits(self.raw_data_mut(), 0x2F, 3, 5, lips.y() as u64);
637
638 self.is_modified = true;
639 }
640
641 pub fn glasses(&self) -> Glasses {
643 self.glasses
644 }
645
646 pub fn set_glasses(&mut self, glasses: Glasses) {
648 self.glasses = glasses;
649
650 write_bits(
651 self.raw_data_mut(),
652 0x30,
653 0,
654 4,
655 u8::from(glasses.glasses_type()) as u64,
656 );
657 write_bits(
658 self.raw_data_mut(),
659 0x30,
660 4,
661 3,
662 u8::from(glasses.glasses_color()) as u64,
663 );
664 write_bits(self.raw_data_mut(), 0x30, 7, 4, glasses.size() as u64);
665 write_bits(self.raw_data_mut(), 0x31, 3, 5, glasses.y() as u64);
666
667 self.is_modified = true;
668 }
669
670 pub fn facial_hair(&self) -> FacialHair {
672 self.facial_hair
673 }
674
675 pub fn set_facial_hair(&mut self, facial_hair: FacialHair) {
677 self.facial_hair = facial_hair;
678
679 write_bits(
680 self.raw_data_mut(),
681 0x32,
682 0,
683 2,
684 u8::from(facial_hair.mustache_type()) as u64,
685 );
686 write_bits(
687 self.raw_data_mut(),
688 0x32,
689 2,
690 2,
691 u8::from(facial_hair.beard_type()) as u64,
692 );
693 write_bits(
694 self.raw_data_mut(),
695 0x32,
696 4,
697 3,
698 u8::from(facial_hair.color()) as u64,
699 );
700 write_bits(
701 self.raw_data_mut(),
702 0x32,
703 7,
704 4,
705 facial_hair.mustache_size() as u64,
706 );
707 write_bits(
708 self.raw_data_mut(),
709 0x33,
710 3,
711 5,
712 facial_hair.mustache_y() as u64,
713 );
714
715 self.is_modified = true;
716 }
717
718 pub fn mole(&self) -> Mole {
720 self.mole
721 }
722
723 pub fn set_mole(&mut self, mole: Mole) {
725 self.mole = mole;
726
727 write_bits(self.raw_data_mut(), 0x34, 0, 1, mole.has_mole() as u64);
728 write_bits(self.raw_data_mut(), 0x34, 1, 4, mole.size() as u64);
729 write_bits(self.raw_data_mut(), 0x34, 5, 5, mole.y() as u64);
730 write_bits(self.raw_data_mut(), 0x35, 2, 5, mole.x() as u64);
731
732 self.is_modified = true;
733 }
734
735 pub fn creator_name(&self) -> &str {
737 &self.creator_name
738 }
739
740 pub fn set_creator_name(&mut self, creator_name: &str) {
744 if creator_name.len() > 10 {
745 return;
746 }
747 self.creator_name = creator_name.to_string();
748
749 let creator_name_bytes = string_to_utf16be(creator_name);
750
751 let mut padded = [0u8; 0x14];
752 padded[..creator_name_bytes.len()].copy_from_slice(&creator_name_bytes);
753 self.raw_data_mut()[0x36..0x4A].copy_from_slice(&padded);
754
755 self.is_modified = true;
756 }
757}
758
759fn utf16be_to_string(bytes: &[u8]) -> Result<String, std::string::FromUtf16Error> {
767 let utf16: Vec<u16> = bytes
768 .chunks_exact(2)
769 .map(|c| u16::from_be_bytes([c[0], c[1]]))
770 .take_while(|&u| u != 0)
771 .collect();
772
773 String::from_utf16(&utf16)
774}
775
776fn string_to_utf16be(string: &str) -> Vec<u8> {
780 string
781 .encode_utf16()
782 .collect::<Vec<u16>>()
783 .iter()
784 .flat_map(|&u| u.to_be_bytes())
785 .collect()
786}
787
788fn creation_date_from_timestamp(value: u32) -> NaiveDateTime {
793 let clock_rate = 0.25; let epoch_shift = 1_136_073_600; let total_seconds = (value as f64 / clock_rate).floor() as i64;
796
797 let duration = Duration::seconds(total_seconds);
798 let epoch = DateTime::from_timestamp(epoch_shift, 0).unwrap();
799
800 epoch.naive_utc() + duration
801}
802
803fn timestamp_from_creation_date(date: NaiveDateTime) -> u32 {
808 let clock_rate = 0.25; let epoch_shift = 1_136_073_600; let epoch = DateTime::from_timestamp(epoch_shift, 0).unwrap();
811
812 let duration = date.signed_duration_since(epoch.naive_utc());
813 let total_seconds = duration.num_seconds();
814
815 (total_seconds as f64 * clock_rate).floor() as u32
816}