diff --git a/ctru-rs/Cargo.toml b/ctru-rs/Cargo.toml index a7a160c..a79e7ac 100644 --- a/ctru-rs/Cargo.toml +++ b/ctru-rs/Cargo.toml @@ -1,5 +1,5 @@ [package] -authors = [ "Rust3DS Org", "Ronald Kinard " ] +authors = ["Rust3DS Org", "Ronald Kinard "] description = "A safe wrapper around smealum's ctrulib." license = "Zlib" name = "ctru-rs" diff --git a/ctru-rs/examples/audio-filters.rs b/ctru-rs/examples/audio-filters.rs index 327ede4..3ef76a6 100644 --- a/ctru-rs/examples/audio-filters.rs +++ b/ctru-rs/examples/audio-filters.rs @@ -37,10 +37,10 @@ fn fill_buffer(audio_data: &mut [u8], frequency: f32) { fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); let mut note: usize = 4; @@ -68,7 +68,7 @@ fn main() { let mut wave_info1 = Wave::new(audio_data1, AudioFormat::PCM16Stereo, false); let mut wave_info2 = Wave::new(audio_data2, AudioFormat::PCM16Stereo, false); - let mut ndsp = Ndsp::init().expect("Couldn't obtain NDSP controller"); + let mut ndsp = Ndsp::new().expect("Couldn't obtain NDSP controller"); // This line isn't needed since the default NDSP configuration already sets the output mode to `Stereo` ndsp.set_output_mode(OutputMode::Stereo); @@ -154,10 +154,6 @@ fn main() { altern = !altern; } - // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); - //Wait for VBlank gfx.wait_for_vblank(); } diff --git a/ctru-rs/examples/buttons.rs b/ctru-rs/examples/buttons.rs index 39f24d9..8bba6c7 100644 --- a/ctru-rs/examples/buttons.rs +++ b/ctru-rs/examples/buttons.rs @@ -3,10 +3,10 @@ use ctru::prelude::*; fn main() { ctru::use_panic_handler(); - let apt = Apt::init().unwrap(); - let mut hid = Hid::init().unwrap(); - let gfx = Gfx::init().unwrap(); - let console = Console::init(gfx.top_screen.borrow_mut()); + let apt = Apt::new().unwrap(); + let mut hid = Hid::new().unwrap(); + let gfx = Gfx::new().unwrap(); + let console = Console::new(gfx.top_screen.borrow_mut()); println!("Hi there! Try pressing a button"); println!("\x1b[29;16HPress Start to exit"); @@ -63,9 +63,6 @@ fn main() { // Save our current key presses for the next frame old_keys = keys; - // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); } } diff --git a/ctru-rs/examples/camera-image.rs b/ctru-rs/examples/camera-image.rs index 46a96d4..0042599 100644 --- a/ctru-rs/examples/camera-image.rs +++ b/ctru-rs/examples/camera-image.rs @@ -1,6 +1,6 @@ use ctru::prelude::*; use ctru::services::cam::{Cam, Camera, OutputFormat, ShutterSound, ViewSize}; -use ctru::services::gfx::Screen; +use ctru::services::gfx::{Flush, Screen, Swap}; use ctru::services::gspgpu::FramebufferFormat; use std::time::Duration; @@ -16,22 +16,21 @@ const WAIT_TIMEOUT: Duration = Duration::from_millis(300); fn main() { ctru::use_panic_handler(); - let apt = Apt::init().expect("Failed to initialize Apt service."); - let mut hid = Hid::init().expect("Failed to initialize Hid service."); - let gfx = Gfx::init().expect("Failed to initialize GFX service."); + let apt = Apt::new().expect("Failed to initialize Apt service."); + let mut hid = Hid::new().expect("Failed to initialize Hid service."); + let gfx = Gfx::new().expect("Failed to initialize GFX service."); - gfx.top_screen.borrow_mut().set_double_buffering(true); - gfx.top_screen - .borrow_mut() - .set_framebuffer_format(FramebufferFormat::Rgb565); - gfx.bottom_screen.borrow_mut().set_double_buffering(false); - let _console = Console::init(gfx.bottom_screen.borrow_mut()); + let mut top_screen = gfx.top_screen.borrow_mut(); + top_screen.set_double_buffering(true); + top_screen.set_framebuffer_format(FramebufferFormat::Rgb565); + + let _console = Console::new(gfx.bottom_screen.borrow_mut()); let mut keys_down; println!("Initializing camera"); - let mut cam = Cam::init().expect("Failed to initialize CAM service."); + let mut cam = Cam::new().expect("Failed to initialize CAM service."); { let camera = &mut cam.outer_right_cam; @@ -86,15 +85,12 @@ fn main() { cam.play_shutter_sound(ShutterSound::Normal) .expect("Failed to play shutter sound"); - rotate_image_to_screen( - &buf, - gfx.top_screen.borrow_mut().raw_framebuffer().ptr, - WIDTH, - HEIGHT, - ); + rotate_image_to_screen(&buf, top_screen.raw_framebuffer().ptr, WIDTH, HEIGHT); + + // We will only flush the "camera" screen, since the other screen is handled by `Console` + top_screen.flush_buffers(); + top_screen.swap_buffers(); - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); } } diff --git a/ctru-rs/examples/file-explorer.rs b/ctru-rs/examples/file-explorer.rs index 5b256c9..6d30590 100644 --- a/ctru-rs/examples/file-explorer.rs +++ b/ctru-rs/examples/file-explorer.rs @@ -11,14 +11,14 @@ use std::path::{Path, PathBuf}; fn main() { ctru::use_panic_handler(); - let apt = Apt::init().unwrap(); - let mut hid = Hid::init().unwrap(); - let gfx = Gfx::init().unwrap(); + let apt = Apt::new().unwrap(); + let mut hid = Hid::new().unwrap(); + let gfx = Gfx::new().unwrap(); #[cfg(all(feature = "romfs", romfs_exists))] - let _romfs = ctru::services::romfs::RomFS::init().unwrap(); + let _romfs = ctru::services::romfs::RomFS::new().unwrap(); - FileExplorer::init(&apt, &mut hid, &gfx).run(); + FileExplorer::new(&apt, &mut hid, &gfx).run(); } struct FileExplorer<'a> { @@ -32,10 +32,10 @@ struct FileExplorer<'a> { } impl<'a> FileExplorer<'a> { - fn init(apt: &'a Apt, hid: &'a mut Hid, gfx: &'a Gfx) -> Self { + fn new(apt: &'a Apt, hid: &'a mut Hid, gfx: &'a Gfx) -> Self { let mut top_screen = gfx.top_screen.borrow_mut(); top_screen.set_wide_mode(true); - let console = Console::init(top_screen); + let console = Console::new(top_screen); FileExplorer { apt, @@ -68,8 +68,6 @@ impl<'a> FileExplorer<'a> { self.get_input_and_run(Self::set_exact_path); } - self.gfx.flush_buffers(); - self.gfx.swap_buffers(); self.gfx.wait_for_vblank(); } } diff --git a/ctru-rs/examples/futures-basic.rs b/ctru-rs/examples/futures-basic.rs index ee2e3be..c41245c 100644 --- a/ctru-rs/examples/futures-basic.rs +++ b/ctru-rs/examples/futures-basic.rs @@ -15,10 +15,10 @@ use std::os::horizon::thread::BuilderExt; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); // Give ourselves up to 30% of the system core's time apt.set_app_cpu_time_limit(30) @@ -68,8 +68,6 @@ fn main() { frame_count = 0; } - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); } } diff --git a/ctru-rs/examples/futures-tokio.rs b/ctru-rs/examples/futures-tokio.rs index cbb446d..986e930 100644 --- a/ctru-rs/examples/futures-tokio.rs +++ b/ctru-rs/examples/futures-tokio.rs @@ -8,10 +8,10 @@ use std::time::Duration; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); // Give ourselves up to 30% of the system core's time apt.set_app_cpu_time_limit(30) @@ -63,8 +63,6 @@ fn main() { break; } - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); } } diff --git a/ctru-rs/examples/gfx-3d-mode.rs b/ctru-rs/examples/gfx-3d-mode.rs index 13b4d3c..582994e 100644 --- a/ctru-rs/examples/gfx-3d-mode.rs +++ b/ctru-rs/examples/gfx-3d-mode.rs @@ -1,5 +1,5 @@ use ctru::prelude::*; -use ctru::services::gfx::{Screen, Side, TopScreen3D}; +use ctru::services::gfx::{Flush, Screen, Side, Swap, TopScreen3D}; /// See `graphics-bitmap.rs` for details on how the image is generated. /// @@ -12,17 +12,16 @@ static ZERO: &[u8] = &[0; IMAGE.len()]; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.bottom_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.bottom_screen.borrow_mut()); println!("Press Start to exit.\nPress A to switch sides (be sure to have 3D mode enabled)."); gfx.top_screen.borrow_mut().set_double_buffering(true); - let top_screen = TopScreen3D::from(&gfx.top_screen); - let (mut left, mut right) = top_screen.split_mut(); + let mut top_screen = TopScreen3D::from(&gfx.top_screen); let mut current_side = Side::Left; @@ -35,6 +34,8 @@ fn main() { break; } + let (mut left, mut right) = top_screen.split_mut(); + let left_buf = left.raw_framebuffer(); let right_buf = right.raw_framebuffer(); @@ -61,9 +62,10 @@ fn main() { buf.copy_from(IMAGE.as_ptr(), IMAGE.len()); } - // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); + drop((left, right)); + + top_screen.flush_buffers(); + top_screen.swap_buffers(); //Wait for VBlank gfx.wait_for_vblank(); diff --git a/ctru-rs/examples/gfx-bitmap.rs b/ctru-rs/examples/gfx-bitmap.rs new file mode 100644 index 0000000..f680ff2 --- /dev/null +++ b/ctru-rs/examples/gfx-bitmap.rs @@ -0,0 +1,74 @@ +use ctru::prelude::*; +use ctru::services::gfx::{Flush, Screen, Swap}; + +/// Ferris image taken from and scaled down to 320x240px. +/// To regenerate the data, you will need to install `imagemagick` and run this +/// command from the `examples` directory: +/// +/// ```sh +/// magick assets/ferris.png -channel-fx "red<=>blue" -rotate 90 assets/ferris.rgb +/// ``` +/// +/// This creates an image appropriate for the default frame buffer format of +/// [`Bgr8`](ctru::services::gspgpu::FramebufferFormat::Bgr8) +/// and rotates the image 90° to account for the portrait mode screen. +static IMAGE: &[u8] = include_bytes!("assets/ferris.rgb"); + +fn main() { + ctru::use_panic_handler(); + + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); + + println!("\x1b[21;4HPress Start to exit, or A to flip the image."); + + let mut bottom_screen = gfx.bottom_screen.borrow_mut(); + + // We don't need double buffering in this example. + // In this way we can draw our image only once on screen. + bottom_screen.set_double_buffering(false); + // Swapping buffers commits the change from the line above. + bottom_screen.swap_buffers(); + + // 3 bytes per pixel, we just want to reverse the pixels but not individual bytes + let flipped_image: Vec<_> = IMAGE.chunks(3).rev().flatten().copied().collect(); + + let mut image_bytes = IMAGE; + + // Main loop + while apt.main_loop() { + //Scan all the inputs. This should be done once for each frame + hid.scan_input(); + + if hid.keys_down().contains(KeyPad::START) { + break; + } + + // We assume the image is the correct size already, so we drop width + height. + let frame_buffer = bottom_screen.raw_framebuffer(); + + if hid.keys_down().contains(KeyPad::A) { + image_bytes = if std::ptr::eq(image_bytes, IMAGE) { + &flipped_image[..] + } else { + IMAGE + }; + } + + // this copies more than necessary (once per frame) but it's fine... + unsafe { + frame_buffer + .ptr + .copy_from(image_bytes.as_ptr(), image_bytes.len()); + } + + // Flush framebuffers. Since we're not using double buffering, + // this will render the pixels immediately + bottom_screen.flush_buffers(); + + //Wait for VBlank + gfx.wait_for_vblank(); + } +} diff --git a/ctru-rs/examples/gfx-wide-mode.rs b/ctru-rs/examples/gfx-wide-mode.rs index f781c89..8036538 100644 --- a/ctru-rs/examples/gfx-wide-mode.rs +++ b/ctru-rs/examples/gfx-wide-mode.rs @@ -3,10 +3,10 @@ use ctru::prelude::*; fn main() { ctru::use_panic_handler(); - let apt = Apt::init().unwrap(); - let mut hid = Hid::init().unwrap(); - let gfx = Gfx::init().unwrap(); - let mut console = Console::init(gfx.top_screen.borrow_mut()); + let apt = Apt::new().unwrap(); + let mut hid = Hid::new().unwrap(); + let gfx = Gfx::new().unwrap(); + let mut console = Console::new(gfx.top_screen.borrow_mut()); println!("Press A to enable/disable wide screen mode."); @@ -23,12 +23,10 @@ fn main() { let wide_mode = gfx.top_screen.borrow().is_wide(); gfx.top_screen.borrow_mut().set_wide_mode(!wide_mode); - console = Console::init(gfx.top_screen.borrow_mut()); + console = Console::new(gfx.top_screen.borrow_mut()); println!("Press A to enable/disable wide screen mode."); } - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); } } diff --git a/ctru-rs/examples/graphics-bitmap.rs b/ctru-rs/examples/graphics-bitmap.rs index ebbf53e..df9ce11 100644 --- a/ctru-rs/examples/graphics-bitmap.rs +++ b/ctru-rs/examples/graphics-bitmap.rs @@ -1,5 +1,5 @@ use ctru::prelude::*; -use ctru::services::gfx::Screen; +use ctru::services::gfx::{Flush, Screen, Swap}; /// Ferris image taken from and scaled down to 320x240px. /// To regenerate the data, you will need to install `imagemagick` and run this @@ -17,10 +17,10 @@ static IMAGE: &[u8] = include_bytes!("assets/ferris.rgb"); fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); println!("\x1b[21;16HPress Start to exit."); @@ -48,8 +48,8 @@ fn main() { } // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); + bottom_screen.flush_buffers(); + bottom_screen.swap_buffers(); //Wait for VBlank gfx.wait_for_vblank(); diff --git a/ctru-rs/examples/hashmaps.rs b/ctru-rs/examples/hashmaps.rs index 87ad8be..7d4d8c4 100644 --- a/ctru-rs/examples/hashmaps.rs +++ b/ctru-rs/examples/hashmaps.rs @@ -8,10 +8,10 @@ fn main() { // HashMaps generate hashes thanks to the 3DS' cryptografically secure generator. // This generator is only active when activating the `PS` service. // This service is automatically initialized. - let apt = Apt::init().unwrap(); - let mut hid = Hid::init().unwrap(); - let gfx = Gfx::init().unwrap(); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let apt = Apt::new().unwrap(); + let mut hid = Hid::new().unwrap(); + let gfx = Gfx::new().unwrap(); + let _console = Console::new(gfx.top_screen.borrow_mut()); let mut map = std::collections::HashMap::new(); map.insert("A Key!", 102); @@ -21,8 +21,6 @@ fn main() { println!("{map:#?}"); while apt.main_loop() { - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); hid.scan_input(); diff --git a/ctru-rs/examples/hello-both-screens.rs b/ctru-rs/examples/hello-both-screens.rs index 7395967..f2007f1 100644 --- a/ctru-rs/examples/hello-both-screens.rs +++ b/ctru-rs/examples/hello-both-screens.rs @@ -3,16 +3,16 @@ use ctru::prelude::*; fn main() { ctru::use_panic_handler(); - let apt = Apt::init().unwrap(); - let mut hid = Hid::init().unwrap(); - let gfx = Gfx::init().unwrap(); + let apt = Apt::new().unwrap(); + let mut hid = Hid::new().unwrap(); + let gfx = Gfx::new().unwrap(); // Start a console on the top screen - let top_screen = Console::init(gfx.top_screen.borrow_mut()); + let top_screen = Console::new(gfx.top_screen.borrow_mut()); // Start a console on the bottom screen. // The most recently initialized console will be active by default - let bottom_screen = Console::init(gfx.bottom_screen.borrow_mut()); + let bottom_screen = Console::new(gfx.bottom_screen.borrow_mut()); // Let's print on the top screen first top_screen.select(); @@ -27,8 +27,6 @@ fn main() { println!("\x1b[29;16HPress Start to exit"); while apt.main_loop() { - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); hid.scan_input(); diff --git a/ctru-rs/examples/hello-world.rs b/ctru-rs/examples/hello-world.rs index 697ec7c..a92cb90 100644 --- a/ctru-rs/examples/hello-world.rs +++ b/ctru-rs/examples/hello-world.rs @@ -5,10 +5,10 @@ use std::io::BufWriter; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); let out = b"Hello fellow Rustaceans, I'm on the Nintendo 3DS!"; let width = 24; @@ -29,9 +29,6 @@ fn main() { if hid.keys_down().contains(KeyPad::START) { break; } - // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); //Wait for VBlank gfx.wait_for_vblank(); diff --git a/ctru-rs/examples/linear-memory.rs b/ctru-rs/examples/linear-memory.rs index b3afced..e6c18dc 100644 --- a/ctru-rs/examples/linear-memory.rs +++ b/ctru-rs/examples/linear-memory.rs @@ -6,10 +6,10 @@ use ctru::prelude::*; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); let linear_space_before = LinearAllocator::free_space(); @@ -37,9 +37,6 @@ fn main() { if hid.keys_down().contains(KeyPad::START) { break; } - // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); //Wait for VBlank gfx.wait_for_vblank(); diff --git a/ctru-rs/examples/mii-selector.rs b/ctru-rs/examples/mii-selector.rs index ef7d7d3..d489e07 100644 --- a/ctru-rs/examples/mii-selector.rs +++ b/ctru-rs/examples/mii-selector.rs @@ -4,12 +4,12 @@ use ctru::prelude::*; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); - let mut mii_selector = MiiSelector::init(); + let mut mii_selector = MiiSelector::new(); mii_selector.set_initial_index(3); mii_selector.blacklist_user_mii(0.into()); mii_selector.set_title("Great Mii Selector!"); @@ -33,9 +33,6 @@ fn main() { if hid.keys_down().contains(KeyPad::START) { break; } - // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); //Wait for VBlank gfx.wait_for_vblank(); diff --git a/ctru-rs/examples/network-sockets.rs b/ctru-rs/examples/network-sockets.rs index ca2d163..bbea510 100644 --- a/ctru-rs/examples/network-sockets.rs +++ b/ctru-rs/examples/network-sockets.rs @@ -7,14 +7,14 @@ use std::time::Duration; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().unwrap(); - let _console = Console::init(gfx.top_screen.borrow_mut()); - let mut hid = Hid::init().unwrap(); - let apt = Apt::init().unwrap(); + let gfx = Gfx::new().unwrap(); + let _console = Console::new(gfx.top_screen.borrow_mut()); + let mut hid = Hid::new().unwrap(); + let apt = Apt::new().unwrap(); println!("\nlibctru sockets demo\n"); - let soc = Soc::init().unwrap(); + let soc = Soc::new().unwrap(); let server = TcpListener::bind("0.0.0.0:80").unwrap(); server.set_nonblocking(true).unwrap(); diff --git a/ctru-rs/examples/output-3dslink.rs b/ctru-rs/examples/output-3dslink.rs index 1fe0c6a..8314efa 100644 --- a/ctru-rs/examples/output-3dslink.rs +++ b/ctru-rs/examples/output-3dslink.rs @@ -13,11 +13,11 @@ use ctru::prelude::*; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); - let mut soc = Soc::init().expect("Couldn't obtain SOC controller"); + let mut soc = Soc::new().expect("Couldn't obtain SOC controller"); soc.redirect_to_3dslink(true, true) .expect("unable to redirect stdout/err to 3dslink server"); @@ -33,9 +33,6 @@ fn main() { if hid.keys_down().contains(KeyPad::START) { break; } - // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); //Wait for VBlank gfx.wait_for_vblank(); diff --git a/ctru-rs/examples/romfs.rs b/ctru-rs/examples/romfs.rs index c729c32..1138203 100644 --- a/ctru-rs/examples/romfs.rs +++ b/ctru-rs/examples/romfs.rs @@ -3,17 +3,17 @@ use ctru::prelude::*; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); cfg_if::cfg_if! { // Run this code if RomFS are wanted and available // This never fails as `ctru-rs` examples inherit all of the `ctru` features, // but it might if a normal user application wasn't setup correctly if #[cfg(all(feature = "romfs", romfs_exists))] { - let _romfs = ctru::services::romfs::RomFS::init().unwrap(); + let _romfs = ctru::services::romfs::RomFS::new().unwrap(); let f = std::fs::read_to_string("romfs:/test-file.txt").unwrap(); println!("Contents of test-file.txt: \n{f}\n"); @@ -36,9 +36,6 @@ fn main() { if hid.keys_down().contains(KeyPad::START) { break; } - // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); //Wait for VBlank gfx.wait_for_vblank(); diff --git a/ctru-rs/examples/software-keyboard.rs b/ctru-rs/examples/software-keyboard.rs index 954fdd0..39b5549 100644 --- a/ctru-rs/examples/software-keyboard.rs +++ b/ctru-rs/examples/software-keyboard.rs @@ -4,23 +4,21 @@ use ctru::prelude::*; fn main() { ctru::use_panic_handler(); - let apt = Apt::init().unwrap(); - let mut hid = Hid::init().unwrap(); - let gfx = Gfx::init().unwrap(); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let apt = Apt::new().unwrap(); + let mut hid = Hid::new().unwrap(); + let gfx = Gfx::new().unwrap(); + let _console = Console::new(gfx.top_screen.borrow_mut()); println!("Press A to enter some text or press Start to quit"); while apt.main_loop() { - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); hid.scan_input(); if hid.keys_down().contains(KeyPad::A) { // Prepares a software keyboard with two buttons: One to cancel input and one - // to accept it. You can also use `Swkbd::init()` to launch the keyboard in different + // to accept it. You can also use `Swkbd::new()` to launch the keyboard in different // configurations. let mut keyboard = Swkbd::default(); diff --git a/ctru-rs/examples/system-configuration.rs b/ctru-rs/examples/system-configuration.rs index cd81a02..001233d 100644 --- a/ctru-rs/examples/system-configuration.rs +++ b/ctru-rs/examples/system-configuration.rs @@ -4,11 +4,11 @@ use ctru::services::cfgu::Cfgu; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let cfgu = Cfgu::init().expect("Couldn't obtain CFGU controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let cfgu = Cfgu::new().expect("Couldn't obtain CFGU controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); println!("\x1b[0;0HRegion: {:?}", cfgu.region().unwrap()); println!("\x1b[10;0HLanguage: {:?}", cfgu.language().unwrap()); @@ -22,9 +22,6 @@ fn main() { if hid.keys_down().contains(KeyPad::START) { break; } - // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); //Wait for VBlank gfx.wait_for_vblank(); diff --git a/ctru-rs/examples/thread-basic.rs b/ctru-rs/examples/thread-basic.rs index 73be659..33a8ea9 100644 --- a/ctru-rs/examples/thread-basic.rs +++ b/ctru-rs/examples/thread-basic.rs @@ -8,10 +8,10 @@ use std::time::Duration; fn main() { ctru::use_panic_handler(); - let apt = Apt::init().unwrap(); - let mut hid = Hid::init().unwrap(); - let gfx = Gfx::init().unwrap(); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let apt = Apt::new().unwrap(); + let mut hid = Hid::new().unwrap(); + let gfx = Gfx::new().unwrap(); + let _console = Console::new(gfx.top_screen.borrow_mut()); let prio = std::os::horizon::thread::current_priority(); println!("Main thread prio: {}\n", prio); @@ -34,8 +34,6 @@ fn main() { } while apt.main_loop() { - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); hid.scan_input(); diff --git a/ctru-rs/examples/thread-info.rs b/ctru-rs/examples/thread-info.rs index 968e858..28297ac 100644 --- a/ctru-rs/examples/thread-info.rs +++ b/ctru-rs/examples/thread-info.rs @@ -9,10 +9,10 @@ use std::os::horizon::thread::BuilderExt; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); // Give ourselves up to 30% of the system core's time apt.set_app_cpu_time_limit(30) @@ -45,8 +45,6 @@ fn main() { break; } - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); } } diff --git a/ctru-rs/examples/thread-locals.rs b/ctru-rs/examples/thread-locals.rs index 09e2082..80d8508 100644 --- a/ctru-rs/examples/thread-locals.rs +++ b/ctru-rs/examples/thread-locals.rs @@ -12,11 +12,11 @@ std::thread_local! { fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); gfx.top_screen.borrow_mut().set_wide_mode(true); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let _console = Console::new(gfx.top_screen.borrow_mut()); // Give ourselves up to 30% of the system core's time apt.set_app_cpu_time_limit(30) @@ -61,8 +61,6 @@ fn main() { break; } - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); } } diff --git a/ctru-rs/examples/time-rtc.rs b/ctru-rs/examples/time-rtc.rs index 86db923..377fd5c 100644 --- a/ctru-rs/examples/time-rtc.rs +++ b/ctru-rs/examples/time-rtc.rs @@ -3,11 +3,11 @@ use ctru::prelude::*; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); - let _console = Console::init(gfx.top_screen.borrow_mut()); + let _console = Console::new(gfx.top_screen.borrow_mut()); print!("\x1b[30;16HPress Start to exit."); @@ -36,10 +36,6 @@ fn main() { println!("\x1b[1;1H{hours:0>2}:{minutes:0>2}:{seconds:0>2}"); println!("{weekday} {month} {day} {year}"); - // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); - //Wait for VBlank gfx.wait_for_vblank(); } diff --git a/ctru-rs/examples/title-info.rs b/ctru-rs/examples/title-info.rs index a18534e..fee5cb6 100644 --- a/ctru-rs/examples/title-info.rs +++ b/ctru-rs/examples/title-info.rs @@ -5,12 +5,12 @@ use ctru::services::fs::FsMediaType; fn main() { ctru::use_panic_handler(); - let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); - let mut hid = Hid::init().expect("Couldn't obtain HID controller"); - let apt = Apt::init().expect("Couldn't obtain APT controller"); - let am = Am::init().expect("Couldn't obtain AM controller"); - let top_screen = Console::init(gfx.top_screen.borrow_mut()); - let bottom_screen = Console::init(gfx.bottom_screen.borrow_mut()); + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + let am = Am::new().expect("Couldn't obtain AM controller"); + let top_screen = Console::new(gfx.top_screen.borrow_mut()); + let bottom_screen = Console::new(gfx.bottom_screen.borrow_mut()); let sd_count = am .title_count(FsMediaType::Sd) @@ -106,10 +106,6 @@ fn main() { refresh = false; } - // Flush and swap framebuffers - gfx.flush_buffers(); - gfx.swap_buffers(); - //Wait for VBlank gfx.wait_for_vblank(); } diff --git a/ctru-rs/examples/touch-screen.rs b/ctru-rs/examples/touch-screen.rs new file mode 100644 index 0000000..204f324 --- /dev/null +++ b/ctru-rs/examples/touch-screen.rs @@ -0,0 +1,49 @@ +use ctru::prelude::*; + +fn main() { + ctru::use_panic_handler(); + + let gfx = Gfx::new().expect("Couldn't obtain GFX controller"); + let mut hid = Hid::new().expect("Couldn't obtain HID controller"); + let apt = Apt::new().expect("Couldn't obtain APT controller"); + + let console = Console::new(gfx.top_screen.borrow_mut()); + + // We'll hold the previous touch position for comparison. + let mut old_touch: (u16, u16) = (0, 0); + + println!("\x1b[29;16HPress Start to exit"); + + while apt.main_loop() { + hid.scan_input(); + + if hid.keys_down().contains(KeyPad::START) { + break; + } + + // Get X and Y coordinates of the touch point. + // The touch screen is 320x240. + let touch: (u16, u16) = hid.touch_position(); + + // We only want to print the position when it's different + // from what it was on the previous frame + if touch != old_touch { + // Special case for when the user lifts the stylus/finger from the screen. + // This is done to avoid some screen tearing. + if touch == (0, 0) { + console.clear(); + + // Print again because we just cleared the screen + println!("\x1b[29;16HPress Start to exit"); + } + + // Move the cursor back to the top of the screen and print the coordinates + print!("\x1b[1;1HTouch Screen position: {:#?}", touch); + } + + // Save our current touch position for the next frame + old_touch = touch; + + gfx.wait_for_vblank(); + } +} diff --git a/ctru-rs/src/applets/mii_selector.rs b/ctru-rs/src/applets/mii_selector.rs index 8d289ee..a6acd61 100644 --- a/ctru-rs/src/applets/mii_selector.rs +++ b/ctru-rs/src/applets/mii_selector.rs @@ -8,14 +8,14 @@ use std::ffi::CString; /// Index of a Mii used to configure some parameters of the Mii Selector /// Can be either a single index, or _all_ Miis -#[derive(Debug, Clone)] -pub enum MiiConfigIndex { +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum Index { Index(u32), All, } /// The type of a Mii with their respective data -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub enum MiiType { Guest { index: u32, name: String }, User, @@ -41,7 +41,7 @@ bitflags! { /// ``` /// use ctru::applets::mii_selector::MiiSelector; /// -/// let mut mii_selector = MiiSelector::init(); +/// let mut mii_selector = MiiSelector::new(); /// mii_selector.set_title("Example Mii selector"); /// /// let result = mii_selector.launch().unwrap(); @@ -54,7 +54,7 @@ pub struct MiiSelector { /// Return value from a MiiSelector's launch #[non_exhaustive] #[derive(Clone, Debug)] -pub struct MiiSelectorReturn { +pub struct SelectionResult { pub mii_data: MiiData, pub is_mii_selected: bool, pub mii_type: MiiType, @@ -62,13 +62,13 @@ pub struct MiiSelectorReturn { /// Error type for the Mii selector #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum MiiLaunchError { +pub enum LaunchError { InvalidChecksum, } impl MiiSelector { /// Initializes a Mii Selector - pub fn init() -> Self { + pub fn new() -> Self { let mut config = Box::::default(); unsafe { ctru_sys::miiSelectorInit(config.as_mut()); @@ -94,40 +94,40 @@ impl MiiSelector { } /// Whitelist a guest Mii - pub fn whitelist_guest_mii(&mut self, mii_index: MiiConfigIndex) { + pub fn whitelist_guest_mii(&mut self, mii_index: Index) { let index = match mii_index { - MiiConfigIndex::Index(i) => i, - MiiConfigIndex::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS, + Index::Index(i) => i, + Index::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS, }; unsafe { ctru_sys::miiSelectorWhitelistGuestMii(self.config.as_mut(), index) } } /// Blacklist a guest Mii - pub fn blacklist_guest_mii(&mut self, mii_index: MiiConfigIndex) { + pub fn blacklist_guest_mii(&mut self, mii_index: Index) { let index = match mii_index { - MiiConfigIndex::Index(i) => i, - MiiConfigIndex::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS, + Index::Index(i) => i, + Index::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS, }; unsafe { ctru_sys::miiSelectorBlacklistGuestMii(self.config.as_mut(), index) } } /// Whitelist a user Mii - pub fn whitelist_user_mii(&mut self, mii_index: MiiConfigIndex) { + pub fn whitelist_user_mii(&mut self, mii_index: Index) { let index = match mii_index { - MiiConfigIndex::Index(i) => i, - MiiConfigIndex::All => ctru_sys::MIISELECTOR_USERMII_SLOTS, + Index::Index(i) => i, + Index::All => ctru_sys::MIISELECTOR_USERMII_SLOTS, }; unsafe { ctru_sys::miiSelectorWhitelistUserMii(self.config.as_mut(), index) } } /// Blacklist a user Mii - pub fn blacklist_user_mii(&mut self, mii_index: MiiConfigIndex) { + pub fn blacklist_user_mii(&mut self, mii_index: Index) { let index = match mii_index { - MiiConfigIndex::Index(i) => i, - MiiConfigIndex::All => ctru_sys::MIISELECTOR_USERMII_SLOTS, + Index::Index(i) => i, + Index::All => ctru_sys::MIISELECTOR_USERMII_SLOTS, }; unsafe { ctru_sys::miiSelectorBlacklistUserMii(self.config.as_mut(), index) } @@ -143,24 +143,30 @@ impl MiiSelector { /// Launch the Mii Selector. /// Returns an error when the checksum of the Mii is invalid. - pub fn launch(&mut self) -> Result { + pub fn launch(&mut self) -> Result { let mut return_val = Box::::default(); unsafe { ctru_sys::miiSelectorLaunch(self.config.as_mut(), return_val.as_mut()) } if unsafe { ctru_sys::miiSelectorChecksumIsValid(return_val.as_mut()) } { Ok((*return_val).into()) } else { - Err(MiiLaunchError::InvalidChecksum) + Err(LaunchError::InvalidChecksum) } } } -impl From for MiiSelectorReturn { +impl Default for MiiSelector { + fn default() -> Self { + Self::new() + } +} + +impl From for SelectionResult { fn from(ret: ctru_sys::MiiSelectorReturn) -> Self { let raw_mii_data = ret.mii; let mut guest_mii_name = ret.guest_mii_name; - MiiSelectorReturn { + SelectionResult { mii_data: raw_mii_data.into(), is_mii_selected: ret.no_mii_selected == 0, mii_type: if ret.guest_mii_index != 0xFFFFFFFF { @@ -179,7 +185,7 @@ impl From for MiiSelectorReturn { } } -impl From for MiiConfigIndex { +impl From for Index { fn from(v: u32) -> Self { Self::Index(v) } diff --git a/ctru-rs/src/applets/swkbd.rs b/ctru-rs/src/applets/swkbd.rs index 0af7dee..8f4aab6 100644 --- a/ctru-rs/src/applets/swkbd.rs +++ b/ctru-rs/src/applets/swkbd.rs @@ -7,6 +7,7 @@ use std::iter::once; use std::str; /// An instance of the software keyboard. +#[derive(Clone)] pub struct Swkbd { state: Box, } @@ -18,7 +19,7 @@ pub struct Swkbd { /// Numpad is a number pad. /// Western is a text keyboard without japanese symbols (only applies to JPN systems). For other /// systems it's the same as a Normal keyboard. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum Kind { Normal = ctru_sys::SWKBD_TYPE_NORMAL, @@ -28,7 +29,7 @@ pub enum Kind { } /// Represents which button the user pressed to close the software keyboard. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum Button { Left = ctru_sys::SWKBD_BUTTON_LEFT, @@ -37,7 +38,7 @@ pub enum Button { } /// Error type for the software keyboard. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(i32)] pub enum Error { InvalidInput = ctru_sys::SWKBD_INVALID_INPUT, @@ -51,7 +52,7 @@ pub enum Error { } /// Restrictions on keyboard input -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum ValidInput { Anything = ctru_sys::SWKBD_ANYTHING, @@ -89,7 +90,7 @@ bitflags! { impl Swkbd { /// Initializes a software keyboard of the specified type and the chosen number of buttons /// (from 1-3). - pub fn init(keyboard_type: Kind, num_buttons: i32) -> Self { + pub fn new(keyboard_type: Kind, num_buttons: i32) -> Self { unsafe { let mut state = Box::::default(); swkbdInit(state.as_mut(), keyboard_type.into(), num_buttons, -1); @@ -207,7 +208,7 @@ impl Swkbd { impl Default for Swkbd { fn default() -> Self { - Swkbd::init(Kind::Normal, 2) + Swkbd::new(Kind::Normal, 2) } } diff --git a/ctru-rs/src/console.rs b/ctru-rs/src/console.rs index c0a8765..e3ba62e 100644 --- a/ctru-rs/src/console.rs +++ b/ctru-rs/src/console.rs @@ -16,7 +16,11 @@ impl<'screen> Console<'screen> { /// Initialize a console on the chosen screen, overwriting whatever was on the screen /// previously (including other consoles). The new console is automatically selected for /// printing. - pub fn init(screen: RefMut<'screen, dyn Screen>) -> Self { + /// + /// # Notes + /// + /// [Console] automatically takes care of flushing and swapping buffers for its screen when printing. + pub fn new(screen: RefMut<'screen, dyn Screen>) -> Self { let mut context = Box::::default(); unsafe { consoleInit(screen.as_raw(), context.as_mut()) }; diff --git a/ctru-rs/src/lib.rs b/ctru-rs/src/lib.rs index 504b66f..210d37f 100644 --- a/ctru-rs/src/lib.rs +++ b/ctru-rs/src/lib.rs @@ -54,7 +54,7 @@ fn panic_hook_setup() { if main_thread == std::thread::current().id() && console::Console::exists() { println!("\nPress SELECT to exit the software"); - match Hid::init() { + match Hid::new() { Ok(mut hid) => loop { hid.scan_input(); let keys = hid.keys_down(); diff --git a/ctru-rs/src/services/am.rs b/ctru-rs/src/services/am.rs index ada179e..70bd151 100644 --- a/ctru-rs/src/services/am.rs +++ b/ctru-rs/src/services/am.rs @@ -6,6 +6,7 @@ use std::mem::MaybeUninit; #[derive(Copy, Clone, Debug)] #[repr(transparent)] pub struct TitleInfo(ctru_sys::AM_TitleEntry); + impl TitleInfo { pub fn id(&self) -> u64 { self.0.titleID @@ -61,7 +62,7 @@ impl<'a> Title<'a> { pub struct Am(()); impl Am { - pub fn init() -> crate::Result { + pub fn new() -> crate::Result { unsafe { ResultCode(ctru_sys::amInit())?; Ok(Am(())) diff --git a/ctru-rs/src/services/apt.rs b/ctru-rs/src/services/apt.rs index aa1dd28..f7731be 100644 --- a/ctru-rs/src/services/apt.rs +++ b/ctru-rs/src/services/apt.rs @@ -3,7 +3,7 @@ use crate::error::ResultCode; pub struct Apt(()); impl Apt { - pub fn init() -> crate::Result { + pub fn new() -> crate::Result { unsafe { ResultCode(ctru_sys::aptInit())?; Ok(Apt(())) diff --git a/ctru-rs/src/services/cam.rs b/ctru-rs/src/services/cam.rs index 52ce926..4a06421 100644 --- a/ctru-rs/src/services/cam.rs +++ b/ctru-rs/src/services/cam.rs @@ -21,7 +21,7 @@ pub struct Cam { } /// Flag to pass to [Camera::flip_image] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum FlipMode { None = ctru_sys::FLIP_NONE, @@ -31,7 +31,7 @@ pub enum FlipMode { } /// Flag to pass to [Camera::set_view_size] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum ViewSize { TopLCD = ctru_sys::SIZE_CTR_TOP_LCD, @@ -48,7 +48,7 @@ pub enum ViewSize { } /// Flag to pass to [Camera::set_frame_rate] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum FrameRate { Fps15 = ctru_sys::FRAME_RATE_15, @@ -68,7 +68,7 @@ pub enum FrameRate { /// Flag to pass to [Camera::set_white_balance] or /// [Camera::set_white_balance_without_base_up] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum WhiteBalance { /// Normal @@ -86,7 +86,7 @@ pub enum WhiteBalance { } /// Flag to pass to [Camera::set_photo_mode] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum PhotoMode { Normal = ctru_sys::PHOTO_MODE_NORMAL, @@ -97,7 +97,7 @@ pub enum PhotoMode { } /// Flag to pass to [Camera::set_effect] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum Effect { None = ctru_sys::EFFECT_NONE, @@ -109,7 +109,7 @@ pub enum Effect { } /// Flag to pass to [Camera::set_contrast] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum Contrast { /// OFF @@ -121,7 +121,7 @@ pub enum Contrast { } /// Flag to pass to [Camera::set_lens_correction] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum LensCorrection { Off = ctru_sys::LENS_CORRECTION_DARK, @@ -130,7 +130,7 @@ pub enum LensCorrection { } /// Flag to pass to [Camera::set_output_format] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum OutputFormat { Yuv422 = ctru_sys::OUTPUT_YUV_422, @@ -138,7 +138,7 @@ pub enum OutputFormat { } /// Flag to pass to [Cam::play_shutter_sound] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum ShutterSound { Normal = ctru_sys::SHUTTER_SOUND_TYPE_NORMAL, @@ -169,6 +169,7 @@ impl TryFrom for FramebufferFormat { } /// Struct containing coordinates passed to [Camera::set_trimming_params]. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct TrimmingParams { x_start: i16, y_start: i16, @@ -193,11 +194,11 @@ impl TrimmingParams { } /// Represents data used by the camera to calibrate image quality -#[derive(Default)] +#[derive(Default, Clone, Copy, Debug)] pub struct ImageQualityCalibrationData(pub ctru_sys::CAMU_ImageQualityCalibrationData); /// Represents data used by the camera to calibrate image quality when using both outward cameras -#[derive(Default)] +#[derive(Default, Clone, Copy, Debug)] pub struct StereoCameraCalibrationData(pub ctru_sys::CAMU_StereoCameraCalibrationData); /// Represents the camera on the inside of the 3DS @@ -770,7 +771,7 @@ impl Cam { /// This function will return an error if the service was unable to be initialized. /// Since this service requires no special or elevated permissions, errors are /// rare in practice. - pub fn init() -> crate::Result { + pub fn new() -> crate::Result { unsafe { ResultCode(ctru_sys::camInit())?; Ok(Cam { diff --git a/ctru-rs/src/services/cfgu.rs b/ctru-rs/src/services/cfgu.rs index 3f268c7..a9cc411 100644 --- a/ctru-rs/src/services/cfgu.rs +++ b/ctru-rs/src/services/cfgu.rs @@ -4,7 +4,7 @@ use crate::error::ResultCode; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum Region { Japan = ctru_sys::CFG_REGION_JPN, @@ -16,7 +16,7 @@ pub enum Region { Taiwan = ctru_sys::CFG_REGION_TWN, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum Language { Japanese = ctru_sys::CFG_LANGUAGE_JP, @@ -33,15 +33,15 @@ pub enum Language { TraditionalChinese = ctru_sys::CFG_LANGUAGE_TW, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum SystemModel { - Model3DS = ctru_sys::CFG_MODEL_3DS, - Model3DSXL = ctru_sys::CFG_MODEL_3DSXL, - ModelNew3DS = ctru_sys::CFG_MODEL_N3DS, - Model2DS = ctru_sys::CFG_MODEL_2DS, - ModelNew3DSXL = ctru_sys::CFG_MODEL_N3DSXL, - ModelNew2DSXL = ctru_sys::CFG_MODEL_N2DSXL, + Old3DS = ctru_sys::CFG_MODEL_3DS, + Old3DSXL = ctru_sys::CFG_MODEL_3DSXL, + New3DS = ctru_sys::CFG_MODEL_N3DS, + Old2DS = ctru_sys::CFG_MODEL_2DS, + New3DSXL = ctru_sys::CFG_MODEL_N3DSXL, + New2DSXL = ctru_sys::CFG_MODEL_N2DSXL, } /// Represents the configuration service. No actions can be performed @@ -61,7 +61,7 @@ impl Cfgu { /// ctrulib services are reference counted, so this function may be called /// as many times as desired and the service will not exit until all /// instances of Cfgu drop out of scope. - pub fn init() -> crate::Result { + pub fn new() -> crate::Result { ResultCode(unsafe { ctru_sys::cfguInit() })?; Ok(Cfgu(())) } @@ -163,12 +163,12 @@ impl TryFrom for SystemModel { fn try_from(value: u8) -> Result { match value as u32 { - ctru_sys::CFG_MODEL_3DS => Ok(SystemModel::Model3DS), - ctru_sys::CFG_MODEL_3DSXL => Ok(SystemModel::Model3DSXL), - ctru_sys::CFG_MODEL_N3DS => Ok(SystemModel::ModelNew3DS), - ctru_sys::CFG_MODEL_2DS => Ok(SystemModel::Model2DS), - ctru_sys::CFG_MODEL_N3DSXL => Ok(SystemModel::ModelNew3DSXL), - ctru_sys::CFG_MODEL_N2DSXL => Ok(SystemModel::ModelNew2DSXL), + ctru_sys::CFG_MODEL_3DS => Ok(SystemModel::Old3DS), + ctru_sys::CFG_MODEL_3DSXL => Ok(SystemModel::Old3DSXL), + ctru_sys::CFG_MODEL_N3DS => Ok(SystemModel::New3DS), + ctru_sys::CFG_MODEL_2DS => Ok(SystemModel::Old2DS), + ctru_sys::CFG_MODEL_N3DSXL => Ok(SystemModel::New3DSXL), + ctru_sys::CFG_MODEL_N2DSXL => Ok(SystemModel::New2DSXL), _ => Err(()), } } diff --git a/ctru-rs/src/services/fs.rs b/ctru-rs/src/services/fs.rs index e3f45b0..04e0c1e 100644 --- a/ctru-rs/src/services/fs.rs +++ b/ctru-rs/src/services/fs.rs @@ -23,17 +23,13 @@ bitflags! { const FS_OPEN_WRITE = 2; const FS_OPEN_CREATE = 4; } -} -bitflags! { #[derive(Default)] struct FsWrite: u32 { const FS_WRITE_FLUSH = 1; const FS_WRITE_UPDATE_TIME = 256; } -} -bitflags! { #[derive(Default)] struct FsAttribute: u32 { const FS_ATTRIBUTE_DIRECTORY = 1; @@ -43,7 +39,7 @@ bitflags! { } } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum FsMediaType { Nand = ctru_sys::MEDIATYPE_NAND, @@ -51,7 +47,7 @@ pub enum FsMediaType { GameCard = ctru_sys::MEDIATYPE_GAME_CARD, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum PathType { Invalid = ctru_sys::PATH_INVALID, @@ -61,7 +57,7 @@ pub enum PathType { UTF16 = ctru_sys::PATH_UTF16, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum ArchiveID { RomFS = ctru_sys::ARCHIVE_ROMFS, @@ -103,7 +99,7 @@ pub struct Fs(()); /// ```no_run /// use ctru::services::fs::Fs; /// -/// let mut fs = Fs::init().unwrap(); +/// let mut fs = Fs::new().unwrap(); /// let sdmc_archive = fs.sdmc().unwrap(); /// ``` pub struct Archive { @@ -129,11 +125,8 @@ pub struct Archive { /// use std::io::prelude::*; /// use ctru::services::fs::{Fs, File}; /// -/// let mut fs = Fs::init()?; +/// let mut fs = Fs::new()?; /// let mut sdmc = fs.sdmc()?; -/// -/// let mut file = File::create(&mut sdmc, "/foo.txt")?; -/// file.write_all(b"Hello, world!")?; /// # /// # Ok(()) /// # } @@ -148,7 +141,7 @@ pub struct Archive { /// use std::io::prelude::*; /// use ctru::services::fs::{Fs, File}; /// -/// let mut fs = Fs::init()?; +/// let mut fs = Fs::new()?; /// let mut sdmc = fs.sdmc()?; /// /// let mut file = File::open(&sdmc, "/foo.txt")?; @@ -171,7 +164,7 @@ pub struct Archive { /// use std::io::prelude::*; /// use ctru::services::fs::{Fs, File}; /// -/// let mut fs = Fs::init()?; +/// let mut fs = Fs::new()?; /// let mut sdmc = fs.sdmc()?; /// /// let file = File::open(&sdmc, "/foo.txt")?; @@ -227,7 +220,7 @@ pub struct Metadata { /// ```no_run /// use ctru::services::fs::{Fs, OpenOptions}; /// -/// let mut fs = Fs::init().unwrap(); +/// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); /// let file = OpenOptions::new() /// .read(true) @@ -242,7 +235,7 @@ pub struct Metadata { /// ```no_run /// use ctru::services::fs::{Fs, OpenOptions}; /// -/// let mut fs = Fs::init().unwrap(); +/// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); /// let file = OpenOptions::new() /// .read(true) @@ -252,7 +245,7 @@ pub struct Metadata { /// .open("foo.txt") /// .unwrap(); /// ``` -#[derive(Clone, Default)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct OpenOptions { read: bool, write: bool, @@ -316,7 +309,7 @@ impl Fs { /// ctrulib services are reference counted, so this function may be called /// as many times as desired and the service will not exit until all /// instances of Fs drop out of scope. - pub fn init() -> crate::Result { + pub fn new() -> crate::Result { unsafe { let r = ctru_sys::fsInit(); if r < 0 { @@ -369,7 +362,7 @@ impl File { /// ```no_run /// use ctru::services::fs::{Fs, File}; /// - /// let mut fs = Fs::init().unwrap(); + /// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); /// let mut f = File::open(&sdmc_archive, "/foo.txt").unwrap(); /// ``` @@ -398,7 +391,7 @@ impl File { /// ```no_run /// use ctru::services::fs::{Fs, File}; /// - /// let mut fs = Fs::init().unwrap(); + /// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); /// let mut f = File::create(&mut sdmc_archive, "/foo.txt").unwrap(); /// ``` diff --git a/ctru-rs/src/services/gfx.rs b/ctru-rs/src/services/gfx.rs index 40d4740..3a5ba37 100644 --- a/ctru-rs/src/services/gfx.rs +++ b/ctru-rs/src/services/gfx.rs @@ -9,11 +9,12 @@ use crate::services::gspgpu::{self, FramebufferFormat}; use crate::services::ServiceReference; mod private { - use super::{BottomScreen, TopScreen, TopScreenLeft, TopScreenRight}; + use super::{BottomScreen, TopScreen, TopScreen3D, TopScreenLeft, TopScreenRight}; pub trait Sealed {} impl Sealed for TopScreen {} + impl Sealed for TopScreen3D<'_> {} impl Sealed for TopScreenLeft {} impl Sealed for TopScreenRight {} impl Sealed for BottomScreen {} @@ -34,33 +35,36 @@ pub trait Screen: private::Sealed { /// Note that the pointer of the framebuffer returned by this function can /// change after each call to this function if double buffering is enabled. fn raw_framebuffer(&mut self) -> RawFrameBuffer { - let mut width = 0; - let mut height = 0; + let mut width: u16 = 0; + let mut height: u16 = 0; let ptr = unsafe { ctru_sys::gfxGetFramebuffer(self.as_raw(), self.side().into(), &mut width, &mut height) }; RawFrameBuffer { ptr, - width, - height, + width: width.into(), + height: height.into(), screen: PhantomData, } } /// Sets whether to use double buffering. Enabled by default. /// - /// Note that even when double buffering is disabled, one should still use the `swap_buffers` - /// method on each frame to keep the gsp configuration up to date + /// [`Swap::swap_buffers`] must be called after this function for the configuration + /// change to take effect. fn set_double_buffering(&mut self, enabled: bool) { unsafe { ctru_sys::gfxSetDoubleBuffering(self.as_raw(), enabled) } } - /// Gets the framebuffer format + /// Gets the framebuffer format. fn framebuffer_format(&self) -> FramebufferFormat { unsafe { ctru_sys::gfxGetScreenFormat(self.as_raw()) }.into() } - /// Change the framebuffer format + /// Change the framebuffer format. + /// + /// [`Swap::swap_buffers`] must be called after this method for the configuration + /// change to take effect. fn set_framebuffer_format(&mut self, fmt: FramebufferFormat) { unsafe { ctru_sys::gfxSetScreenFormat(self.as_raw(), fmt.into()) } } @@ -75,17 +79,98 @@ pub struct TopScreen { /// A helper container for both sides of the top screen. Once the [`TopScreen`] is /// converted into this, 3D mode will be enabled until this struct is dropped. -pub struct TopScreen3D<'top_screen> { - screen: &'top_screen RefCell, +pub struct TopScreen3D<'screen> { + screen: &'screen RefCell, +} + +/// A screen that can have its frame buffers swapped, if double buffering is enabled. +/// +/// This trait applies to all [`Screen`]s that have swappable frame buffers. +pub trait Swap: private::Sealed { + /// Swaps the video buffers. + /// + /// If double buffering is disabled, "swapping" the buffers has the side effect + /// of committing any configuration changes to the buffers (e.g. [`set_wide_mode`], + /// [`set_framebuffer_format`], [`set_double_buffering`]). + /// + /// This should be called once per frame at most. + /// + /// [`set_wide_mode`]: TopScreen::set_wide_mode + /// [`set_framebuffer_format`]: Screen::set_framebuffer_format + /// [`set_double_buffering`]: Screen::set_double_buffering + fn swap_buffers(&mut self); +} + +impl Swap for TopScreen3D<'_> { + fn swap_buffers(&mut self) { + unsafe { + ctru_sys::gfxScreenSwapBuffers(ctru_sys::GFX_TOP, true); + } + } +} + +impl Swap for TopScreen { + fn swap_buffers(&mut self) { + unsafe { + ctru_sys::gfxScreenSwapBuffers(ctru_sys::GFX_TOP, false); + } + } +} + +impl Swap for BottomScreen { + fn swap_buffers(&mut self) { + unsafe { + ctru_sys::gfxScreenSwapBuffers(ctru_sys::GFX_BOTTOM, false); + } + } +} + +/// A screen with buffers that can be flushed. This trait applies to any [`Screen`] +/// that has data written to its frame buffer. +pub trait Flush: private::Sealed { + /// Flushes the video buffer(s) for this screen. Note that you must still call + /// [`Swap::swap_buffers`] after this method for the buffer contents to be displayed. + fn flush_buffers(&mut self); +} + +impl Flush for S { + fn flush_buffers(&mut self) { + let framebuffer = self.raw_framebuffer(); + + // Flush the data array. `self.raw_framebuffer` should get the correct parameters for all kinds of screens + unsafe { + ctru_sys::GSPGPU_FlushDataCache( + framebuffer.ptr.cast(), + (framebuffer.height * framebuffer.width) as u32, + ) + }; + } } -struct TopScreenLeft; +impl Flush for TopScreen3D<'_> { + /// Unlike most other implementations of [`Flush`], this flushes the buffers for both + /// the left and right sides of the top screen. + fn flush_buffers(&mut self) { + let (mut left, mut right) = self.split_mut(); + left.flush_buffers(); + right.flush_buffers(); + } +} -struct TopScreenRight; +/// The left side of the top screen, when using 3D mode. +#[derive(Debug)] +#[non_exhaustive] +pub struct TopScreenLeft; +/// The right side of the top screen, when using 3D mode. +#[derive(Debug)] #[non_exhaustive] +pub struct TopScreenRight; + /// The bottom screen. Mutable access to this struct is required to write to the /// bottom screen's frame buffer. +#[derive(Debug)] +#[non_exhaustive] pub struct BottomScreen; /// Representation of a framebuffer for one [`Side`] of the top screen, or the @@ -96,14 +181,14 @@ pub struct RawFrameBuffer<'screen> { /// Pointer to graphics data to be rendered. pub ptr: *mut u8, /// The width of the framebuffer in pixels. - pub width: u16, + pub width: usize, /// The height of the framebuffer in pixels. - pub height: u16, + pub height: usize, /// Keep a mutable reference to the Screen for which this framebuffer is tied. screen: PhantomData<&'screen mut dyn Screen>, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] /// Side of top screen framebuffer /// @@ -128,10 +213,17 @@ pub struct Gfx { static GFX_ACTIVE: Mutex = Mutex::new(0); impl Gfx { + /// Creates a new [Gfx] instance with default init values + /// It's the same as calling: + /// `Gfx::with_formats(FramebufferFormat::Bgr8, FramebufferFormat::Bgr8, false)` + pub fn new() -> Result { + Gfx::with_formats(FramebufferFormat::Bgr8, FramebufferFormat::Bgr8, false) + } + /// Initialize the Gfx module with the chosen framebuffer formats for the top and bottom /// screens /// - /// Use `Gfx::init()` instead of this function to initialize the module with default parameters + /// Use `Gfx::new()` instead of this function to initialize the module with default parameters pub fn with_formats( top_fb_fmt: FramebufferFormat, bottom_fb_fmt: FramebufferFormat, @@ -155,32 +247,6 @@ impl Gfx { }) } - /// Creates a new [Gfx] instance with default init values - /// It's the same as calling: - /// `Gfx::with_formats(FramebufferFormat::Bgr8, FramebufferFormat::Bgr8, false)` - pub fn init() -> Result { - Gfx::with_formats(FramebufferFormat::Bgr8, FramebufferFormat::Bgr8, false) - } - - /// Flushes the current framebuffers - pub fn flush_buffers(&self) { - unsafe { ctru_sys::gfxFlushBuffers() }; - } - - /// Swaps the framebuffers and sets the gsp state - /// - /// Use this function when working with software rendering - pub fn swap_buffers(&self) { - unsafe { ctru_sys::gfxSwapBuffers() }; - } - - /// Swaps the framebuffers without manipulating the gsp state - /// - /// Use this function when working with GPU rendering - pub fn swap_buffers_gpu(&self) { - unsafe { ctru_sys::gfxSwapBuffersGpu() }; - } - /// Waits for the vertical blank interrupt /// /// Use this to synchronize your application with the refresh rate of the LCD screens @@ -191,22 +257,20 @@ impl Gfx { impl TopScreen3D<'_> { /// Immutably borrow the two sides of the screen as `(left, right)`. - pub fn split(&self) -> (Ref, Ref) { - Ref::map_split(self.screen.borrow(), |screen| { - (&screen.left as _, &screen.right as _) - }) + pub fn split(&self) -> (Ref, Ref) { + Ref::map_split(self.screen.borrow(), |screen| (&screen.left, &screen.right)) } /// Mutably borrow the two sides of the screen as `(left, right)`. - pub fn split_mut(&self) -> (RefMut, RefMut) { + pub fn split_mut(&self) -> (RefMut, RefMut) { RefMut::map_split(self.screen.borrow_mut(), |screen| { - (&mut screen.left as _, &mut screen.right as _) + (&mut screen.left, &mut screen.right) }) } } -impl<'top_screen> From<&'top_screen RefCell> for TopScreen3D<'top_screen> { - fn from(top_screen: &'top_screen RefCell) -> Self { +impl<'screen> From<&'screen RefCell> for TopScreen3D<'screen> { + fn from(top_screen: &'screen RefCell) -> Self { unsafe { ctru_sys::gfxSet3D(true); } @@ -232,6 +296,9 @@ impl TopScreen { } /// Enable or disable wide mode on the top screen. + /// + /// [`Swap::swap_buffers`] must be called after this method for the configuration + /// to take effect. pub fn set_wide_mode(&mut self, enable: bool) { unsafe { ctru_sys::gfxSetWide(enable); @@ -244,6 +311,8 @@ impl TopScreen { } } +// When 3D mode is disabled, only the left side is used, so this Screen impl +// just forwards everything to the TopScreenLeft. impl Screen for TopScreen { fn as_raw(&self) -> ctru_sys::gfxScreen_t { self.left.as_raw() @@ -294,6 +363,6 @@ mod tests { #[test] fn gfx_duplicate() { // We don't need to build a `Gfx` because the test runner has one already - assert!(matches!(Gfx::init(), Err(Error::ServiceAlreadyActive))); + assert!(matches!(Gfx::new(), Err(Error::ServiceAlreadyActive))); } } diff --git a/ctru-rs/src/services/gspgpu.rs b/ctru-rs/src/services/gspgpu.rs index 234c088..9f9219c 100644 --- a/ctru-rs/src/services/gspgpu.rs +++ b/ctru-rs/src/services/gspgpu.rs @@ -1,6 +1,6 @@ //! GSPGPU service -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum Event { Psc0 = ctru_sys::GSPGPU_EVENT_PSC0, @@ -13,7 +13,7 @@ pub enum Event { } /// Framebuffer formats supported by the 3DS -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum FramebufferFormat { /// RGBA8. 4 bytes per pixel diff --git a/ctru-rs/src/services/hid.rs b/ctru-rs/src/services/hid.rs index 31dd4d9..fa91657 100644 --- a/ctru-rs/src/services/hid.rs +++ b/ctru-rs/src/services/hid.rs @@ -8,16 +8,15 @@ use crate::error::ResultCode; bitflags::bitflags! { /// A set of flags corresponding to the button and directional pad /// inputs on the 3DS - #[derive(Default)] pub struct KeyPad: u32 { const A = ctru_sys::KEY_A; const B = ctru_sys::KEY_B; const SELECT = ctru_sys::KEY_SELECT; const START = ctru_sys::KEY_START; - const DRIGHT = ctru_sys::KEY_DRIGHT; - const DLEFT = ctru_sys::KEY_DLEFT; - const DUP = ctru_sys::KEY_DUP; - const DDOWN = ctru_sys::KEY_DDOWN; + const DPAD_RIGHT = ctru_sys::KEY_DRIGHT; + const DPAD_LEFT = ctru_sys::KEY_DLEFT; + const DPAD_UP = ctru_sys::KEY_DUP; + const DPAD_DOWN = ctru_sys::KEY_DDOWN; const R = ctru_sys::KEY_R; const L = ctru_sys::KEY_L; const X = ctru_sys::KEY_X; @@ -34,10 +33,10 @@ bitflags::bitflags! { const CPAD_UP = ctru_sys::KEY_CPAD_UP; const CPAD_DOWN = ctru_sys::KEY_CPAD_DOWN; // Convenience catch-all for the dpad and cpad - const UP = KeyPad::DUP.bits() | KeyPad::CPAD_UP.bits(); - const DOWN = KeyPad::DDOWN.bits() | KeyPad::CPAD_DOWN.bits(); - const LEFT = KeyPad::DLEFT.bits() | KeyPad::CPAD_LEFT.bits(); - const RIGHT = KeyPad::DRIGHT.bits() | KeyPad::CPAD_RIGHT.bits(); + const UP = KeyPad::DPAD_UP.bits() | KeyPad::CPAD_UP.bits(); + const DOWN = KeyPad::DPAD_DOWN.bits() | KeyPad::CPAD_DOWN.bits(); + const LEFT = KeyPad::DPAD_LEFT.bits() | KeyPad::CPAD_LEFT.bits(); + const RIGHT = KeyPad::DPAD_RIGHT.bits() | KeyPad::CPAD_RIGHT.bits(); } } @@ -47,12 +46,6 @@ bitflags::bitflags! { /// This service requires no special permissions to use. pub struct Hid(()); -/// Represents user input to the touchscreen. -pub struct TouchPosition(ctru_sys::touchPosition); - -/// Represents the current position of the 3DS circle pad. -pub struct CirclePosition(ctru_sys::circlePosition); - /// Initializes the HID service. /// /// # Errors @@ -61,7 +54,7 @@ pub struct CirclePosition(ctru_sys::circlePosition); /// Since this service requires no special or elevated permissions, errors are /// rare in practice. impl Hid { - pub fn init() -> crate::Result { + pub fn new() -> crate::Result { unsafe { ResultCode(ctru_sys::hidInit())?; Ok(Hid(())) @@ -101,47 +94,33 @@ impl Hid { KeyPad::from_bits_truncate(keys) } } -} - -impl Default for TouchPosition { - fn default() -> Self { - TouchPosition(ctru_sys::touchPosition { px: 0, py: 0 }) - } -} -impl TouchPosition { - /// Create a new TouchPosition instance. - pub fn new() -> Self { - Self::default() - } + /// Returns the current touch position in pixels (x, y). + /// + /// # Notes + /// + /// (0, 0) represents the top left corner of the screen. + pub fn touch_position(&mut self) -> (u16, u16) { + let mut res = ctru_sys::touchPosition { px: 0, py: 0 }; - /// Returns the current touch position in pixels. - pub fn get(&mut self) -> (u16, u16) { unsafe { - ctru_sys::hidTouchRead(&mut self.0); + ctru_sys::hidTouchRead(&mut res); } - (self.0.px, self.0.py) - } -} - -impl Default for CirclePosition { - fn default() -> Self { - CirclePosition(ctru_sys::circlePosition { dx: 0, dy: 0 }) + (res.px, res.py) } -} -impl CirclePosition { - /// Create a new CirclePosition instance. - pub fn new() -> Self { - Self::default() - } + /// Returns the current circle pad position in relative (x, y). + /// + /// # Notes + /// + /// (0, 0) represents the center of the circle pad. + pub fn circlepad_position(&mut self) -> (i16, i16) { + let mut res = ctru_sys::circlePosition { dx: 0, dy: 0 }; - /// Returns the current circle pad position in (x, y) form. - pub fn get(&mut self) -> (i16, i16) { unsafe { - ctru_sys::hidCircleRead(&mut self.0); + ctru_sys::hidCircleRead(&mut res); } - (self.0.dx, self.0.dy) + (res.dx, res.dy) } } diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index fa93cf6..8f67b1b 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -14,7 +14,7 @@ use std::sync::Mutex; const NUMBER_OF_CHANNELS: u8 = 24; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum OutputMode { Mono = ctru_sys::NDSP_OUTPUT_MONO, @@ -22,7 +22,7 @@ pub enum OutputMode { Surround = ctru_sys::NDSP_OUTPUT_SURROUND, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum AudioFormat { PCM8Mono = ctru_sys::NDSP_FORMAT_MONO_PCM8, @@ -32,12 +32,12 @@ pub enum AudioFormat { } /// Representation of volume mix for a channel. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct AudioMix { raw: [f32; 12], } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u32)] pub enum InterpolationType { Polyphase = ctru_sys::NDSP_INTERP_POLYPHASE, @@ -45,7 +45,7 @@ pub enum InterpolationType { None = ctru_sys::NDSP_INTERP_NONE, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum NdspError { /// Channel ID InvalidChannel(u8), @@ -80,7 +80,7 @@ impl Ndsp { /// /// This function will return an error if an instance of the `Ndsp` struct already exists /// or if there are any issues during initialization. - pub fn init() -> crate::Result { + pub fn new() -> crate::Result { let _service_handler = ServiceReference::new( &NDSP_ACTIVE, false, diff --git a/ctru-rs/src/services/ndsp/wave.rs b/ctru-rs/src/services/ndsp/wave.rs index a47c113..feff4cd 100644 --- a/ctru-rs/src/services/ndsp/wave.rs +++ b/ctru-rs/src/services/ndsp/wave.rs @@ -11,7 +11,7 @@ pub struct Wave { played_on_channel: Option, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(u8)] /// Enum representing the playback status of a [Wave]. pub enum WaveStatus { diff --git a/ctru-rs/src/services/ps.rs b/ctru-rs/src/services/ps.rs index a14f2c4..1d5bd69 100644 --- a/ctru-rs/src/services/ps.rs +++ b/ctru-rs/src/services/ps.rs @@ -6,6 +6,7 @@ use crate::error::ResultCode; use crate::Result; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u32)] pub enum AESAlgorithm { CbcEnc = ctru_sys::PS_ALGORITHM_CBC_ENC, @@ -16,6 +17,7 @@ pub enum AESAlgorithm { CcmDec = ctru_sys::PS_ALGORITHM_CCM_DEC, } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u32)] pub enum AESKeyType { Keyslot0D = ctru_sys::PS_KEYSLOT_0D, @@ -56,7 +58,7 @@ impl Ps { pub fn generate_random_bytes(&self, out: &mut [u8]) -> crate::Result<()> { ResultCode(unsafe { - ctru_sys::PS_GenerateRandomBytes(out as *mut _ as *mut _, out.len()) + ctru_sys::PS_GenerateRandomBytes(out.as_mut_ptr().cast(), out.len()) })?; Ok(()) } diff --git a/ctru-rs/src/services/romfs.rs b/ctru-rs/src/services/romfs.rs index fd022e8..49369a6 100644 --- a/ctru-rs/src/services/romfs.rs +++ b/ctru-rs/src/services/romfs.rs @@ -25,7 +25,7 @@ pub struct RomFS { static ROMFS_ACTIVE: Mutex = Mutex::new(0); impl RomFS { - pub fn init() -> crate::Result { + pub fn new() -> crate::Result { let _service_handler = ServiceReference::new( &ROMFS_ACTIVE, true, @@ -50,7 +50,7 @@ mod tests { #[test] fn romfs_counter() { - let _romfs = RomFS::init().unwrap(); + let _romfs = RomFS::new().unwrap(); let value = *ROMFS_ACTIVE.lock().unwrap(); assert_eq!(value, 1); diff --git a/ctru-rs/src/services/soc.rs b/ctru-rs/src/services/soc.rs index c5df066..5b9c696 100644 --- a/ctru-rs/src/services/soc.rs +++ b/ctru-rs/src/services/soc.rs @@ -25,7 +25,7 @@ impl Soc { /// # Errors /// /// This function will return an error if the `Soc` service is already initialized - pub fn init() -> crate::Result { + pub fn new() -> crate::Result { Self::init_with_buffer_size(0x100000) } @@ -107,8 +107,8 @@ mod tests { #[test] fn soc_duplicate() { - let _soc = Soc::init().unwrap(); + let _soc = Soc::new().unwrap(); - assert!(matches!(Soc::init(), Err(Error::ServiceAlreadyActive))) + assert!(matches!(Soc::new(), Err(Error::ServiceAlreadyActive))) } } diff --git a/ctru-rs/src/services/sslc.rs b/ctru-rs/src/services/sslc.rs index 99eb456..341155f 100644 --- a/ctru-rs/src/services/sslc.rs +++ b/ctru-rs/src/services/sslc.rs @@ -8,23 +8,12 @@ pub struct SslC(()); impl SslC { /// Initialize the service - pub fn init() -> crate::Result { + pub fn new() -> crate::Result { unsafe { ResultCode(ctru_sys::sslcInit(0))?; Ok(SslC(())) } } - - /// Fill `buf` with `buf.len()` random bytes - pub fn generate_random_data(&self, buf: &mut [u8]) -> crate::Result<()> { - unsafe { - ResultCode(ctru_sys::sslcGenerateRandomData( - buf.as_ptr() as _, - buf.len() as u32, - ))?; - Ok(()) - } - } } impl Drop for SslC { diff --git a/ctru-rs/src/test_runner.rs b/ctru-rs/src/test_runner.rs index 6f157e3..97aa5f4 100644 --- a/ctru-rs/src/test_runner.rs +++ b/ctru-rs/src/test_runner.rs @@ -12,13 +12,13 @@ use crate::prelude::*; /// runs all tests in series, "failing" on the first one to panic (really, the /// panic is just treated the same as any normal application panic). pub(crate) fn run(tests: &[&TestDescAndFn]) { - let gfx = Gfx::init().unwrap(); - let mut hid = Hid::init().unwrap(); - let apt = Apt::init().unwrap(); + let gfx = Gfx::new().unwrap(); + let mut hid = Hid::new().unwrap(); + let apt = Apt::new().unwrap(); let mut top_screen = gfx.top_screen.borrow_mut(); top_screen.set_wide_mode(true); - let _console = Console::init(top_screen); + let _console = Console::new(top_screen); let opts = TestOpts { force_run_in_process: true, @@ -39,8 +39,6 @@ pub(crate) fn run(tests: &[&TestDescAndFn]) { println!("Press START to exit."); while apt.main_loop() { - gfx.flush_buffers(); - gfx.swap_buffers(); gfx.wait_for_vblank(); hid.scan_input();