diff --git a/Makefile b/Makefile index 943c9380..2ad79275 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ -#.PHONY: all dev emuiibo emuiibo-dev sysmodule sysmodule-dev overlay emuiigen dist clean emuiibo-clean emuiigen-clean - TARGET_TRIPLE := aarch64-nintendo-switch-freestanding PROGRAM_ID := 0100000000000352 +.PHONY: all dev clean emuiibo emuiibo-dev sysmodule sysmodule-dev overlay emuiigen dist dist-dev emuiibo-clean emuiigen-clean + all: emuiibo emuiigen dev: emuiibo-dev emuiigen @@ -33,6 +33,8 @@ dist: sysmodule overlay @cp $(CURDIR)/overlay/emuiibo.ovl $(CURDIR)/SdOut/switch/.overlays/emuiibo.ovl @mkdir -p $(CURDIR)/SdOut/emuiibo/overlay @cp -r $(CURDIR)/overlay/lang $(CURDIR)/SdOut/emuiibo/overlay/ + @zip -r $(CURDIR)/emuiibo.zip SdOut + @echo "Output created at $(CURDIR)/SdOut" dist-dev: sysmodule-dev overlay @rm -rf $(CURDIR)/SdOut @@ -44,6 +46,7 @@ dist-dev: sysmodule-dev overlay @cp $(CURDIR)/overlay/emuiibo.ovl $(CURDIR)/SdOut/switch/.overlays/emuiibo.ovl @mkdir -p $(CURDIR)/SdOut/emuiibo/overlay @cp -r $(CURDIR)/overlay/lang $(CURDIR)/SdOut/emuiibo/overlay/ + @echo "Output (dev) created at $(CURDIR)/SdOut" emuiigen: @cd emuiigen && mvn package diff --git a/README.md b/README.md index 1af291ff..10cf4ffb 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,8 @@ While old emuiibo formats are supported and converted to the current format (see ![Screenshot](screenshots/emuiigen.png) +> Note: emuiigen is made to work on Java 11+! + Now you can copy the generated amiibo folder onto your SD card, in `sd:/emuiibo/amiibo` or in any subdirectories inside it! ### Supported figures diff --git a/cur-changelog.md b/cur-changelog.md new file mode 100644 index 00000000..6cf1d26b --- /dev/null +++ b/cur-changelog.md @@ -0,0 +1,5 @@ +# `v1.1.2` + +## emuiibo + +- Updated for the latest changes in Rust libraries diff --git a/emuiibo/Cargo.lock b/emuiibo/Cargo.lock index e720f38d..06e5f6d3 100644 --- a/emuiibo/Cargo.lock +++ b/emuiibo/Cargo.lock @@ -33,9 +33,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bitfield-struct" @@ -59,9 +59,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cipher" @@ -85,9 +85,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -113,9 +113,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "emuiibo" -version = "1.1.1" +version = "1.1.2" dependencies = [ "aes", "atomic_enum", @@ -130,6 +136,38 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "enum-iterator" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4549325971814bda7a44061bf3fe7e487d447cba01e4220a4b454d630d7a016" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -151,9 +189,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "hmac" @@ -175,15 +213,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" [[package]] name = "libc" -version = "0.2.172" +version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" [[package]] name = "libm" @@ -202,24 +240,23 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "logpacket" version = "0.1.0" -source = "git+https://github.com/aarch64-switch-rs/logpacket#d807c993fb4578e3809d91e3484c7d97f59eb3db" +source = "git+https://github.com/aarch64-switch-rs/logpacket?tag=0.1.0#d807c993fb4578e3809d91e3484c7d97f59eb3db" [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "num-derive" @@ -244,12 +281,15 @@ dependencies = [ [[package]] name = "nx" -version = "0.2.0" -source = "git+https://github.com/aarch64-switch-rs/nx#695865b3cad9e6cc89a12d17cfc7bd15d28d45de" +version = "0.5.0" +source = "git+https://github.com/aarch64-switch-rs/nx#8518d8488a63d1d04932b677372d4382977c7b74" dependencies = [ "arrayvec", "atomic_enum", "bitfield-struct", + "embedded-io", + "enum-iterator", + "enum_dispatch", "linked_list_allocator", "lock_api", "logpacket", @@ -266,12 +306,19 @@ dependencies = [ [[package]] name = "nx-derive" version = "0.1.0" -source = "git+https://github.com/aarch64-switch-rs/nx#695865b3cad9e6cc89a12d17cfc7bd15d28d45de" +source = "git+https://github.com/aarch64-switch-rs/nx#8518d8488a63d1d04932b677372d4382977c7b74" dependencies = [ + "proc-macro2", "quote", "syn", ] +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + [[package]] name = "paste" version = "1.0.15" @@ -280,27 +327,27 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_core", ] @@ -313,9 +360,9 @@ checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" [[package]] name = "scopeguard" @@ -325,18 +372,28 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -345,14 +402,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -389,9 +447,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.101" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", @@ -400,21 +458,21 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unwinding" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8393f2782b6060a807337ff353780c1ca15206f9ba2424df18cb6e733bd7b345" +checksum = "60612c845ef41699f39dc8c5391f252942c0a88b7d15da672eff0d14101bbd6d" dependencies = [ "gimli", ] @@ -427,6 +485,6 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" diff --git a/emuiibo/Cargo.toml b/emuiibo/Cargo.toml index 35aa4a91..d51ef5ef 100644 --- a/emuiibo/Cargo.toml +++ b/emuiibo/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "emuiibo" -version = "1.1.1" +version = "1.1.2" authors = ["XorTroll"] edition = "2024" @@ -21,7 +21,7 @@ sha2 = { version = "0.10.9", default-features = false } [package.metadata.nx.nsp.npdm] name = "emuiibo" signature_key_generation = 0 -main_thread_stack_size = "0x100000" +main_thread_stack_size = "0x30000" main_thread_priority = 49 main_thread_core_number = 3 system_resource_size = 0 diff --git a/emuiibo/src/amiibo/bin.rs b/emuiibo/src/amiibo/bin.rs index 5c701fde..c9c41988 100644 --- a/emuiibo/src/amiibo/bin.rs +++ b/emuiibo/src/amiibo/bin.rs @@ -241,7 +241,7 @@ pub struct Struct2 { } const_assert!(core::mem::size_of::() == 0x4); -define_bit_enum! { +define_bit_set! { Flags (u8) { None = 0, // TODO: more flags here? bits 0-3 are probably for internal use as they get masked out in both 3DS and here... @@ -1086,51 +1086,51 @@ impl MiiFormat { util::ArrayWideString::from_string(name.get_string()?) }, font_region: mii::FontRegion::Standard, - faceline_color: core::mem::transmute(self.get_favorite_color()), - gender: core::mem::transmute(self.get_gender()), + faceline_color: unsafe { core::mem::transmute(self.get_favorite_color()) }, + gender: unsafe { core::mem::transmute(self.get_gender()) }, height: self.height, build: self.build, type_val: 0, region_move: !self.get_disable_sharing_flag() as u8, - faceline_type: core::mem::transmute(self.get_faceline_type()), + faceline_type: unsafe { core::mem::transmute(self.get_faceline_type()) }, favorite_color: self.get_faceline_color(), - faceline_wrinkle: core::mem::transmute(self.get_faceline_wrinkle()), - faceline_make: core::mem::transmute(self.get_faceline_make()), - hair_type: core::mem::transmute(self.hair_type), + faceline_wrinkle: unsafe { core::mem::transmute(self.get_faceline_wrinkle()) }, + faceline_make: unsafe { core::mem::transmute(self.get_faceline_make()) }, + hair_type: unsafe { core::mem::transmute(self.hair_type) }, hair_color: self.get_hair_color(), - hair_flip: core::mem::transmute(self.get_hair_flip()), - eye_type: core::mem::transmute(self.get_eye_type()), + hair_flip: unsafe { core::mem::transmute(self.get_hair_flip()) }, + eye_type: unsafe { core::mem::transmute(self.get_eye_type()) }, eye_color: self.get_eye_color(), eye_scale: self.get_eye_scale(), eye_aspect: self.get_eye_aspect(), eye_rotate: self.get_eye_rotate(), eye_x: self.get_eye_x(), eye_y: self.get_eye_y(), - eyebrow_type: core::mem::transmute(self.get_eyebrow_type()), + eyebrow_type: unsafe { core::mem::transmute(self.get_eyebrow_type()) }, eyebrow_color: self.get_eyebrow_color(), eyebrow_scale: self.get_eyebrow_scale(), eyebrow_aspect: self.get_eyebrow_aspect(), eyebrow_rotate: self.get_eyebrow_rotate(), eyebrow_x: self.get_eyebrow_x(), eyebrow_y: self.get_eyebrow_y(), - nose_type: core::mem::transmute(self.get_nose_type()), + nose_type: unsafe { core::mem::transmute(self.get_nose_type()) }, nose_scale: self.get_nose_scale(), nose_y: self.get_nose_y(), - mouth_type: core::mem::transmute(self.get_mouth_type()), + mouth_type: unsafe { core::mem::transmute(self.get_mouth_type()) }, mouth_color: self.get_mouth_color(), mouth_scale: self.get_mouth_scale(), mouth_aspect: self.get_mouth_aspect(), mouth_y: self.get_mouth_y(), beard_color: self.get_beard_color(), - beard_type: core::mem::transmute(self.get_beard_type()), - mustache_type: core::mem::transmute(self.get_mustache_type()), + beard_type: unsafe { core::mem::transmute(self.get_beard_type()) }, + mustache_type: unsafe { core::mem::transmute(self.get_mustache_type()) }, mustache_scale: self.get_mustache_scale(), mustache_y: self.get_mustache_y(), - glass_type: core::mem::transmute(self.get_glass_type()), + glass_type: unsafe { core::mem::transmute(self.get_glass_type()) }, glass_color: self.get_glass_color(), glass_scale: self.get_glass_scale(), glass_y: self.get_glass_y(), - mole_type: core::mem::transmute(self.get_mole_type()), + mole_type: unsafe { core::mem::transmute(self.get_mole_type()) }, mole_scale: self.get_mole_scale(), mole_x: self.get_mole_x(), mole_y: self.get_mole_y(), @@ -1379,6 +1379,7 @@ impl PlainFormat { mii_charinfo_file, name: { let name_be = self.dec_data.settings.name_be; + log!("Maybe here {:?}\n", name_be.as_buffer()); let name_str = name_be.get_string()?; if name_str.is_empty() { fsext::get_path_file_name(&path) diff --git a/emuiibo/src/amiibo/compat.rs b/emuiibo/src/amiibo/compat.rs index 036ba6e8..8863067e 100644 --- a/emuiibo/src/amiibo/compat.rs +++ b/emuiibo/src/amiibo/compat.rs @@ -37,7 +37,7 @@ fn convert_deprecated_virtual_amiibos_in_dir(path: &str) -> Result<()> { let key_set_file = fs::open_file(RETAIL_KEY_SET_FILE, fs::FileOpenOption::Read()); if let Ok(mut key_set_file) = key_set_file { if let Ok(key_set_v) = key_set_file.read_val::() { - log!("Found key_retail.bin --- old amiibo / raw dump conversions will include encrypted sections too!"); + log!("Found key_retail.bin --- old amiibo / raw dump conversions will include encrypted sections too!\n"); key_set = Some(key_set_v); } } @@ -63,6 +63,7 @@ fn convert_deprecated_virtual_amiibos_in_dir(path: &str) -> Result<()> { Some(v3_amiibo.convert(key_set)) } else { + log!("Not a deprecated amiibo format, skipping...\n"); None } }; @@ -85,6 +86,9 @@ fn convert_deprecated_virtual_amiibos_in_dir(path: &str) -> Result<()> { pub fn convert_deprecated_virtual_amiibos() { log!("Analyzing deprecated dir...\n"); let _ = convert_deprecated_virtual_amiibos_in_dir(super::DEPRECATED_VIRTUAL_AMIIBO_DIR); + log!("Done analyzing deprecated dir...\n"); + log!("Analyzing regular dir...\n"); let _ = convert_deprecated_virtual_amiibos_in_dir(super::VIRTUAL_AMIIBO_DIR); -} \ No newline at end of file + log!("Done analyzing regular dir...\n"); +} diff --git a/emuiibo/src/amiibo/fmt.rs b/emuiibo/src/amiibo/fmt.rs index 25202e9f..6a1d1e59 100644 --- a/emuiibo/src/amiibo/fmt.rs +++ b/emuiibo/src/amiibo/fmt.rs @@ -207,7 +207,7 @@ impl VirtualAmiibo { else { let random_mii = miiext::generate_random_mii()?; let mut mii_charinfo_file = fs::open_file(mii_charinfo_path.as_str(), fs::FileOpenOption::Create() | fs::FileOpenOption::Write() | fs::FileOpenOption::Append())?; - mii_charinfo_file.write_val(&random_mii)?; + mii_charinfo_file.write_val::<_, true>(&random_mii)?; Ok(random_mii) } } @@ -324,23 +324,25 @@ impl VirtualAmiibo { pub fn produce_tag_info(&self) -> Result { let mut tag_info = nfp::TagInfo { - uuid: [0; 0xA], - uuid_length: 0, - reserved_1: [0; 0x15], + uid: nfp::TagId { + uuid: [0; 0xA], + uuid_length: 0, + reserved_1: [0; 0x15], + }, protocol: u32::MAX, tag_type: u32::MAX, reserved_2: [0; 0x30] }; if self.info.use_random_uuid { - super::generate_random_uuid(&mut tag_info.uuid)?; - tag_info.uuid_length = tag_info.uuid.len() as u8; + super::generate_random_uuid(&mut tag_info.uid.uuid)?; + tag_info.uid.uuid_length = tag_info.uid.uuid.len() as u8; } else { unsafe { - let uuid_len = self.info.uuid.len().min(tag_info.uuid.len()); - tag_info.uuid_length = uuid_len as u8; - core::ptr::copy(self.info.uuid.as_ptr(), tag_info.uuid.as_mut_ptr(), uuid_len); + let uuid_len = self.info.uuid.len().min(tag_info.uid.uuid.len()); + tag_info.uid.uuid_length = uuid_len as u8; + core::ptr::copy(self.info.uuid.as_ptr(), tag_info.uid.uuid.as_mut_ptr(), uuid_len); } } @@ -369,12 +371,28 @@ impl VirtualAmiibo { } pub fn produce_model_info(&self) -> Result { + // Dummy code until a proper function is implemented + + #[derive(Copy, Clone)] + struct A { + game_character_id: u16, + character_variant: u8 + } + + #[derive(Copy, Clone)] + union CharacterId { + a: A, + character_id: [u8; 3] + } + + let character_id = CharacterId { a: A { game_character_id: self.info.id.game_character_id, character_variant: self.info.id.character_variant } }; + + // TODO: adapt and do what nfc actually does Ok(nfp::ModelInfo { - game_character_id: self.info.id.game_character_id, - character_variant: self.info.id.character_variant, - series: self.info.id.series, - model_number: self.info.id.model_number, // Note: we should technically reverse it since nfp wants it reversed... but it only works this way? - figure_type: self.info.id.figure_type, + character_id: unsafe { character_id.character_id }, + series_id: self.info.id.series, + numbering_id: self.info.id.model_number, // Note: we should technically reverse it since nfp wants it reversed... but it only works this way? + nfp_type: self.info.id.figure_type, reserved: [0; 0x39] }) } @@ -384,7 +402,7 @@ impl VirtualAmiibo { mii_store_data: mii::StoreData::from_charinfo(self.mii_charinfo)?, first_write_date: self.info.first_write_date.to_date(), name: util::ArrayString::from_str(&self.info.name.clone()[0..self.info.name.len().min(10)]), - unk: 0, + font_region: 0, reserved: [0; 0x8E] }) } @@ -396,29 +414,30 @@ impl VirtualAmiibo { Some(ref area_entry) => ncm::ProgramId(area_entry.program_id), None => DEFAULY_EMPTY_AREA_PROGRAM_ID }; - let console_family = { + let app_area_version = { + // TODO: change this and do what nfc actually does // 0x0100 for Switch, 0x0004 for 3DS, 0x0005 for Wii U match program_id.0 >> 48 { - 0x0100 => nfp::ConsoleFamily::NintendoSwitch, - 0x0004 => nfp::ConsoleFamily::Nintendo3DS, - 0x0005 => nfp::ConsoleFamily::NintendoWiiU, - _ => nfp::ConsoleFamily::Default + 0x0100 => nfp::ApplicationAreaVersion::NintendoSwitch, + 0x0004 => nfp::ApplicationAreaVersion::Nintendo3DS, + 0x0005 => nfp::ApplicationAreaVersion::NintendoWiiU, + _ => nfp::ApplicationAreaVersion::Default } }; Ok(nfp::AdminInfo { - program_id, + app_id: program_id, access_id: match cur_area { Some(ref area_entry) => area_entry.access_id, None => 0 }, - crc32_change_counter: 0, // TODO: just stub this? + terminal_id_crc32_change_counter: 0, // TODO: just stub this? flags: match cur_area { Some(_) => nfp::AdminInfoFlags::IsInitialized() | nfp::AdminInfoFlags::HasApplicationArea(), None => nfp::AdminInfoFlags::IsInitialized() }, - tag_type: 0x2, - console_family, + unk: 0x2, + app_area_version, pad: [0; 0x7], reserved: [0; 0x28] }) @@ -442,7 +461,7 @@ impl VirtualAmiibo { let mii_charinfo_path = format!("{}/{}", self.path, self.info.mii_charinfo_file); let _ = fs::remove_file(mii_charinfo_path.as_str()); let mut mii_charinfo_file = fs::open_file(mii_charinfo_path.as_str(), fs::FileOpenOption::Create() | fs::FileOpenOption::Write() | fs::FileOpenOption::Append())?; - mii_charinfo_file.write_val(&self.mii_charinfo)?; + mii_charinfo_file.write_val::<_, true>(&self.mii_charinfo)?; let areas_json_path = format!("{}/areas.json", self.path); write_serialize_json!(areas_json_path.as_str(), &self.areas)?; diff --git a/emuiibo/src/amiibo/v1.rs b/emuiibo/src/amiibo/v1.rs index cefd6fc8..7dcbd9de 100644 --- a/emuiibo/src/amiibo/v1.rs +++ b/emuiibo/src/amiibo/v1.rs @@ -48,7 +48,7 @@ impl compat::DeprecatedVirtualAmiiboFormat for VirtualAmiibo { let access_id = plain_bin.dec_data.settings.access_id_be.swap_bytes(); let program_id = ncm::ProgramId(plain_bin.dec_data.settings.program_id_be.swap_bytes()); let bin_area = area::ApplicationArea::from(&amiibo, access_id); - unsafe {bin_area.create(plain_bin.dec_data.app_area.as_ptr(), plain_bin.dec_data.app_area.len(), false)?;} + bin_area.create(plain_bin.dec_data.app_area.as_ptr(), plain_bin.dec_data.app_area.len(), false)?; amiibo.ensure_area_registered(access_id, program_id); } @@ -65,12 +65,12 @@ impl compat::DeprecatedVirtualAmiiboFormat for VirtualAmiibo { { let conv_bin_path = format!("{}/converted-format.bin", deprecated_path); let mut conv_bin_file = fs::open_file(conv_bin_path.as_str(), fs::FileOpenOption::Create() | fs::FileOpenOption::Write() | fs::FileOpenOption::Append())?; - conv_bin_file.write_val(&conv_bin)?; + conv_bin_file.write_val::<_, true>(&conv_bin)?; } { let plain_bin_path = format!("{}/plain-format.bin", deprecated_path); let mut plain_bin_file = fs::open_file(plain_bin_path.as_str(), fs::FileOpenOption::Create() | fs::FileOpenOption::Write() | fs::FileOpenOption::Append())?; - plain_bin_file.write_val(&plain_bin)?; + plain_bin_file.write_val::<_, true>(&plain_bin)?; } Ok(amiibo) diff --git a/emuiibo/src/amiibo/v2.rs b/emuiibo/src/amiibo/v2.rs index a82da3d6..90291633 100644 --- a/emuiibo/src/amiibo/v2.rs +++ b/emuiibo/src/amiibo/v2.rs @@ -62,7 +62,7 @@ impl super::VirtualAmiiboFormat for VirtualAmiibo { true => { let mii_charinfo = miiext::generate_random_mii()?; let mut file = fs::open_file(mii_charinfo_path.as_str(), fs::FileOpenOption::Create() | fs::FileOpenOption::Write() | fs::FileOpenOption::Append())?; - file.write_val(&mii_charinfo)?; + file.write_val::<_, true>(&mii_charinfo)?; mii_charinfo }, false => { @@ -122,7 +122,7 @@ impl compat::DeprecatedVirtualAmiiboFormat for VirtualAmiibo { if existing_access_id.is_none() || (existing_id != access_id) { let bin_area = area::ApplicationArea::from(&amiibo, access_id); // TSAFETY: This is fine as we're writing from a valid memory range - unsafe {bin_area.create(plain_bin.dec_data.app_area.as_ptr(), plain_bin.dec_data.app_area.len(), false)?;} + bin_area.create(plain_bin.dec_data.app_area.as_ptr(), plain_bin.dec_data.app_area.len(), false)?; amiibo.ensure_area_registered(access_id, program_id); } @@ -141,12 +141,12 @@ impl compat::DeprecatedVirtualAmiiboFormat for VirtualAmiibo { { let conv_bin_path = format!("{}/amiibo-converted.bin", deprecated_path); let mut conv_bin_file = fs::open_file(conv_bin_path.as_str(), fs::FileOpenOption::Create() | fs::FileOpenOption::Write() | fs::FileOpenOption::Append())?; - conv_bin_file.write_val(&conv_bin)?; + conv_bin_file.write_val::<_, true>(&conv_bin)?; } { let plain_bin_path = format!("{}/amiibo-plain.bin", deprecated_path); let mut plain_bin_file = fs::open_file(plain_bin_path.as_str(), fs::FileOpenOption::Create() | fs::FileOpenOption::Write() | fs::FileOpenOption::Append())?; - plain_bin_file.write_val(&plain_bin)?; + plain_bin_file.write_val::<_, true>(&plain_bin)?; } let old_mii_charinfo_path = format!("{}/mii.dat", self.path); diff --git a/emuiibo/src/amiibo/v3.rs b/emuiibo/src/amiibo/v3.rs index f7a980c0..da073d39 100644 --- a/emuiibo/src/amiibo/v3.rs +++ b/emuiibo/src/amiibo/v3.rs @@ -149,7 +149,7 @@ impl super::VirtualAmiiboFormat for VirtualAmiibo { | fs::FileOpenOption::Write() | fs::FileOpenOption::Append(), )?; - file.write_val(&mii_charinfo)?; + file.write_val::<_, true>(&mii_charinfo)?; mii_charinfo } false => { diff --git a/emuiibo/src/area.rs b/emuiibo/src/area.rs index 09d865ea..39ed8578 100644 --- a/emuiibo/src/area.rs +++ b/emuiibo/src/area.rs @@ -50,24 +50,24 @@ impl ApplicationArea { } } - pub unsafe fn create(&self, data: *const u8, data_size: usize, _recreate: bool) -> Result<()> { + pub fn create(&self, data: *const u8, data_size: usize, _recreate: bool) -> Result<()> { // TODO: difference between create and recreate commands? // write already overwrites the area file self.write(data, data_size) } /// SAFETY: `data` must be a valid, non-null pointer - pub unsafe fn write(&self, data: *const u8, data_size: usize) -> Result<()> { + pub fn write(&self, data: *const u8, data_size: usize) -> Result<()> { let _ = fs::remove_file(self.area_file.as_str()); let mut file = fs::open_file(self.area_file.as_str(), fs::FileOpenOption::Create() | fs::FileOpenOption::Write() | fs::FileOpenOption::Append())?; - file.write_array(core::slice::from_raw_parts(data,data_size))?; + file.write_array::<_, true>(unsafe { core::slice::from_raw_parts(data,data_size) })?; Ok(()) } /// SAFETY: `data` must be a valid, non-null pointer pub unsafe fn read(&self, data: *mut u8, data_size: usize) -> Result<()> { let mut file = fs::open_file(self.area_file.as_str(), fs::FileOpenOption::Read())?; - file.read_array(core::slice::from_raw_parts_mut(data, data_size))?; + file.read_array(unsafe { core::slice::from_raw_parts_mut(data, data_size) })?; Ok(()) } diff --git a/emuiibo/src/emu.rs b/emuiibo/src/emu.rs index 32c0afad..48dbd9e3 100644 --- a/emuiibo/src/emu.rs +++ b/emuiibo/src/emu.rs @@ -92,10 +92,12 @@ pub fn set_active_virtual_amiibo_status(status: VirtualAmiiboStatus) { } pub fn register_intercepted_application_id(application_id: ncm::ProgramId) { + log!("RegisterInterceptedApplicationId -- application_id: {:#X}\n", application_id.0); G_INTERCEPTED_APPLICATION_IDS.lock().push(application_id.0); } pub fn unregister_intercepted_application_id(application_id: ncm::ProgramId) { + log!("UnregisterInterceptedApplicationId -- application_id: {:#X}\n", application_id.0); G_INTERCEPTED_APPLICATION_IDS .lock() .retain(|&id| id != application_id.0); diff --git a/emuiibo/src/fsext.rs b/emuiibo/src/fsext.rs index 47aec52e..73b2147a 100644 --- a/emuiibo/src/fsext.rs +++ b/emuiibo/src/fsext.rs @@ -58,7 +58,9 @@ pub fn get_path_file_name_without_extension(path: String) -> String { pub fn recreate_directory(path: impl AsRef) -> Result<()> { let path = path.as_ref(); // The directory might not already exist, thus this attempt to delete it could fail - let _ = fs::remove_dir_all(path); + if let Err(rc) = fs::remove_dir_all(path) { + log!("Error removing directory {}: {:?}\n", path, rc); + } fs::create_directory(path)?; Ok(()) } @@ -83,7 +85,7 @@ macro_rules! write_serialize_json { if let Ok(json_data) = serde_json::to_vec_pretty($t) { let _ = nx::fs::remove_file($path); let mut file = nx::fs::open_file($path, nx::fs::FileOpenOption::Create() | nx::fs::FileOpenOption::Write() | nx::fs::FileOpenOption::Append())?; - file.write_array(&json_data)?; + file.write_array::<_, true>(&json_data)?; Ok(()) } else { diff --git a/emuiibo/src/ipc/emu.rs b/emuiibo/src/ipc/emu.rs index 46d7f594..af4a068b 100644 --- a/emuiibo/src/ipc/emu.rs +++ b/emuiibo/src/ipc/emu.rs @@ -48,7 +48,6 @@ impl IEmulationServiceServer for EmulationServer { } fn get_emulation_status(&mut self) -> Result { - log!("GetEmulationStatus -- (...)\n"); let status = emu::get_emulation_status(); Ok(status) } @@ -88,7 +87,6 @@ impl IEmulationServiceServer for EmulationServer { } fn get_active_virtual_amiibo_status(&mut self) -> Result { - log!("GetActiveVirtualAmiiboStatus -- (...)\n"); let status = emu::get_active_virtual_amiibo_status(); Ok(status) } @@ -100,7 +98,6 @@ impl IEmulationServiceServer for EmulationServer { } fn is_application_id_intercepted(&mut self, application_id: ncm::ProgramId) -> Result { - log!("IsApplicationIdIntercepted -- app_id: {:#X}\n", application_id.0); Ok(emu::is_application_id_intercepted(application_id)) } @@ -121,11 +118,11 @@ impl IEmulationServiceServer for EmulationServer { let amiibo = amiibo.as_ref().unwrap(); - let areas = out_areas.as_slice_mut()?; + let areas = out_areas.as_maybeuninit_mut()?; let count = areas.len().min(amiibo.areas.areas.len()); for i in 0..count { - areas[i] = amiibo.areas.areas[i]; + areas[i].write(amiibo.areas.areas[i]); } Ok(count as u32) diff --git a/emuiibo/src/ipc/nfp.rs b/emuiibo/src/ipc/nfp.rs index b26e7f60..9c06b8bd 100644 --- a/emuiibo/src/ipc/nfp.rs +++ b/emuiibo/src/ipc/nfp.rs @@ -1,8 +1,10 @@ -use nx::mem::Shared; +use nx::diag::abort; +use nx::rc; use nx::result::*; use nx::ipc::sf; use nx::ipc::sf::nfp; use nx::ipc::sf::ncm; +use nx::service::nfp::DeviceHandle; use nx::wait; use nx::sync; use nx::service::hid; @@ -12,11 +14,62 @@ use crate::area; use crate::emu; static G_INPUT_CTX: generic_once_cell::OnceCell = generic_once_cell::OnceCell::new(); +static G_STATE: sync::Mutex> = sync::Mutex::new(None); +static G_EMU_HANDLER_THREAD: sync::Mutex>> = sync::Mutex::new(None); + +fn set_state(state: nfp::State) { + G_STATE.lock().as_mut().unwrap().state = state; +} + +fn set_device_state(device_state: nfp::DeviceState) { + G_STATE.lock().as_mut().unwrap().device_state = device_state; +} + +fn get_state() -> nfp::State { + G_STATE.lock().as_ref().unwrap().state +} + +fn get_device_state() -> nfp::DeviceState { + G_STATE.lock().as_ref().unwrap().device_state +} + +fn is_state(state: nfp::State) -> bool { + G_STATE.lock().as_ref().unwrap().state == state +} + +fn is_device_state(device_state: nfp::DeviceState) -> bool { + G_STATE.lock().as_ref().unwrap().device_state == device_state +} + +fn emu_handler_thread_fn() { + loop { + // { + // if G_STATE.lock().as_ref().unwrap().should_end_thread == true { + // return; + // } + // } + + let status = emu::get_active_virtual_amiibo_status(); + G_STATE.lock().as_mut().unwrap().handle_virtual_amiibo_status(status); + let _ = thread::sleep(100_000_000); + } +} pub fn initialize() -> Result<()> { let supported_tags = hid::NpadStyleTag::FullKey() | hid::NpadStyleTag::Handheld() | hid::NpadStyleTag::JoyDual() | hid::NpadStyleTag::JoyLeft() | hid::NpadStyleTag::JoyRight(); - let _ = G_INPUT_CTX.set(input::Context::new(supported_tags, 1)?); + let ctx = input::Context::new(supported_tags, 1)?; + if let Err(_) = G_INPUT_CTX.set(ctx) { + abort::abort(abort::AbortLevel::SvcBreak(), rc::ResultNotSupported::make()); + } + G_STATE.set(Some(EmulationState::new()?)); + + G_EMU_HANDLER_THREAD.set(Some(thread::Builder::new().core(thread::ThreadStartCore::Default).priority(thread::ThreadPriority::Set(0x2B)).name("emuiibo.EmuHandler").stack_size(0x1000).spawn(move || { + log!("[{}] Emu handler thread started!\n", thread::get_current_thread_name()); + emu_handler_thread_fn(); + log!("[{}] Emu handler thread ended!\n", thread::get_current_thread_name()); + })?)); + Ok(()) } @@ -27,9 +80,7 @@ pub fn get_input_context() -> &'static input::Context { pub struct EmulationHandler { application_id: ncm::ProgramId, - emulation_state: Shared, - current_opened_area: area::ApplicationArea, - emu_handler_thread: Option> + current_opened_area: area::ApplicationArea } pub struct EmulationState { @@ -37,19 +88,19 @@ pub struct EmulationState { deactivate_event: wait::SystemEvent, availability_change_event: wait::SystemEvent, state: nfp::State, - device_state: nfp::DeviceState, - should_end_thread: bool, + device_state: nfp::DeviceState } impl EmulationState { pub fn new() -> Result { - Ok(Self { activate_event: wait::SystemEvent::new()?, deactivate_event: wait::SystemEvent::new()?, availability_change_event: wait::SystemEvent::new()?, state: nfp::State::NonInitialized, device_state: nfp::DeviceState::Unavailable, should_end_thread: false }) + Ok(Self { activate_event: wait::SystemEvent::new()?, deactivate_event: wait::SystemEvent::new()?, availability_change_event: wait::SystemEvent::new()?, state: nfp::State::NonInitialized, device_state: nfp::DeviceState::Unavailable }) } fn handle_virtual_amiibo_status(&mut self, status: emu::VirtualAmiiboStatus) { match status { emu::VirtualAmiiboStatus::Connected => match self.device_state { nfp::DeviceState::SearchingForTag => { + log!("[EmulationState] Virtual Amiibo connected -> device_state = TagFound\n"); self.device_state = nfp::DeviceState::TagFound; self.activate_event.signal().expect("signaling our own event should never fail"); }, @@ -57,7 +108,8 @@ impl EmulationState { }, emu::VirtualAmiiboStatus::Disconnected => match self.device_state{ nfp::DeviceState::TagFound | nfp::DeviceState::TagMounted => { - self.device_state =nfp::DeviceState::SearchingForTag; + log!("[EmulationState] Virtual Amiibo disconnected -> device_state = SearchingForTag\n"); + self.device_state = nfp::DeviceState::SearchingForTag; self.deactivate_event.signal().expect("signaling our own event should never fail"); }, _ => {} @@ -71,7 +123,7 @@ impl EmulationHandler { pub fn new(application_id: ncm::ProgramId) -> Result { log!("\n[{:#X}] New handler!\n", application_id.0); - Ok(Self { application_id, emulation_state: Shared::new(EmulationState::new()?), emu_handler_thread: None, current_opened_area: area::ApplicationArea::new() }) + Ok(Self { application_id, current_opened_area: area::ApplicationArea::new() }) } #[inline] @@ -79,68 +131,33 @@ impl EmulationHandler { self.application_id } - pub fn is_state(&mut self, state: nfp::State) -> bool { - self.emulation_state.lock().state == state - } - - pub fn is_device_state(&mut self, device_state: nfp::DeviceState) -> bool { - self.emulation_state.lock().device_state == device_state - } - - fn emu_handler_thread_fn(handler: Shared) { - loop { - { - let handle_handle = handler.lock(); - if handle_handle.should_end_thread == true { - return; - } - } - - let mut handle_handle = handler.lock(); - let status = emu::get_active_virtual_amiibo_status(); - handle_handle.handle_virtual_amiibo_status(status); - let _ = thread::sleep(100_000_000); - } - - } - pub fn initialize(&mut self, aruid: sf::AppletResourceUserId, mcu_data: sf::InMapAliasBuffer) -> Result<()> { // TODO: make use of aruid or mcu data? - result_return_unless!(self.is_state(nfp::State::NonInitialized), nfp::rc::ResultDeviceNotFound); - log!("[{:#X}] Initialize -- aruid: {}, process_id: {}, mcu_version_data: (count: {})\n", self.application_id.0, aruid.aruid, aruid.process_id, mcu_data.get_count()); + // result_return_unless!(is_state(nfp::State::NonInitialized), nfp::rc::ResultDeviceNotFound); + log!("[{:#X}] Initialize -- state: {:?}, device state: {:?}, aruid: {}, process_id: {}, mcu_version_data: (count: {})\n", self.application_id.0, get_state(), get_device_state(), aruid.aruid, aruid.process_id, mcu_data.get_count()); let mcu_ver_datas = mcu_data.get_maybe_unaligned(); for mcu_ver_data in mcu_ver_datas { log!("[{:#X}] Initialize -- mcu version: {}\n", self.application_id.0, mcu_ver_data.version); } - { - let mut emulation_state_handle = self.emulation_state.lock(); - emulation_state_handle.state = nfp::State::Initialized; - emulation_state_handle.device_state = nfp::DeviceState::Initialized; - } + set_state(nfp::State::Initialized); + set_device_state(nfp::DeviceState::Initialized); - // TODO: different thread names depending on the app id? - let thread_name = format!("emuWoker:{:X?}", self.application_id.0); - let handle = self.emulation_state.clone(); - self.emu_handler_thread = Some(thread::Builder::new().core(thread::ThreadStartCore::Default).priority(thread::ThreadPriority::Set(0x2B)).name(thread_name).stack_size(0x1000).spawn(move || { - Self::emu_handler_thread_fn(handle); - })?); Ok(()) } pub fn finalize(&mut self) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - log!("[{:#X}] Finalize -- (...)\n", self.application_id.0); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + log!("[{:#X}] Finalize -- state: {:?}, device state: {:?}\n", self.application_id.0, get_state(), get_device_state()); - let mut emulation_state_handle = self.emulation_state.lock(); - emulation_state_handle.state = nfp::State::NonInitialized; - emulation_state_handle.device_state = nfp::DeviceState::Finalized; + G_STATE.lock().as_mut().unwrap().state = nfp::State::NonInitialized; + G_STATE.lock().as_mut().unwrap().device_state = nfp::DeviceState::Unavailable; Ok(()) } pub fn list_devices(&mut self, mut out_devices: sf::OutPointerBuffer) -> Result { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - log!("[{:#X}] ListDevices -- out_devices: (count: {})\n", self.application_id.0, out_devices.get_count()); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + log!("[{:#X}] ListDevices -- state: {:?}, device_state: {:?}, out_devices: (count: {})\n", self.application_id.0, get_state(), get_device_state(), out_devices.get_count()); // Note: a DeviceHandle's id != npad_id on official nfp, but we treat them as the same thing since we don't care about it // Official nfp would store the npad_id somewhere else for the command below which retrieves it @@ -159,47 +176,46 @@ impl EmulationHandler { } }; - let devices = out_devices.as_slice_mut()?; - devices[0].id = fake_device_npad_id as u32; + out_devices.as_maybeuninit_mut()?[0].write(DeviceHandle { id: fake_device_npad_id as u32, reserved: [0; 4] }); Ok(1) } pub fn start_detection(&mut self, device_handle: nfp::DeviceHandle) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::Initialized) || self.is_device_state(nfp::DeviceState::TagRemoved), nfp::rc::ResultDeviceNotFound); - log!("[{:#X}] StartDetection -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::Initialized) || is_device_state(nfp::DeviceState::TagRemoved), nfp::rc::ResultDeviceNotFound); + log!("[{:#X}] StartDetection -- state: {:?}, device state: {:?}, device_handle: (fake id: {}) -> device_state = SearchingForTag\n", self.application_id.0, get_state(), get_device_state(), device_handle.id); - self.emulation_state.lock().device_state = nfp::DeviceState::SearchingForTag; + G_STATE.lock().as_mut().unwrap().device_state = nfp::DeviceState::SearchingForTag; Ok(()) } pub fn stop_detection(&mut self, device_handle: nfp::DeviceHandle) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - log!("[{:#X}] StopDetection -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + log!("[{:#X}] StopDetection -- device_handle: (fake id: {}) -> device_state = Initialized\n", self.application_id.0, device_handle.id); - self.emulation_state.lock().device_state = nfp::DeviceState::Initialized; + G_STATE.lock().as_mut().unwrap().device_state = nfp::DeviceState::Initialized; Ok(()) } pub fn mount(&mut self, device_handle: nfp::DeviceHandle, model_type: nfp::ModelType, mount_target: nfp::MountTarget) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - log!("[{:#X}] Mount -- device_handle: (fake id: {}), model_type: {:?}, mount_target: {:?}\n", self.application_id.0, device_handle.id, model_type, mount_target); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + log!("[{:#X}] Mount -- device_handle: (fake id: {}), model_type: {:?}, mount_target: {:?} - device_state = TagMounted\n", self.application_id.0, device_handle.id, model_type, mount_target); - self.emulation_state.lock().device_state = nfp::DeviceState::TagMounted; + G_STATE.lock().as_mut().unwrap().device_state = nfp::DeviceState::TagMounted; Ok(()) } pub fn unmount(&mut self, device_handle: nfp::DeviceHandle) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - log!("[{:#X}] Unmount -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + log!("[{:#X}] Unmount -- device_handle: (fake id: {}) -> device_state = TagFound\n", self.application_id.0, device_handle.id); - self.emulation_state.lock().device_state = nfp::DeviceState::TagFound; + G_STATE.lock().as_mut().unwrap().device_state = nfp::DeviceState::TagFound; Ok(()) } pub fn open_application_area(&mut self, device_handle: nfp::DeviceHandle, access_id: nfp::AccessId) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] OpenApplicationArea -- device_handle: (fake id: {}), access_id: {:#X}\n", self.application_id.0, device_handle.id, access_id); match emu::get_active_virtual_amiibo().as_mut() { @@ -218,8 +234,8 @@ impl EmulationHandler { } pub fn get_application_area(&mut self, device_handle: nfp::DeviceHandle, out_data: sf::OutMapAliasBuffer) -> Result { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); result_return_unless!(self.current_opened_area.exists(), nfp::rc::ResultAreaNeedsToBeCreated); log!("[{:#X}] GetApplicationArea -- device_handle: (fake id: {}), out_data: (buf_size: {:#X})\n", self.application_id.0, device_handle.id, out_data.get_size()); @@ -232,8 +248,8 @@ impl EmulationHandler { } pub fn set_application_area(&mut self, device_handle: nfp::DeviceHandle, data: sf::InMapAliasBuffer) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); result_return_unless!(self.current_opened_area.exists(), nfp::rc::ResultAreaNeedsToBeCreated); log!("[{:#X}] SetApplicationArea -- device_handle: (fake id: {}), data: (buf_size: {:#X})\n", self.application_id.0, device_handle.id, data.get_size()); @@ -241,7 +257,7 @@ impl EmulationHandler { let size = core::cmp::min(area_size, data.get_size()); // TODO check the pointer for nulls and return appropriate error code - unsafe {self.current_opened_area.write(data.get_address(), size)?;} + self.current_opened_area.write(data.get_address(), size)?; if let Some(amiibo) = emu::get_active_virtual_amiibo().as_mut() { amiibo.notify_written()?; } @@ -249,22 +265,22 @@ impl EmulationHandler { } pub fn flush(&mut self, device_handle: nfp::DeviceHandle) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] Flush -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); Ok(()) } pub fn restore(&mut self, device_handle: nfp::DeviceHandle) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] Restore -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); Ok(()) } pub fn create_application_area(&mut self, device_handle: nfp::DeviceHandle, access_id: nfp::AccessId, data: sf::InMapAliasBuffer) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] CreateApplicationArea -- device_handle: (fake id: {}), access_id: {:#X}, data: (buf_size: {:#X})\n", self.application_id.0, device_handle.id, access_id, data.get_size()); match emu::get_active_virtual_amiibo().as_mut() { @@ -272,7 +288,7 @@ impl EmulationHandler { let application_area = area::ApplicationArea::from_id(&amiibo, self.application_id.0, access_id); result_return_if!(application_area.exists(), nfp::rc::ResultAreaNeedsToBeCreated); // TODO check the pointer for nulls and return appropriate error code - unsafe { application_area.create(data.get_address(), data.get_size(), false)?; } + application_area.create(data.get_address(), data.get_size(), false)?; amiibo.notify_written() }, None => { @@ -282,8 +298,8 @@ impl EmulationHandler { } pub fn get_tag_info(&mut self, device_handle: nfp::DeviceHandle, mut out_tag_info: sf::OutFixedPointerBuffer) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagFound) || self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagFound) || is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] GetTagInfo -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); match emu::get_active_virtual_amiibo().as_ref() { @@ -298,8 +314,8 @@ impl EmulationHandler { } pub fn get_register_info(&mut self, device_handle: nfp::DeviceHandle, mut out_register_info: sf::OutFixedPointerBuffer) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] GetRegisterInfo -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); match emu::get_active_virtual_amiibo().as_ref() { @@ -314,8 +330,8 @@ impl EmulationHandler { } pub fn get_common_info(&mut self, device_handle: nfp::DeviceHandle, mut out_common_info: sf::OutFixedPointerBuffer) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] GetCommonInfo -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); match emu::get_active_virtual_amiibo().as_ref() { @@ -330,8 +346,8 @@ impl EmulationHandler { } pub fn get_model_info(&mut self, device_handle: nfp::DeviceHandle, mut out_model_info: sf::OutFixedPointerBuffer) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] GetModelInfo -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); match emu::get_active_virtual_amiibo().as_ref() { @@ -346,39 +362,41 @@ impl EmulationHandler { } pub fn attach_activate_event(&mut self, device_handle: nfp::DeviceHandle) -> Result { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] AttachActivateEvent -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); - Ok(sf::Handle::from(self.emulation_state.lock().activate_event.client_handle)) + Ok(sf::Handle::from(G_STATE.lock().as_ref().unwrap().activate_event.client_handle)) } pub fn attach_deactivate_event(&mut self, device_handle: nfp::DeviceHandle) -> Result { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] AttachDeactivateEvent -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); - Ok(sf::Handle::from(self.emulation_state.lock().deactivate_event.client_handle)) + Ok(sf::Handle::from(G_STATE.lock().as_ref().unwrap().deactivate_event.client_handle)) } pub fn get_state(&mut self) -> Result { - log!("[{:#X}] GetState -- (...)\n", self.application_id.0); - Ok(self.emulation_state.lock().state) + let state = G_STATE.lock().as_ref().unwrap().state; + log!("[{:#X}] GetState -> state: {:?}\n", self.application_id.0, state as u32); + Ok(state) } pub fn get_device_state(&mut self, device_handle: nfp::DeviceHandle) -> Result { - log!("[{:#X}] GetDeviceState -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); - Ok(self.emulation_state.lock().device_state) + let device_state = G_STATE.lock().as_ref().unwrap().device_state; + log!("[{:#X}] GetDeviceState -- device_handle: (fake id: {}) -> device_state: {:?}\n", self.application_id.0, device_handle.id, device_state as u32); + Ok(device_state) } pub fn get_npad_id(&mut self, device_handle: nfp::DeviceHandle) -> Result { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] GetNpadId -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); Ok(unsafe { core::mem::transmute(device_handle.id) }) } pub fn get_application_area_size(&mut self, device_handle: nfp::DeviceHandle) -> Result { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); result_return_unless!(self.current_opened_area.exists(), nfp::rc::ResultAreaNeedsToBeCreated); log!("[{:#X}] GetApplicationAreaSize -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); @@ -387,22 +405,22 @@ impl EmulationHandler { } pub fn attach_availability_change_event(&mut self) -> Result { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] AttachAvailabilityChangeEvent -- (...)\n", self.application_id.0); - Ok(sf::Handle::from(self.emulation_state.lock().availability_change_event.client_handle)) + Ok(sf::Handle::from(G_STATE.lock().as_ref().unwrap().availability_change_event.client_handle)) } pub fn recreate_application_area(&mut self, device_handle: nfp::DeviceHandle, access_id: nfp::AccessId, data: sf::InMapAliasBuffer) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] RecreateApplicationArea -- device_handle: (fake id: {}), access_id: {:#X}, data: (buf_size: {:#X})\n", self.application_id.0, device_handle.id, access_id, data.get_size()); match emu::get_active_virtual_amiibo().as_mut() { Some(amiibo) => { let application_area = area::ApplicationArea::from_id(&amiibo, self.application_id.0, access_id); // TODO check the pointer for nulls and return appropriate error code - unsafe {application_area.create(data.get_address(), data.get_size(), true)?; } + application_area.create(data.get_address(), data.get_size(), true)?; amiibo.notify_written() }, None => { @@ -418,8 +436,8 @@ impl EmulationHandler { } pub fn get_admin_info(&mut self, device_handle: nfp::DeviceHandle, mut out_admin_info: sf::OutFixedPointerBuffer) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] GetAdminInfo -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); match emu::get_active_virtual_amiibo().as_ref() { @@ -435,8 +453,8 @@ impl EmulationHandler { } pub fn get_register_info_private(&mut self, device_handle: nfp::DeviceHandle, mut out_register_info_private: sf::OutFixedPointerBuffer) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] GetRegisterInfoPrivate -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); match emu::get_active_virtual_amiibo().as_ref() { @@ -452,13 +470,13 @@ impl EmulationHandler { } pub fn set_register_info_private(&mut self, device_handle: nfp::DeviceHandle, register_info_private: sf::InFixedPointerBuffer) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] SetRegisterInfoPrivate -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); match emu::get_active_virtual_amiibo().as_mut() { Some(amiibo) => { - amiibo.update_from_register_info_private(register_info_private.get_var())?; + amiibo.update_from_register_info_private(register_info_private.get_var()?)?; }, None => { return Err(nfp::rc::ResultDeviceNotFound::make()); @@ -469,8 +487,8 @@ impl EmulationHandler { } pub fn delete_register_info(&mut self, device_handle: nfp::DeviceHandle) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] DeleteRegisterInfo -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); match emu::get_active_virtual_amiibo().as_mut() { @@ -485,8 +503,8 @@ impl EmulationHandler { } pub fn delete_application_area(&mut self, device_handle: nfp::DeviceHandle) -> Result<()> { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] DeleteApplicationArea -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); match emu::get_active_virtual_amiibo().as_mut() { @@ -502,8 +520,8 @@ impl EmulationHandler { } pub fn exists_application_area(&mut self, device_handle: nfp::DeviceHandle) -> Result { - result_return_unless!(self.is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); - result_return_unless!(self.is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_state(nfp::State::Initialized), nfp::rc::ResultDeviceNotFound); + result_return_unless!(is_device_state(nfp::DeviceState::TagMounted), nfp::rc::ResultDeviceNotFound); log!("[{:#X}] ExistsApplicationArea -- device_handle: (fake id: {})\n", self.application_id.0, device_handle.id); match emu::get_active_virtual_amiibo().as_ref() { @@ -520,10 +538,10 @@ impl EmulationHandler { impl Drop for EmulationHandler { fn drop(&mut self) { log!("[{:#X}] Dropping handler...\n", self.application_id.0); - self.emulation_state.lock().should_end_thread = true; - if let Some(thread_handle) = self.emu_handler_thread.take() { - thread_handle.join().expect("We shouldn't expect any of the threads to panic. There isn't anything very interesting happening"); - } + // G_STATE.lock().as_mut().unwrap().should_end_thread = true; + // if let Some(thread_handle) = self.emu_handler_thread.take() { + // thread_handle.join().expect("We shouldn't expect any of the threads to panic. There isn't anything very interesting happening"); + // } } } diff --git a/emuiibo/src/ipc/nfp/sys.rs b/emuiibo/src/ipc/nfp/sys.rs index 4fe75379..78a829db 100644 --- a/emuiibo/src/ipc/nfp/sys.rs +++ b/emuiibo/src/ipc/nfp/sys.rs @@ -3,6 +3,7 @@ use nx::ipc::sf::ncm; use nx::result::*; use nx::ipc::sf; use nx::ipc::server; +use nx::ipc::sf::ProcessId; use nx::ipc::sf::nfp; use nx::ipc::sf::nfp::ISystemServer; use nx::ipc::sf::nfp::ISystemManagerServer; @@ -17,18 +18,25 @@ pub struct SystemEmulator { impl SystemEmulator { pub fn new(application_id: ncm::ProgramId) -> Result { + emu::register_intercepted_application_id(application_id); Ok(Self { handler: EmulationHandler::new(application_id)? }) } } +impl Drop for SystemEmulator { + fn drop(&mut self) { + emu::unregister_intercepted_application_id(self.handler.get_application_id()); + } +} + impl ISystemServer for SystemEmulator { - fn initialize_system(&mut self, process_id: sf::AppletResourceUserId, _reserved: u64, mcu_data: sf::InMapAliasBuffer) -> Result<()> { + fn initialize(&mut self, process_id: sf::AppletResourceUserId, _reserved: ProcessId, mcu_data: sf::InMapAliasBuffer) -> Result<()> { self.handler.initialize(process_id, mcu_data) } - fn finalize_system(&mut self) -> Result<()> { + fn finalize(&mut self) -> Result<()> { self.handler.finalize() } diff --git a/emuiibo/src/ipc/nfp/user.rs b/emuiibo/src/ipc/nfp/user.rs index db413e0d..d858e25a 100644 --- a/emuiibo/src/ipc/nfp/user.rs +++ b/emuiibo/src/ipc/nfp/user.rs @@ -20,7 +20,6 @@ pub struct UserEmulator { impl UserEmulator { pub fn new(application_id: ncm::ProgramId) -> Result { emu::register_intercepted_application_id(application_id); - Ok(Self { handler: EmulationHandler::new(application_id)? }) @@ -34,11 +33,7 @@ impl Drop for UserEmulator { } impl IUserServer for UserEmulator { - fn initialize(&mut self, aruid: applet::AppletResourceUserId, mcu_data: sf::InMapAliasBuffer) -> Result<()> { - self.handler.initialize(aruid, mcu_data) - } - - fn initialize_2(&mut self, aruid: applet::AppletResourceUserId, mcu_data: sf::InMapAliasBuffer) -> Result<()> { + fn initialize(&mut self, aruid: applet::AppletResourceUserId, _reserved: sf::ProcessId, mcu_data: sf::InMapAliasBuffer) -> Result<()> { self.handler.initialize(aruid, mcu_data) } @@ -151,7 +146,6 @@ pub struct UserManager { impl IUserManagerServer for UserManager { fn create_user_interface(&mut self) -> Result { - emu::register_intercepted_application_id(self.info.program_id); UserEmulator::new(self.info.program_id) } } diff --git a/emuiibo/src/logger.rs b/emuiibo/src/logger.rs index 8cdf02ec..9a8d5c55 100644 --- a/emuiibo/src/logger.rs +++ b/emuiibo/src/logger.rs @@ -39,7 +39,7 @@ pub fn log_str(log_str: &str) { .lock() .as_mut() .expect("We only allow logging after the log file has been opened") - .write_array(log_str.as_bytes()); + .write_array::<_, true>(log_str.as_bytes()); } } diff --git a/emuiibo/src/main.rs b/emuiibo/src/main.rs index 7f8b2d67..5457e3d0 100644 --- a/emuiibo/src/main.rs +++ b/emuiibo/src/main.rs @@ -4,17 +4,15 @@ #[macro_use] extern crate nx; -#[macro_use] extern crate alloc; extern crate emuiibo; -use nx::diag; use nx::diag::abort; use nx::fs; use nx::ipc::server; +use nx::rc; use nx::result::*; -use nx::svc; use nx::thread; use nx::util; @@ -24,27 +22,27 @@ use core::panic; rrt0_define_default_module_name!(); -const CUSTOM_HEAP_SIZE: usize = 0x8000; +const CUSTOM_HEAP_SIZE: usize = 0x10000; static mut CUSTOM_HEAP: [u8; CUSTOM_HEAP_SIZE] = [0; CUSTOM_HEAP_SIZE]; #[unsafe(no_mangle)] #[allow(static_mut_refs)] -pub fn initialize_heap(_hbl_heap: util::PointerAndSize) -> util::PointerAndSize { +pub fn initialize_heap(_override_heap: util::PointerAndSize) -> util::PointerAndSize { unsafe { // SAFETY: CUSTOM_HEAP must only ever be referenced from here, and nowhere else. util::PointerAndSize::new(&raw mut CUSTOM_HEAP as _, CUSTOM_HEAP.len()) } } -use nx::diag::log::lm::LmLogger; -use nx::diag::log::LogSeverity; - #[unsafe(no_mangle)] pub fn main() -> Result<()> { thread::set_current_thread_name("emuiibo.Main"); fs::initialize_fspsrv_session()?; fs::mount_sd_card("sdmc")?; - fsext::ensure_directories()?; + + if let Err(rc) = fsext::ensure_directories() { + log!("Error creating directories: {:?}\n", rc); + } if let Err(rc) = logger::initialize() { let _a = rc; @@ -52,17 +50,17 @@ pub fn main() -> Result<()> { log!("Logging Initialized!\n"); if let Err(e) = nx::rand::initialize() { - log!("Error initlializing rand provider: {:?}", e); + log!("Error initializing rand provider: {:?}\n", e); return Ok(()); } if let Err(e) = miiext::initialize() { - log!("Error initlializing mii module provider: {:?}", e); + log!("Error initializing mii module provider: {:?}\n", e); return Ok(()); } if let Err(e) = miiext::export_miis() { - log!("Error exporting mii module provider: {:?}", e); + log!("Error exporting mii module provider: {:?}\n", e); return Ok(()); } @@ -70,13 +68,15 @@ pub fn main() -> Result<()> { emu::load_emulation_status(); if let Err(e) = ipc::nfp::initialize() { - log!("Error initializing nfp module provider: {:?}", e); - return Ok(()); + abort::abort(abort::AbortLevel::SvcBreak(), e); + // log!("Error initializing nfp module provider: {:?}", e); } const POINTER_BUF_SIZE: usize = 0x1000; type Manager = server::ServerManager; + log!("Servicing IPC...\n"); + let mut manager = Manager::new()?; manager.register_mitm_service_server::()?; manager.register_mitm_service_server::()?; @@ -91,5 +91,6 @@ pub fn main() -> Result<()> { #[panic_handler] fn panic_handler(info: &panic::PanicInfo) -> ! { - util::simple_panic_handler::(info, abort::AbortLevel::SvcBreak()) + log!("Panic! at emuiibo thread '{}' -> {}\n", thread::get_current_thread_name(), info); + abort::abort(abort::AbortLevel::SvcBreak(), rc::ResultPanicked::make()) } diff --git a/emuiibo/src/miiext.rs b/emuiibo/src/miiext.rs index 4c321a7b..f26444ab 100644 --- a/emuiibo/src/miiext.rs +++ b/emuiibo/src/miiext.rs @@ -2,8 +2,7 @@ use nx::result::*; use nx::ipc::sf; use nx::service; use nx::service::mii; -use nx::service::mii::{DatabaseService, IDatabaseServiceClient}; -use nx::service::mii::IStaticServiceClient; +use nx::service::mii::{MiiDatabase, IMiiDatabaseClient, IStaticClient}; use nx::sync::sys::mutex::Mutex; use nx::fs; use alloc::vec::Vec; @@ -11,15 +10,10 @@ use alloc::vec::Vec; pub use generic_once_cell::OnceCell; static G_STATIC_SRV: OnceCell = OnceCell::new(); -static G_DB_SRV: OnceCell = OnceCell::new(); +static G_DB_SRV: OnceCell = OnceCell::new(); #[inline] -fn get_static_service() -> Result<&'static mii::StaticService> { - G_STATIC_SRV.get().ok_or(nx::rc::ResultNotInitialized::make()) -} - -#[inline] -fn get_database_service() -> Result<&'static DatabaseService> { +fn get_database_service() -> Result<&'static MiiDatabase> { G_DB_SRV.get().ok_or(nx::rc::ResultNotInitialized::make()) } @@ -46,9 +40,9 @@ pub const EXPORTED_MIIS_DIR: &'static str = "sdmc:/emuiibo/miis"; pub fn export_miis() -> Result<()> { let mii_count = get_database_service()?.get_count(MII_SOURCE_FLAG)?; - let miis: Vec = vec![Default::default(); mii_count as usize]; + let mut miis: Vec = vec![Default::default(); mii_count as usize]; - let mii_total = get_database_service()?.get_1(MII_SOURCE_FLAG, sf::Buffer::from_array(&miis))?; + let mii_total = get_database_service()?.get_one(MII_SOURCE_FLAG, sf::Buffer::from_mut_array(&mut miis))?; for i in 0..mii_total { let mii = miis[i as usize]; @@ -57,12 +51,12 @@ pub fn export_miis() -> Result<()> { let mii_path = format!("{}/mii-charinfo.bin", mii_dir_path); let mut mii_file = fs::open_file(mii_path.as_str(), fs::FileOpenOption::Create() | fs::FileOpenOption::Write() | fs::FileOpenOption::Append())?; - mii_file.write_val(&mii)?; + mii_file.write_val::<_, true>(&mii)?; let mii_name = format!("{}/name.txt", mii_dir_path); let mut mii_name_file = fs::open_file(mii_name.as_str(), fs::FileOpenOption::Create() | fs::FileOpenOption::Write() | fs::FileOpenOption::Append())?; let actual_name = mii.name.get_string()?; - mii_name_file.write_array(actual_name.as_bytes())?; + mii_name_file.write_array::<_, true>(actual_name.as_bytes())?; } Ok(()) diff --git a/emuiigen/pom.xml b/emuiigen/pom.xml index 559be38b..b4e1f1a4 100644 --- a/emuiigen/pom.xml +++ b/emuiigen/pom.xml @@ -8,7 +8,7 @@ com.xortroll.emuiibo.emuiigen emuiigen - 1.1.1 + 1.1.2 emuiigen @@ -18,9 +18,8 @@ emuiigen official - true + 1.9.0 1.8 - 1.7.10 diff --git a/overlay/source/Main.cpp b/overlay/source/main.cpp similarity index 100% rename from overlay/source/Main.cpp rename to overlay/source/main.cpp